Home | History | Annotate | Download | only in eeprom
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2009-2016 CompuLab, Ltd.
      4  *
      5  * Authors: Nikita Kiryanov <nikita (at) compulab.co.il>
      6  *	    Igor Grinberg <grinberg (at) 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