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