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/kernel.h> 11 #include <eeprom_layout.h> 12 #include <eeprom_field.h> 13 14 #define NO_LAYOUT_FIELDS "Unknown layout. Dumping raw data\n" 15 16 struct eeprom_field layout_unknown[1] = { 17 { NO_LAYOUT_FIELDS, 256, NULL, eeprom_field_print_bin, 18 eeprom_field_update_bin }, 19 }; 20 21 /* 22 * eeprom_layout_detect() - detect layout based on the contents of the data. 23 * @data: Pointer to the data to be analyzed. 24 * 25 * Returns: the detected layout version. 26 */ 27 __weak int eeprom_layout_detect(unsigned char *data) 28 { 29 return LAYOUT_VERSION_UNRECOGNIZED; 30 } 31 32 /* 33 * __eeprom_layout_assign() - set the layout fields 34 * @layout: A pointer to an existing struct layout. 35 * @layout_version: The version number of the desired layout 36 */ 37 __weak void __eeprom_layout_assign(struct eeprom_layout *layout, 38 int layout_version) 39 { 40 layout->fields = layout_unknown; 41 layout->num_of_fields = ARRAY_SIZE(layout_unknown); 42 } 43 void eeprom_layout_assign(struct eeprom_layout *layout, int layout_version) \ 44 __attribute__((weak, alias("__eeprom_layout_assign"))); 45 46 /* 47 * eeprom_layout_print() - print the layout and the data which is assigned to it 48 * @layout: A pointer to an existing struct layout. 49 */ 50 static void eeprom_layout_print(const struct eeprom_layout *layout) 51 { 52 int i; 53 struct eeprom_field *fields = layout->fields; 54 55 for (i = 0; i < layout->num_of_fields; i++) 56 fields[i].print(&fields[i]); 57 } 58 59 /* 60 * eeprom_layout_update_field() - update a single field in the layout data. 61 * @layout: A pointer to an existing struct layout. 62 * @field_name: The name of the field to update. 63 * @new_data: The new field data (a string. Format depends on the field) 64 * 65 * Returns: 0 on success, negative error value on failure. 66 */ 67 static int eeprom_layout_update_field(struct eeprom_layout *layout, 68 char *field_name, char *new_data) 69 { 70 int i, err; 71 struct eeprom_field *fields = layout->fields; 72 73 if (new_data == NULL) 74 return 0; 75 76 if (field_name == NULL) 77 return -1; 78 79 for (i = 0; i < layout->num_of_fields; i++) { 80 if (fields[i].name == RESERVED_FIELDS || 81 strcmp(fields[i].name, field_name)) 82 continue; 83 84 err = fields[i].update(&fields[i], new_data); 85 if (err) 86 printf("Invalid data for field %s\n", field_name); 87 88 return err; 89 } 90 91 printf("No such field '%s'\n", field_name); 92 93 return -1; 94 } 95 96 /* 97 * eeprom_layout_setup() - setup layout struct with the layout data and 98 * metadata as dictated by layout_version 99 * @layout: A pointer to an existing struct layout. 100 * @buf: A buffer initialized with the eeprom data. 101 * @buf_size: Size of buf in bytes. 102 * @layout version: The version number of the layout. 103 */ 104 void eeprom_layout_setup(struct eeprom_layout *layout, unsigned char *buf, 105 unsigned int buf_size, int layout_version) 106 { 107 int i; 108 109 if (layout_version == LAYOUT_VERSION_AUTODETECT) 110 layout->layout_version = eeprom_layout_detect(buf); 111 else 112 layout->layout_version = layout_version; 113 114 eeprom_layout_assign(layout, layout_version); 115 layout->data = buf; 116 for (i = 0; i < layout->num_of_fields; i++) { 117 layout->fields[i].buf = buf; 118 buf += layout->fields[i].size; 119 } 120 121 layout->data_size = buf_size; 122 layout->print = eeprom_layout_print; 123 layout->update = eeprom_layout_update_field; 124 } 125