xref: /rk3399_rockchip-uboot/common/eeprom/eeprom_field.c (revision 08ca213acadef61748dc62d48b0f5c4bed8b8c2d)
1*aa9e6044SNikita Kiryanov /*
2*aa9e6044SNikita Kiryanov  * (C) Copyright 2009-2016 CompuLab, Ltd.
3*aa9e6044SNikita Kiryanov  *
4*aa9e6044SNikita Kiryanov  * Authors: Nikita Kiryanov <nikita@compulab.co.il>
5*aa9e6044SNikita Kiryanov  *	    Igor Grinberg <grinberg@compulab.co.il>
6*aa9e6044SNikita Kiryanov  *
7*aa9e6044SNikita Kiryanov  * SPDX-License-Identifier:	GPL-2.0+
8*aa9e6044SNikita Kiryanov  */
9*aa9e6044SNikita Kiryanov 
10*aa9e6044SNikita Kiryanov #include <common.h>
11*aa9e6044SNikita Kiryanov #include <linux/string.h>
12*aa9e6044SNikita Kiryanov #include <eeprom_field.h>
13*aa9e6044SNikita Kiryanov 
__eeprom_field_print_bin(const struct eeprom_field * field,char * delimiter,bool reverse)14*aa9e6044SNikita Kiryanov static void __eeprom_field_print_bin(const struct eeprom_field *field,
15*aa9e6044SNikita Kiryanov 				     char *delimiter, bool reverse)
16*aa9e6044SNikita Kiryanov {
17*aa9e6044SNikita Kiryanov 	int i;
18*aa9e6044SNikita Kiryanov 	int from = reverse ? field->size - 1 : 0;
19*aa9e6044SNikita Kiryanov 	int to = reverse ? 0 : field->size - 1;
20*aa9e6044SNikita Kiryanov 
21*aa9e6044SNikita Kiryanov 	printf(PRINT_FIELD_SEGMENT, field->name);
22*aa9e6044SNikita Kiryanov 	for (i = from; i != to; reverse ? i-- : i++)
23*aa9e6044SNikita Kiryanov 		printf("%02x%s", field->buf[i], delimiter);
24*aa9e6044SNikita Kiryanov 
25*aa9e6044SNikita Kiryanov 	printf("%02x\n", field->buf[i]);
26*aa9e6044SNikita Kiryanov }
27*aa9e6044SNikita Kiryanov 
__eeprom_field_update_bin(struct eeprom_field * field,const char * value,bool reverse)28*aa9e6044SNikita Kiryanov static int __eeprom_field_update_bin(struct eeprom_field *field,
29*aa9e6044SNikita Kiryanov 				     const char *value, bool reverse)
30*aa9e6044SNikita Kiryanov {
31*aa9e6044SNikita Kiryanov 	int len = strlen(value);
32*aa9e6044SNikita Kiryanov 	int k, j, i = reverse ? len - 1 : 0;
33*aa9e6044SNikita Kiryanov 	unsigned char byte;
34*aa9e6044SNikita Kiryanov 	char *endptr;
35*aa9e6044SNikita Kiryanov 
36*aa9e6044SNikita Kiryanov 	/* each two characters in the string fit in one byte */
37*aa9e6044SNikita Kiryanov 	if (len > field->size * 2)
38*aa9e6044SNikita Kiryanov 		return -1;
39*aa9e6044SNikita Kiryanov 
40*aa9e6044SNikita Kiryanov 	memset(field->buf, 0, field->size);
41*aa9e6044SNikita Kiryanov 
42*aa9e6044SNikita Kiryanov 	/* i - string iterator, j - buf iterator */
43*aa9e6044SNikita Kiryanov 	for (j = 0; j < field->size; j++) {
44*aa9e6044SNikita Kiryanov 		byte = 0;
45*aa9e6044SNikita Kiryanov 		char tmp[3] = { 0, 0, 0 };
46*aa9e6044SNikita Kiryanov 
47*aa9e6044SNikita Kiryanov 		if ((reverse && i < 0) || (!reverse && i >= len))
48*aa9e6044SNikita Kiryanov 			break;
49*aa9e6044SNikita Kiryanov 
50*aa9e6044SNikita Kiryanov 		for (k = 0; k < 2; k++) {
51*aa9e6044SNikita Kiryanov 			if (reverse && i == 0) {
52*aa9e6044SNikita Kiryanov 				tmp[k] = value[i];
53*aa9e6044SNikita Kiryanov 				break;
54*aa9e6044SNikita Kiryanov 			}
55*aa9e6044SNikita Kiryanov 
56*aa9e6044SNikita Kiryanov 			tmp[k] = value[reverse ? i - 1 + k : i + k];
57*aa9e6044SNikita Kiryanov 		}
58*aa9e6044SNikita Kiryanov 
59*aa9e6044SNikita Kiryanov 		byte = simple_strtoul(tmp, &endptr, 0);
60*aa9e6044SNikita Kiryanov 		if (*endptr != '\0' || byte < 0)
61*aa9e6044SNikita Kiryanov 			return -1;
62*aa9e6044SNikita Kiryanov 
63*aa9e6044SNikita Kiryanov 		field->buf[j] = byte;
64*aa9e6044SNikita Kiryanov 		i = reverse ? i - 2 : i + 2;
65*aa9e6044SNikita Kiryanov 	}
66*aa9e6044SNikita Kiryanov 
67*aa9e6044SNikita Kiryanov 	return 0;
68*aa9e6044SNikita Kiryanov }
69*aa9e6044SNikita Kiryanov 
__eeprom_field_update_bin_delim(struct eeprom_field * field,char * value,char * delimiter)70*aa9e6044SNikita Kiryanov static int __eeprom_field_update_bin_delim(struct eeprom_field *field,
71*aa9e6044SNikita Kiryanov 					   char *value, char *delimiter)
72*aa9e6044SNikita Kiryanov {
73*aa9e6044SNikita Kiryanov 	int count = 0;
74*aa9e6044SNikita Kiryanov 	int i, val;
75*aa9e6044SNikita Kiryanov 	const char *tmp = value;
76*aa9e6044SNikita Kiryanov 	char *tok;
77*aa9e6044SNikita Kiryanov 	char *endptr;
78*aa9e6044SNikita Kiryanov 
79*aa9e6044SNikita Kiryanov 	tmp = strstr(tmp, delimiter);
80*aa9e6044SNikita Kiryanov 	while (tmp != NULL) {
81*aa9e6044SNikita Kiryanov 		count++;
82*aa9e6044SNikita Kiryanov 		tmp++;
83*aa9e6044SNikita Kiryanov 		tmp = strstr(tmp, delimiter);
84*aa9e6044SNikita Kiryanov 	}
85*aa9e6044SNikita Kiryanov 
86*aa9e6044SNikita Kiryanov 	if (count > field->size)
87*aa9e6044SNikita Kiryanov 		return -1;
88*aa9e6044SNikita Kiryanov 
89*aa9e6044SNikita Kiryanov 	tok = strtok(value, delimiter);
90*aa9e6044SNikita Kiryanov 	for (i = 0; tok && i < field->size; i++) {
91*aa9e6044SNikita Kiryanov 		val = simple_strtoul(tok, &endptr, 0);
92*aa9e6044SNikita Kiryanov 		if (*endptr != '\0')
93*aa9e6044SNikita Kiryanov 			return -1;
94*aa9e6044SNikita Kiryanov 
95*aa9e6044SNikita Kiryanov 		/* here we assume that each tok is no more than byte long */
96*aa9e6044SNikita Kiryanov 		field->buf[i] = (unsigned char)val;
97*aa9e6044SNikita Kiryanov 		tok = strtok(NULL, delimiter);
98*aa9e6044SNikita Kiryanov 	}
99*aa9e6044SNikita Kiryanov 
100*aa9e6044SNikita Kiryanov 	return 0;
101*aa9e6044SNikita Kiryanov }
102*aa9e6044SNikita Kiryanov 
103*aa9e6044SNikita Kiryanov /**
104*aa9e6044SNikita Kiryanov  * eeprom_field_print_bin() - print a field which contains binary data
105*aa9e6044SNikita Kiryanov  *
106*aa9e6044SNikita Kiryanov  * Treat the field data as simple binary data, and print it as two digit
107*aa9e6044SNikita Kiryanov  * hexadecimal values.
108*aa9e6044SNikita Kiryanov  * Sample output:
109*aa9e6044SNikita Kiryanov  *      Field Name       0102030405060708090a
110*aa9e6044SNikita Kiryanov  *
111*aa9e6044SNikita Kiryanov  * @field:	an initialized field to print
112*aa9e6044SNikita Kiryanov  */
eeprom_field_print_bin(const struct eeprom_field * field)113*aa9e6044SNikita Kiryanov void eeprom_field_print_bin(const struct eeprom_field *field)
114*aa9e6044SNikita Kiryanov {
115*aa9e6044SNikita Kiryanov 	__eeprom_field_print_bin(field, "", false);
116*aa9e6044SNikita Kiryanov }
117*aa9e6044SNikita Kiryanov 
118*aa9e6044SNikita Kiryanov /**
119*aa9e6044SNikita Kiryanov  * eeprom_field_update_bin() - Update field with new data in binary form
120*aa9e6044SNikita Kiryanov  *
121*aa9e6044SNikita Kiryanov  * @field:	an initialized field
122*aa9e6044SNikita Kiryanov  * @value:	a string of values (i.e. "10b234a")
123*aa9e6044SNikita Kiryanov  */
eeprom_field_update_bin(struct eeprom_field * field,char * value)124*aa9e6044SNikita Kiryanov int eeprom_field_update_bin(struct eeprom_field *field, char *value)
125*aa9e6044SNikita Kiryanov {
126*aa9e6044SNikita Kiryanov 	return __eeprom_field_update_bin(field, value, false);
127*aa9e6044SNikita Kiryanov }
128*aa9e6044SNikita Kiryanov 
129*aa9e6044SNikita Kiryanov /**
130*aa9e6044SNikita Kiryanov  * eeprom_field_update_reserved() - Update reserved field with new data in
131*aa9e6044SNikita Kiryanov  *				    binary form
132*aa9e6044SNikita Kiryanov  *
133*aa9e6044SNikita Kiryanov  * @field:	an initialized field
134*aa9e6044SNikita Kiryanov  * @value:	a space delimited string of byte values (i.e. "1 02 3 0x4")
135*aa9e6044SNikita Kiryanov  */
eeprom_field_update_reserved(struct eeprom_field * field,char * value)136*aa9e6044SNikita Kiryanov int eeprom_field_update_reserved(struct eeprom_field *field, char *value)
137*aa9e6044SNikita Kiryanov {
138*aa9e6044SNikita Kiryanov 	return __eeprom_field_update_bin_delim(field, value, " ");
139*aa9e6044SNikita Kiryanov }
140*aa9e6044SNikita Kiryanov 
141*aa9e6044SNikita Kiryanov /**
142*aa9e6044SNikita Kiryanov  * eeprom_field_print_bin_rev() - print a field which contains binary data in
143*aa9e6044SNikita Kiryanov  *				  reverse order
144*aa9e6044SNikita Kiryanov  *
145*aa9e6044SNikita Kiryanov  * Treat the field data as simple binary data, and print it in reverse order
146*aa9e6044SNikita Kiryanov  * as two digit hexadecimal values.
147*aa9e6044SNikita Kiryanov  *
148*aa9e6044SNikita Kiryanov  * Data in field:
149*aa9e6044SNikita Kiryanov  *                      0102030405060708090a
150*aa9e6044SNikita Kiryanov  * Sample output:
151*aa9e6044SNikita Kiryanov  *      Field Name      0a090807060504030201
152*aa9e6044SNikita Kiryanov  *
153*aa9e6044SNikita Kiryanov  * @field:	an initialized field to print
154*aa9e6044SNikita Kiryanov  */
eeprom_field_print_bin_rev(const struct eeprom_field * field)155*aa9e6044SNikita Kiryanov void eeprom_field_print_bin_rev(const struct eeprom_field *field)
156*aa9e6044SNikita Kiryanov {
157*aa9e6044SNikita Kiryanov 	__eeprom_field_print_bin(field, "", true);
158*aa9e6044SNikita Kiryanov }
159*aa9e6044SNikita Kiryanov 
160*aa9e6044SNikita Kiryanov /**
161*aa9e6044SNikita Kiryanov  * eeprom_field_update_bin_rev() - Update field with new data in binary form,
162*aa9e6044SNikita Kiryanov  *				   storing it in reverse
163*aa9e6044SNikita Kiryanov  *
164*aa9e6044SNikita Kiryanov  * This function takes a string of byte values, and stores them
165*aa9e6044SNikita Kiryanov  * in the field in the reverse order. i.e. if the input string was "1234",
166*aa9e6044SNikita Kiryanov  * "3412" will be written to the field.
167*aa9e6044SNikita Kiryanov  *
168*aa9e6044SNikita Kiryanov  * @field:	an initialized field
169*aa9e6044SNikita Kiryanov  * @value:	a string of byte values
170*aa9e6044SNikita Kiryanov  */
eeprom_field_update_bin_rev(struct eeprom_field * field,char * value)171*aa9e6044SNikita Kiryanov int eeprom_field_update_bin_rev(struct eeprom_field *field, char *value)
172*aa9e6044SNikita Kiryanov {
173*aa9e6044SNikita Kiryanov 	return __eeprom_field_update_bin(field, value, true);
174*aa9e6044SNikita Kiryanov }
175*aa9e6044SNikita Kiryanov 
176*aa9e6044SNikita Kiryanov /**
177*aa9e6044SNikita Kiryanov  * eeprom_field_print_mac_addr() - print a field which contains a mac address
178*aa9e6044SNikita Kiryanov  *
179*aa9e6044SNikita Kiryanov  * Treat the field data as simple binary data, and print it formatted as a MAC
180*aa9e6044SNikita Kiryanov  * address.
181*aa9e6044SNikita Kiryanov  * Sample output:
182*aa9e6044SNikita Kiryanov  *      Field Name     01:02:03:04:05:06
183*aa9e6044SNikita Kiryanov  *
184*aa9e6044SNikita Kiryanov  * @field:	an initialized field to print
185*aa9e6044SNikita Kiryanov  */
eeprom_field_print_mac(const struct eeprom_field * field)186*aa9e6044SNikita Kiryanov void eeprom_field_print_mac(const struct eeprom_field *field)
187*aa9e6044SNikita Kiryanov {
188*aa9e6044SNikita Kiryanov 	__eeprom_field_print_bin(field, ":", false);
189*aa9e6044SNikita Kiryanov }
190*aa9e6044SNikita Kiryanov 
191*aa9e6044SNikita Kiryanov /**
192*aa9e6044SNikita Kiryanov  * eeprom_field_update_mac() - Update a mac address field which contains binary
193*aa9e6044SNikita Kiryanov  *			       data
194*aa9e6044SNikita Kiryanov  *
195*aa9e6044SNikita Kiryanov  * @field:	an initialized field
196*aa9e6044SNikita Kiryanov  * @value:	a colon delimited string of byte values (i.e. "1:02:3:ff")
197*aa9e6044SNikita Kiryanov  */
eeprom_field_update_mac(struct eeprom_field * field,char * value)198*aa9e6044SNikita Kiryanov int eeprom_field_update_mac(struct eeprom_field *field, char *value)
199*aa9e6044SNikita Kiryanov {
200*aa9e6044SNikita Kiryanov 	return __eeprom_field_update_bin_delim(field, value, ":");
201*aa9e6044SNikita Kiryanov }
202*aa9e6044SNikita Kiryanov 
203*aa9e6044SNikita Kiryanov /**
204*aa9e6044SNikita Kiryanov  * eeprom_field_print_ascii() - print a field which contains ASCII data
205*aa9e6044SNikita Kiryanov  * @field:	an initialized field to print
206*aa9e6044SNikita Kiryanov  */
eeprom_field_print_ascii(const struct eeprom_field * field)207*aa9e6044SNikita Kiryanov void eeprom_field_print_ascii(const struct eeprom_field *field)
208*aa9e6044SNikita Kiryanov {
209*aa9e6044SNikita Kiryanov 	char format[8];
210*aa9e6044SNikita Kiryanov 
211*aa9e6044SNikita Kiryanov 	sprintf(format, "%%.%ds\n", field->size);
212*aa9e6044SNikita Kiryanov 	printf(PRINT_FIELD_SEGMENT, field->name);
213*aa9e6044SNikita Kiryanov 	printf(format, field->buf);
214*aa9e6044SNikita Kiryanov }
215*aa9e6044SNikita Kiryanov 
216*aa9e6044SNikita Kiryanov /**
217*aa9e6044SNikita Kiryanov  * eeprom_field_update_ascii() - Update field with new data in ASCII form
218*aa9e6044SNikita Kiryanov  * @field:	an initialized field
219*aa9e6044SNikita Kiryanov  * @value:	the new string data
220*aa9e6044SNikita Kiryanov  *
221*aa9e6044SNikita Kiryanov  * Returns 0 on success, -1 of failure (new string too long).
222*aa9e6044SNikita Kiryanov  */
eeprom_field_update_ascii(struct eeprom_field * field,char * value)223*aa9e6044SNikita Kiryanov int eeprom_field_update_ascii(struct eeprom_field *field, char *value)
224*aa9e6044SNikita Kiryanov {
225*aa9e6044SNikita Kiryanov 	if (strlen(value) >= field->size) {
226*aa9e6044SNikita Kiryanov 		printf("%s: new data too long\n", field->name);
227*aa9e6044SNikita Kiryanov 		return -1;
228*aa9e6044SNikita Kiryanov 	}
229*aa9e6044SNikita Kiryanov 
230*aa9e6044SNikita Kiryanov 	strncpy((char *)field->buf, value, field->size - 1);
231*aa9e6044SNikita Kiryanov 	field->buf[field->size - 1] = '\0';
232*aa9e6044SNikita Kiryanov 
233*aa9e6044SNikita Kiryanov 	return 0;
234*aa9e6044SNikita Kiryanov }
235*aa9e6044SNikita Kiryanov 
236*aa9e6044SNikita Kiryanov /**
237*aa9e6044SNikita Kiryanov  * eeprom_field_print_reserved() - print the "Reserved fields" field
238*aa9e6044SNikita Kiryanov  *
239*aa9e6044SNikita Kiryanov  * Print a notice that the following field_size bytes are reserved.
240*aa9e6044SNikita Kiryanov  *
241*aa9e6044SNikita Kiryanov  * Sample output:
242*aa9e6044SNikita Kiryanov  *      Reserved fields              (64 bytes)
243*aa9e6044SNikita Kiryanov  *
244*aa9e6044SNikita Kiryanov  * @field:	an initialized field to print
245*aa9e6044SNikita Kiryanov  */
eeprom_field_print_reserved(const struct eeprom_field * field)246*aa9e6044SNikita Kiryanov void eeprom_field_print_reserved(const struct eeprom_field *field)
247*aa9e6044SNikita Kiryanov {
248*aa9e6044SNikita Kiryanov 	printf(PRINT_FIELD_SEGMENT, "Reserved fields\t");
249*aa9e6044SNikita Kiryanov 	printf("(%d bytes)\n", field->size);
250*aa9e6044SNikita Kiryanov }
251