diff --git a/board/CZ.NIC/turris_omnia/Makefile b/board/CZ.NIC/turris_omnia/Makefile index 341378b4e54..216e11958a7 100644 --- a/board/CZ.NIC/turris_omnia/Makefile +++ b/board/CZ.NIC/turris_omnia/Makefile @@ -3,3 +3,4 @@ # Copyright (C) 2017 Marek BehĂșn obj-y := turris_omnia.o ../turris_atsha_otp.o ../turris_common.o +obj-$(CONFIG_CMD_EEPROM_LAYOUT) += eeprom.o diff --git a/board/CZ.NIC/turris_omnia/eeprom.c b/board/CZ.NIC/turris_omnia/eeprom.c new file mode 100644 index 00000000000..a4f1dab469f --- /dev/null +++ b/board/CZ.NIC/turris_omnia/eeprom.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2024 Marek BehĂșn + */ + +#include +#include +#include +#include +#include +#include +#include + +#define _DEF_FIELD(_n, _s, _t) \ + { _n, _s, NULL, eeprom_field_print_ ## _t, eeprom_field_update_ ## _t } + +static void eeprom_field_print_ramsz(const struct eeprom_field *field) +{ + printf(PRINT_FIELD_SEGMENT, field->name); + printf("%u\n", get_unaligned_le32(field->buf)); +} + +static int eeprom_field_update_ramsz(struct eeprom_field *field, char *value) +{ + u32 sz; + + if (value[0] == '1' || value[0] == '2' || value[0] == '4') + sz = value[0] - '0'; + else + return -1; + + if (value[1] != '\0') + return -1; + + put_unaligned_le32(sz, field->buf); + + return 0; +} + +static void eeprom_field_print_region(const struct eeprom_field *field) +{ + eeprom_field_print_ascii(field); +} + +static int eeprom_field_update_region(struct eeprom_field *field, char *value) +{ + if (strlen(value) != 2) { + printf("%s: has to be 2 characters\n", field->name); + return -1; + } + + memcpy(field->buf, value, 2); + memset(&field->buf[2], '\0', 2); + + return 0; +} + +static struct eeprom_field omnia_layout[] = { + _DEF_FIELD("Magic constant", 4, bin), + _DEF_FIELD("RAM size in GB", 4, ramsz), + _DEF_FIELD("Wi-Fi Region", 4, region), + _DEF_FIELD("CRC32 checksum", 4, bin), +}; + +static struct eeprom_field *crc_field = &omnia_layout[3]; + +static int omnia_update_field(struct eeprom_layout *layout, char *field_name, + char *new_data) +{ + struct eeprom_field *field; + int err; + + if (!new_data) + return 0; + + if (!field_name) + return -1; + + field = eeprom_layout_find_field(layout, field_name, true); + if (!field) + return -1; + + err = field->update(field, new_data); + if (err) { + printf("Invalid data for field %s\n", field_name); + return err; + } + + if (field < crc_field) { + u32 crc = crc32(0, layout->data, 12); + put_unaligned_le32(crc, crc_field->buf); + } + + return 0; +} + +void eeprom_layout_assign(struct eeprom_layout *layout, int) +{ + layout->fields = omnia_layout; + layout->num_of_fields = ARRAY_SIZE(omnia_layout); + layout->update = omnia_update_field; + layout->data_size = 16; +} + +int eeprom_layout_detect(unsigned char *) +{ + /* Turris Omnia has only one version of EEPROM layout */ + return 0; +}