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>
This commit is contained in:
parent
970dd9c466
commit
03ce014cfc
|
@ -27,6 +27,14 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "ifdtool.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)
|
static fdbar_t *find_fd(char *image, int size)
|
||||||
{
|
{
|
||||||
int i, found = 0;
|
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;
|
region.size = region.limit - region.base + 1;
|
||||||
|
if (region.size < 0)
|
||||||
|
region.size = 0;
|
||||||
|
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *region_name(int region_type)
|
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) {
|
if (region_type < 0 || region_type > 4) {
|
||||||
fprintf(stderr, "Invalid region type.\n");
|
fprintf(stderr, "Invalid region type.\n");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return regions[region_type];
|
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 region_names[region_type].terse;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *region_filename(int region_type)
|
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)" : "");
|
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)
|
static void dump_frba(frba_t * frba)
|
||||||
{
|
{
|
||||||
printf("Found Region Section\n");
|
printf("Found Region Section\n");
|
||||||
|
@ -144,6 +163,30 @@ static void dump_frba(frba_t * frba)
|
||||||
dump_region(4, 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)
|
static void decode_spi_frequency(unsigned int freq)
|
||||||
{
|
{
|
||||||
switch (freq) {
|
switch (freq) {
|
||||||
|
@ -422,6 +465,17 @@ static void dump_fd(char *image, int size)
|
||||||
dump_fmsba((fmsba_t *) (image + (((fdb->flmap2) & 0xff) << 4)));
|
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)
|
static void write_regions(char *image, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -608,6 +662,7 @@ static void print_usage(const char *name)
|
||||||
printf("usage: %s [-vhdix?] <filename>\n", name);
|
printf("usage: %s [-vhdix?] <filename>\n", name);
|
||||||
printf("\n"
|
printf("\n"
|
||||||
" -d | --dump: dump intel firmware descriptor\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"
|
" -x | --extract: extract intel fd modules\n"
|
||||||
" -i | --inject <region>:<module> inject file <module> into region <region>\n"
|
" -i | --inject <region>:<module> inject file <module> into region <region>\n"
|
||||||
" -s | --spifreq <20|33|50> set the SPI frequency\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 opt, option_index = 0;
|
||||||
int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;
|
int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;
|
||||||
int mode_em100 = 0, mode_locked = 0, mode_unlocked = 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;
|
int region_type = -1, inputfreq = 0;
|
||||||
enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
|
enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
|
||||||
|
|
||||||
static struct option long_options[] = {
|
static struct option long_options[] = {
|
||||||
{"dump", 0, NULL, 'd'},
|
{"dump", 0, NULL, 'd'},
|
||||||
|
{"layout", 1, NULL, 'f'},
|
||||||
{"extract", 0, NULL, 'x'},
|
{"extract", 0, NULL, 'x'},
|
||||||
{"inject", 1, NULL, 'i'},
|
{"inject", 1, NULL, 'i'},
|
||||||
{"spifreq", 1, NULL, 's'},
|
{"spifreq", 1, NULL, 's'},
|
||||||
|
@ -643,12 +700,21 @@ int main(int argc, char *argv[])
|
||||||
{0, 0, 0, 0}
|
{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) {
|
long_options, &option_index)) != EOF) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'd':
|
case 'd':
|
||||||
mode_dump = 1;
|
mode_dump = 1;
|
||||||
break;
|
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':
|
case 'x':
|
||||||
mode_extract = 1;
|
mode_extract = 1;
|
||||||
break;
|
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_spifreq | mode_em100 | mode_unlocked |
|
||||||
mode_locked)) > 1) {
|
mode_locked)) > 1) {
|
||||||
fprintf(stderr, "You may not specify more than one mode.\n\n");
|
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);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mode_dump + mode_extract + mode_inject + mode_spifreq +
|
if ((mode_dump + mode_layout + mode_extract + mode_inject +
|
||||||
mode_em100 + mode_locked + mode_unlocked) == 0) {
|
mode_spifreq + mode_em100 + mode_locked +
|
||||||
|
mode_unlocked) == 0) {
|
||||||
fprintf(stderr, "You need to specify a mode.\n\n");
|
fprintf(stderr, "You need to specify a mode.\n\n");
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -785,6 +852,9 @@ int main(int argc, char *argv[])
|
||||||
if (mode_dump)
|
if (mode_dump)
|
||||||
dump_fd(image, size);
|
dump_fd(image, size);
|
||||||
|
|
||||||
|
if (mode_layout)
|
||||||
|
dump_layout(image, size, layout_fname);
|
||||||
|
|
||||||
if (mode_extract)
|
if (mode_extract)
|
||||||
write_regions(image, size);
|
write_regions(image, size);
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#define IFDTOOL_VERSION "1.1"
|
#define IFDTOOL_VERSION "1.1"
|
||||||
|
|
||||||
|
#define LAYOUT_LINELEN 80
|
||||||
|
|
||||||
enum spi_frequency {
|
enum spi_frequency {
|
||||||
SPI_FREQUENCY_20MHZ = 0,
|
SPI_FREQUENCY_20MHZ = 0,
|
||||||
SPI_FREQUENCY_33MHZ = 1,
|
SPI_FREQUENCY_33MHZ = 1,
|
||||||
|
@ -109,3 +111,8 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int base, limit, size;
|
int base, limit, size;
|
||||||
} region_t;
|
} region_t;
|
||||||
|
|
||||||
|
struct region_name {
|
||||||
|
char *pretty;
|
||||||
|
char *terse;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue