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