diff options
author | Bill Richardson <wfrichar@chromium.org> | 2012-07-26 13:10:59 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-07-26 16:25:34 -0700 |
commit | 9429f8807a0fed0fe6c1d2276217480f043cb4c5 (patch) | |
tree | f7da509e0acd222cc6bdfda4d569a6474916fbc9 /utility | |
parent | 09d0c2e487653ada95768abe5cb9bfbf8dbfe6bb (diff) | |
download | vboot-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>
Diffstat (limited to 'utility')
-rw-r--r-- | utility/dump_fmap.c | 152 |
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)) { |