Arthur Heymans has uploaded this change for review.

View Change

[WIP]Add support to get layout from a binary fmap file

Already seems to mostly work, but needs to be cleaned up.

Change-Id: I0e7fad38ed79a84d41358e1f175c36d255786c12
Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>
---
M Makefile
M cli_classic.c
A fmap.c
A fmap.h
M layout.c
5 files changed, 166 insertions(+), 6 deletions(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/03/23203/1
diff --git a/Makefile b/Makefile
index 3370247..64f1f1e 100644
--- a/Makefile
+++ b/Makefile
@@ -524,7 +524,7 @@
###############################################################################
# Library code.

-LIB_OBJS = libflashrom.o layout.o flashrom.o udelay.o programmer.o helpers.o ich_descriptors.o
+LIB_OBJS = libflashrom.o layout.o flashrom.o udelay.o programmer.o helpers.o ich_descriptors.o fmap.o

###############################################################################
# Frontend related stuff.
diff --git a/cli_classic.c b/cli_classic.c
index 527bb9f..aa0ed02 100644
--- a/cli_classic.c
+++ b/cli_classic.c
@@ -29,6 +29,7 @@
#include <getopt.h>
#include "flash.h"
#include "flashchips.h"
+#include "fmap.h"
#include "programmer.h"
#include "libflashrom.h"

@@ -124,6 +125,7 @@
{"force", 0, NULL, 'f'},
{"layout", 1, NULL, 'l'},
{"ifd", 0, NULL, 0x0100},
+ {"fmap", 1, NULL, 0x0101},
{"image", 1, NULL, 'i'},
{"list-supported", 0, NULL, 'L'},
{"list-supported-wiki", 0, NULL, 'z'},
@@ -136,6 +138,7 @@

char *filename = NULL;
char *layoutfile = NULL;
+ char *fmapfile = NULL;
#ifndef STANDALONE
char *logfile = NULL;
#endif /* !STANDALONE */
@@ -221,19 +224,31 @@
"more than once. Aborting.\n");
cli_classic_abort_usage();
}
- if (ifd) {
- fprintf(stderr, "Error: --layout and --ifd both specified. Aborting.\n");
+ if (ifd || fmapfile) {
+ fprintf(stderr, "Error: --layout and --ifd/--fmap both specified. Aborting.\n");
cli_classic_abort_usage();
}
layoutfile = strdup(optarg);
break;
case 0x0100:
- if (layoutfile) {
- fprintf(stderr, "Error: --layout and --ifd both specified. Aborting.\n");
+ if (layoutfile || fmapfile) {
+ fprintf(stderr, "Error: --ifd and --layout/--fmap both specified. Aborting.\n");
cli_classic_abort_usage();
}
ifd = 1;
break;
+ case 0x0101:
+ if (fmapfile) {
+ fprintf(stderr, "Error: --fmap specified "
+ "more than once. Aborting.\n");
+ cli_classic_abort_usage();
+ }
+ if (ifd || layoutfile) {
+ fprintf(stderr, "Error: --fmap and --ifd/--layout both specified. Aborting.\n");
+ cli_classic_abort_usage();
+ }
+ fmapfile = strdup(optarg);
+ break;
case 'i':
tempstr = strdup(optarg);
if (register_include_arg(tempstr)) {
@@ -388,6 +403,10 @@
ret = 1;
goto out;
}
+ if (fmapfile && read_fmapfile(fmapfile)) {
+ ret = 1;
+ goto out;
+ }
if (!ifd && process_include_args(get_global_layout())) {
ret = 1;
goto out;
@@ -541,7 +560,7 @@
goto out_shutdown;
}

- if (layoutfile) {
+ if (layoutfile || fmapfile) {
layout = get_global_layout();
} else if (ifd && (flashrom_layout_read_from_ifd(&layout, fill_flash, NULL, 0) ||
process_include_args(layout))) {
diff --git a/fmap.c b/fmap.c
new file mode 100644
index 0000000..c63a1fa
--- /dev/null
+++ b/fmap.c
@@ -0,0 +1,74 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "fmap.h"
+#include "flash.h"
+
+int is_valid_fmap(const struct fmap *fmap)
+{
+ if (memcmp(fmap, FMAP_SIGNATURE, strlen(FMAP_SIGNATURE)) != 0)
+ return 0;
+ /* strings containing the magic tend to fail here */
+ if (fmap->ver_major != FMAP_VER_MAJOR)
+ return 0;
+ /* a basic consistency check: flash should be larger than fmap */
+ if (fmap->size <
+ sizeof(*fmap) + fmap->nareas * sizeof(struct fmap_area))
+ return 0;
+
+ /* fmap-alikes along binary data tend to fail on having a valid,
+ * null-terminated string in the name field.*/
+ int i = 0;
+ while (i < FMAP_STRLEN) {
+ if (fmap->name[i] == 0)
+ break;
+ if (!isgraph(fmap->name[i]))
+ return 0;
+ if (i == FMAP_STRLEN - 1) {
+ /* name is specified to be null terminated single-word string
+ * without spaces. We did not break in the 0 test, we know it
+ * is a printable spaceless string but we're seeing FMAP_STRLEN
+ * symbols, which is one too many.
+ */
+ return 0;
+ }
+ i++;
+ }
+ return 1;
+
+}
+
+static uint64_t to_le(const uint8_t *const dump, const size_t len)
+{
+ int i;
+ uint64_t var = 0;
+ for (i = 0; i < len; i++) {
+ var |= ((uint64_t)dump[i] & 0xff) << (8 * i);
+ }
+ return var;
+}
+
+#define READ_LE_DUMP_INCEASE_IDX(x, dump, i, le) x = to_le(dump, sizeof(x)); \
+ i += sizeof(x); if (i > len) return 1;
+#define READ_MEMCPY_DUMP_INCREASE_IDX(x, dump, i, len) memcpy(x, dump, sizeof(x)); \
+ i += sizeof(x); if (i > len) return 1;
+
+int read_fmap_from_dump(const uint8_t *const dump, const size_t len, struct fmap *fmap)
+{
+ int i = 0, j;
+ READ_MEMCPY_DUMP_INCREASE_IDX(fmap->signature, &dump[i], i, len);
+ fmap->ver_major = dump[i++];
+ fmap->ver_minor = dump[i++];
+ READ_LE_DUMP_INCEASE_IDX(fmap->base, &dump[i], i, len);
+ READ_LE_DUMP_INCEASE_IDX(fmap->size, &dump[i], i, len);
+ READ_MEMCPY_DUMP_INCREASE_IDX(fmap->name, &dump[i], i, len);
+ READ_LE_DUMP_INCEASE_IDX(fmap->nareas, &dump[i], i, len);
+ for (j = 0; j < fmap->nareas; j++) {
+ READ_LE_DUMP_INCEASE_IDX(fmap->areas[j].offset, &dump[i], i, len);
+ READ_LE_DUMP_INCEASE_IDX(fmap->areas[j].size, &dump[i], i, len);
+ READ_MEMCPY_DUMP_INCREASE_IDX(fmap->areas[j].name, &dump[i], i, len);
+ READ_LE_DUMP_INCEASE_IDX(fmap->areas[j].flags, &dump[i], i, len);
+ }
+ return 0;
+}
diff --git a/fmap.h b/fmap.h
new file mode 100644
index 0000000..513c4f9
--- /dev/null
+++ b/fmap.h
@@ -0,0 +1,32 @@
+#include <inttypes.h>
+//#include <compiler.h>
+//#include <valstr.h>
+
+
+#define FMAP_SIGNATURE "__FMAP__"
+#define FMAP_VER_MAJOR 1 /* this header's FMAP minor version */
+#define FMAP_VER_MINOR 1 /* this header's FMAP minor version */
+#define FMAP_STRLEN 32 /* maximum length for strings, */
+
+struct fmap_area {
+ uint32_t offset; /* offset relative to base */
+ uint32_t size; /* size in bytes */
+ uint8_t name[FMAP_STRLEN]; /* descriptive name */
+ uint16_t flags; /* flags for this area */
+} __attribute__((packed));
+
+struct fmap {
+ uint8_t signature[8]; /* "__FMAP__" (0x5F5F464D41505F5F) */
+ uint8_t ver_major; /* major version */
+ uint8_t ver_minor; /* minor version */
+ uint64_t base; /* address of the firmware binary */
+ uint32_t size; /* size of firmware binary in bytes */
+ uint8_t name[FMAP_STRLEN]; /* name of this firmware binary */
+ uint16_t nareas; /* number of areas described by
+ fmap_areas[] below */
+ struct fmap_area areas[];
+} __attribute__((packed));
+
+int is_valid_fmap(const struct fmap *fmap);
+int read_fmapfile(const char *filename);
+int read_fmap_from_dump(const uint8_t *const dump, const size_t len, struct fmap *fmap);
diff --git a/layout.c b/layout.c
index a990adc..53c2bb4 100644
--- a/layout.c
+++ b/layout.c
@@ -23,7 +23,9 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <sys/stat.h>
#include "flash.h"
+#include "fmap.h"
#include "programmer.h"
#include "layout.h"

@@ -103,6 +105,39 @@

return 0;
}
+
+int read_fmapfile(const char *filename)
+{
+ int i;
+ FILE *fmapfile;
+ struct fmap fmap;
+ uint8_t buffer[5000];
+ struct stat st;
+
+ stat(filename, &st);
+ size_t size = st.st_size;
+
+ fmapfile = fopen(filename, "r");
+
+ if (!fmapfile) {
+ msg_gerr("ERROR: Could not open layout file (%s).\n", filename);
+ return -1;
+ }
+
+ fread(buffer, size, 1, fmapfile);
+ if (read_fmap_from_dump(buffer, size, &fmap))
+ return -1;
+
+ layout.num_entries = fmap.nareas;
+ for (i = 0; i < fmap.nareas; i++) {
+ layout.entries[i].start = fmap.areas[i].offset;
+ layout.entries[i].end = fmap.areas[i].offset + fmap.areas[i].size - 1;
+ layout.entries[i].included = 0;
+ layout.entries[i].file = NULL;
+ memcpy(layout.entries[i].name, fmap.areas[i].name, sizeof(layout.entries[i].name));
+ }
+ return 0;
+}
#endif

/* returns the index of the entry (or a negative value if it is not found) */

To view, visit change 23203. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I0e7fad38ed79a84d41358e1f175c36d255786c12
Gerrit-Change-Number: 23203
Gerrit-PatchSet: 1
Gerrit-Owner: Arthur Heymans <arthur@aheymans.xyz>