tlv_eeprom.c 28 KB

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