1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2009-2016 CompuLab, Ltd. 4 * 5 * Authors: Nikita Kiryanov <nikita@compulab.co.il> 6 * Igor Grinberg <grinberg@compulab.co.il> 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 } 250