1 // SPDX-License-Identifier: GPL-2.0+
3 * See file CREDITS for list of people who contributed to this
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>
15 #include <i2c_eeprom.h>
19 #include <asm/global_data.h>
20 #include <linux/ctype.h>
21 #include <u-boot/crc.h>
23 #include "tlv_eeprom.h"
25 DECLARE_GLOBAL_DATA_PTR
;
27 #define MAX_TLV_DEVICES 2
29 /* File scope function prototypes */
30 static bool is_checksum_valid(u8
*eeprom
);
31 static int read_eeprom(int devnum
, u8
*eeprom
);
32 static void show_eeprom(int devnum
, u8
*eeprom
);
33 static void decode_tlv(struct tlvinfo_tlv
*tlv
);
34 static void update_crc(u8
*eeprom
);
35 static int prog_eeprom(int devnum
, 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(int current_dev
);
44 /* The EERPOM contents after being read into memory */
45 static u8 eeprom
[TLV_INFO_MAX_LEN
];
47 static struct udevice
*tlv_devices
[MAX_TLV_DEVICES
];
49 #define to_header(p) ((struct tlvinfo_header *)p)
50 #define to_entry(p) ((struct tlvinfo_tlv *)p)
52 #define HDR_SIZE sizeof(struct tlvinfo_header)
53 #define ENT_SIZE sizeof(struct tlvinfo_tlv)
55 static inline bool is_digit(char c
)
57 return (c
>= '0' && c
<= '9');
63 * Perform basic sanity checks on a TLV field. The TLV is pointed to
64 * by the parameter provided.
65 * 1. The type code is not reserved (0x00 or 0xFF)
67 static inline bool is_valid_tlv(struct tlvinfo_tlv
*tlv
)
69 return((tlv
->type
!= 0x00) && (tlv
->type
!= 0xFF));
75 * Tests if character is an ASCII hex digit
77 static inline u8
is_hex(char p
)
79 return (((p
>= '0') && (p
<= '9')) ||
80 ((p
>= 'A') && (p
<= 'F')) ||
81 ((p
>= 'a') && (p
<= 'f')));
87 * Validate the checksum in the provided TlvInfo EEPROM data. First,
88 * verify that the TlvInfo header is valid, then make sure the last
89 * TLV is a CRC-32 TLV. Then calculate the CRC over the EEPROM data
90 * and compare it to the value stored in the EEPROM CRC-32 TLV.
92 static bool is_checksum_valid(u8
*eeprom
)
94 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
95 struct tlvinfo_tlv
*eeprom_crc
;
96 unsigned int calc_crc
;
97 unsigned int stored_crc
;
99 // Is the eeprom header valid?
100 if (!is_valid_tlvinfo_header(eeprom_hdr
))
103 // Is the last TLV a CRC?
104 eeprom_crc
= to_entry(&eeprom
[HDR_SIZE
+
105 be16_to_cpu(eeprom_hdr
->totallen
) - (ENT_SIZE
+ 4)]);
106 if (eeprom_crc
->type
!= TLV_CODE_CRC_32
|| eeprom_crc
->length
!= 4)
109 // Calculate the checksum
110 calc_crc
= crc32(0, (void *)eeprom
,
111 HDR_SIZE
+ be16_to_cpu(eeprom_hdr
->totallen
) - 4);
112 stored_crc
= (eeprom_crc
->value
[0] << 24) |
113 (eeprom_crc
->value
[1] << 16) |
114 (eeprom_crc
->value
[2] << 8) |
115 eeprom_crc
->value
[3];
116 return calc_crc
== stored_crc
;
122 * Read the EEPROM into memory, if it hasn't already been read.
124 static int read_eeprom(int devnum
, u8
*eeprom
)
127 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
128 struct tlvinfo_tlv
*eeprom_tlv
= to_entry(&eeprom
[HDR_SIZE
]);
130 /* Read the header */
131 ret
= read_tlv_eeprom((void *)eeprom_hdr
, 0, HDR_SIZE
, devnum
);
132 /* If the header was successfully read, read the TLVs */
133 if (ret
== 0 && is_valid_tlvinfo_header(eeprom_hdr
))
134 ret
= read_tlv_eeprom((void *)eeprom_tlv
, HDR_SIZE
,
135 be16_to_cpu(eeprom_hdr
->totallen
), devnum
);
136 else if (ret
== -ENODEV
)
139 // If the contents are invalid, start over with default contents
140 if (!is_valid_tlvinfo_header(eeprom_hdr
) ||
141 !is_checksum_valid(eeprom
)) {
142 strcpy(eeprom_hdr
->signature
, TLV_INFO_ID_STRING
);
143 eeprom_hdr
->version
= TLV_INFO_VERSION
;
144 eeprom_hdr
->totallen
= cpu_to_be16(0);
149 show_eeprom(devnum
, eeprom
);
158 * Display the contents of the EEPROM
160 static void show_eeprom(int devnum
, u8
*eeprom
)
167 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
168 struct tlvinfo_tlv
*eeprom_tlv
;
170 if (!is_valid_tlvinfo_header(eeprom_hdr
)) {
171 printf("EEPROM does not contain data in a valid TlvInfo format.\n");
175 printf("TLV: %u\n", devnum
);
176 printf("TlvInfo Header:\n");
177 printf(" Id String: %s\n", eeprom_hdr
->signature
);
178 printf(" Version: %d\n", eeprom_hdr
->version
);
179 printf(" Total Length: %d\n", be16_to_cpu(eeprom_hdr
->totallen
));
181 printf("TLV Name Code Len Value\n");
182 printf("-------------------- ---- --- -----\n");
184 tlv_end
= HDR_SIZE
+ be16_to_cpu(eeprom_hdr
->totallen
);
185 while (curr_tlv
< tlv_end
) {
186 eeprom_tlv
= to_entry(&eeprom
[curr_tlv
]);
187 if (!is_valid_tlv(eeprom_tlv
)) {
188 printf("Invalid TLV field starting at EEPROM offset %d\n",
192 decode_tlv(eeprom_tlv
);
193 curr_tlv
+= ENT_SIZE
+ eeprom_tlv
->length
;
196 printf("Checksum is %s.\n",
197 is_checksum_valid(eeprom
) ? "valid" : "invalid");
200 printf("EEPROM dump: (0x%x bytes)", TLV_INFO_MAX_LEN
);
201 for (i
= 0; i
< TLV_INFO_MAX_LEN
; i
++) {
203 printf("\n%02X: ", i
);
204 printf("%02X ", eeprom
[i
]);
211 * Struct for displaying the TLV codes and names.
213 struct tlv_code_desc
{
219 * List of TLV codes and names.
221 static struct tlv_code_desc tlv_code_list
[] = {
222 { TLV_CODE_PRODUCT_NAME
, "Product Name"},
223 { TLV_CODE_PART_NUMBER
, "Part Number"},
224 { TLV_CODE_SERIAL_NUMBER
, "Serial Number"},
225 { TLV_CODE_MAC_BASE
, "Base MAC Address"},
226 { TLV_CODE_MANUF_DATE
, "Manufacture Date"},
227 { TLV_CODE_DEVICE_VERSION
, "Device Version"},
228 { TLV_CODE_LABEL_REVISION
, "Label Revision"},
229 { TLV_CODE_PLATFORM_NAME
, "Platform Name"},
230 { TLV_CODE_ONIE_VERSION
, "ONIE Version"},
231 { TLV_CODE_MAC_SIZE
, "MAC Addresses"},
232 { TLV_CODE_MANUF_NAME
, "Manufacturer"},
233 { TLV_CODE_MANUF_COUNTRY
, "Country Code"},
234 { TLV_CODE_VENDOR_NAME
, "Vendor Name"},
235 { TLV_CODE_DIAG_VERSION
, "Diag Version"},
236 { TLV_CODE_SERVICE_TAG
, "Service Tag"},
237 { TLV_CODE_VENDOR_EXT
, "Vendor Extension"},
238 { TLV_CODE_CRC_32
, "CRC-32"},
242 * Look up a TLV name by its type.
244 static inline const char *tlv_type2name(u8 type
)
246 char *name
= "Unknown";
249 for (i
= 0; i
< ARRAY_SIZE(tlv_code_list
); i
++) {
250 if (tlv_code_list
[i
].m_code
== type
) {
251 name
= tlv_code_list
[i
].m_name
;
262 * Print a string representing the contents of the TLV field. The format of
264 * 1. The name of the field left justified in 20 characters
265 * 2. The type code in hex right justified in 5 characters
266 * 3. The length in decimal right justified in 4 characters
267 * 4. The value, left justified in however many characters it takes
268 * The validity of EEPROM contents and the TLV field have been verified
269 * prior to calling this function.
271 #define DECODE_NAME_MAX 20
274 * The max decode value is currently for the 'raw' type or the 'vendor
275 * extension' type, both of which have the same decode format. The
276 * max decode string size is computed as follows:
278 * strlen(" 0xFF") * TLV_VALUE_MAX_LEN + 1
281 #define DECODE_VALUE_MAX ((5 * TLV_VALUE_MAX_LEN) + 1)
283 static void decode_tlv(struct tlvinfo_tlv
*tlv
)
285 char name
[DECODE_NAME_MAX
];
286 char value
[DECODE_VALUE_MAX
];
289 strncpy(name
, tlv_type2name(tlv
->type
), DECODE_NAME_MAX
);
292 case TLV_CODE_PRODUCT_NAME
:
293 case TLV_CODE_PART_NUMBER
:
294 case TLV_CODE_SERIAL_NUMBER
:
295 case TLV_CODE_MANUF_DATE
:
296 case TLV_CODE_LABEL_REVISION
:
297 case TLV_CODE_PLATFORM_NAME
:
298 case TLV_CODE_ONIE_VERSION
:
299 case TLV_CODE_MANUF_NAME
:
300 case TLV_CODE_MANUF_COUNTRY
:
301 case TLV_CODE_VENDOR_NAME
:
302 case TLV_CODE_DIAG_VERSION
:
303 case TLV_CODE_SERVICE_TAG
:
304 memcpy(value
, tlv
->value
, tlv
->length
);
305 value
[tlv
->length
] = 0;
307 case TLV_CODE_MAC_BASE
:
308 sprintf(value
, "%02X:%02X:%02X:%02X:%02X:%02X",
309 tlv
->value
[0], tlv
->value
[1], tlv
->value
[2],
310 tlv
->value
[3], tlv
->value
[4], tlv
->value
[5]);
312 case TLV_CODE_DEVICE_VERSION
:
313 sprintf(value
, "%u", tlv
->value
[0]);
315 case TLV_CODE_MAC_SIZE
:
316 sprintf(value
, "%u", (tlv
->value
[0] << 8) | tlv
->value
[1]);
318 case TLV_CODE_VENDOR_EXT
:
320 for (i
= 0; (i
< (DECODE_VALUE_MAX
/ 5)) && (i
< tlv
->length
);
322 sprintf(value
, "%s 0x%02X", value
, tlv
->value
[i
]);
325 case TLV_CODE_CRC_32
:
326 sprintf(value
, "0x%02X%02X%02X%02X",
327 tlv
->value
[0], tlv
->value
[1],
328 tlv
->value
[2], tlv
->value
[3]);
332 for (i
= 0; (i
< (DECODE_VALUE_MAX
/ 5)) && (i
< tlv
->length
);
334 sprintf(value
, "%s 0x%02X", value
, tlv
->value
[i
]);
339 name
[DECODE_NAME_MAX
- 1] = 0;
340 printf("%-20s 0x%02X %3d %s\n", name
, tlv
->type
, tlv
->length
, value
);
346 * This function updates the CRC-32 TLV. If there is no CRC-32 TLV, then
347 * one is added. This function should be called after each update to the
348 * EEPROM structure, to make sure the CRC is always correct.
350 static void update_crc(u8
*eeprom
)
352 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
353 struct tlvinfo_tlv
*eeprom_crc
;
354 unsigned int calc_crc
;
357 // Discover the CRC TLV
358 if (!tlvinfo_find_tlv(eeprom
, TLV_CODE_CRC_32
, &eeprom_index
)) {
359 unsigned int totallen
= be16_to_cpu(eeprom_hdr
->totallen
);
361 if ((totallen
+ ENT_SIZE
+ 4) > TLV_TOTAL_LEN_MAX
)
363 eeprom_index
= HDR_SIZE
+ totallen
;
364 eeprom_hdr
->totallen
= cpu_to_be16(totallen
+ ENT_SIZE
+ 4);
366 eeprom_crc
= to_entry(&eeprom
[eeprom_index
]);
367 eeprom_crc
->type
= TLV_CODE_CRC_32
;
368 eeprom_crc
->length
= 4;
370 // Calculate the checksum
371 calc_crc
= crc32(0, (void *)eeprom
,
372 HDR_SIZE
+ be16_to_cpu(eeprom_hdr
->totallen
) - 4);
373 eeprom_crc
->value
[0] = (calc_crc
>> 24) & 0xFF;
374 eeprom_crc
->value
[1] = (calc_crc
>> 16) & 0xFF;
375 eeprom_crc
->value
[2] = (calc_crc
>> 8) & 0xFF;
376 eeprom_crc
->value
[3] = (calc_crc
>> 0) & 0xFF;
382 * Write the EEPROM data from CPU memory to the hardware.
384 static int prog_eeprom(int devnum
, u8
*eeprom
)
387 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
392 eeprom_len
= HDR_SIZE
+ be16_to_cpu(eeprom_hdr
->totallen
);
393 ret
= write_tlv_eeprom(eeprom
, eeprom_len
, devnum
);
395 printf("Programming failed.\n");
399 printf("Programming passed.\n");
404 * show_tlv_code_list - Display the list of TLV codes and names
406 void show_tlv_code_list(void)
410 printf("TLV Code TLV Name\n");
411 printf("======== =================\n");
412 for (i
= 0; i
< ARRAY_SIZE(tlv_code_list
); i
++) {
413 printf("0x%02X %s\n",
414 tlv_code_list
[i
].m_code
,
415 tlv_code_list
[i
].m_name
);
422 * This function implements the tlv_eeprom command.
424 int do_tlv_eeprom(struct cmd_tbl
*cmdtp
, int flag
, int argc
, char *const argv
[])
427 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
428 static unsigned int current_dev
;
429 /* Set to 1 if we've read EEPROM into memory */
430 static int has_been_read
;
433 // If no arguments, read the EERPOM and display its contents
435 if (!has_been_read
) {
436 ret
= read_eeprom(current_dev
, eeprom
);
438 printf("Failed to read EEPROM data from device.\n");
444 show_eeprom(current_dev
, eeprom
);
448 // We only look at the first character to the command, so "read" and
449 // "reset" will both be treated as "read".
457 devnum
= simple_strtoul(argv
[2], NULL
, 0);
458 if (devnum
>= MAX_TLV_DEVICES
) {
459 printf("Invalid device number\n");
462 current_dev
= devnum
;
468 // Read the EEPROM contents
471 ret
= read_eeprom(current_dev
, eeprom
);
473 printf("Failed to read EEPROM data from device.\n");
477 printf("EEPROM data loaded from device to memory.\n");
481 // Subsequent commands require that the EEPROM has already been read.
482 if (!has_been_read
) {
483 printf("Please read the EEPROM data first, using the 'tlv_eeprom read' command.\n");
487 // Handle the commands that don't take parameters
490 case 'w': /* write */
491 prog_eeprom(current_dev
, eeprom
);
493 case 'e': /* erase */
494 strcpy(eeprom_hdr
->signature
, TLV_INFO_ID_STRING
);
495 eeprom_hdr
->version
= TLV_INFO_VERSION
;
496 eeprom_hdr
->totallen
= cpu_to_be16(0);
498 printf("EEPROM data in memory reset.\n");
501 show_tlv_code_list();
504 show_tlv_devices(current_dev
);
507 return CMD_RET_USAGE
;
512 // The set command takes one or two args.
514 return CMD_RET_USAGE
;
516 // Set command. If the TLV exists in the EEPROM, delete it. Then if
517 // data was supplied for this TLV add the TLV with the new contents at
522 tcode
= simple_strtoul(argv
[2], NULL
, 0);
523 tlvinfo_delete_tlv(eeprom
, tcode
);
525 tlvinfo_add_tlv(eeprom
, tcode
, argv
[3]);
527 return CMD_RET_USAGE
;
534 * This macro defines the tlv_eeprom command line command.
536 U_BOOT_CMD(tlv_eeprom
, 4, 1, do_tlv_eeprom
,
537 "Display and program the system EEPROM data block.",
538 "[read|write|set <type_code> <string_value>|erase|list]\n"
540 " - With no arguments display the current contents.\n"
541 "tlv_eeprom dev [dev]\n"
542 " - List devices or set current EEPROM device.\n"
544 " - Load EEPROM data from device to memory.\n"
546 " - Write the EEPROM data to persistent storage.\n"
547 "tlv_eeprom set <type_code> <string_value>\n"
548 " - Set a field to a value.\n"
549 " - If no string_value, field is deleted.\n"
550 " - Use 'tlv_eeprom write' to make changes permanent.\n"
552 " - Reset the in memory EEPROM data.\n"
553 " - Use 'tlv_eeprom read' to refresh the in memory EEPROM data.\n"
554 " - Use 'tlv_eeprom write' to make changes permanent.\n"
556 " - List the understood TLV codes and names.\n"
562 * This function finds the TLV with the supplied code in the EERPOM.
563 * An offset from the beginning of the EEPROM is returned in the
564 * eeprom_index parameter if the TLV is found.
566 static bool tlvinfo_find_tlv(u8
*eeprom
, u8 tcode
, int *eeprom_index
)
568 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
569 struct tlvinfo_tlv
*eeprom_tlv
;
572 // Search through the TLVs, looking for the first one which matches the
573 // supplied type code.
574 *eeprom_index
= HDR_SIZE
;
575 eeprom_end
= HDR_SIZE
+ be16_to_cpu(eeprom_hdr
->totallen
);
576 while (*eeprom_index
< eeprom_end
) {
577 eeprom_tlv
= to_entry(&eeprom
[*eeprom_index
]);
578 if (!is_valid_tlv(eeprom_tlv
))
580 if (eeprom_tlv
->type
== tcode
)
582 *eeprom_index
+= ENT_SIZE
+ eeprom_tlv
->length
;
590 * This function deletes the TLV with the specified type code from the
593 static bool tlvinfo_delete_tlv(u8
*eeprom
, u8 code
)
597 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
598 struct tlvinfo_tlv
*eeprom_tlv
;
600 // Find the TLV and then move all following TLVs "forward"
601 if (tlvinfo_find_tlv(eeprom
, code
, &eeprom_index
)) {
602 eeprom_tlv
= to_entry(&eeprom
[eeprom_index
]);
603 tlength
= ENT_SIZE
+ eeprom_tlv
->length
;
604 memcpy(&eeprom
[eeprom_index
], &eeprom
[eeprom_index
+ tlength
],
606 be16_to_cpu(eeprom_hdr
->totallen
) - eeprom_index
-
608 eeprom_hdr
->totallen
=
609 cpu_to_be16(be16_to_cpu(eeprom_hdr
->totallen
) -
620 * This function adds a TLV to the EEPROM, converting the value (a string) to
621 * the format in which it will be stored in the EEPROM.
623 #define MAX_TLV_VALUE_LEN 256
624 static bool tlvinfo_add_tlv(u8
*eeprom
, int tcode
, char *strval
)
626 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
627 struct tlvinfo_tlv
*eeprom_tlv
;
630 char data
[MAX_TLV_VALUE_LEN
];
633 // Encode each TLV type into the format to be stored in the EERPOM
635 case TLV_CODE_PRODUCT_NAME
:
636 case TLV_CODE_PART_NUMBER
:
637 case TLV_CODE_SERIAL_NUMBER
:
638 case TLV_CODE_LABEL_REVISION
:
639 case TLV_CODE_PLATFORM_NAME
:
640 case TLV_CODE_ONIE_VERSION
:
641 case TLV_CODE_MANUF_NAME
:
642 case TLV_CODE_MANUF_COUNTRY
:
643 case TLV_CODE_VENDOR_NAME
:
644 case TLV_CODE_DIAG_VERSION
:
645 case TLV_CODE_SERVICE_TAG
:
646 strncpy(data
, strval
, MAX_TLV_VALUE_LEN
);
647 new_tlv_len
= min_t(size_t, MAX_TLV_VALUE_LEN
, strlen(strval
));
649 case TLV_CODE_DEVICE_VERSION
:
650 value
= simple_strtoul(strval
, NULL
, 0);
652 printf("ERROR: Device version must be 255 or less. Value supplied: %u",
656 data
[0] = value
& 0xFF;
659 case TLV_CODE_MAC_SIZE
:
660 value
= simple_strtoul(strval
, NULL
, 0);
661 if (value
>= 65536) {
662 printf("ERROR: MAC Size must be 65535 or less. Value supplied: %u",
666 data
[0] = (value
>> 8) & 0xFF;
667 data
[1] = value
& 0xFF;
670 case TLV_CODE_MANUF_DATE
:
671 if (set_date(data
, strval
) != 0)
675 case TLV_CODE_MAC_BASE
:
676 if (set_mac(data
, strval
) != 0)
680 case TLV_CODE_CRC_32
:
681 printf("WARNING: The CRC TLV is set automatically and cannot be set manually.\n");
683 case TLV_CODE_VENDOR_EXT
:
685 if (set_bytes(data
, strval
, &new_tlv_len
) != 0)
690 // Is there room for this TLV?
691 if ((be16_to_cpu(eeprom_hdr
->totallen
) + ENT_SIZE
+ new_tlv_len
) >
693 printf("ERROR: There is not enough room in the EERPOM to save data.\n");
697 // Add TLV at the end, overwriting CRC TLV if it exists
698 if (tlvinfo_find_tlv(eeprom
, TLV_CODE_CRC_32
, &eeprom_index
))
699 eeprom_hdr
->totallen
=
700 cpu_to_be16(be16_to_cpu(eeprom_hdr
->totallen
) -
703 eeprom_index
= HDR_SIZE
+ be16_to_cpu(eeprom_hdr
->totallen
);
704 eeprom_tlv
= to_entry(&eeprom
[eeprom_index
]);
705 eeprom_tlv
->type
= tcode
;
706 eeprom_tlv
->length
= new_tlv_len
;
707 memcpy(eeprom_tlv
->value
, data
, new_tlv_len
);
709 // Update the total length and calculate (add) a new CRC-32 TLV
710 eeprom_hdr
->totallen
= cpu_to_be16(be16_to_cpu(eeprom_hdr
->totallen
) +
711 ENT_SIZE
+ new_tlv_len
);
720 * Converts a string MAC address into a binary buffer.
722 * This function takes a pointer to a MAC address string
723 * (i.e."XX:XX:XX:XX:XX:XX", where "XX" is a two-digit hex number).
724 * The string format is verified and then converted to binary and
725 * stored in a buffer.
727 static int set_mac(char *buf
, const char *string
)
729 char *p
= (char *)string
;
735 printf("ERROR: NULL mac addr string passed in.\n");
739 if (strlen(p
) != 17) {
740 printf("ERROR: MAC address strlen() != 17 -- %zu\n", strlen(p
));
741 printf("ERROR: Bad MAC address format: %s\n", string
);
745 for (i
= 0; i
< 17; i
++) {
749 printf("ERROR: mac: p[%i] != :, found: `%c'\n",
754 } else if (!is_hex(p
[i
])) {
756 printf("ERROR: mac: p[%i] != hex digit, found: `%c'\n",
763 printf("ERROR: Bad MAC address format: %s\n", string
);
767 /* Convert string to binary */
768 for (i
= 0, p
= (char *)string
; i
< 6; i
++) {
769 buf
[i
] = p
? hextoul(p
, &end
) : 0;
771 p
= (*end
) ? end
+ 1 : end
;
774 if (!is_valid_ethaddr((u8
*)buf
)) {
775 printf("ERROR: MAC address must not be 00:00:00:00:00:00, a multicast address or FF:FF:FF:FF:FF:FF.\n");
776 printf("ERROR: Bad MAC address format: %s\n", string
);
786 * Validates the format of the data string
788 * This function takes a pointer to a date string (i.e. MM/DD/YYYY hh:mm:ss)
789 * and validates that the format is correct. If so the string is copied
790 * to the supplied buffer.
792 static int set_date(char *buf
, const char *string
)
797 printf("ERROR: NULL date string passed in.\n");
801 if (strlen(string
) != 19) {
802 printf("ERROR: Date strlen() != 19 -- %zu\n", strlen(string
));
803 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
808 for (i
= 0; string
[i
] != 0; i
++) {
812 if (string
[i
] != '/') {
813 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
819 if (string
[i
] != ' ') {
820 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
827 if (string
[i
] != ':') {
828 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
834 if (!is_digit(string
[i
])) {
835 printf("ERROR: Bad date format (MM/DD/YYYY hh:mm:ss): %s\n",
850 * Converts a space-separated string of decimal numbers into a
853 * This function takes a pointer to a space-separated string of decimal
854 * numbers (i.e. "128 0x55 0321") with "C" standard radix specifiers
855 * and converts them to an array of bytes.
857 static int set_bytes(char *buf
, const char *string
, int *converted_accum
)
859 char *p
= (char *)string
;
864 printf("ERROR: NULL string passed in.\n");
868 /* Convert string to bytes */
869 for (i
= 0, p
= (char *)string
; (i
< TLV_VALUE_MAX_LEN
) && (*p
!= 0);
871 while ((*p
== ' ') || (*p
== '\t') || (*p
== ',') ||
877 printf("ERROR: Non-digit found in byte string: (%s)\n",
881 byte
= simple_strtoul(p
, &p
, 0);
883 printf("ERROR: The value specified is greater than 255: (%u) in string: %s\n",
887 buf
[i
] = byte
& 0xFF;
891 if (i
== TLV_VALUE_MAX_LEN
&& (*p
!= 0)) {
892 printf("ERROR: Trying to assign too many bytes (max: %d) in string: %s\n",
893 TLV_VALUE_MAX_LEN
, string
);
897 *converted_accum
= i
;
901 static void show_tlv_devices(int current_dev
)
905 for (dev
= 0; dev
< MAX_TLV_DEVICES
; dev
++)
906 if (tlv_devices
[dev
])
907 printf("TLV: %u%s\n", dev
,
908 (dev
== current_dev
) ? " (*)" : "");
911 static int find_tlv_devices(struct udevice
**tlv_devices_p
)
917 for (ret
= uclass_first_device_check(UCLASS_I2C_EEPROM
, &dev
);
919 ret
= uclass_next_device_check(&dev
)) {
921 tlv_devices_p
[count_dev
++] = dev
;
922 if (count_dev
>= MAX_TLV_DEVICES
)
926 return (count_dev
== 0) ? -ENODEV
: 0;
929 static struct udevice
*find_tlv_device_by_index(int dev_num
)
931 struct udevice
*local_tlv_devices
[MAX_TLV_DEVICES
] = {};
932 struct udevice
**tlv_devices_p
;
935 if (gd
->flags
& (GD_FLG_RELOC
| GD_FLG_SPL_INIT
)) {
936 /* Assume BSS is initialized; use static data */
937 if (tlv_devices
[dev_num
])
938 return tlv_devices
[dev_num
];
939 tlv_devices_p
= tlv_devices
;
941 tlv_devices_p
= local_tlv_devices
;
944 ret
= find_tlv_devices(tlv_devices_p
);
945 if (ret
== 0 && tlv_devices_p
[dev_num
])
946 return tlv_devices_p
[dev_num
];
952 * read_tlv_eeprom - read the hwinfo from i2c EEPROM
954 int read_tlv_eeprom(void *eeprom
, int offset
, int len
, int dev_num
)
958 if (dev_num
>= MAX_TLV_DEVICES
)
961 dev
= find_tlv_device_by_index(dev_num
);
965 return i2c_eeprom_read(dev
, offset
, eeprom
, len
);
969 * write_tlv_eeprom - write the hwinfo to i2c EEPROM
971 int write_tlv_eeprom(void *eeprom
, int len
, int dev
)
973 if (!(gd
->flags
& GD_FLG_RELOC
))
975 if (!tlv_devices
[dev
])
978 return i2c_eeprom_write(tlv_devices
[dev
], 0, eeprom
, len
);
981 int read_tlvinfo_tlv_eeprom(void *eeprom
, struct tlvinfo_header
**hdr
,
982 struct tlvinfo_tlv
**first_entry
, int dev_num
)
985 struct tlvinfo_header
*tlv_hdr
;
986 struct tlvinfo_tlv
*tlv_ent
;
988 /* Read TLV header */
989 ret
= read_tlv_eeprom(eeprom
, 0, HDR_SIZE
, dev_num
);
994 if (!is_valid_tlvinfo_header(tlv_hdr
))
997 /* Read TLV entries */
998 tlv_ent
= to_entry(&tlv_hdr
[1]);
999 ret
= read_tlv_eeprom(tlv_ent
, HDR_SIZE
,
1000 be16_to_cpu(tlv_hdr
->totallen
), dev_num
);
1003 if (!is_checksum_valid(eeprom
))
1007 *first_entry
= tlv_ent
;
1013 * mac_read_from_eeprom
1015 * Read the MAC addresses from EEPROM
1017 * This function reads the MAC addresses from EEPROM and sets the
1018 * appropriate environment variables for each one read.
1020 * The environment variables are only set if they haven't been set already.
1021 * This ensures that any user-saved variables are never overwritten.
1023 * This function must be called after relocation.
1025 int mac_read_from_eeprom(void)
1029 struct tlvinfo_tlv
*eeprom_tlv
;
1032 struct tlvinfo_header
*eeprom_hdr
= to_header(eeprom
);
1033 int devnum
= 0; // TODO: support multiple EEPROMs
1037 if (read_eeprom(devnum
, eeprom
)) {
1038 printf("Read failed.\n");
1043 if (tlvinfo_find_tlv(eeprom
, TLV_CODE_MAC_SIZE
, &eeprom_index
)) {
1044 eeprom_tlv
= to_entry(&eeprom
[eeprom_index
]);
1045 maccount
= (eeprom_tlv
->value
[0] << 8) | eeprom_tlv
->value
[1];
1048 memcpy(macbase
, "\0\0\0\0\0\0", 6);
1049 if (tlvinfo_find_tlv(eeprom
, TLV_CODE_MAC_BASE
, &eeprom_index
)) {
1050 eeprom_tlv
= to_entry(&eeprom
[eeprom_index
]);
1051 memcpy(macbase
, eeprom_tlv
->value
, 6);
1054 for (i
= 0; i
< maccount
; i
++) {
1055 if (is_valid_ethaddr(macbase
)) {
1059 sprintf(ethaddr
, "%02X:%02X:%02X:%02X:%02X:%02X",
1060 macbase
[0], macbase
[1], macbase
[2],
1061 macbase
[3], macbase
[4], macbase
[5]);
1062 sprintf(enetvar
, i
? "eth%daddr" : "ethaddr", i
);
1063 /* Only initialize environment variables that are blank
1064 * (i.e. have not yet been set)
1066 if (!env_get(enetvar
))
1067 env_set(enetvar
, ethaddr
);
1070 if (macbase
[5] == 0) {
1072 if (macbase
[4] == 0) {
1074 if (macbase
[3] == 0) {
1084 printf("%s v%u len=%u\n", eeprom_hdr
->signature
, eeprom_hdr
->version
,
1085 be16_to_cpu(eeprom_hdr
->totallen
));
1090 int serial_read_from_eeprom(int devnum
)
1092 char serialstr
[257];
1094 struct tlvinfo_tlv
*eeprom_tlv
;
1096 if (env_get("serial#"))
1099 if (read_eeprom(devnum
, eeprom
)) {
1100 printf("Read failed.\n");
1104 if (tlvinfo_find_tlv(eeprom
, TLV_CODE_SERIAL_NUMBER
, &eeprom_index
)) {
1105 eeprom_tlv
= to_entry(&eeprom
[eeprom_index
]);
1106 memcpy(serialstr
, eeprom_tlv
->value
, eeprom_tlv
->length
);
1107 serialstr
[eeprom_tlv
->length
] = 0;
1108 env_set("serial#", serialstr
);