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