Commit aa9e60441095ee3f20a109742e3ba5cdfd28458b

Authored by Nikita Kiryanov
Committed by Tom Rini
1 parent 2636ac65a8

cmd: eeprom: add support for layout aware commands

Introduce the (optional) eeprom print and eeprom update commands.

These commands are eeprom layout aware:
* The eeprom print command prints the contents of the eeprom in a human
  readable way (eeprom layout fields, and data formatted to be fit for human
  consumption).
* The eeprom update command allows user to update eeprom fields by specifying
  the field name, and providing the new data in a human readable format (same
  format as displayed by the eeprom print command).
* Both commands can either auto detect the layout, or be told which layout to
  use.

New CONFIG options:
CONFIG_CMD_EEPROM_LAYOUT - enables commands.
CONFIG_EEPROM_LAYOUT_HELP_STRING - tells user what layout names are supported

Feature API:
__weak int parse_layout_version(char *str)
	- override to provide your own layout name parsing
__weak void __eeprom_layout_assign(struct eeprom_layout *layout, int layout_version);
	- override to setup the layout metadata based on the version
__weak int eeprom_layout_detect(unsigned char *data)
	- override to provide your own algorithm for detecting layout version
eeprom_field.c
	- contains various printing and updating functions for common types of
	  eeprom fields. Can be used for defining custom layouts.

Cc: Heiko Schocher <hs@denx.de>
Cc: Marek Vasut <marex@denx.de>
Cc: Simon Glass <sjg@chromium.org>
Cc: Igor Grinberg <grinberg@compulab.co.il>
Cc: Tom Rini <trini@konsulko.com>
Signed-off-by: Nikita Kiryanov <nikita@compulab.co.il>

Showing 7 changed files with 598 additions and 1 deletions Side-by-side Diff

... ... @@ -1003,6 +1003,7 @@
1003 1003 CONFIG_CMD_ECHO echo arguments
1004 1004 CONFIG_CMD_EDITENV edit env variable
1005 1005 CONFIG_CMD_EEPROM * EEPROM read/write support
  1006 + CONFIG_CMD_EEPROM_LAYOUT* EEPROM layout aware commands
1006 1007 CONFIG_CMD_ELF * bootelf, bootvx
1007 1008 CONFIG_CMD_ENV_CALLBACK * display details about env callbacks
1008 1009 CONFIG_CMD_ENV_FLAGS * display details about env flags
... ... @@ -207,6 +207,131 @@
207 207 return ret;
208 208 }
209 209  
  210 +#ifdef CONFIG_CMD_EEPROM_LAYOUT
  211 +#include <eeprom_layout.h>
  212 +
  213 +__weak int eeprom_parse_layout_version(char *str)
  214 +{
  215 + return LAYOUT_VERSION_UNRECOGNIZED;
  216 +}
  217 +
  218 +static unsigned char eeprom_buf[CONFIG_SYS_EEPROM_SIZE];
  219 +
  220 +#ifndef CONFIG_EEPROM_LAYOUT_HELP_STRING
  221 +#define CONFIG_EEPROM_LAYOUT_HELP_STRING "<not defined>"
  222 +#endif
  223 +
  224 +enum eeprom_action {
  225 + EEPROM_PRINT,
  226 + EEPROM_UPDATE,
  227 + EEPROM_ACTION_INVALID,
  228 +};
  229 +
  230 +static enum eeprom_action parse_action(char *cmd)
  231 +{
  232 + if (!strncmp(cmd, "print", 5))
  233 + return EEPROM_PRINT;
  234 + if (!strncmp(cmd, "update", 6))
  235 + return EEPROM_UPDATE;
  236 +
  237 + return EEPROM_ACTION_INVALID;
  238 +}
  239 +
  240 +static int parse_numeric_param(char *str)
  241 +{
  242 + char *endptr;
  243 + int value = simple_strtol(str, &endptr, 16);
  244 +
  245 + return (*endptr != '\0') ? -1 : value;
  246 +}
  247 +
  248 +static int eeprom_execute_command(enum eeprom_action action, int i2c_bus,
  249 + int i2c_addr, int layout_ver, char *key,
  250 + char *value)
  251 +{
  252 + int rcode;
  253 + struct eeprom_layout layout;
  254 +
  255 + if (action == EEPROM_ACTION_INVALID)
  256 + return CMD_RET_USAGE;
  257 +
  258 + eeprom_init(i2c_bus);
  259 + rcode = eeprom_read(i2c_addr, 0, eeprom_buf, CONFIG_SYS_EEPROM_SIZE);
  260 + if (rcode < 0)
  261 + return rcode;
  262 +
  263 + eeprom_layout_setup(&layout, eeprom_buf, CONFIG_SYS_EEPROM_SIZE,
  264 + layout_ver);
  265 +
  266 + if (action == EEPROM_PRINT) {
  267 + layout.print(&layout);
  268 + return 0;
  269 + }
  270 +
  271 + layout.update(&layout, key, value);
  272 +
  273 + rcode = eeprom_write(i2c_addr, 0, layout.data, CONFIG_SYS_EEPROM_SIZE);
  274 +
  275 + return rcode;
  276 +}
  277 +
  278 +#define NEXT_PARAM(argc, index) { (argc)--; (index)++; }
  279 +static int do_eeprom_layout(cmd_tbl_t *cmdtp, int flag, int argc,
  280 + char * const argv[])
  281 +{
  282 + int layout_ver = LAYOUT_VERSION_AUTODETECT;
  283 + enum eeprom_action action = EEPROM_ACTION_INVALID;
  284 + int i2c_bus = -1, i2c_addr = -1, index = 0;
  285 + char *field_name = "";
  286 + char *field_value = "";
  287 +
  288 + if (argc <= 1)
  289 + return CMD_RET_USAGE;
  290 +
  291 + NEXT_PARAM(argc, index); /* Skip program name */
  292 +
  293 + action = parse_action(argv[index]);
  294 + NEXT_PARAM(argc, index);
  295 +
  296 + if (argc <= 1)
  297 + return CMD_RET_USAGE;
  298 +
  299 + if (!strcmp(argv[index], "-l")) {
  300 + NEXT_PARAM(argc, index);
  301 +
  302 + layout_ver = eeprom_parse_layout_version(argv[index]);
  303 + NEXT_PARAM(argc, index);
  304 + }
  305 +
  306 + if (argc <= 1)
  307 + return CMD_RET_USAGE;
  308 +
  309 + i2c_bus = parse_numeric_param(argv[index]);
  310 + NEXT_PARAM(argc, index);
  311 +
  312 + i2c_addr = parse_numeric_param(argv[index]);
  313 + NEXT_PARAM(argc, index);
  314 +
  315 + if (action == EEPROM_PRINT)
  316 + goto done;
  317 +
  318 + if (argc) {
  319 + field_name = argv[index];
  320 + NEXT_PARAM(argc, index);
  321 + }
  322 +
  323 + if (argc) {
  324 + field_value = argv[index];
  325 + NEXT_PARAM(argc, index);
  326 + }
  327 +
  328 +done:
  329 + return eeprom_execute_command(action, i2c_bus, i2c_addr, layout_ver,
  330 + field_name, field_value);
  331 +}
  332 +
  333 +#endif
  334 +
210 335 static int do_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
211 336 {
212 337 const char *const fmt =
... ... @@ -216,6 +341,13 @@
216 341 ulong dev_addr, addr, off, cnt;
217 342 int bus_addr;
218 343  
  344 +#ifdef CONFIG_CMD_EEPROM_LAYOUT
  345 + if (argc >= 2) {
  346 + if (!strcmp(argv[1], "update") || !strcmp(argv[1], "print"))
  347 + return do_eeprom_layout(cmdtp, flag, argc, argv);
  348 + }
  349 +#endif
  350 +
219 351 switch (argc) {
220 352 #ifdef CONFIG_SYS_DEF_EEPROM_ADDR
221 353 case 5:
222 354  
... ... @@ -261,10 +393,24 @@
261 393 }
262 394  
263 395 U_BOOT_CMD(
264   - eeprom, 7, 1, do_eeprom,
  396 + eeprom, 8, 1, do_eeprom,
265 397 "EEPROM sub-system",
266 398 "read <bus> <devaddr> addr off cnt\n"
267 399 "eeprom write <bus> <devaddr> addr off cnt\n"
268 400 " - read/write `cnt' bytes from `devaddr` EEPROM at offset `off'"
  401 +#ifdef CONFIG_CMD_EEPROM_LAYOUT
  402 + "\n"
  403 + "eeprom print [-l <layout_version>] bus devaddr\n"
  404 + " - Print layout fields and their data in human readable format\n"
  405 + "eeprom update [-l <layout_version>] bus devaddr <field_name> <field_value>\n"
  406 + " - Update a specific eeprom field with new data.\n"
  407 + " The new data must be written in the same human readable format as shown by the print command.\n"
  408 + "\n"
  409 + "LAYOUT VERSIONS\n"
  410 + "The -l option can be used to force the command to interpret the EEPROM data using the chosen layout.\n"
  411 + "If the -l option is omitted, the command will auto detect the layout based on the data in the EEPROM.\n"
  412 + "The values which can be provided with the -l option are:\n"
  413 + CONFIG_EEPROM_LAYOUT_HELP_STRING"\n"
  414 +#endif
269 415 )
... ... @@ -156,6 +156,9 @@
156 156 endif
157 157 endif
158 158  
  159 +ifdef CONFIG_CMD_EEPROM_LAYOUT
  160 +obj-y += eeprom/eeprom_field.o eeprom/eeprom_layout.o
  161 +endif
159 162 # We always have this since drivers/ddr/fs/interactive.c needs it
160 163 obj-$(CONFIG_CMDLINE) += cli_simple.o
161 164  
common/eeprom/eeprom_field.c
  1 +/*
  2 + * (C) Copyright 2009-2016 CompuLab, Ltd.
  3 + *
  4 + * Authors: Nikita Kiryanov <nikita@compulab.co.il>
  5 + * Igor Grinberg <grinberg@compulab.co.il>
  6 + *
  7 + * SPDX-License-Identifier: GPL-2.0+
  8 + */
  9 +
  10 +#include <common.h>
  11 +#include <linux/string.h>
  12 +#include <eeprom_field.h>
  13 +
  14 +static void __eeprom_field_print_bin(const struct eeprom_field *field,
  15 + char *delimiter, bool reverse)
  16 +{
  17 + int i;
  18 + int from = reverse ? field->size - 1 : 0;
  19 + int to = reverse ? 0 : field->size - 1;
  20 +
  21 + printf(PRINT_FIELD_SEGMENT, field->name);
  22 + for (i = from; i != to; reverse ? i-- : i++)
  23 + printf("%02x%s", field->buf[i], delimiter);
  24 +
  25 + printf("%02x\n", field->buf[i]);
  26 +}
  27 +
  28 +static int __eeprom_field_update_bin(struct eeprom_field *field,
  29 + const char *value, bool reverse)
  30 +{
  31 + int len = strlen(value);
  32 + int k, j, i = reverse ? len - 1 : 0;
  33 + unsigned char byte;
  34 + char *endptr;
  35 +
  36 + /* each two characters in the string fit in one byte */
  37 + if (len > field->size * 2)
  38 + return -1;
  39 +
  40 + memset(field->buf, 0, field->size);
  41 +
  42 + /* i - string iterator, j - buf iterator */
  43 + for (j = 0; j < field->size; j++) {
  44 + byte = 0;
  45 + char tmp[3] = { 0, 0, 0 };
  46 +
  47 + if ((reverse && i < 0) || (!reverse && i >= len))
  48 + break;
  49 +
  50 + for (k = 0; k < 2; k++) {
  51 + if (reverse && i == 0) {
  52 + tmp[k] = value[i];
  53 + break;
  54 + }
  55 +
  56 + tmp[k] = value[reverse ? i - 1 + k : i + k];
  57 + }
  58 +
  59 + byte = simple_strtoul(tmp, &endptr, 0);
  60 + if (*endptr != '\0' || byte < 0)
  61 + return -1;
  62 +
  63 + field->buf[j] = byte;
  64 + i = reverse ? i - 2 : i + 2;
  65 + }
  66 +
  67 + return 0;
  68 +}
  69 +
  70 +static int __eeprom_field_update_bin_delim(struct eeprom_field *field,
  71 + char *value, char *delimiter)
  72 +{
  73 + int count = 0;
  74 + int i, val;
  75 + const char *tmp = value;
  76 + char *tok;
  77 + char *endptr;
  78 +
  79 + tmp = strstr(tmp, delimiter);
  80 + while (tmp != NULL) {
  81 + count++;
  82 + tmp++;
  83 + tmp = strstr(tmp, delimiter);
  84 + }
  85 +
  86 + if (count > field->size)
  87 + return -1;
  88 +
  89 + tok = strtok(value, delimiter);
  90 + for (i = 0; tok && i < field->size; i++) {
  91 + val = simple_strtoul(tok, &endptr, 0);
  92 + if (*endptr != '\0')
  93 + return -1;
  94 +
  95 + /* here we assume that each tok is no more than byte long */
  96 + field->buf[i] = (unsigned char)val;
  97 + tok = strtok(NULL, delimiter);
  98 + }
  99 +
  100 + return 0;
  101 +}
  102 +
  103 +/**
  104 + * eeprom_field_print_bin() - print a field which contains binary data
  105 + *
  106 + * Treat the field data as simple binary data, and print it as two digit
  107 + * hexadecimal values.
  108 + * Sample output:
  109 + * Field Name 0102030405060708090a
  110 + *
  111 + * @field: an initialized field to print
  112 + */
  113 +void eeprom_field_print_bin(const struct eeprom_field *field)
  114 +{
  115 + __eeprom_field_print_bin(field, "", false);
  116 +}
  117 +
  118 +/**
  119 + * eeprom_field_update_bin() - Update field with new data in binary form
  120 + *
  121 + * @field: an initialized field
  122 + * @value: a string of values (i.e. "10b234a")
  123 + */
  124 +int eeprom_field_update_bin(struct eeprom_field *field, char *value)
  125 +{
  126 + return __eeprom_field_update_bin(field, value, false);
  127 +}
  128 +
  129 +/**
  130 + * eeprom_field_update_reserved() - Update reserved field with new data in
  131 + * binary form
  132 + *
  133 + * @field: an initialized field
  134 + * @value: a space delimited string of byte values (i.e. "1 02 3 0x4")
  135 + */
  136 +int eeprom_field_update_reserved(struct eeprom_field *field, char *value)
  137 +{
  138 + return __eeprom_field_update_bin_delim(field, value, " ");
  139 +}
  140 +
  141 +/**
  142 + * eeprom_field_print_bin_rev() - print a field which contains binary data in
  143 + * reverse order
  144 + *
  145 + * Treat the field data as simple binary data, and print it in reverse order
  146 + * as two digit hexadecimal values.
  147 + *
  148 + * Data in field:
  149 + * 0102030405060708090a
  150 + * Sample output:
  151 + * Field Name 0a090807060504030201
  152 + *
  153 + * @field: an initialized field to print
  154 + */
  155 +void eeprom_field_print_bin_rev(const struct eeprom_field *field)
  156 +{
  157 + __eeprom_field_print_bin(field, "", true);
  158 +}
  159 +
  160 +/**
  161 + * eeprom_field_update_bin_rev() - Update field with new data in binary form,
  162 + * storing it in reverse
  163 + *
  164 + * This function takes a string of byte values, and stores them
  165 + * in the field in the reverse order. i.e. if the input string was "1234",
  166 + * "3412" will be written to the field.
  167 + *
  168 + * @field: an initialized field
  169 + * @value: a string of byte values
  170 + */
  171 +int eeprom_field_update_bin_rev(struct eeprom_field *field, char *value)
  172 +{
  173 + return __eeprom_field_update_bin(field, value, true);
  174 +}
  175 +
  176 +/**
  177 + * eeprom_field_print_mac_addr() - print a field which contains a mac address
  178 + *
  179 + * Treat the field data as simple binary data, and print it formatted as a MAC
  180 + * address.
  181 + * Sample output:
  182 + * Field Name 01:02:03:04:05:06
  183 + *
  184 + * @field: an initialized field to print
  185 + */
  186 +void eeprom_field_print_mac(const struct eeprom_field *field)
  187 +{
  188 + __eeprom_field_print_bin(field, ":", false);
  189 +}
  190 +
  191 +/**
  192 + * eeprom_field_update_mac() - Update a mac address field which contains binary
  193 + * data
  194 + *
  195 + * @field: an initialized field
  196 + * @value: a colon delimited string of byte values (i.e. "1:02:3:ff")
  197 + */
  198 +int eeprom_field_update_mac(struct eeprom_field *field, char *value)
  199 +{
  200 + return __eeprom_field_update_bin_delim(field, value, ":");
  201 +}
  202 +
  203 +/**
  204 + * eeprom_field_print_ascii() - print a field which contains ASCII data
  205 + * @field: an initialized field to print
  206 + */
  207 +void eeprom_field_print_ascii(const struct eeprom_field *field)
  208 +{
  209 + char format[8];
  210 +
  211 + sprintf(format, "%%.%ds\n", field->size);
  212 + printf(PRINT_FIELD_SEGMENT, field->name);
  213 + printf(format, field->buf);
  214 +}
  215 +
  216 +/**
  217 + * eeprom_field_update_ascii() - Update field with new data in ASCII form
  218 + * @field: an initialized field
  219 + * @value: the new string data
  220 + *
  221 + * Returns 0 on success, -1 of failure (new string too long).
  222 + */
  223 +int eeprom_field_update_ascii(struct eeprom_field *field, char *value)
  224 +{
  225 + if (strlen(value) >= field->size) {
  226 + printf("%s: new data too long\n", field->name);
  227 + return -1;
  228 + }
  229 +
  230 + strncpy((char *)field->buf, value, field->size - 1);
  231 + field->buf[field->size - 1] = '\0';
  232 +
  233 + return 0;
  234 +}
  235 +
  236 +/**
  237 + * eeprom_field_print_reserved() - print the "Reserved fields" field
  238 + *
  239 + * Print a notice that the following field_size bytes are reserved.
  240 + *
  241 + * Sample output:
  242 + * Reserved fields (64 bytes)
  243 + *
  244 + * @field: an initialized field to print
  245 + */
  246 +void eeprom_field_print_reserved(const struct eeprom_field *field)
  247 +{
  248 + printf(PRINT_FIELD_SEGMENT, "Reserved fields\t");
  249 + printf("(%d bytes)\n", field->size);
  250 +}
common/eeprom/eeprom_layout.c
  1 +/*
  2 + * (C) Copyright 2009-2016 CompuLab, Ltd.
  3 + *
  4 + * Authors: Nikita Kiryanov <nikita@compulab.co.il>
  5 + * Igor Grinberg <grinberg@compulab.co.il>
  6 + *
  7 + * SPDX-License-Identifier: GPL-2.0+
  8 + */
  9 +
  10 +#include <common.h>
  11 +#include <linux/kernel.h>
  12 +#include <eeprom_layout.h>
  13 +#include <eeprom_field.h>
  14 +
  15 +#define NO_LAYOUT_FIELDS "Unknown layout. Dumping raw data\n"
  16 +
  17 +struct eeprom_field layout_unknown[1] = {
  18 + { NO_LAYOUT_FIELDS, 256, NULL, eeprom_field_print_bin,
  19 + eeprom_field_update_bin },
  20 +};
  21 +
  22 +/*
  23 + * eeprom_layout_detect() - detect layout based on the contents of the data.
  24 + * @data: Pointer to the data to be analyzed.
  25 + *
  26 + * Returns: the detected layout version.
  27 + */
  28 +__weak int eeprom_layout_detect(unsigned char *data)
  29 +{
  30 + return LAYOUT_VERSION_UNRECOGNIZED;
  31 +}
  32 +
  33 +/*
  34 + * __eeprom_layout_assign() - set the layout fields
  35 + * @layout: A pointer to an existing struct layout.
  36 + * @layout_version: The version number of the desired layout
  37 + */
  38 +__weak void __eeprom_layout_assign(struct eeprom_layout *layout,
  39 + int layout_version)
  40 +{
  41 + layout->fields = layout_unknown;
  42 + layout->num_of_fields = ARRAY_SIZE(layout_unknown);
  43 +}
  44 +void eeprom_layout_assign(struct eeprom_layout *layout, int layout_version) \
  45 + __attribute__((weak, alias("__eeprom_layout_assign")));
  46 +
  47 +/*
  48 + * eeprom_layout_print() - print the layout and the data which is assigned to it
  49 + * @layout: A pointer to an existing struct layout.
  50 + */
  51 +static void eeprom_layout_print(const struct eeprom_layout *layout)
  52 +{
  53 + int i;
  54 + struct eeprom_field *fields = layout->fields;
  55 +
  56 + for (i = 0; i < layout->num_of_fields; i++)
  57 + fields[i].print(&fields[i]);
  58 +}
  59 +
  60 +/*
  61 + * eeprom_layout_update_field() - update a single field in the layout data.
  62 + * @layout: A pointer to an existing struct layout.
  63 + * @field_name: The name of the field to update.
  64 + * @new_data: The new field data (a string. Format depends on the field)
  65 + *
  66 + * Returns: 0 on success, negative error value on failure.
  67 + */
  68 +static int eeprom_layout_update_field(struct eeprom_layout *layout,
  69 + char *field_name, char *new_data)
  70 +{
  71 + int i, err;
  72 + struct eeprom_field *fields = layout->fields;
  73 +
  74 + if (new_data == NULL)
  75 + return 0;
  76 +
  77 + if (field_name == NULL)
  78 + return -1;
  79 +
  80 + for (i = 0; i < layout->num_of_fields; i++) {
  81 + if (fields[i].name == RESERVED_FIELDS ||
  82 + strcmp(fields[i].name, field_name))
  83 + continue;
  84 +
  85 + err = fields[i].update(&fields[i], new_data);
  86 + if (err)
  87 + printf("Invalid data for field %s\n", field_name);
  88 +
  89 + return err;
  90 + }
  91 +
  92 + printf("No such field '%s'\n", field_name);
  93 +
  94 + return -1;
  95 +}
  96 +
  97 +/*
  98 + * eeprom_layout_setup() - setup layout struct with the layout data and
  99 + * metadata as dictated by layout_version
  100 + * @layout: A pointer to an existing struct layout.
  101 + * @buf: A buffer initialized with the eeprom data.
  102 + * @buf_size: Size of buf in bytes.
  103 + * @layout version: The version number of the layout.
  104 + */
  105 +void eeprom_layout_setup(struct eeprom_layout *layout, unsigned char *buf,
  106 + unsigned int buf_size, int layout_version)
  107 +{
  108 + int i;
  109 +
  110 + if (layout_version == LAYOUT_VERSION_AUTODETECT)
  111 + layout->layout_version = eeprom_layout_detect(buf);
  112 + else
  113 + layout->layout_version = layout_version;
  114 +
  115 + eeprom_layout_assign(layout, layout_version);
  116 + layout->data = buf;
  117 + for (i = 0; i < layout->num_of_fields; i++) {
  118 + layout->fields[i].buf = buf;
  119 + buf += layout->fields[i].size;
  120 + }
  121 +
  122 + layout->data_size = buf_size;
  123 + layout->print = eeprom_layout_print;
  124 + layout->update = eeprom_layout_update_field;
  125 +}
include/eeprom_field.h
  1 +/*
  2 + * (C) Copyright 2009-2016 CompuLab, Ltd.
  3 + *
  4 + * Authors: Nikita Kiryanov <nikita@compulab.co.il>
  5 + * Igor Grinberg <grinberg@compulab.co.il>
  6 + *
  7 + * SPDX-License-Identifier: GPL-2.0+
  8 + */
  9 +
  10 +#ifndef _FIELD_
  11 +#define _FIELD_
  12 +
  13 +#define PRINT_FIELD_SEGMENT "%-30s"
  14 +
  15 +struct eeprom_field {
  16 + char *name;
  17 + int size;
  18 + unsigned char *buf;
  19 +
  20 + void (*print)(const struct eeprom_field *eeprom_field);
  21 + int (*update)(struct eeprom_field *eeprom_field, char *value);
  22 +};
  23 +
  24 +void eeprom_field_print_bin(const struct eeprom_field *field);
  25 +int eeprom_field_update_bin(struct eeprom_field *field, char *value);
  26 +
  27 +void eeprom_field_print_bin_rev(const struct eeprom_field *field);
  28 +int eeprom_field_update_bin_rev(struct eeprom_field *field, char *value);
  29 +
  30 +void eeprom_field_print_mac(const struct eeprom_field *field);
  31 +int eeprom_field_update_mac(struct eeprom_field *field, char *value);
  32 +
  33 +void eeprom_field_print_ascii(const struct eeprom_field *field);
  34 +int eeprom_field_update_ascii(struct eeprom_field *field, char *value);
  35 +
  36 +void eeprom_field_print_reserved(const struct eeprom_field *field);
  37 +int eeprom_field_update_reserved(struct eeprom_field *field, char *value);
  38 +
  39 +#endif
include/eeprom_layout.h
  1 +/*
  2 + * (C) Copyright 2009-2016 CompuLab, Ltd.
  3 + *
  4 + * Authors: Nikita Kiryanov <nikita@compulab.co.il>
  5 + * Igor Grinberg <grinberg@compulab.co.il>
  6 + *
  7 + * SPDX-License-Identifier: GPL-2.0+
  8 + */
  9 +
  10 +#ifndef _LAYOUT_
  11 +#define _LAYOUT_
  12 +
  13 +#define RESERVED_FIELDS NULL
  14 +#define LAYOUT_VERSION_UNRECOGNIZED -1
  15 +#define LAYOUT_VERSION_AUTODETECT -2
  16 +
  17 +struct eeprom_layout {
  18 + struct eeprom_field *fields;
  19 + int num_of_fields;
  20 + int layout_version;
  21 + unsigned char *data;
  22 + int data_size;
  23 + void (*print)(const struct eeprom_layout *eeprom_layout);
  24 + int (*update)(struct eeprom_layout *eeprom_layout, char *field_name,
  25 + char *new_data);
  26 +};
  27 +
  28 +void eeprom_layout_setup(struct eeprom_layout *layout, unsigned char *buf,
  29 + unsigned int buf_size, int layout_version);
  30 +__weak void __eeprom_layout_assign(struct eeprom_layout *layout,
  31 + int layout_version);
  32 +
  33 +#endif