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