150476Speter// SPDX-License-Identifier: GPL-2.0+ 220388Sadam/* 320388Sadam * (C) Copyright 2009-2016 CompuLab, Ltd. 420388Sadam * 520388Sadam * Authors: Nikita Kiryanov <nikita@compulab.co.il> 6174990Sache * Igor Grinberg <grinberg@compulab.co.il> 720388Sadam */ 820388Sadam 920388Sadam#include <common.h> 1020388Sadam#include <linux/kernel.h> 1120388Sadam#include <eeprom_layout.h> 1220388Sadam#include <eeprom_field.h> 1320388Sadam 1420388Sadam#define NO_LAYOUT_FIELDS "Unknown layout. Dumping raw data\n" 1520388Sadam 1620388Sadamstruct eeprom_field layout_unknown[1] = { 1720388Sadam { NO_LAYOUT_FIELDS, 256, NULL, eeprom_field_print_bin, 1820388Sadam eeprom_field_update_bin }, 1920388Sadam}; 2020388Sadam 21174990Sache/* 2220388Sadam * eeprom_layout_detect() - detect layout based on the contents of the data. 2320388Sadam * @data: Pointer to the data to be analyzed. 2420388Sadam * 2520388Sadam * Returns: the detected layout version. 2620388Sadam */ 2720388Sadam__weak int eeprom_layout_detect(unsigned char *data) 2820388Sadam{ 2920388Sadam return LAYOUT_VERSION_UNRECOGNIZED; 3020388Sadam} 3120388Sadam 3220388Sadam/* 3320388Sadam * __eeprom_layout_assign() - set the layout fields 3420388Sadam * @layout: A pointer to an existing struct layout. 3520388Sadam * @layout_version: The version number of the desired layout 3620388Sadam */ 3720388Sadam__weak void __eeprom_layout_assign(struct eeprom_layout *layout, 3820388Sadam int layout_version) 3920388Sadam{ 4020388Sadam layout->fields = layout_unknown; 4120388Sadam layout->num_of_fields = ARRAY_SIZE(layout_unknown); 4220388Sadam} 4320388Sadamvoid eeprom_layout_assign(struct eeprom_layout *layout, int layout_version) \ 4420388Sadam __attribute__((weak, alias("__eeprom_layout_assign"))); 4520388Sadam 4620388Sadam/* 4720388Sadam * eeprom_layout_print() - print the layout and the data which is assigned to it 4820388Sadam * @layout: A pointer to an existing struct layout. 4920388Sadam */ 5020388Sadamstatic void eeprom_layout_print(const struct eeprom_layout *layout) 5120388Sadam{ 5220388Sadam int i; 5320388Sadam struct eeprom_field *fields = layout->fields; 5420388Sadam 5520388Sadam for (i = 0; i < layout->num_of_fields; i++) 5620388Sadam fields[i].print(&fields[i]); 5720388Sadam} 5820388Sadam 5920388Sadam/* 6020388Sadam * eeprom_layout_update_field() - update a single field in the layout data. 6120388Sadam * @layout: A pointer to an existing struct layout. 6274570Sache * @field_name: The name of the field to update. 6320388Sadam * @new_data: The new field data (a string. Format depends on the field) 6420388Sadam * 6520388Sadam * Returns: 0 on success, negative error value on failure. 6654090Sache */ 6720388Sadamstatic int eeprom_layout_update_field(struct eeprom_layout *layout, 6820388Sadam char *field_name, char *new_data) 6920388Sadam{ 7020388Sadam int i, err; 7120388Sadam struct eeprom_field *fields = layout->fields; 7220388Sadam 7320388Sadam if (new_data == NULL) 7420388Sadam return 0; 7520388Sadam 7620388Sadam if (field_name == NULL) 7720388Sadam return -1; 7854090Sache 7953943Sache for (i = 0; i < layout->num_of_fields; i++) { 80174990Sache if (fields[i].name == RESERVED_FIELDS || 8153943Sache strcmp(fields[i].name, field_name)) 8253943Sache continue; 8353943Sache 8453943Sache err = fields[i].update(&fields[i], new_data); 8553943Sache if (err) 8653943Sache printf("Invalid data for field %s\n", field_name); 8753943Sache 8853943Sache return err; 8953943Sache } 9053943Sache 9153943Sache printf("No such field '%s'\n", field_name); 9253943Sache 9353943Sache return -1; 9453943Sache} 9574413Sache 9653943Sache/* 9774413Sache * eeprom_layout_setup() - setup layout struct with the layout data and 9853961Sache * metadata as dictated by layout_version 9974413Sache * @layout: A pointer to an existing struct layout. 10053961Sache * @buf: A buffer initialized with the eeprom data. 10174413Sache * @buf_size: Size of buf in bytes. 10274413Sache * @layout version: The version number of the layout. 103 */ 104void 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