diff options
author | Chris Douglass <cdouglass.orion@gmail.com> | 2014-02-26 13:30:13 -0500 |
---|---|---|
committer | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2014-02-28 21:10:46 +0100 |
commit | 03ce014cfc35a1c51eadec46d30169b2c641e011 (patch) | |
tree | 53ba1d2662c051d527d58ed4b944d06bf9f43272 | |
parent | 970dd9c46672bd194189296977ac8bbf098c139e (diff) | |
download | coreboot-03ce014cfc35a1c51eadec46d30169b2c641e011.tar.xz |
util/ifdtool: add option to dump flashrom layout
Dump the Intel Flash Descriptor map in the format expected
by flashrom's "layout" option.
Example usage:
Given a 4MB flash image vpx7654.bin that was generated by Intel's
FITC tool for a 6-Series chipset...
./ifdtool --layout l.txt vpx7654.bin
cat l.txt
00000000:00000fff fd
00180000:003fffff bios
00001000:0017ffff me
00fff000:00000fff gbe
00fff000:00000fff pd
Change-Id: Ib740178ed6935b5f6e1dba1be674303f9f980429
Signed-off-by: Christopher Douglass <cdouglass.orion@gmail.com>
Reviewed-on: http://review.coreboot.org/5306
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
-rw-r--r-- | util/ifdtool/ifdtool.c | 96 | ||||
-rw-r--r-- | util/ifdtool/ifdtool.h | 7 |
2 files changed, 90 insertions, 13 deletions
diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c index 9eadc0a33c..b5a0ac2f65 100644 --- a/util/ifdtool/ifdtool.c +++ b/util/ifdtool/ifdtool.c @@ -27,6 +27,14 @@ #include <sys/stat.h> #include "ifdtool.h" +static const struct region_name region_names[5] = { + { "Flash Descriptor", "fd" }, + { "BIOS", "bios" }, + { "Intel ME", "me" }, + { "GbE", "gbe" }, + { "Platform Data", "pd" } +}; + static fdbar_t *find_fd(char *image, int size) { int i, found = 0; @@ -81,26 +89,30 @@ static region_t get_region(frba_t *frba, int region_type) } region.size = region.limit - region.base + 1; + if (region.size < 0) + region.size = 0; return region; } static const char *region_name(int region_type) { - static const char *regions[5] = { - "Flash Descriptor", - "BIOS", - "Intel ME", - "GbE", - "Platform Data" - }; + if (region_type < 0 || region_type > 4) { + fprintf(stderr, "Invalid region type.\n"); + exit (EXIT_FAILURE); + } + + return region_names[region_type].pretty; +} +static const char *region_name_short(int region_type) +{ if (region_type < 0 || region_type > 4) { fprintf(stderr, "Invalid region type.\n"); exit (EXIT_FAILURE); } - return regions[region_type]; + return region_names[region_type].terse; } static const char *region_filename(int region_type) @@ -129,6 +141,13 @@ static void dump_region(int num, frba_t *frba) region.size < 1 ? "(unused)" : ""); } +static void dump_region_layout(char *buf, size_t bufsize, int num, frba_t *frba) +{ + region_t region = get_region(frba, num); + snprintf(buf, bufsize, "%08x:%08x %s\n", + region.base, region.limit, region_name_short(num)); +} + static void dump_frba(frba_t * frba) { printf("Found Region Section\n"); @@ -144,6 +163,30 @@ static void dump_frba(frba_t * frba) dump_region(4, frba); } +static void dump_frba_layout(frba_t * frba, char *layout_fname) +{ + char buf[LAYOUT_LINELEN]; + size_t bufsize = LAYOUT_LINELEN; + int i; + + int layout_fd = open(layout_fname, O_WRONLY | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + if (layout_fd == -1) { + perror("Could not open file"); + exit(EXIT_FAILURE); + } + + for (i = 0; i <= 4; i++) { + dump_region_layout(buf, bufsize, i, frba); + if (write(layout_fd, buf, strlen(buf)) < 0) { + perror("Could not write to file"); + exit(EXIT_FAILURE); + } + } + close(layout_fd); + printf("Wrote layout to %s\n", layout_fname); +} + static void decode_spi_frequency(unsigned int freq) { switch (freq) { @@ -422,6 +465,17 @@ static void dump_fd(char *image, int size) dump_fmsba((fmsba_t *) (image + (((fdb->flmap2) & 0xff) << 4))); } +static void dump_layout(char *image, int size, char *layout_fname) +{ + fdbar_t *fdb = find_fd(image, size); + if (!fdb) + exit(EXIT_FAILURE); + + dump_frba_layout((frba_t *) + (image + (((fdb->flmap0 >> 16) & 0xff) << 4)), + layout_fname); +} + static void write_regions(char *image, int size) { int i; @@ -608,6 +662,7 @@ static void print_usage(const char *name) printf("usage: %s [-vhdix?] <filename>\n", name); printf("\n" " -d | --dump: dump intel firmware descriptor\n" + " -f | --layout <filename> dump regions into a flashrom layout file\n" " -x | --extract: extract intel fd modules\n" " -i | --inject <region>:<module> inject file <module> into region <region>\n" " -s | --spifreq <20|33|50> set the SPI frequency\n" @@ -626,12 +681,14 @@ int main(int argc, char *argv[]) int opt, option_index = 0; int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0; int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0; - char *region_type_string = NULL, *region_fname = NULL; + int mode_layout = 0; + char *region_type_string = NULL, *region_fname = NULL, *layout_fname = NULL; int region_type = -1, inputfreq = 0; enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ; static struct option long_options[] = { {"dump", 0, NULL, 'd'}, + {"layout", 1, NULL, 'f'}, {"extract", 0, NULL, 'x'}, {"inject", 1, NULL, 'i'}, {"spifreq", 1, NULL, 's'}, @@ -643,12 +700,21 @@ int main(int argc, char *argv[]) {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "dxi:s:eluvh?", + while ((opt = getopt_long(argc, argv, "df:xi:s:eluvh?", long_options, &option_index)) != EOF) { switch (opt) { case 'd': mode_dump = 1; break; + case 'f': + mode_layout = 1; + layout_fname = strdup(optarg); + if (!layout_fname) { + fprintf(stderr, "No layout file specified\n"); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + break; case 'x': mode_extract = 1; break; @@ -733,7 +799,7 @@ int main(int argc, char *argv[]) } } - if ((mode_dump + mode_extract + mode_inject + + if ((mode_dump + mode_layout + mode_extract + mode_inject + (mode_spifreq | mode_em100 | mode_unlocked | mode_locked)) > 1) { fprintf(stderr, "You may not specify more than one mode.\n\n"); @@ -741,8 +807,9 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if ((mode_dump + mode_extract + mode_inject + mode_spifreq + - mode_em100 + mode_locked + mode_unlocked) == 0) { + if ((mode_dump + mode_layout + mode_extract + mode_inject + + mode_spifreq + mode_em100 + mode_locked + + mode_unlocked) == 0) { fprintf(stderr, "You need to specify a mode.\n\n"); print_usage(argv[0]); exit(EXIT_FAILURE); @@ -785,6 +852,9 @@ int main(int argc, char *argv[]) if (mode_dump) dump_fd(image, size); + if (mode_layout) + dump_layout(image, size, layout_fname); + if (mode_extract) write_regions(image, size); diff --git a/util/ifdtool/ifdtool.h b/util/ifdtool/ifdtool.h index 7537f1d009..ed8f440bd1 100644 --- a/util/ifdtool/ifdtool.h +++ b/util/ifdtool/ifdtool.h @@ -20,6 +20,8 @@ #include <stdint.h> #define IFDTOOL_VERSION "1.1" +#define LAYOUT_LINELEN 80 + enum spi_frequency { SPI_FREQUENCY_20MHZ = 0, SPI_FREQUENCY_33MHZ = 1, @@ -109,3 +111,8 @@ typedef struct { typedef struct { int base, limit, size; } region_t; + +struct region_name { + char *pretty; + char *terse; +}; |