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 26DECLARE_GLOBAL_DATA_PTR; 27 28#define MAX_TLV_DEVICES 2 29 30/* File scope function prototypes */ 31static bool is_checksum_valid(u8 *eeprom); 32static int read_eeprom(int devnum, u8 *eeprom); 33static void show_eeprom(int devnum, u8 *eeprom); 34static void decode_tlv(struct tlvinfo_tlv *tlv); 35static void update_crc(u8 *eeprom); 36static int prog_eeprom(int devnum, u8 *eeprom); 37static bool tlvinfo_find_tlv(u8 *eeprom, u8 tcode, int *eeprom_index); 38static bool tlvinfo_delete_tlv(u8 *eeprom, u8 code); 39static bool tlvinfo_add_tlv(u8 *eeprom, int tcode, char *strval); 40static int set_mac(char *buf, const char *string); 41static int set_date(char *buf, const char *string); 42static int set_bytes(char *buf, const char *string, int *converted_accum); 43static void show_tlv_devices(int current_dev); 44 45/* The EERPOM contents after being read into memory */ 46static u8 eeprom[TLV_INFO_MAX_LEN]; 47 48static 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 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(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 */ 161static 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 */ 214struct tlv_code_desc { 215 u8 m_code; 216 char *m_name; 217}; 218 219/** 220 * List of TLV codes and names. 221 */ 222static 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 */ 245static 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 284static 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 */ 351static 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 */ 385static 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 */ 407void 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 */ 425int 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 */ 537U_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 */ 567static 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 */ 594static 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 625static 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 */ 728static 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 */ 793static 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 */ 858static 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 902static 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 912static 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 930static 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 */ 955int 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 */ 972int 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 982int 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 */ 1026int 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 1091int serial_read_from_eeprom(int devnum) 1092{ 1093 char serialstr[257]; 1094 int eeprom_index; 1095 struct tlvinfo_tlv *eeprom_tlv; 1096 1097 if (env_get("serial#")) 1098 return 0; 1099 1100 if (read_eeprom(devnum, eeprom)) { 1101 printf("Read failed.\n"); 1102 return -1; 1103 } 1104 1105 if (tlvinfo_find_tlv(eeprom, TLV_CODE_SERIAL_NUMBER, &eeprom_index)) { 1106 eeprom_tlv = to_entry(&eeprom[eeprom_index]); 1107 memcpy(serialstr, eeprom_tlv->value, eeprom_tlv->length); 1108 serialstr[eeprom_tlv->length] = 0; 1109 env_set("serial#", serialstr); 1110 } 1111 1112 return 0; 1113} 1114