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