1 /* 2 * (C) Copyright 2009-2016 CompuLab, Ltd. 3 * 4 * Authors: Nikita Kiryanov <nikita@compulab.co.il> 5 * Igor Grinberg <grinberg@compulab.co.il> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 10 #include <common.h> 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 59 byte = simple_strtoul(tmp, &endptr, 0); 60 if (*endptr != '\0' || byte < 0) 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 } 251