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