Edward O'Callaghan has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/74065 )
Change subject: util/flashchips_db_jsoniser: Initial version ......................................................................
util/flashchips_db_jsoniser: Initial version
This is a quick hack to help with migrating the flashchips db out of C code into a pure, declarative JSON data format. This can be transformed to whatever is prefered long term later however this gets us across the bridge.
Change-Id: I3b65caeb811ec0978091c543ccffb5a1b0d254ba Signed-off-by: Edward O'Callaghan quasisec@google.com --- A util/flashchips_db_jsoniser/main.c A util/flashchips_db_jsoniser/meson.build 2 files changed, 322 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/65/74065/1
diff --git a/util/flashchips_db_jsoniser/main.c b/util/flashchips_db_jsoniser/main.c new file mode 100644 index 0000000..829e58e --- /dev/null +++ b/util/flashchips_db_jsoniser/main.c @@ -0,0 +1,299 @@ +/* + * This file is part of the flashrom project. + * + * Copyright (C) 2023 Google Australia. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include "flash.h" +#include "flashchips.h" +#include "writeprotect.h" + +static char *strcat_realloc_copy(char *dest, const char *src) +{ + dest = realloc(dest, strlen(dest) + strlen(src) + 1); + if (!dest) { + return NULL; + } + strcat(dest, src); + return dest; +} + +/* + * Return a string corresponding to the bustype parameter. + * Memory is obtained with malloc() and must be freed with free() by the caller. + */ +static char *flashbuses_to_text_copy(enum chipbustype bustype) +{ + char *ret = calloc(1, 1); + /* + * FIXME: Once all chipsets and flash chips have been updated, NONSPI + * will cease to exist and should be eliminated here as well. + */ + if (bustype == BUS_NONSPI) { + ret = strcat_realloc_copy(ret, "BUS_NONSPI, "); + } else { + if (bustype & BUS_PARALLEL) + ret = strcat_realloc_copy(ret, "BUS_PARALLEL, "); + if (bustype & BUS_LPC) + ret = strcat_realloc_copy(ret, "BUS_LPC, "); + if (bustype & BUS_FWH) + ret = strcat_realloc_copy(ret, "BUS_FWH, "); + if (bustype & BUS_SPI) + ret = strcat_realloc_copy(ret, "BUS_SPI, "); + if (bustype & BUS_PROG) + ret = strcat_realloc_copy(ret, "BUS_PROG, "); + if (bustype == BUS_NONE) + ret = strcat_realloc_copy(ret, "BUS_NONE, "); + } + /* Kill last comma. */ + ret[strlen(ret) - 2] = '\0'; + ret = realloc(ret, strlen(ret) + 1); + return ret; +} + +static char *decode_test_state(enum test_state ts) +{ + switch (ts) { + case OK: return "OK"; + case NT: return "NT"; + case BAD: return "BAD"; + case DEP: return "DEP"; + case NA: return "NA"; + } + return NULL; +}; + +static char *decode_cmdset(int cmdset) +{ + switch (cmdset) { + case SPI25: return "SPI25"; + case SPI_EDI: return "SPI_EDI"; + } + return NULL; +} + +static char *decode_probefn(enum probe_func probe) +{ + switch (probe) { + case PROBE_JEDEC: return "PROBE_JEDEC"; + case PROBE_JEDEC_29GL: return "PROBE_JEDEC_29GL"; + case PROBE_OPAQUE: return "PROBE_OPAQUE"; + case PROBE_EDI_KB9012: return "EDI_PROBE_KB9012"; + case PROBE_AT82802AB: return "PROBE_82802AB"; + case PROBE_W29EE011: return "PROBE_W29EE011"; + case PROBE_EN29LV640B: return "PROBE_EN29LV640B"; + case PROBE_SPI_AT25F: return "PROBE_SPI_AT25F"; + case PROBE_SPI_AT45DB: return "PROBE_SPI_AT45DB"; + case PROBE_SPI_BIG_SPANSION: return "PROBE_SPI_BIG_SPANSION"; + case PROBE_SPI_RDID: return "PROBE_SPI_RDID"; + case PROBE_SPI_RDID4: return "PROBE_SPI_RDID4"; + case PROBE_SPI_REMS: return "PROBE_SPI_REMS"; + case PROBE_SPI_RES1: return "PROBE_SPI_RES1"; + case PROBE_SPI_RES2: return "PROBE_SPI_RES2"; + case PROBE_SPI_SFDP: return "PROBE_SPI_SFDP"; + case PROBE_SPI_ST95: return "PROBE_SPI_ST95"; + + case NO_PROBE_FUNC: return "NO_PROBE_FUNC"; + }; + return NULL; +} + +static char *decode_block_eraser_type(int block_erase) +{ + switch (block_erase) { + case SPI_BLOCK_ERASE_EMULATION: return "SPI_BLOCK_ERASE_EMULATION"; + case SPI_BLOCK_ERASE_20: return "SPI_BLOCK_ERASE_20"; + case SPI_BLOCK_ERASE_21: return "SPI_BLOCK_ERASE_21"; + case SPI_BLOCK_ERASE_40: return "SPI_BLOCK_ERASE_40"; + case SPI_BLOCK_ERASE_50: return "SPI_BLOCK_ERASE_50"; + case SPI_BLOCK_ERASE_52: return "SPI_BLOCK_ERASE_52"; + case SPI_BLOCK_ERASE_53: return "SPI_BLOCK_ERASE_53"; + case SPI_BLOCK_ERASE_5C: return "SPI_BLOCK_ERASE_5C"; + case SPI_BLOCK_ERASE_60: return "SPI_BLOCK_ERASE_60"; + case SPI_BLOCK_ERASE_62: return "SPI_BLOCK_ERASE_62"; + case SPI_BLOCK_ERASE_81: return "SPI_BLOCK_ERASE_81"; + case SPI_BLOCK_ERASE_C4: return "SPI_BLOCK_ERASE_C4"; + case SPI_BLOCK_ERASE_C7: return "SPI_BLOCK_ERASE_C7"; + case SPI_BLOCK_ERASE_D7: return "SPI_BLOCK_ERASE_D7"; + case SPI_BLOCK_ERASE_D8: return "SPI_BLOCK_ERASE_D8"; + case SPI_BLOCK_ERASE_DB: return "SPI_BLOCK_ERASE_DB"; + case SPI_BLOCK_ERASE_DC: return "SPI_BLOCK_ERASE_DC"; + case S25FL_BLOCK_ERASE: return "S25FL_BLOCK_ERASE"; + case S25FS_BLOCK_ERASE_D8: return "S25FS_BLOCK_ERASE_D8"; + case JEDEC_SECTOR_ERASE: return "JEDEC_SECTOR_ERASE"; + case JEDEC_BLOCK_ERASE: return "JEDEC_BLOCK_ERASE"; + case JEDEC_CHIP_BLOCK_ERASE: return "JEDEC_CHIP_BLOCK_ERASE"; + case OPAQUE_ERASE: return "OPAQUE_ERASE"; + case SPI_ERASE_AT45CS_SECTOR: return "SPI_ERASE_AT45CS_SECTOr"; + case SPI_ERASE_AT45DB_BLOCK: return "SPI_ERASE_AT45DB_BLOCK"; + case SPI_ERASE_AT45DB_CHIP: return "SPI_ERASE_AT45DB_CHIP"; + case SPI_ERASE_AT45DB_PAGE: return "SPI_ERASE_AT45DB_PAGE"; + case SPI_ERASE_AT45DB_SECTOR: return "SPI_ERASE_AT45DB_SECTOR"; + case ERASE_CHIP_28SF040: return "ERASE_CHIP_28SF040"; + case ERASE_SECTOR_28SF040: return "ERASE_SECTOR_28SF040"; + case ERASE_BLOCK_82802AB: return "ERASE_BLOCK_82802AB"; + case ERASE_SECTOR_49LFXXXC: return "ERASE_SECTOR_49LFXXXC"; + case STM50_SECTOR_ERASE: return "ERASE_SECTOR_STM50"; + case EDI_CHIP_BLOCK_ERASE: return "EDI_CHIP_BLOCK_ERASE"; + + case NO_BLOCK_ERASE_FUNC: return "NO_BLOCK_ERASE_FUNC"; + }; + + return NULL; +} + +static void decode_block_erasers(const struct block_eraser *bes) +{ + printf("\t\t\t\t"block_erasers": [\n"); + + for (unsigned i = 0; i < NUM_ERASEFUNCTIONS; i++) { + const struct block_eraser *be = &bes[i]; + + if (i) printf(",\n"); + printf("\t\t\t\t\t{\n"); + printf("\t\t\t\t\t\t"%d": [\n", i); + for (unsigned j = 0; j < NUM_ERASEREGIONS; j++) { + struct eraseblock block = be->eraseblocks[j]; + if (j) printf(",\n"); + printf("\t\t\t\t\t\t\t{\n"); + printf("\t\t\t\t\t\t\t\t"size": %d,\n", block.size); + printf("\t\t\t\t\t\t\t\t"count": %d\n", block.size); + printf("\t\t\t\t\t\t\t}"); + } + printf("\t\t\t\t\t\t],\n"); + + enum block_erase_func block_erase = be->block_erase; + const char *block_erase_type = decode_block_eraser_type(block_erase); + printf("\t\t\t\t\t\t"block_erase": "%s"\n", block_erase_type); + + printf("\t\t\t\t\t}\n"); + } + + printf("\t\t\t\t],\n"); +} + +static char *decode_writefn(int write) +{ + switch (write) { + case WRITE_JEDEC: return "WRITE_JEDEC"; + case WRITE_JEDEC1: return "WRITE_JEDEC_1"; + case WRITE_OPAQUE: return "WRITE_OPAQUE"; + case SPI_CHIP_WRITE1: return "SPI_CHIP_WRITE_1"; + case SPI_CHIP_WRITE256: return "SPI_CHIP_WRITE_256"; + case SPI_WRITE_AAI: return "SPI_AAI_WRITE"; + case SPI_WRITE_AT45DB: return "SPI_WRITE_AT45DB"; + case WRITE_28SF040: return "WRITE_28SF040"; + case WRITE_82802AB: return "WRITE_82802AB"; + case WRITE_EN29LV640B: return "WRITE_EN29LV640B"; + case EDI_CHIP_WRITE: return "EDI_CHIP_WRITE"; + + case NO_WRITE_FUNC: return "NO_WRITE_FUNC"; + }; + + return NULL; +} + +static char *decode_readfn(int read) +{ + switch (read) { + case SPI_CHIP_READ: return "SPI_CHIP_READ"; + case READ_OPAQUE: return "READ_OPAQUE"; + case READ_MEMMAPPED: return "READ_MEMMAPPED"; + case EDI_CHIP_READ: return "EDI_CHIP_READ"; + case SPI_READ_AT45DB: return "SPI_READ_AT45DB"; + case SPI_READ_AT45DB_E8: return "SPI_READ_AT45DB_E8"; + + case NO_READ_FUNC: return "NO_READ_FUNC"; + }; + + return NULL; +} +int main() +{ + printf("{\n\t\t"flashchips": [\n"); + + for (unsigned int i = 0; i < flashchips_size; i++) { + if (i) printf(",\n"); + printf("\t\t\t{\n"); + + printf("\t\t\t\t"vendor": "%s",\n", flashchips[i].vendor); + printf("\t\t\t\t"name": "%s",\n", flashchips[i].name); + + // bustype + char *bustype = flashbuses_to_text_copy(flashchips[i].bustype); + printf("\t\t\t\t"bustype": "%s",\n", bustype); + free(bustype); + + printf("\t\t\t\t"manufacture_id": %d,\n", flashchips[i].manufacture_id); + printf("\t\t\t\t"model_id": %d,\n", flashchips[i].model_id); + printf("\t\t\t\t"total_size": %d,\n", flashchips[i].total_size); + printf("\t\t\t\t"page_size": %d,\n", flashchips[i].page_size); + printf("\t\t\t\t"feature_bits": %d,\n", flashchips[i].feature_bits); + + // tested + char *pts = decode_test_state(flashchips[i].tested.probe); + char *rts = decode_test_state(flashchips[i].tested.read); + char *ets = decode_test_state(flashchips[i].tested.erase); + char *wts = decode_test_state(flashchips[i].tested.write); + char *wpts = decode_test_state(flashchips[i].tested.wp); + printf("\t\t\t\t"test_state": [\n"); + printf("\t\t\t\t\t{ "probe": "%s"},\n", pts); + printf("\t\t\t\t\t{ "read": "%s"},\n", rts); + printf("\t\t\t\t\t{ "erase": "%s"},\n", ets); + printf("\t\t\t\t\t{ "write": "%s"},\n", wts); + printf("\t\t\t\t\t{ "wp": "%s"}\n", wpts); + printf("\t\t\t\t],\n"); + + // spi_cmd_set + char *cmdset = decode_cmdset(flashchips[i].spi_cmd_set); + printf("\t\t\t\t"spi_cmd_set": "%s",\n", cmdset); + + // probe_func probe; + char *probefn = decode_probefn(flashchips[i].probe); + printf("\t\t\t\t"probe": "%s",\n", probefn); + + printf("\t\t\t\t"probe_timing": %d,\n", flashchips[i].probe_timing); + + // block_erasers[NUM_ERASEFUNCTIONS]; + decode_block_erasers(flashchips[i].block_erasers); + + // enum write_func write; + const char *writefn = decode_writefn(flashchips[i].write); + printf("\t\t\t\t"write": "%s",\n", writefn); + + // enum read_func read; + const char *readfn = decode_readfn(flashchips[i].read); + printf("\t\t\t\t"read": "%s",\n", readfn); + + // struct voltage { + // uint16_t min; + // uint16_t max; + // } voltage; + printf("\t\t\t\t"voltage": [\n"); + printf("\t\t\t\t\t{ "min": %d },\n", flashchips[i].voltage.min); + printf("\t\t\t\t\t{ "max": %d }\n", flashchips[i].voltage.max); + printf("\t\t\t\t]\n"); + + // enum write_granularity gran; + + printf("\n\t\t\t}\n"); + } + + printf("\t]\n}"); + return 0; +} diff --git a/util/flashchips_db_jsoniser/meson.build b/util/flashchips_db_jsoniser/meson.build new file mode 100644 index 0000000..a28f047 --- /dev/null +++ b/util/flashchips_db_jsoniser/meson.build @@ -0,0 +1,8 @@ +project('json', 'c') +include_dir = include_directories('../../include') +executable('json', + include_directories : include_dir, + sources : [ + 'main.c', '../../flashchips.c' + ] +)