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