1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-27 15:12:36 +02:00

Add option to read ROM layout from IFD

Add an option --ifd to read the ROM layout from an Intel Firmware
Descriptor (IFD). Works the same as the -l option, if given, -i
specifies the images to update.

v2: o Rebased on libflashrom, use libflashrom interface.
    o Use functions from ich_descriptors.c.

v3: o Move ich_descriptors.o to LIB_OBJS, thus build it independent
      of arch and programmers.
    o Bail out if we aren't compiled for little endian.
    o Update flashrom.8.tmpl.

v4: o Incorporated David's comments.
    o Removed single-character `-d` option.

v5: Changed region names to match the output of `ifdtool --layout ...`

Change-Id: Ifafff2bf6d5c5e62283416b3269723f81fdc0fa3
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/17953
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Nico Huber 2013-06-14 11:55:26 +02:00 committed by Nico Huber
parent ad18631b59
commit 305f417ea5
11 changed files with 195 additions and 25 deletions

View File

@ -519,7 +519,7 @@ CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \
###############################################################################
# Library code.
LIB_OBJS = libflashrom.o layout.o flashrom.o udelay.o programmer.o helpers.o
LIB_OBJS = libflashrom.o layout.o flashrom.o udelay.o programmer.o helpers.o ich_descriptors.o
###############################################################################
# Frontend related stuff.
@ -731,7 +731,7 @@ FEATURE_CFLAGS += -D'CONFIG_INTERNAL=1'
PROGRAMMER_OBJS += processor_enable.o chipset_enable.o board_enable.o cbtable.o internal.o
ifeq ($(ARCH), x86)
PROGRAMMER_OBJS += it87spi.o it85spi.o sb600spi.o amd_imc.o wbsio_spi.o mcp6x_spi.o
PROGRAMMER_OBJS += ichspi.o ich_descriptors.o dmi.o
PROGRAMMER_OBJS += ichspi.o dmi.o
ifeq ($(CONFIG_INTERNAL_DMI), yes)
FEATURE_CFLAGS += -D'CONFIG_INTERNAL_DMI=1'
endif

View File

@ -42,7 +42,7 @@ static void cli_classic_usage(const char *name)
"-z|"
#endif
"-p <programmername>[:<parameters>] [-c <chipname>]\n"
"[-E|(-r|-w|-v) <file>] [-l <layoutfile> [-i <imagename>]...] [-n] [-N] [-f]]\n"
"[-E|(-r|-w|-v) <file>] [(-l <layoutfile>|--ifd) [-i <imagename>]...] [-n] [-N] [-f]]\n"
"[-V[V[V]]] [-o <logfile>]\n\n", name);
printf(" -h | --help print this help text\n"
@ -57,6 +57,7 @@ static void cli_classic_usage(const char *name)
" -n | --noverify don't auto-verify\n"
" -N | --noverify-all verify included regions only (cf. -i)\n"
" -l | --layout <layoutfile> read ROM layout from <layoutfile>\n"
" --ifd read layout from an Intel Firmware Descriptor\n"
" -i | --image <name> only flash image <name> from flash layout\n"
" -o | --output <logfile> log output to <logfile>\n"
" -L | --list-supported print supported devices\n"
@ -99,12 +100,13 @@ int main(int argc, char *argv[])
struct flashctx *fill_flash;
const char *name;
int namelen, opt, i, j;
int startchip = -1, chipcount = 0, option_index = 0, force = 0;
int startchip = -1, chipcount = 0, option_index = 0, force = 0, ifd = 0;
#if CONFIG_PRINT_WIKI == 1
int list_supported_wiki = 0;
#endif
int read_it = 0, write_it = 0, erase_it = 0, verify_it = 0;
int dont_verify_it = 0, dont_verify_all = 0, list_supported = 0, operation_specified = 0;
struct flashrom_layout *layout = NULL;
enum programmer prog = PROGRAMMER_INVALID;
int ret = 0;
@ -120,6 +122,7 @@ int main(int argc, char *argv[])
{"verbose", 0, NULL, 'V'},
{"force", 0, NULL, 'f'},
{"layout", 1, NULL, 'l'},
{"ifd", 0, NULL, 0x0100},
{"image", 1, NULL, 'i'},
{"list-supported", 0, NULL, 'L'},
{"list-supported-wiki", 0, NULL, 'z'},
@ -220,8 +223,19 @@ int main(int argc, char *argv[])
"more than once. Aborting.\n");
cli_classic_abort_usage();
}
if (ifd) {
fprintf(stderr, "Error: --layout and --ifd both specified. Aborting.\n");
cli_classic_abort_usage();
}
layoutfile = strdup(optarg);
break;
case 0x0100:
if (layoutfile) {
fprintf(stderr, "Error: --layout and --ifd both specified. Aborting.\n");
cli_classic_abort_usage();
}
ifd = 1;
break;
case 'i':
tempstr = strdup(optarg);
if (register_include_arg(tempstr)) {
@ -376,7 +390,7 @@ int main(int argc, char *argv[])
ret = 1;
goto out;
}
if (process_include_args()) {
if (!ifd && process_include_args(get_global_layout())) {
ret = 1;
goto out;
}
@ -529,9 +543,15 @@ int main(int argc, char *argv[])
goto out_shutdown;
}
if (layoutfile)
flashrom_layout_set(fill_flash, get_global_layout());
if (layoutfile) {
layout = get_global_layout();
} else if (ifd && (flashrom_layout_read_from_ifd(&layout, fill_flash, NULL, 0) ||
process_include_args(layout))) {
ret = 1;
goto out_shutdown;
}
flashrom_layout_set(fill_flash, layout);
flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE, !!force);
flashrom_flag_set(fill_flash, FLASHROM_FLAG_FORCE_BOARDMISMATCH, !!force_boardmismatch);
flashrom_flag_set(fill_flash, FLASHROM_FLAG_VERIFY_AFTER_WRITE, !dont_verify_it);
@ -551,6 +571,8 @@ int main(int argc, char *argv[])
else if (verify_it)
ret = do_verify(fill_flash, filename);
flashrom_layout_release(layout);
out_shutdown:
programmer_shutdown();
out:

View File

@ -287,6 +287,8 @@ void list_programmers_linebreak(int startcol, int cols, int paren);
int selfcheck(void);
int read_buf_from_file(unsigned char *buf, unsigned long size, const char *filename);
int write_buf_to_file(const unsigned char *buf, unsigned long size, const char *filename);
int prepare_flash_access(struct flashctx *, bool read_it, bool write_it, bool erase_it, bool verify_it);
void finalize_flash_access(struct flashctx *);
int do_read(struct flashctx *, const char *filename);
int do_erase(struct flashctx *);
int do_write(struct flashctx *, const char *const filename);
@ -354,7 +356,6 @@ __attribute__((format(printf, 2, 3)));
/* layout.c */
int register_include_arg(char *name);
int process_include_args(void);
int read_romlayout(const char *name);
int normalize_romentries(const struct flashctx *flash);
void layout_cleanup(void);

View File

@ -48,8 +48,8 @@ flashrom \- detect, read, write, verify and erase flash chips
\fB\-p\fR <programmername>[:<parameters>]
[\fB\-E\fR|\fB\-r\fR <file>|\fB\-w\fR <file>|\fB\-v\fR <file>] \
[\fB\-c\fR <chipname>]
[\fB\-l\fR <file> [\fB\-i\fR <image>]] [\fB\-n\fR] [\fB\-N\fR] \
[\fB\-f\fR]]
[(\fB\-l\fR <file>|\fB\-\-ifd\fR) [\fB\-i\fR <image>]] \
[\fB\-n\fR] [\fB\-N\fR] [\fB\-f\fR]]
[\fB\-V\fR[\fBV\fR[\fBV\fR]]] [\fB-o\fR <logfile>]
.SH DESCRIPTION
.B flashrom
@ -195,6 +195,22 @@ To update only the images named
.sp
Overlapping sections are not supported.
.TP
.B "\-\-ifd"
Read ROM layout from Intel Firmware Descriptor.
.sp
flashrom supports ROM layouts given by an Intel Firmware Descriptor
(IFD). The on-chip descriptor will be read and used to generate the
layout. If you need to change the layout, you have to update the IFD
only first.
.sp
The following ROM images may be present in an IFD:
.sp
fd the IFD itself
bios the host firmware aka. BIOS
me Intel Management Engine firmware
gbe gigabit ethernet firmware
pd platform specific data
.TP
.B "\-i, \-\-image <imagename>"
Only flash region/image
.B <imagename>

View File

@ -2168,9 +2168,9 @@ int chip_safety_check(const struct flashctx *flash, int force, int read_it, int
return 0;
}
static int prepare_flash_access(struct flashctx *const flash,
const bool read_it, const bool write_it,
const bool erase_it, const bool verify_it)
int prepare_flash_access(struct flashctx *const flash,
const bool read_it, const bool write_it,
const bool erase_it, const bool verify_it)
{
if (chip_safety_check(flash, flash->flags.force, read_it, write_it, erase_it, verify_it)) {
msg_cerr("Aborting.\n");
@ -2193,7 +2193,7 @@ static int prepare_flash_access(struct flashctx *const flash,
return 0;
}
static void finalize_flash_access(struct flashctx *const flash)
void finalize_flash_access(struct flashctx *const flash)
{
unmap_flash(flash);
}

View File

@ -23,6 +23,7 @@
#ifdef ICH_DESCRIPTORS_FROM_DUMP_ONLY
#include <stdio.h>
#include <string.h>
#define print(t, ...) printf(__VA_ARGS__)
#endif
@ -38,7 +39,7 @@
#include "programmer.h"
#ifndef min
#define min(a, b) (a < b) ? a : b
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
void prettyprint_ich_reg_vscc(uint32_t reg_val, int verbosity, bool print_vcl)
@ -916,4 +917,42 @@ int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc)
msg_pdbg2(" done.\n");
return ICH_RET_OK;
}
/**
* @brief Read a layout from the dump of an Intel ICH descriptor.
*
* @param layout Pointer where to store the layout.
* @param dump The descriptor dump to read from.
* @param len The length of the descriptor dump.
*
* @return 0 on success,
* 1 if the descriptor couldn't be parsed.
*/
int layout_from_ich_descriptors(struct ich_layout *const layout, const void *const dump, const size_t len)
{
static const char *regions[] = { "fd", "bios", "me", "gbe", "pd" };
struct ich_descriptors desc;
if (read_ich_descriptors_from_dump(dump, len, &desc))
return 1;
memset(layout, 0x00, sizeof(*layout));
size_t i, j;
for (i = 0, j = 0; i < min(desc.content.NR + 1, ARRAY_SIZE(regions)); ++i) {
const chipoff_t base = ICH_FREG_BASE(desc.region.FLREGs[i]);
const chipoff_t limit = ICH_FREG_LIMIT(desc.region.FLREGs[i]) + 0xfff;
if (limit <= base)
continue;
layout->entries[j].start = base;
layout->entries[j].end = limit;
layout->entries[j].included = false;
snprintf(layout->entries[j].name, sizeof(layout->entries[j].name), "%s", regions[i]);
++j;
}
layout->base.entries = layout->entries;
layout->base.num_entries = j;
return 0;
}
#endif /* ICH_DESCRIPTORS_FROM_DUMP_ONLY */

View File

@ -584,4 +584,6 @@ int read_ich_descriptors_from_dump(const uint32_t *dump, unsigned int len, struc
int read_ich_descriptors_via_fdo(void *spibar, struct ich_descriptors *desc);
int getFCBA_component_density(enum ich_chipset cs, const struct ich_descriptors *desc, uint8_t idx);
int layout_from_ich_descriptors(struct ich_layout *, const void *dump, size_t len);
#endif /* __ICH_DESCRIPTORS_H__ */

View File

@ -35,7 +35,7 @@ static struct flashrom_layout layout = { entries, 0 };
static char *include_args[MAX_ROMLAYOUT];
static int num_include_args = 0; /* the number of valid include_args. */
const struct flashrom_layout *get_global_layout(void)
struct flashrom_layout *get_global_layout(void)
{
return &layout;
}
@ -132,17 +132,17 @@ int register_include_arg(char *name)
}
/* returns the index of the entry (or a negative value if it is not found) */
static int find_romentry(char *name)
static int find_romentry(struct flashrom_layout *const l, char *name)
{
int i;
if (layout.num_entries == 0)
if (l->num_entries == 0)
return -1;
msg_gspew("Looking for region \"%s\"... ", name);
for (i = 0; i < layout.num_entries; i++) {
if (!strcmp(layout.entries[i].name, name)) {
layout.entries[i].included = 1;
for (i = 0; i < l->num_entries; i++) {
if (!strcmp(l->entries[i].name, name)) {
l->entries[i].included = 1;
msg_gspew("found.\n");
return i;
}
@ -154,7 +154,7 @@ static int find_romentry(char *name)
/* process -i arguments
* returns 0 to indicate success, >0 to indicate failure
*/
int process_include_args(void)
int process_include_args(struct flashrom_layout *const l)
{
int i;
unsigned int found = 0;
@ -163,7 +163,7 @@ int process_include_args(void)
return 0;
/* User has specified an area, but no layout file is loaded. */
if (layout.num_entries == 0) {
if (l->num_entries == 0) {
msg_gerr("Region requested (with -i \"%s\"), "
"but no layout data is available.\n",
include_args[0]);
@ -171,7 +171,7 @@ int process_include_args(void)
}
for (i = 0; i < num_include_args; i++) {
if (find_romentry(include_args[i]) < 0) {
if (find_romentry(l, include_args[i]) < 0) {
msg_gerr("Invalid region specified: \"%s\".\n",
include_args[i]);
return 1;

View File

@ -57,6 +57,13 @@ struct single_layout {
struct romentry entry;
};
const struct flashrom_layout *get_global_layout(void);
struct ich_layout {
struct flashrom_layout base;
struct romentry entries[5];
};
struct flashrom_layout *get_global_layout(void);
int process_include_args(struct flashrom_layout *);
#endif /* !__LAYOUT_H__ */

View File

@ -31,6 +31,8 @@
#include "flash.h"
#include "programmer.h"
#include "layout.h"
#include "hwaccess.h"
#include "ich_descriptors.h"
#include "libflashrom.h"
/**
@ -304,6 +306,86 @@ int flashrom_layout_include_region(struct flashrom_layout *const layout, const c
return 1;
}
/**
* @brief Read a layout from the Intel ICH descriptor in the flash.
*
* Optionally verify that the layout matches the one in the given
* descriptor dump.
*
* @param[out] layout Points to a struct flashrom_layout pointer that
* gets set if the descriptor is read and parsed
* successfully.
* @param[in] flashctx Flash context to read the descriptor from flash.
* @param[in] dump The descriptor dump to compare to or NULL.
* @param[in] len The length of the descriptor dump.
*
* @return 0 on success,
* 6 if descriptor parsing isn't implemented for the host,
* 5 if the descriptors don't match,
* 4 if the descriptor dump couldn't be parsed,
* 3 if the descriptor on flash couldn't be parsed,
* 2 if the descriptor on flash couldn't be read,
* 1 on any other error.
*/
int flashrom_layout_read_from_ifd(struct flashrom_layout **const layout, struct flashctx *const flashctx,
const void *const dump, const size_t len)
{
#ifndef __FLASHROM_LITTLE_ENDIAN__
return 6;
#else
struct ich_layout dump_layout;
int ret = 1;
void *const desc = malloc(0x1000);
struct ich_layout *const chip_layout = malloc(sizeof(*chip_layout));
if (!desc || !chip_layout) {
msg_gerr("Out of memory!\n");
goto _free_ret;
}
if (prepare_flash_access(flashctx, true, false, false, false))
goto _free_ret;
msg_cinfo("Reading ich descriptor... ");
if (flashctx->chip->read(flashctx, desc, 0, 0x1000)) {
msg_cerr("Read operation failed!\n");
msg_cinfo("FAILED.\n");
ret = 2;
goto _finalize_ret;
}
msg_cinfo("done.\n");
if (layout_from_ich_descriptors(chip_layout, desc, 0x1000)) {
ret = 3;
goto _finalize_ret;
}
if (dump) {
if (layout_from_ich_descriptors(&dump_layout, dump, len)) {
ret = 4;
goto _finalize_ret;
}
if (chip_layout->base.num_entries != dump_layout.base.num_entries ||
memcmp(chip_layout->entries, dump_layout.entries, sizeof(dump_layout.entries))) {
ret = 5;
goto _finalize_ret;
}
}
*layout = (struct flashrom_layout *)chip_layout;
ret = 0;
_finalize_ret:
finalize_flash_access(flashctx);
_free_ret:
if (ret)
free(chip_layout);
free(desc);
return ret;
#endif
}
/**
* @brief Free a layout.
*

View File

@ -63,6 +63,7 @@ int flashrom_image_write(struct flashrom_flashctx *, const void *buffer, size_t
int flashrom_image_verify(struct flashrom_flashctx *, const void *buffer, size_t buffer_len);
struct flashrom_layout;
int flashrom_layout_read_from_ifd(struct flashrom_layout **, struct flashrom_flashctx *, const void *dump, size_t len);
int flashrom_layout_include_region(struct flashrom_layout *, const char *name);
void flashrom_layout_release(struct flashrom_layout *);
void flashrom_layout_set(struct flashrom_flashctx *, const struct flashrom_layout *);