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