Edward O'Callaghan has uploaded this change for review.
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'
+ ]
+)
To view, visit change 74065. To unsubscribe, or for help writing mail filters, visit settings.