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