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