ifdtool: Add validate option to ifdtool

Add an option to ifdtool which validates that the flash regions defined
in the descriptor match the coresponding areas in the FMAP.

BUG=chromium:992215
TEST=Ran 'ifdtool -t' with a good bios image and verify no issues
     run 'ifdtool -t' with a bad bios image and verify expected issues

Signed-off-by: Mathew King <mathewk@chromium.org>
Change-Id: Idebf105dee1b8f829d54bd65c82867af7aa4aded
Reviewed-on: https://review.coreboot.org/c/coreboot/+/34802
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Mathew King
2019-08-08 14:59:25 -06:00
committed by Patrick Georgi
parent 006eb9d8c8
commit c7ddc999fc
8 changed files with 150 additions and 16 deletions

View File

@ -22,6 +22,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <commonlib/helpers.h>
#include <fmap.h>
#include "ifdtool.h"
#ifndef O_BINARY
@ -46,15 +47,15 @@ static int selected_chip = 0;
static int platform = -1;
static const struct region_name region_names[MAX_REGIONS] = {
{ "Flash Descriptor", "fd", "flashregion_0_flashdescriptor.bin" },
{ "BIOS", "bios", "flashregion_1_bios.bin" },
{ "Intel ME", "me", "flashregion_2_intel_me.bin" },
{ "GbE", "gbe", "flashregion_3_gbe.bin" },
{ "Platform Data", "pd", "flashregion_4_platform_data.bin" },
{ "Reserved", "res1", "flashregion_5_reserved.bin" },
{ "Reserved", "res2", "flashregion_6_reserved.bin" },
{ "Reserved", "res3", "flashregion_7_reserved.bin" },
{ "EC", "ec", "flashregion_8_ec.bin" },
{ "Flash Descriptor", "fd", "flashregion_0_flashdescriptor.bin", "SI_DESC" },
{ "BIOS", "bios", "flashregion_1_bios.bin", "SI_BIOS" },
{ "Intel ME", "me", "flashregion_2_intel_me.bin", "SI_ME" },
{ "GbE", "gbe", "flashregion_3_gbe.bin", "SI_GBE" },
{ "Platform Data", "pd", "flashregion_4_platform_data.bin", "SI_PDR" },
{ "Reserved", "res1", "flashregion_5_reserved.bin", NULL },
{ "Reserved", "res2", "flashregion_6_reserved.bin", NULL },
{ "Reserved", "res3", "flashregion_7_reserved.bin", NULL },
{ "EC", "ec", "flashregion_8_ec.bin", "SI_EC" },
};
/* port from flashrom */
@ -804,6 +805,51 @@ static void write_regions(char *image, int size)
}
}
static void validate_layout(char *image, int size)
{
uint i, errors = 0;
struct fmap *fmap;
long int fmap_loc = fmap_find((uint8_t *)image, size);
const frba_t *frba = find_frba(image, size);
if (fmap_loc < 0 || !frba)
exit(EXIT_FAILURE);
fmap = (struct fmap *)(image + fmap_loc);
for (i = 0; i < max_regions; i++) {
if (region_names[i].fmapname == NULL)
continue;
region_t region = get_region(frba, i);
if (region.size == 0)
continue;
const struct fmap_area *area =
fmap_find_area(fmap, region_names[i].fmapname);
if (!area)
continue;
if ((uint)region.base != area->offset ||
(uint)region.size != area->size) {
printf("Region mismatch between %s and %s\n",
region_names[i].terse, area->name);
printf(" Descriptor region %s:\n", region_names[i].terse);
printf(" offset: 0x%08x\n", region.base);
printf(" length: 0x%08x\n", region.size);
printf(" FMAP area %s:\n", area->name);
printf(" offset: 0x%08x\n", area->offset);
printf(" length: 0x%08x\n", area->size);
errors++;
}
}
if (errors > 0)
exit(EXIT_FAILURE);
}
static void write_image(const char *filename, char *image, int size)
{
char new_filename[FILENAME_MAX]; // allow long file names
@ -1359,6 +1405,7 @@ static void print_usage(const char *name)
printf("\n"
" -d | --dump: dump intel firmware descriptor\n"
" -f | --layout <filename> dump regions into a flashrom layout file\n"
" -t | --validate Validate that the firmware descriptor layout matches the fmap layout\n"
" -x | --extract: extract intel fd modules\n"
" -i | --inject <region>:<module> inject file <module> into region <region>\n"
" -n | --newlayout <filename> update regions using a flashrom layout file\n"
@ -1388,7 +1435,7 @@ 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;
int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0, mode_validate = 0;
int mode_layout = 0, mode_newlayout = 0, mode_density = 0;
int mode_altmedisable = 0, altmedisable = 0;
char *region_type_string = NULL, *region_fname = NULL;
@ -1413,10 +1460,11 @@ int main(int argc, char *argv[])
{"version", 0, NULL, 'v'},
{"help", 0, NULL, 'h'},
{"platform", 0, NULL, 'p'},
{"validate", 0, NULL, 't'},
{0, 0, 0, 0}
};
while ((opt = getopt_long(argc, argv, "df:D:C:M:xi:n:s:p:eluvh?",
while ((opt = getopt_long(argc, argv, "df:D:C:M:xi:n:s:p:eluvth?",
long_options, &option_index)) != EOF) {
switch (opt) {
case 'd':
@ -1593,6 +1641,9 @@ int main(int argc, char *argv[])
}
fprintf(stderr, "Platform is: %s\n", optarg);
break;
case 't':
mode_validate = 1;
break;
case 'v':
print_version();
exit(EXIT_SUCCESS);
@ -1608,7 +1659,7 @@ int main(int argc, char *argv[])
if ((mode_dump + mode_layout + mode_extract + mode_inject +
mode_newlayout + (mode_spifreq | mode_em100 | mode_unlocked |
mode_locked) + mode_altmedisable) > 1) {
mode_locked) + mode_altmedisable + mode_layout) > 1) {
fprintf(stderr, "You may not specify more than one mode.\n\n");
print_usage(argv[0]);
exit(EXIT_FAILURE);
@ -1616,7 +1667,7 @@ int main(int argc, char *argv[])
if ((mode_dump + mode_layout + mode_extract + mode_inject +
mode_newlayout + mode_spifreq + mode_em100 + mode_locked +
mode_unlocked + mode_density + mode_altmedisable) == 0) {
mode_unlocked + mode_density + mode_altmedisable + mode_validate) == 0) {
fprintf(stderr, "You need to specify a mode.\n\n");
print_usage(argv[0]);
exit(EXIT_FAILURE);
@ -1667,6 +1718,9 @@ int main(int argc, char *argv[])
if (mode_extract)
write_regions(image, size);
if (mode_validate)
validate_layout(image, size);
if (mode_inject)
inject_region(filename, image, size, region_type,
region_fname);