summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2012-07-26 13:10:59 -0700
committerGerrit <chrome-bot@google.com>2012-07-26 16:25:34 -0700
commit9429f8807a0fed0fe6c1d2276217480f043cb4c5 (patch)
treef7da509e0acd222cc6bdfda4d569a6474916fbc9
parent09d0c2e487653ada95768abe5cb9bfbf8dbfe6bb (diff)
downloadvboot-9429f8807a0fed0fe6c1d2276217480f043cb4c5.tar.gz
Add human-readable output option to dump_fmap
The '-h' option will display the FMAP in a heirarchical nested format. BUG=none TEST=manual $ dump_fmap -h stumpy_bios.bin SI_BIOS 00180000 00800000 680000 RO_SECTION 0670000 0800000 190000 BOOT_STUB 700000 800000 100000 GBB 680000 700000 80000 RO_PADDING 670840 680000 f7c0 RO_FRID 670800 670840 40 FMAP 670000 670800 800 RO_UNUSED_2 0590000 0670000 e0000 RO_VPD 0570000 0590000 20000 RO_UNUSED_1 0400000 0570000 170000 RW_SECTION_B 0300000 0400000 100000 RW_FWID_B 3fffc0 400000 40 FW_MAIN_B 310000 3fffc0 effc0 VBLOCK_B 300000 310000 10000 RW_SECTION_A 0200000 0300000 100000 RW_FWID_A 2fffc0 300000 40 FW_MAIN_A 210000 2fffc0 effc0 VBLOCK_A 200000 210000 10000 RW_SHARED 01e8000 0200000 18000 DEV_CFG 1fc000 200000 4000 RW_MRC_CACHE 1ec000 1fc000 10000 RW_ENVIRONMENT 1e8000 1ec000 4000 RW_UNUSED 0181000 01e8000 67000 RW_VPD 0180000 0181000 1000 SI_ALL 00000000 00180000 180000 SI_ME 0001000 0180000 17f000 SI_DESC 0000000 0001000 1000 Change-Id: I41672b62528dac32663bc300ff013e8003d3efa8 Reviewed-on: https://gerrit.chromium.org/gerrit/28513 Commit-Ready: Bill Richardson <wfrichar@chromium.org> Tested-by: Bill Richardson <wfrichar@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--utility/dump_fmap.c152
1 files changed, 124 insertions, 28 deletions
diff --git a/utility/dump_fmap.c b/utility/dump_fmap.c
index d4a3eb1c..2f2ff93c 100644
--- a/utility/dump_fmap.c
+++ b/utility/dump_fmap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
@@ -17,21 +17,22 @@
#include "fmap.h"
-enum { FMT_NORMAL, FMT_PRETTY, FMT_FLASHROM };
+enum { FMT_NORMAL, FMT_PRETTY, FMT_FLASHROM, FMT_HUMAN };
/* global variables */
static int opt_extract = 0;
static int opt_format = FMT_NORMAL;
-static char* progname;
-static void* base_of_rom;
+static char *progname;
+static void *base_of_rom;
/* Return 0 if successful */
-static int dump_fmap(const void* ptr, int argc, char *argv[]) {
+static int dump_fmap(const void *ptr, int argc, char *argv[])
+{
int i, retval = 0;
char buf[80]; // DWR: magic number
- const FmapHeader* fmh = (const FmapHeader*) ptr;
- const FmapAreaHeader* ah = (const FmapAreaHeader*) (ptr + sizeof(FmapHeader));
+ const FmapHeader *fmh = (const FmapHeader*)ptr;
+ const FmapAreaHeader *ah = (const FmapAreaHeader*)(ptr + sizeof(FmapHeader));
if (FMT_NORMAL == opt_format) {
snprintf(buf, FMAP_SIGNATURE_SIZE+1, "%s", fmh->fmap_signature);
@@ -45,30 +46,29 @@ static int dump_fmap(const void* ptr, int argc, char *argv[]) {
printf("fmap_nareas: %d\n", fmh->fmap_nareas);
}
- for (i=0; i<fmh->fmap_nareas; i++, ah++) {
+ for (i = 0; i < fmh->fmap_nareas; i++, ah++) {
snprintf(buf, FMAP_NAMELEN+1, "%s", ah->area_name);
if (argc) {
int j, found=0;
- for (j=0; j<argc; j++)
+ for (j = 0; j < argc; j++)
if (!strcmp(argv[j], buf)) {
- found = 1;
- break;
- }
+ found = 1;
+ break;
+ }
if (!found) {
continue;
}
}
- switch(opt_format)
- {
+ switch (opt_format) {
case FMT_PRETTY:
printf("%s %d %d\n", buf, ah->area_offset, ah->area_size);
break;
case FMT_FLASHROM:
if (ah->area_size)
printf("0x%08x:0x%08x %s\n", ah->area_offset,
- ah->area_offset + ah->area_size - 1, buf);
+ ah->area_offset + ah->area_size - 1, buf);
break;
default:
printf("area: %d\n", i+1);
@@ -78,11 +78,11 @@ static int dump_fmap(const void* ptr, int argc, char *argv[]) {
}
if (opt_extract) {
- char* s;
- for (s=buf;* s; s++)
+ char *s;
+ for (s = buf; *s; s++)
if (*s == ' ')
*s = '_';
- FILE* fp = fopen(buf,"wb");
+ FILE *fp = fopen(buf,"wb");
if (!fp) {
fprintf(stderr, "%s: can't open %s: %s\n",
progname, buf, strerror(errno));
@@ -106,12 +106,97 @@ static int dump_fmap(const void* ptr, int argc, char *argv[]) {
}
-int main(int argc, char* argv[]) {
+/* Sort by start, then size, then name */
+static int by_start(FmapAreaHeader *a, FmapAreaHeader *b)
+{
+ if (a->area_offset == b->area_offset) {
+
+ if (a->area_size == b->area_size )
+ return strncmp(a->area_name, b->area_name, FMAP_NAMELEN) < 0;
+
+ return a->area_size < b->area_size;
+ }
+
+ return a->area_offset > b->area_offset;
+}
+
+
+
+static void isort(FmapAreaHeader *ary, int num,
+ int (*lessthan)(FmapAreaHeader *a, FmapAreaHeader *b))
+{
+ int i, j;
+ FmapAreaHeader tmp;
+
+ for (i = 1; i < num; i++) {
+ tmp = ary[i];
+ for (j = i; j && lessthan(ary+j-1, &tmp); j--)
+ ary[j] = ary[j-1];
+ ary[j] = tmp;
+ }
+}
+
+/* Return 0 if successful */
+static int human_fmap(void *ptr)
+{
+ int i, j;
+ uint32_t end_i;
+ FmapHeader *fmh = (FmapHeader *)ptr;
+ FmapAreaHeader *ah = (FmapAreaHeader *)(fmh + 1);
+ FmapAreaHeader tmp;
+
+ /* We're using mmap() with MAP_PRIVATE, so we can freely fiddle with the fmap
+ * data. We'll sort the areas, reusing the flags field for indentation. */
+ for (i = 0; i < fmh->fmap_nareas; i++)
+ ah[i].area_flags = 0;
+
+ /* First, sort by start and size. */
+ isort(ah, fmh->fmap_nareas, by_start);
+
+ /* Now figure out indentation. */
+ for (i = 0; i < fmh->fmap_nareas - 1; i++) {
+ end_i = ah[i].area_offset + ah[i].area_size;
+ for (j = i+1; (j < fmh->fmap_nareas &&
+ ah[j].area_offset + ah[j].area_size <= end_i &&
+ /* Don't double-indent identical blocks. */
+ !(ah[i].area_offset == ah[j].area_offset &&
+ ah[i].area_size == ah[j].area_size)); j++)
+ ah[j].area_flags++;
+ }
+
+ /* Rearrange nested blocks */
+ for (i = 0; i < fmh->fmap_nareas - 1; i++) {
+ tmp = ah[i];
+ for (j = i+1; (j < fmh->fmap_nareas &&
+ tmp.area_flags < ah[j].area_flags); j++)
+ ah[j-1] = ah[j];
+ ah[j-1] = tmp;
+ }
+
+ /* Print the results. */
+ printf("%-20s %8s %8s %6s\n", "# name", "start", "end", "size");
+ for (i = fmh->fmap_nareas - 1; i>= 0; i--) {
+ for (j = 0; j < ah[i].area_flags; j++)
+ printf(" ");
+ printf("%-*s", 20 - ah[i].area_flags * 2, ah[i].area_name);
+ printf(" %*s%0*x", ah[i].area_flags, "",
+ 8 - ah[i].area_flags, ah[i].area_offset);
+ printf(" %*s%0*x", ah[i].area_flags, "",
+ 8 - ah[i].area_flags, ah[i].area_offset + ah[i].area_size);
+ printf(" %6x\n", ah[i].area_size);
+ }
+
+ return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
int c;
int errorcnt = 0;
struct stat sb;
int fd;
- const char* fmap;
+ const char *fmap;
int retval = 1;
progname = strrchr(argv[0], '/');
@@ -120,10 +205,9 @@ int main(int argc, char* argv[]) {
else
progname = argv[0];
- opterr = 0; /* quiet, you */
- while ((c=getopt(argc, argv, ":xpf")) != -1) {
- switch (c)
- {
+ opterr = 0; /* quiet, you */
+ while ((c = getopt(argc, argv, ":xpfh")) != -1) {
+ switch (c) {
case 'x':
opt_extract = 1;
break;
@@ -133,6 +217,9 @@ int main(int argc, char* argv[]) {
case 'f':
opt_format = FMT_FLASHROM;
break;
+ case 'h':
+ opt_format = FMT_HUMAN;
+ break;
case '?':
fprintf(stderr, "%s: unrecognized switch: -%c\n",
progname, optopt);
@@ -151,12 +238,14 @@ int main(int argc, char* argv[]) {
if (errorcnt || optind >= argc) {
fprintf(stderr,
- "\nUsage: %s [-x] [-p|-f] FLASHIMAGE [NAME...]\n\n"
+ "\nUsage: %s [-x] [-p|-f|-h] FLASHIMAGE [NAME...]\n\n"
"Display (and extract with -x) the FMAP components from a BIOS image.\n"
"The -p option makes the output easier to parse by scripts.\n"
"The -f option emits the FMAP in the format used by flashrom.\n"
"\n"
"Specify one or more NAMEs to only print sections that exactly match.\n"
+ "\n"
+ "The -h option shows the whole FMAP in human-readable form.\n"
"\n",
progname);
return 1;
@@ -181,7 +270,7 @@ int main(int argc, char* argv[]) {
if (FMT_NORMAL == opt_format)
printf("opened %s\n", argv[optind]);
- base_of_rom = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ base_of_rom = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
if (base_of_rom == (char*)-1) {
fprintf(stderr, "%s: can't mmap %s: %s\n",
progname,
@@ -194,9 +283,16 @@ int main(int argc, char* argv[]) {
fmap = FmapFind((char*) base_of_rom, sb.st_size);
if (fmap) {
- if (FMT_NORMAL == opt_format)
+ switch (opt_format) {
+ case FMT_HUMAN:
+ retval = human_fmap((void *)fmap);
+ break;
+ case FMT_NORMAL:
printf("hit at 0x%08x\n", (uint32_t) (fmap - (char*) base_of_rom));
- retval = dump_fmap(fmap, argc-optind-1, argv+optind+1);
+ /* fallthrough */
+ default:
+ retval = dump_fmap(fmap, argc-optind-1, argv+optind+1);
+ }
}
if (0 != munmap(base_of_rom, sb.st_size)) {