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