Edward O'Callaghan has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/69610 )
Change subject: poc json chip entry parser ......................................................................
poc json chip entry parser
Change-Id: If3e591468a60cb8846860e8b4ac1978b33f11aec Signed-off-by: Edward O'Callaghan quasisec@google.com --- A subprojects/chip.txt A subprojects/json_chip.c 2 files changed, 297 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/10/69610/1
diff --git a/subprojects/chip.txt b/subprojects/chip.txt new file mode 100644 index 0000000..7b06889 --- /dev/null +++ b/subprojects/chip.txt @@ -0,0 +1,45 @@ + { + "vendor" : "Winbond", + "name" : "W25Q128.V", + "bustype" : BUS_SPI, + "manufacture_id": WINBOND_NEX_ID, + "model_id" : WINBOND_NEX_W25Q128_V, + "total_size" : 16384, + "page_size" : 256, + "feature_bits" : [FEATURE_WRSR_WREN, FEATURE_OTP, FEATURE_WRSR_EXT2, FEATURE_WRSR2, FEATURE_WRSR3], + "tested" : TEST_OK_PREW, + "probe" : PROBE_SPI_RDID, + "probe_timing" : TIMING_ZERO, + "block_erasers" : + [ + { + "eraseblocks" : [4 * 1024, 4096], + "block_erase" : SPI_BLOCK_ERASE_20, + }, { + "eraseblocks" : [32 * 1024, 512], + "block_erase" : SPI_BLOCK_ERASE_52, + }, { + "eraseblocks" : [64 * 1024, 256], + "block_erase" : SPI_BLOCK_ERASE_D8, + }, { + "eraseblocks" : [16 * 1024 * 1024, 1], + "block_erase" : SPI_BLOCK_ERASE_60, + }, { + "eraseblocks" : [16 * 1024 * 1024, 1], + "block_erase" : SPI_BLOCK_ERASE_C7, + } + ], + "write" : SPI_CHIP_WRITE256, + "read" : SPI_CHIP_READ, + "voltage" : [2700, 3600], + "reg_bits" : + { + "srp" : [STATUS1, 7, RW], + "srl" : [STATUS2, 0, RW], + "tb" : [STATUS1, 5, RW], + "sec" : [STATUS1, 6, RW], + "cmp" : [STATUS2, 6, RW], + "wps" : [STATUS3, 2, RW], + }, + "decode_range" : DECODE_RANGE_SPI25, + }, diff --git a/subprojects/json_chip.c b/subprojects/json_chip.c new file mode 100644 index 0000000..ad16fc1 --- /dev/null +++ b/subprojects/json_chip.c @@ -0,0 +1,242 @@ +#include "jsmn/jsmn.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* JSONify flashchips db worked example. */ + +static int jsoneq (const char *json, jsmntok_t *tok, const char *s) { + if (tok->type == JSMN_STRING && (int)strlen (s) == tok->end - tok->start && + strncmp (json + tok->start, s, tok->end - tok->start) == 0) { + return 0; + } + return -1; +} + +int main () { + int i; + int r; + jsmn_parser p; + jsmntok_t t[128] = {0}; /* no. of expected tokens */ + char *data = NULL; + + FILE *fp = fopen ("chip.txt", "r"); + if (fp) { + if (fseek (fp, 0L, SEEK_END) == 0) { + long bufsize = ftell (fp); + if (bufsize == -1) { + exit (1); + } + + data = malloc (sizeof (char) * (bufsize + 1)); + + if (fseek (fp, 0L, SEEK_SET) != 0) { + free (data); + exit (1); + } + + size_t newLen = fread (data, sizeof (char), bufsize, fp); + if (ferror (fp) != 0) { + fputs ("Error reading file", stderr); + } else { + data[newLen++] = '\0'; + } + } + fclose (fp); + } + + jsmn_init (&p); + r = jsmn_parse (&p, data, strlen (data), t, sizeof (t) / sizeof (t[0])); + if (r < 0) { + printf ("Failed to parse JSON: %d\n", r); + return 1; + } + + /* Assume the top-level element is an object */ + if (r < 1 || t[0].type != JSMN_OBJECT) { + printf ("Object expected\n"); + return 1; + } + + /* Loop over all keys of the root object */ + for (i = 1; i < r; i++) { + if (jsoneq (data, &t[i], "vendor") == 0) { + /* We may use strndup() to fetch string value */ + printf ("- vendor: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "name") == 0) { + /* We may additionally check if the value is either "true" or "false" */ + printf ("- name: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "bustype") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- bustype: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "manufacture_id") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- manufacture_id: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "model_id") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- model_id: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "total_size") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- total_size: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "page_size") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- page_size: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "feature_bits") == 0) { + int j; + printf ("- feature_bits:\n"); + if (t[i + 1].type != JSMN_ARRAY) { + continue; /* We expect groups to be an array of strings */ + } + for (j = 0; j < t[i + 1].size; j++) { + jsmntok_t *g = &t[i + j + 2]; + printf (" * %.*s\n", g->end - g->start, data + g->start); + } + i += t[i + 1].size + 1; + } else if (jsoneq (data, &t[i], "tested") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- tested: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "probe") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- probe: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "probe_timing") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- probe_timing: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + // .block_erasers = + // { + // { + // .eraseblocks = { {4 * 1024, 4096} }, + // .block_erase = SPI_BLOCK_ERASE_20, + // }, { + // .eraseblocks = { {32 * 1024, 512} }, + // .block_erase = SPI_BLOCK_ERASE_52, + // }, { + // .eraseblocks = { {64 * 1024, 256} }, + // .block_erase = SPI_BLOCK_ERASE_D8, + // }, { + // .eraseblocks = { {16 * 1024 * 1024, 1} + //}, .block_erase = SPI_BLOCK_ERASE_60, + // }, { + // .eraseblocks = { {16 * 1024 * 1024, 1} + //}, .block_erase = SPI_BLOCK_ERASE_C7, + // } + // }, + // } else if (jsoneq(data, &t[i], "block_erasers") == 0) { + // int j, k; + // printf("- block_erasers:\n"); + // if (t[i + 1].type != JSMN_OBJECT) { + // continue; /* We expect groups to be an array of strings */ + // } + // for (j = 0; j < t[i + 1].size; j++) { + // jsmntok_t *g = &t[i + j + 2]; + // if (g[j + 1].type != JSMN_OBJECT) { + // continue; + // } + // for (k = 0; k < g[j + 1].size; k++) { + // jsmntok_t *h = &g[i + j + k + 2]; + // printf(" * %.*s\n", h->end - h->start, data + + // h->start); + // } + // } + // i += t[i + 1].size + 1; + } else if (jsoneq (data, &t[i], "write") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- write: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "read") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- read: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else if (jsoneq (data, &t[i], "voltage") == 0) { + int j; + printf ("- voltage:\n"); + if (t[i + 1].type != JSMN_ARRAY) { + continue; /* We expect groups to be an array of strings */ + } + for (j = 0; j < t[i + 1].size; j++) { + jsmntok_t *g = &t[i + j + 2]; + printf (" * %.*s\n", g->end - g->start, data + g->start); + } + i += t[i + 1].size + 1; + } else if (jsoneq (data, &t[i], "reg_bits") == 0) { + int j, k; + printf ("- reg_bits:\n"); + if (t[i + 1].type != JSMN_OBJECT) { + continue; /* We expect reg_bits to be an object */ + } + // printf("- ZZZ: %.*s\n", t[i + 1].end - t[i + 1].start, + // data + t[i + 1].start); + // for (j = 0; j < t[i + 1].size; j++) { + j = 0; // XXX + jsmntok_t *g = &t[i + j + 2]; + // if (g[j + 1].type != JSMN_ARRAY) { // if the val at key g[j + 1] + //is not an array continue; continue; + // } + for (k = 0; k < g[j + 1].size; k++) { + printf ("X\n"); + jsmntok_t *h = &g[k + 1]; // value of g[k] key. + if (h->type != + JSMN_ARRAY) { // if the val at key g[k] is not an array continue; + printf ("Y\n"); + continue; + } + if (jsoneq (data, &g[k], "srp") == 0) { + printf (" srp: %.*s\n", h->end - h->start, data + h->start); + } else if (jsoneq (data, &g[k], "srl") == 0) { + printf (" srl: %.*s\n", h->end - h->start, data + h->start); + } else if (jsoneq (data, &g[k], "tb") == 0) { + printf (" tb: %.*s\n", h->end - h->start, data + h->start); + } else if (jsoneq (data, &g[k], "sec") == 0) { + printf (" sec: %.*s\n", h->end - h->start, data + h->start); + } else if (jsoneq (data, &g[k], "cmp") == 0) { + printf (" cmp: %.*s\n", h->end - h->start, data + h->start); + } else if (jsoneq (data, &g[k], "wps") == 0) { + printf (" wps: %.*s\n", h->end - h->start, data + h->start); + } else { + printf (" <UNKNOWN>: %.*s\n", g[k].end - g[k].start, + data + g[k].start); + } + // TODO(handle bp) object. + // "bp" : + // { + // [STATUS1, 2, RW], + // [STATUS1, 3, RW], + // [STATUS1, 4, RW] + // }, + } + //} + i += t[i + 1].size + 1; + } else if (jsoneq (data, &t[i], "decode_range") == 0) { + /* We may want to do strtol() here to get numeric value */ + printf ("- decode_range: %.*s\n", t[i + 1].end - t[i + 1].start, + data + t[i + 1].start); + i++; + } else { + printf ("Unexpected key: %.*s\n", t[i].end - t[i].start, + data + t[i].start); + } + } + + return EXIT_SUCCESS; +}