command: Remove the cmd_tbl_t typedef
[oweals/u-boot.git] / cmd / tlv_eeprom.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * See file CREDITS for list of people who contributed to this
4  * project.
5  *
6  * Copyright (C) 2013 Curt Brune <curt@cumulusnetworks.com>
7  * Copyright (C) 2014 Srideep <srideep_devireddy@dell.com>
8  * Copyright (C) 2013 Miles Tseng <miles_tseng@accton.com>
9  * Copyright (C) 2014,2016 david_yang <david_yang@accton.com>
10  */
11
12 #include <common.h>
13 #include <command.h>
14 #include <dm.h>
15 #include <i2c.h>
16 #include <i2c_eeprom.h>
17 #include <env.h>
18 #include <init.h>
19 #include <net.h>
20 #include <linux/ctype.h>
21 #include <u-boot/crc.h>
22
23 #include "tlv_eeprom.h"
24
25 DECLARE_GLOBAL_DATA_PTR;
26
27 #define MAX_TLV_DEVICES 2
28
29 /* File scope function prototypes */
30 static bool is_checksum_valid(u8 *eeprom);
31 static int read_eeprom(u8 *eeprom);
32 static void show_eeprom(u8 *eeprom);
33 static void decode_tlv(struct tlvinfo_tlv *tlv);
34 static void update_crc(u8 *eeprom);
35 static int prog_eeprom(u8 *eeprom);
36 static bool tlvinfo_find_tlv(u8 *eeprom, u8 tcode, int *eeprom_index);
37 static bool tlvinfo_delete_tlv(u8 *eeprom, u8 code);
38 static bool tlvinfo_add_tlv(u8 *eeprom, int tcode, char *strval);
39 static int set_mac(char *buf, const char *string);
40 static int set_date(char *buf, const char *string);
41 static int set_bytes(char *buf, const char *string, int *converted_accum);
42 static void show_tlv_devices(void);
43
44 /* Set to 1 if we've read EEPROM into memory */
45 static int has_been_read;
46 /* The EERPOM contents after being read into memory */
47 static u8 eeprom[TLV_INFO_MAX_LEN];
48
49 static struct udevice *tlv_devices[MAX_TLV_DEVICES];
50 static unsigned int current_dev;
51
52 #define to_header(p) ((struct tlvinfo_header *)p)
53 #define to_entry(p) ((struct tlvinfo_tlv *)p)
54
55 #define HDR_SIZE sizeof(struct tlvinfo_header)
56 #define ENT_SIZE sizeof(struct tlvinfo_tlv)
57
58 static inline bool is_digit(char c)
59 {
60         return (c >= '0' && c <= '9');
61 }
62
63 /**
64  *  is_valid_tlv
65  *
66  *  Perform basic sanity checks on a TLV field. The TLV is pointed to
67  *  by the parameter provided.
68  *      1. The type code is not reserved (0x00 or 0xFF)
69  */
70 static inline bool is_valid_tlv(struct tlvinfo_tlv *tlv)
71 {
72         return((tlv->type != 0x00) && (tlv->type != 0xFF));
73 }
74
75 /**
76  *  is_hex
77  *
78  *  Tests if character is an ASCII hex digit
79  */
80 static inline u8 is_hex(char p)
81 {
82         return (((p >= '0') && (p <= '9')) ||
83                 ((p >= 'A') && (p <= 'F')) ||
84                 ((p >= 'a') && (p <= 'f')));
85 }
86
87 /**
88  *  is_checksum_valid
89  *
90  *  Validate the checksum in the provided TlvInfo EEPROM data. First,
91  *  verify that the TlvInfo header is valid, then make sure the last
92  *  TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data
93  *  and compare it to the value stored in the EEPROM CRC-32 TLV.
94  */
95 static bool is_checksum_valid(u8 *eeprom)
96 {
97         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
98         struct tlvinfo_tlv    *eeprom_crc;
99         unsigned int       calc_crc;
100         unsigned int       stored_crc;
101
102         // Is the eeprom header valid?
103         if (!is_valid_tlvinfo_header(eeprom_hdr))
104                 return false;
105
106         // Is the last TLV a CRC?
107         eeprom_crc = to_entry(&eeprom[HDR_SIZE +
108                 be16_to_cpu(eeprom_hdr->totallen) - (ENT_SIZE + 4)]);
109         if (eeprom_crc->type != TLV_CODE_CRC_32 || eeprom_crc->length != 4)
110                 return false;
111
112         // Calculate the checksum
113         calc_crc = crc32(0, (void *)eeprom,
114                          HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen) - 4);
115         stored_crc = (eeprom_crc->value[0] << 24) |
116                 (eeprom_crc->value[1] << 16) |
117                 (eeprom_crc->value[2] <<  8) |
118                 eeprom_crc->value[3];
119         return calc_crc == stored_crc;
120 }
121
122 /**
123  *  read_eeprom
124  *
125  *  Read the EEPROM into memory, if it hasn't already been read.
126  */
127 static int read_eeprom(u8 *eeprom)
128 {
129         int ret;
130         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
131         struct tlvinfo_tlv *eeprom_tlv = to_entry(&eeprom[HDR_SIZE]);
132
133         if (has_been_read)
134                 return 0;
135
136         /* Read the header */
137         ret = read_tlv_eeprom((void *)eeprom_hdr, 0, HDR_SIZE, current_dev);
138         /* If the header was successfully read, read the TLVs */
139         if (ret == 0 && is_valid_tlvinfo_header(eeprom_hdr))
140                 ret = read_tlv_eeprom((void *)eeprom_tlv, HDR_SIZE,
141                                       be16_to_cpu(eeprom_hdr->totallen),
142                                       current_dev);
143
144         // If the contents are invalid, start over with default contents
145         if (!is_valid_tlvinfo_header(eeprom_hdr) ||
146             !is_checksum_valid(eeprom)) {
147                 strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING);
148                 eeprom_hdr->version = TLV_INFO_VERSION;
149                 eeprom_hdr->totallen = cpu_to_be16(0);
150                 update_crc(eeprom);
151         }
152
153         has_been_read = 1;
154
155 #ifdef DEBUG
156         show_eeprom(eeprom);
157 #endif
158
159         return ret;
160 }
161
162 /**
163  *  show_eeprom
164  *
165  *  Display the contents of the EEPROM
166  */
167 static void show_eeprom(u8 *eeprom)
168 {
169         int tlv_end;
170         int curr_tlv;
171         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
172         struct tlvinfo_tlv    *eeprom_tlv;
173
174         if (!is_valid_tlvinfo_header(eeprom_hdr)) {
175                 printf("EEPROM does not contain data in a valid TlvInfo format.\n");
176                 return;
177         }
178
179         printf("TLV: %u\n", current_dev);
180         printf("TlvInfo Header:\n");
181         printf("   Id String:    %s\n", eeprom_hdr->signature);
182         printf("   Version:      %d\n", eeprom_hdr->version);
183         printf("   Total Length: %d\n", be16_to_cpu(eeprom_hdr->totallen));
184
185         printf("TLV Name             Code Len Value\n");
186         printf("-------------------- ---- --- -----\n");
187         curr_tlv = HDR_SIZE;
188         tlv_end  = HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen);
189         while (curr_tlv < tlv_end) {
190                 eeprom_tlv = to_entry(&eeprom[curr_tlv]);
191                 if (!is_valid_tlv(eeprom_tlv)) {
192                         printf("Invalid TLV field starting at EEPROM offset %d\n",
193                                curr_tlv);
194                         return;
195                 }
196                 decode_tlv(eeprom_tlv);
197                 curr_tlv += ENT_SIZE + eeprom_tlv->length;
198         }
199
200         printf("Checksum is %s.\n",
201                is_checksum_valid(eeprom) ? "valid" : "invalid");
202
203 #ifdef DEBUG
204         printf("EEPROM dump: (0x%x bytes)", TLV_INFO_MAX_LEN);
205         for (i = 0; i < TLV_INFO_MAX_LEN; i++) {
206                 if ((i % 16) == 0)
207                         printf("\n%02X: ", i);
208                 printf("%02X ", eeprom[i]);
209         }
210         printf("\n");
211 #endif
212 }
213
214 /**
215  *  Struct for displaying the TLV codes and names.
216  */
217 struct tlv_code_desc {
218         u8    m_code;
219         char *m_name;
220 };
221
222 /**
223  *  List of TLV codes and names.
224  */
225 static struct tlv_code_desc tlv_code_list[] = {
226         { TLV_CODE_PRODUCT_NAME,   "Product Name"},
227         { TLV_CODE_PART_NUMBER,    "Part Number"},
228         { TLV_CODE_SERIAL_NUMBER,  "Serial Number"},
229         { TLV_CODE_MAC_BASE,       "Base MAC Address"},
230         { TLV_CODE_MANUF_DATE,     "Manufacture Date"},
231         { TLV_CODE_DEVICE_VERSION, "Device Version"},
232         { TLV_CODE_LABEL_REVISION, "Label Revision"},
233         { TLV_CODE_PLATFORM_NAME,  "Platform Name"},
234         { TLV_CODE_ONIE_VERSION,   "ONIE Version"},
235         { TLV_CODE_MAC_SIZE,       "MAC Addresses"},
236         { TLV_CODE_MANUF_NAME,     "Manufacturer"},
237         { TLV_CODE_MANUF_COUNTRY,  "Country Code"},
238         { TLV_CODE_VENDOR_NAME,    "Vendor Name"},
239         { TLV_CODE_DIAG_VERSION,   "Diag Version"},
240         { TLV_CODE_SERVICE_TAG,    "Service Tag"},
241         { TLV_CODE_VENDOR_EXT,     "Vendor Extension"},
242         { TLV_CODE_CRC_32,         "CRC-32"},
243 };
244
245 /**
246  *  Look up a TLV name by its type.
247  */
248 static inline const char *tlv_type2name(u8 type)
249 {
250         char *name = "Unknown";
251         int   i;
252
253         for (i = 0; i < ARRAY_SIZE(tlv_code_list); i++) {
254                 if (tlv_code_list[i].m_code == type) {
255                         name = tlv_code_list[i].m_name;
256                         break;
257                 }
258         }
259
260         return name;
261 }
262
263 /*
264  *  decode_tlv
265  *
266  *  Print a string representing the contents of the TLV field. The format of
267  *  the string is:
268  *      1. The name of the field left justified in 20 characters
269  *      2. The type code in hex right justified in 5 characters
270  *      3. The length in decimal right justified in 4 characters
271  *      4. The value, left justified in however many characters it takes
272  *  The validity of EEPROM contents and the TLV field have been verified
273  *  prior to calling this function.
274  */
275 #define DECODE_NAME_MAX     20
276
277 /*
278  * The max decode value is currently for the 'raw' type or the 'vendor
279  * extension' type, both of which have the same decode format.  The
280  * max decode string size is computed as follows:
281  *
282  *   strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1
283  *
284  */
285 #define DECODE_VALUE_MAX    ((5 * TLV_VALUE_MAX_LEN) + 1)
286
287 static void decode_tlv(struct tlvinfo_tlv *tlv)
288 {
289         char name[DECODE_NAME_MAX];
290         char value[DECODE_VALUE_MAX];
291         int i;
292
293         strncpy(name, tlv_type2name(tlv->type), DECODE_NAME_MAX);
294
295         switch (tlv->type) {
296         case TLV_CODE_PRODUCT_NAME:
297         case TLV_CODE_PART_NUMBER:
298         case TLV_CODE_SERIAL_NUMBER:
299         case TLV_CODE_MANUF_DATE:
300         case TLV_CODE_LABEL_REVISION:
301         case TLV_CODE_PLATFORM_NAME:
302         case TLV_CODE_ONIE_VERSION:
303         case TLV_CODE_MANUF_NAME:
304         case TLV_CODE_MANUF_COUNTRY:
305         case TLV_CODE_VENDOR_NAME:
306         case TLV_CODE_DIAG_VERSION:
307         case TLV_CODE_SERVICE_TAG:
308                 memcpy(value, tlv->value, tlv->length);
309                 value[tlv->length] = 0;
310                 break;
311         case TLV_CODE_MAC_BASE:
312                 sprintf(value, "%02X:%02X:%02X:%02X:%02X:%02X",
313                         tlv->value[0], tlv->value[1], tlv->value[2],
314                         tlv->value[3], tlv->value[4], tlv->value[5]);
315                 break;
316         case TLV_CODE_DEVICE_VERSION:
317                 sprintf(value, "%u", tlv->value[0]);
318                 break;
319         case TLV_CODE_MAC_SIZE:
320                 sprintf(value, "%u", (tlv->value[0] << 8) | tlv->value[1]);
321                 break;
322         case TLV_CODE_VENDOR_EXT:
323                 value[0] = 0;
324                 for (i = 0; (i < (DECODE_VALUE_MAX / 5)) && (i < tlv->length);
325                                 i++) {
326                         sprintf(value, "%s 0x%02X", value, tlv->value[i]);
327                 }
328                 break;
329         case TLV_CODE_CRC_32:
330                 sprintf(value, "0x%02X%02X%02X%02X",
331                         tlv->value[0], tlv->value[1],
332                         tlv->value[2], tlv->value[3]);
333                 break;
334         default:
335                 value[0] = 0;
336                 for (i = 0; (i < (DECODE_VALUE_MAX / 5)) && (i < tlv->length);
337                                 i++) {
338                         sprintf(value, "%s 0x%02X", value, tlv->value[i]);
339                 }
340                 break;
341         }
342
343         name[DECODE_NAME_MAX - 1] = 0;
344         printf("%-20s 0x%02X %3d %s\n", name, tlv->type, tlv->length, value);
345 }
346
347 /**
348  *  update_crc
349  *
350  *  This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then
351  *  one is added. This function should be called after each update to the
352  *  EEPROM structure, to make sure the CRC is always correct.
353  */
354 static void update_crc(u8 *eeprom)
355 {
356         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
357         struct tlvinfo_tlv    *eeprom_crc;
358         unsigned int      calc_crc;
359         int               eeprom_index;
360
361         // Discover the CRC TLV
362         if (!tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index)) {
363                 unsigned int totallen = be16_to_cpu(eeprom_hdr->totallen);
364
365                 if ((totallen + ENT_SIZE + 4) > TLV_TOTAL_LEN_MAX)
366                         return;
367                 eeprom_index = HDR_SIZE + totallen;
368                 eeprom_hdr->totallen = cpu_to_be16(totallen + ENT_SIZE + 4);
369         }
370         eeprom_crc = to_entry(&eeprom[eeprom_index]);
371         eeprom_crc->type = TLV_CODE_CRC_32;
372         eeprom_crc->length = 4;
373
374         // Calculate the checksum
375         calc_crc = crc32(0, (void *)eeprom,
376                          HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen) - 4);
377         eeprom_crc->value[0] = (calc_crc >> 24) & 0xFF;
378         eeprom_crc->value[1] = (calc_crc >> 16) & 0xFF;
379         eeprom_crc->value[2] = (calc_crc >>  8) & 0xFF;
380         eeprom_crc->value[3] = (calc_crc >>  0) & 0xFF;
381 }
382
383 /**
384  *  prog_eeprom
385  *
386  *  Write the EEPROM data from CPU memory to the hardware.
387  */
388 static int prog_eeprom(u8 *eeprom)
389 {
390         int ret = 0;
391         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
392         int eeprom_len;
393
394         update_crc(eeprom);
395
396         eeprom_len = HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen);
397         ret = write_tlv_eeprom(eeprom, eeprom_len);
398         if (ret) {
399                 printf("Programming failed.\n");
400                 return -1;
401         }
402
403         printf("Programming passed.\n");
404         return 0;
405 }
406
407 /**
408  *  show_tlv_code_list - Display the list of TLV codes and names
409  */
410 void show_tlv_code_list(void)
411 {
412         int i;
413
414         printf("TLV Code    TLV Name\n");
415         printf("========    =================\n");
416         for (i = 0; i < ARRAY_SIZE(tlv_code_list); i++) {
417                 printf("0x%02X        %s\n",
418                        tlv_code_list[i].m_code,
419                        tlv_code_list[i].m_name);
420         }
421 }
422
423 /**
424  *  do_tlv_eeprom
425  *
426  *  This function implements the tlv_eeprom command.
427  */
428 int do_tlv_eeprom(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
429 {
430         char cmd;
431         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
432
433         // If no arguments, read the EERPOM and display its contents
434         if (argc == 1) {
435                 read_eeprom(eeprom);
436                 show_eeprom(eeprom);
437                 return 0;
438         }
439
440         // We only look at the first character to the command, so "read" and
441         // "reset" will both be treated as "read".
442         cmd = argv[1][0];
443
444         // Read the EEPROM contents
445         if (cmd == 'r') {
446                 has_been_read = 0;
447                 if (!read_eeprom(eeprom))
448                         printf("EEPROM data loaded from device to memory.\n");
449                 return 0;
450         }
451
452         // Subsequent commands require that the EEPROM has already been read.
453         if (!has_been_read) {
454                 printf("Please read the EEPROM data first, using the 'tlv_eeprom read' command.\n");
455                 return 0;
456         }
457
458         // Handle the commands that don't take parameters
459         if (argc == 2) {
460                 switch (cmd) {
461                 case 'w':   /* write */
462                         prog_eeprom(eeprom);
463                         break;
464                 case 'e':   /* erase */
465                         strcpy(eeprom_hdr->signature, TLV_INFO_ID_STRING);
466                         eeprom_hdr->version = TLV_INFO_VERSION;
467                         eeprom_hdr->totallen = cpu_to_be16(0);
468                         update_crc(eeprom);
469                         printf("EEPROM data in memory reset.\n");
470                         break;
471                 case 'l':   /* list */
472                         show_tlv_code_list();
473                         break;
474                 case 'd':   /* dev */
475                         show_tlv_devices();
476                         break;
477                 default:
478                         cmd_usage(cmdtp);
479                         break;
480                 }
481                 return 0;
482         }
483
484         // The set command takes one or two args.
485         if (argc > 4) {
486                 cmd_usage(cmdtp);
487                 return 0;
488         }
489
490         // Set command. If the TLV exists in the EEPROM, delete it. Then if
491         // data was supplied for this TLV add the TLV with the new contents at
492         // the end.
493         if (cmd == 's') {
494                 int tcode;
495
496                 tcode = simple_strtoul(argv[2], NULL, 0);
497                 tlvinfo_delete_tlv(eeprom, tcode);
498                 if (argc == 4)
499                         tlvinfo_add_tlv(eeprom, tcode, argv[3]);
500         } else if (cmd == 'd') { /* 'dev' command */
501                 unsigned int devnum;
502
503                 devnum = simple_strtoul(argv[2], NULL, 0);
504                 if (devnum > MAX_TLV_DEVICES || !tlv_devices[devnum]) {
505                         printf("Invalid device number\n");
506                         return 0;
507                 }
508                 current_dev = devnum;
509                 has_been_read = 0;
510         } else {
511                 cmd_usage(cmdtp);
512         }
513
514         return 0;
515 }
516
517 /**
518  *  This macro defines the tlv_eeprom command line command.
519  */
520 U_BOOT_CMD(tlv_eeprom, 4, 1,  do_tlv_eeprom,
521            "Display and program the system EEPROM data block.",
522            "[read|write|set <type_code> <string_value>|erase|list]\n"
523            "tlv_eeprom\n"
524            "    - With no arguments display the current contents.\n"
525            "tlv_eeprom dev [dev]\n"
526            "    - List devices or set current EEPROM device.\n"
527            "tlv_eeprom read\n"
528            "    - Load EEPROM data from device to memory.\n"
529            "tlv_eeprom write\n"
530            "    - Write the EEPROM data to persistent storage.\n"
531            "tlv_eeprom set <type_code> <string_value>\n"
532            "    - Set a field to a value.\n"
533            "    - If no string_value, field is deleted.\n"
534            "    - Use 'tlv_eeprom write' to make changes permanent.\n"
535            "tlv_eeprom erase\n"
536            "    - Reset the in memory EEPROM data.\n"
537            "    - Use 'tlv_eeprom read' to refresh the in memory EEPROM data.\n"
538            "    - Use 'tlv_eeprom write' to make changes permanent.\n"
539            "tlv_eeprom list\n"
540            "    - List the understood TLV codes and names.\n"
541         );
542
543 /**
544  *  tlvinfo_find_tlv
545  *
546  *  This function finds the TLV with the supplied code in the EERPOM.
547  *  An offset from the beginning of the EEPROM is returned in the
548  *  eeprom_index parameter if the TLV is found.
549  */
550 static bool tlvinfo_find_tlv(u8 *eeprom, u8 tcode, int *eeprom_index)
551 {
552         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
553         struct tlvinfo_tlv    *eeprom_tlv;
554         int eeprom_end;
555
556         // Search through the TLVs, looking for the first one which matches the
557         // supplied type code.
558         *eeprom_index = HDR_SIZE;
559         eeprom_end = HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen);
560         while (*eeprom_index < eeprom_end) {
561                 eeprom_tlv = to_entry(&eeprom[*eeprom_index]);
562                 if (!is_valid_tlv(eeprom_tlv))
563                         return false;
564                 if (eeprom_tlv->type == tcode)
565                         return true;
566                 *eeprom_index += ENT_SIZE + eeprom_tlv->length;
567         }
568         return(false);
569 }
570
571 /**
572  *  tlvinfo_delete_tlv
573  *
574  *  This function deletes the TLV with the specified type code from the
575  *  EEPROM.
576  */
577 static bool tlvinfo_delete_tlv(u8 *eeprom, u8 code)
578 {
579         int eeprom_index;
580         int tlength;
581         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
582         struct tlvinfo_tlv *eeprom_tlv;
583
584         // Find the TLV and then move all following TLVs "forward"
585         if (tlvinfo_find_tlv(eeprom, code, &eeprom_index)) {
586                 eeprom_tlv = to_entry(&eeprom[eeprom_index]);
587                 tlength = ENT_SIZE + eeprom_tlv->length;
588                 memcpy(&eeprom[eeprom_index], &eeprom[eeprom_index + tlength],
589                        HDR_SIZE +
590                        be16_to_cpu(eeprom_hdr->totallen) - eeprom_index -
591                        tlength);
592                 eeprom_hdr->totallen =
593                         cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) -
594                                     tlength);
595                 update_crc(eeprom);
596                 return true;
597         }
598         return false;
599 }
600
601 /**
602  *  tlvinfo_add_tlv
603  *
604  *  This function adds a TLV to the EEPROM, converting the value (a string) to
605  *  the format in which it will be stored in the EEPROM.
606  */
607 #define MAX_TLV_VALUE_LEN   256
608 static bool tlvinfo_add_tlv(u8 *eeprom, int tcode, char *strval)
609 {
610         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
611         struct tlvinfo_tlv *eeprom_tlv;
612         int new_tlv_len = 0;
613         u32 value;
614         char data[MAX_TLV_VALUE_LEN];
615         int eeprom_index;
616
617         // Encode each TLV type into the format to be stored in the EERPOM
618         switch (tcode) {
619         case TLV_CODE_PRODUCT_NAME:
620         case TLV_CODE_PART_NUMBER:
621         case TLV_CODE_SERIAL_NUMBER:
622         case TLV_CODE_LABEL_REVISION:
623         case TLV_CODE_PLATFORM_NAME:
624         case TLV_CODE_ONIE_VERSION:
625         case TLV_CODE_MANUF_NAME:
626         case TLV_CODE_MANUF_COUNTRY:
627         case TLV_CODE_VENDOR_NAME:
628         case TLV_CODE_DIAG_VERSION:
629         case TLV_CODE_SERVICE_TAG:
630                 strncpy(data, strval, MAX_TLV_VALUE_LEN);
631                 new_tlv_len = min_t(size_t, MAX_TLV_VALUE_LEN, strlen(strval));
632                 break;
633         case TLV_CODE_DEVICE_VERSION:
634                 value = simple_strtoul(strval, NULL, 0);
635                 if (value >= 256) {
636                         printf("ERROR: Device version must be 255 or less. Value supplied: %u",
637                                value);
638                         return false;
639                 }
640                 data[0] = value & 0xFF;
641                 new_tlv_len = 1;
642                 break;
643         case TLV_CODE_MAC_SIZE:
644                 value = simple_strtoul(strval, NULL, 0);
645                 if (value >= 65536) {
646                         printf("ERROR: MAC Size must be 65535 or less. Value supplied: %u",
647                                value);
648                         return false;
649                 }
650                 data[0] = (value >> 8) & 0xFF;
651                 data[1] = value & 0xFF;
652                 new_tlv_len = 2;
653                 break;
654         case TLV_CODE_MANUF_DATE:
655                 if (set_date(data, strval) != 0)
656                         return false;
657                 new_tlv_len = 19;
658                 break;
659         case TLV_CODE_MAC_BASE:
660                 if (set_mac(data, strval) != 0)
661                         return false;
662                 new_tlv_len = 6;
663                 break;
664         case TLV_CODE_CRC_32:
665                 printf("WARNING: The CRC TLV is set automatically and cannot be set manually.\n");
666                 return false;
667         case TLV_CODE_VENDOR_EXT:
668         default:
669                 if (set_bytes(data, strval, &new_tlv_len) != 0)
670                         return false;
671                 break;
672         }
673
674         // Is there room for this TLV?
675         if ((be16_to_cpu(eeprom_hdr->totallen) + ENT_SIZE + new_tlv_len) >
676                         TLV_TOTAL_LEN_MAX) {
677                 printf("ERROR: There is not enough room in the EERPOM to save data.\n");
678                 return false;
679         }
680
681         // Add TLV at the end, overwriting CRC TLV if it exists
682         if (tlvinfo_find_tlv(eeprom, TLV_CODE_CRC_32, &eeprom_index))
683                 eeprom_hdr->totallen =
684                         cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) -
685                                         ENT_SIZE - 4);
686         else
687                 eeprom_index = HDR_SIZE + be16_to_cpu(eeprom_hdr->totallen);
688         eeprom_tlv = to_entry(&eeprom[eeprom_index]);
689         eeprom_tlv->type = tcode;
690         eeprom_tlv->length = new_tlv_len;
691         memcpy(eeprom_tlv->value, data, new_tlv_len);
692
693         // Update the total length and calculate (add) a new CRC-32 TLV
694         eeprom_hdr->totallen = cpu_to_be16(be16_to_cpu(eeprom_hdr->totallen) +
695                         ENT_SIZE + new_tlv_len);
696         update_crc(eeprom);
697
698         return true;
699 }
700
701 /**
702  *  set_mac
703  *
704  *  Converts a string MAC address into a binary buffer.
705  *
706  *  This function takes a pointer to a MAC address string
707  *  (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number).
708  *  The string format is verified and then converted to binary and
709  *  stored in a buffer.
710  */
711 static int set_mac(char *buf, const char *string)
712 {
713         char *p = (char *)string;
714         int   i;
715         int   err = 0;
716         char *end;
717
718         if (!p) {
719                 printf("ERROR: NULL mac addr string passed in.\n");
720                 return -1;
721         }
722
723         if (strlen(p) != 17) {
724                 printf("ERROR: MAC address strlen() != 17 -- %zu\n", strlen(p));
725                 printf("ERROR: Bad MAC address format: %s\n", string);
726                 return -1;
727         }
728
729         for (i = 0; i < 17; i++) {
730                 if ((i % 3) == 2) {
731                         if (p[i] != ':') {
732                                 err++;
733                                 printf("ERROR: mac: p[%i] != :, found: `%c'\n",
734                                        i, p[i]);
735                                 break;
736                         }
737                         continue;
738                 } else if (!is_hex(p[i])) {
739                         err++;
740                         printf("ERROR: mac: p[%i] != hex digit, found: `%c'\n",
741                                i, p[i]);
742                         break;
743                 }
744         }
745
746         if (err != 0) {
747                 printf("ERROR: Bad MAC address format: %s\n", string);
748                 return -1;
749         }
750
751         /* Convert string to binary */
752         for (i = 0, p = (char *)string; i < 6; i++) {
753                 buf[i] = p ? simple_strtoul(p, &end, 16) : 0;
754                 if (p)
755                         p = (*end) ? end + 1 : end;
756         }
757
758         if (!is_valid_ethaddr((u8 *)buf)) {
759                 printf("ERROR: MAC address must not be 00:00:00:00:00:00, a multicast address or FF:FF:FF:FF:FF:FF.\n");
760                 printf("ERROR: Bad MAC address format: %s\n", string);
761                 return -1;
762         }
763
764         return 0;
765 }
766
767 /**
768  *  set_date
769  *
770  *  Validates the format of the data string
771  *
772  *  This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss)
773  *  and validates that the format is correct. If so the string is copied
774  *  to the supplied buffer.
775  */
776 static int set_date(char *buf, const char *string)
777 {
778         int i;
779
780         if (!string) {
781                 printf("ERROR: NULL date string passed in.\n");
782                 return -1;
783         }
784
785         if (strlen(string) != 19) {
786                 printf("ERROR: Date strlen() != 19 -- %zu\n", strlen(string));
787                 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
788                        string);
789                 return -1;
790         }
791
792         for (i = 0; string[i] != 0; i++) {
793                 switch (i) {
794                 case 2:
795                 case 5:
796                         if (string[i] != '/') {
797                                 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
798                                        string);
799                                 return -1;
800                         }
801                         break;
802                 case 10:
803                         if (string[i] != ' ') {
804                                 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
805                                        string);
806                                 return -1;
807                         }
808                         break;
809                 case 13:
810                 case 16:
811                         if (string[i] != ':') {
812                                 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
813                                        string);
814                                 return -1;
815                         }
816                         break;
817                 default:
818                         if (!is_digit(string[i])) {
819                                 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
820                                        string);
821                                 return -1;
822                         }
823                         break;
824                 }
825         }
826
827         strcpy(buf, string);
828         return 0;
829 }
830
831 /**
832  *  set_bytes
833  *
834  *  Converts a space-separated string of decimal numbers into a
835  *  buffer of bytes.
836  *
837  *  This function takes a pointer to a space-separated string of decimal
838  *  numbers (i.e. "128 0x55 0321") with "C" standard radix specifiers
839  *  and converts them to an array of bytes.
840  */
841 static int set_bytes(char *buf, const char *string, int *converted_accum)
842 {
843         char *p = (char *)string;
844         int   i;
845         uint  byte;
846
847         if (!p) {
848                 printf("ERROR: NULL string passed in.\n");
849                 return -1;
850         }
851
852         /* Convert string to bytes */
853         for (i = 0, p = (char *)string; (i < TLV_VALUE_MAX_LEN) && (*p != 0);
854                         i++) {
855                 while ((*p == ' ') || (*p == '\t') || (*p == ',') ||
856                        (*p == ';')) {
857                         p++;
858                 }
859                 if (*p != 0) {
860                         if (!is_digit(*p)) {
861                                 printf("ERROR: Non-digit found in byte string: (%s)\n",
862                                        string);
863                                 return -1;
864                         }
865                         byte = simple_strtoul(p, &p, 0);
866                         if (byte >= 256) {
867                                 printf("ERROR: The value specified is greater than 255: (%u) in string: %s\n",
868                                        byte, string);
869                                 return -1;
870                         }
871                         buf[i] = byte & 0xFF;
872                 }
873         }
874
875         if (i == TLV_VALUE_MAX_LEN && (*p != 0)) {
876                 printf("ERROR: Trying to assign too many bytes (max: %d) in string: %s\n",
877                        TLV_VALUE_MAX_LEN, string);
878                 return -1;
879         }
880
881         *converted_accum = i;
882         return 0;
883 }
884
885 static void show_tlv_devices(void)
886 {
887         unsigned int dev;
888
889         for (dev = 0; dev < MAX_TLV_DEVICES; dev++)
890                 if (tlv_devices[dev])
891                         printf("TLV: %u%s\n", dev,
892                                (dev == current_dev) ? " (*)" : "");
893 }
894
895 static int find_tlv_devices(struct udevice **tlv_devices_p)
896 {
897         int ret;
898         int count_dev = 0;
899         struct udevice *dev;
900
901         for (ret = uclass_first_device_check(UCLASS_I2C_EEPROM, &dev);
902                         dev;
903                         ret = uclass_next_device_check(&dev)) {
904                 if (ret == 0)
905                         tlv_devices_p[count_dev++] = dev;
906                 if (count_dev >= MAX_TLV_DEVICES)
907                         break;
908         }
909
910         return (count_dev == 0) ? -ENODEV : 0;
911 }
912
913 static struct udevice *find_tlv_device_by_index(int dev_num)
914 {
915         struct udevice *local_tlv_devices[MAX_TLV_DEVICES] = {};
916         struct udevice **tlv_devices_p;
917         int ret;
918
919         if (gd->flags & (GD_FLG_RELOC | GD_FLG_SPL_INIT)) {
920                 /* Assume BSS is initialized; use static data */
921                 if (tlv_devices[dev_num])
922                         return tlv_devices[dev_num];
923                 tlv_devices_p = tlv_devices;
924         } else {
925                 tlv_devices_p = local_tlv_devices;
926         }
927
928         ret = find_tlv_devices(tlv_devices_p);
929         if (ret == 0 && tlv_devices_p[dev_num])
930                 return tlv_devices_p[dev_num];
931
932         return NULL;
933 }
934
935 /**
936  * read_tlv_eeprom - read the hwinfo from i2c EEPROM
937  */
938 int read_tlv_eeprom(void *eeprom, int offset, int len, int dev_num)
939 {
940         struct udevice *dev;
941
942         if (dev_num >= MAX_TLV_DEVICES)
943                 return -EINVAL;
944
945         dev = find_tlv_device_by_index(dev_num);
946         if (!dev)
947                 return -ENODEV;
948
949         return i2c_eeprom_read(dev, offset, eeprom, len);
950 }
951
952 /**
953  * write_tlv_eeprom - write the hwinfo to i2c EEPROM
954  */
955 int write_tlv_eeprom(void *eeprom, int len)
956 {
957         if (!(gd->flags & GD_FLG_RELOC))
958                 return -ENODEV;
959         if (!tlv_devices[current_dev])
960                 return -ENODEV;
961
962         return i2c_eeprom_write(tlv_devices[current_dev], 0, eeprom, len);
963 }
964
965 int read_tlvinfo_tlv_eeprom(void *eeprom, struct tlvinfo_header **hdr,
966                             struct tlvinfo_tlv **first_entry, int dev_num)
967 {
968         int ret;
969         struct tlvinfo_header *tlv_hdr;
970         struct tlvinfo_tlv *tlv_ent;
971
972         /* Read TLV header */
973         ret = read_tlv_eeprom(eeprom, 0, HDR_SIZE, dev_num);
974         if (ret < 0)
975                 return ret;
976
977         tlv_hdr = eeprom;
978         if (!is_valid_tlvinfo_header(tlv_hdr))
979                 return -EINVAL;
980
981         /* Read TLV entries */
982         tlv_ent = to_entry(&tlv_hdr[1]);
983         ret = read_tlv_eeprom(tlv_ent, HDR_SIZE,
984                               be16_to_cpu(tlv_hdr->totallen), dev_num);
985         if (ret < 0)
986                 return ret;
987         if (!is_checksum_valid(eeprom))
988                 return -EINVAL;
989
990         *hdr = tlv_hdr;
991         *first_entry = tlv_ent;
992
993         return 0;
994 }
995
996 /**
997  *  mac_read_from_eeprom
998  *
999  *  Read the MAC addresses from EEPROM
1000  *
1001  *  This function reads the MAC addresses from EEPROM and sets the
1002  *  appropriate environment variables for each one read.
1003  *
1004  *  The environment variables are only set if they haven't been set already.
1005  *  This ensures that any user-saved variables are never overwritten.
1006  *
1007  *  This function must be called after relocation.
1008  */
1009 int mac_read_from_eeprom(void)
1010 {
1011         unsigned int i;
1012         int eeprom_index;
1013         struct tlvinfo_tlv *eeprom_tlv;
1014         int maccount;
1015         u8 macbase[6];
1016         struct tlvinfo_header *eeprom_hdr = to_header(eeprom);
1017
1018         puts("EEPROM: ");
1019
1020         if (read_eeprom(eeprom)) {
1021                 printf("Read failed.\n");
1022                 return -1;
1023         }
1024
1025         maccount = 1;
1026         if (tlvinfo_find_tlv(eeprom, TLV_CODE_MAC_SIZE, &eeprom_index)) {
1027                 eeprom_tlv = to_entry(&eeprom[eeprom_index]);
1028                 maccount = (eeprom_tlv->value[0] << 8) | eeprom_tlv->value[1];
1029         }
1030
1031         memcpy(macbase, "\0\0\0\0\0\0", 6);
1032         if (tlvinfo_find_tlv(eeprom, TLV_CODE_MAC_BASE, &eeprom_index)) {
1033                 eeprom_tlv = to_entry(&eeprom[eeprom_index]);
1034                 memcpy(macbase, eeprom_tlv->value, 6);
1035         }
1036
1037         for (i = 0; i < maccount; i++) {
1038                 if (is_valid_ethaddr(macbase)) {
1039                         char ethaddr[18];
1040                         char enetvar[11];
1041
1042                         sprintf(ethaddr, "%02X:%02X:%02X:%02X:%02X:%02X",
1043                                 macbase[0], macbase[1], macbase[2],
1044                                 macbase[3], macbase[4], macbase[5]);
1045                         sprintf(enetvar, i ? "eth%daddr" : "ethaddr", i);
1046                         /* Only initialize environment variables that are blank
1047                          * (i.e. have not yet been set)
1048                          */
1049                         if (!env_get(enetvar))
1050                                 env_set(enetvar, ethaddr);
1051
1052                         macbase[5]++;
1053                         if (macbase[5] == 0) {
1054                                 macbase[4]++;
1055                                 if (macbase[4] == 0) {
1056                                         macbase[3]++;
1057                                         if (macbase[3] == 0) {
1058                                                 macbase[0] = 0;
1059                                                 macbase[1] = 0;
1060                                                 macbase[2] = 0;
1061                                         }
1062                                 }
1063                         }
1064                 }
1065         }
1066
1067         printf("%s v%u len=%u\n", eeprom_hdr->signature, eeprom_hdr->version,
1068                be16_to_cpu(eeprom_hdr->totallen));
1069
1070         return 0;
1071 }
1072
1073 /**
1074  *  populate_serial_number - read the serial number from EEPROM
1075  *
1076  *  This function reads the serial number from the EEPROM and sets the
1077  *  appropriate environment variable.
1078  *
1079  *  The environment variable is only set if it has not been set
1080  *  already.  This ensures that any user-saved variables are never
1081  *  overwritten.
1082  *
1083  *  This function must be called after relocation.
1084  */
1085 int populate_serial_number(void)
1086 {
1087         char serialstr[257];
1088         int eeprom_index;
1089         struct tlvinfo_tlv *eeprom_tlv;
1090
1091         if (env_get("serial#"))
1092                 return 0;
1093
1094         if (read_eeprom(eeprom)) {
1095                 printf("Read failed.\n");
1096                 return -1;
1097         }
1098
1099         if (tlvinfo_find_tlv(eeprom, TLV_CODE_SERIAL_NUMBER, &eeprom_index)) {
1100                 eeprom_tlv = to_entry(&eeprom[eeprom_index]);
1101                 memcpy(serialstr, eeprom_tlv->value, eeprom_tlv->length);
1102                 serialstr[eeprom_tlv->length] = 0;
1103                 env_set("serial#", serialstr);
1104         }
1105
1106         return 0;
1107 }