tlv_eeprom.c 28 KB

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