Commit aa9e60441095ee3f20a109742e3ba5cdfd28458b
Committed by
Tom Rini
1 parent
2636ac65a8
Exists in
v2017.01-smarct4x
and in
25 other branches
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
README
... | ... | @@ -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 |
cmd/eeprom.c
... | ... | @@ -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 | ) |
common/Makefile
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 |