parent
f95df118aa
commit
7bdb5bcddb
@ -0,0 +1,381 @@
|
|||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 805290c..5e77a48 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -306,7 +306,7 @@ CHIP_OBJS = jedec.o stm50flw0x0x.o w39.o w29ee011.o \
|
||||||
|
###############################################################################
|
||||||
|
# Library code.
|
||||||
|
|
||||||
|
-LIB_OBJS = layout.o flashrom.o udelay.o programmer.o
|
||||||
|
+LIB_OBJS = layout.o ifd.o flashrom.o udelay.o programmer.o
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# Frontend related stuff.
|
||||||
|
diff --git a/cli_classic.c b/cli_classic.c
|
||||||
|
index 14fb825..b3cc826 100644
|
||||||
|
--- a/cli_classic.c
|
||||||
|
+++ b/cli_classic.c
|
||||||
|
@@ -41,7 +41,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] [-f]]\n"
|
||||||
|
+ "[-E|(-r|-w|-v) <file>] [(-l <layoutfile>|-d) [-i <imagename>]...] [-n] [-f]]\n"
|
||||||
|
"[-V[V[V]]] [-o <logfile>]\n\n", name);
|
||||||
|
|
||||||
|
printf(" -h | --help print this help text\n"
|
||||||
|
@@ -55,6 +55,7 @@ static void cli_classic_usage(const char *name)
|
||||||
|
" -f | --force force specific operations (see man page)\n"
|
||||||
|
" -n | --noverify don't auto-verify\n"
|
||||||
|
" -l | --layout <layoutfile> read ROM layout from <layoutfile>\n"
|
||||||
|
+ " -d | --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"
|
||||||
|
@@ -98,7 +99,7 @@ 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
|
||||||
|
@@ -107,7 +108,7 @@ int main(int argc, char *argv[])
|
||||||
|
enum programmer prog = PROGRAMMER_INVALID;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
- static const char optstring[] = "r:Rw:v:nVEfc:l:i:p:Lzho:";
|
||||||
|
+ static const char optstring[] = "r:Rw:v:nVEfc:l:di:p:Lzho:";
|
||||||
|
static const struct option long_options[] = {
|
||||||
|
{"read", 1, NULL, 'r'},
|
||||||
|
{"write", 1, NULL, 'w'},
|
||||||
|
@@ -118,6 +119,7 @@ int main(int argc, char *argv[])
|
||||||
|
{"verbose", 0, NULL, 'V'},
|
||||||
|
{"force", 0, NULL, 'f'},
|
||||||
|
{"layout", 1, NULL, 'l'},
|
||||||
|
+ {"ifd", 0, NULL, 'd'},
|
||||||
|
{"image", 1, NULL, 'i'},
|
||||||
|
{"list-supported", 0, NULL, 'L'},
|
||||||
|
{"list-supported-wiki", 0, NULL, 'z'},
|
||||||
|
@@ -215,8 +217,20 @@ 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 'd':
|
||||||
|
+ if (layoutfile) {
|
||||||
|
+ fprintf(stderr, "Error: --layout and --ifd both specified. Aborting.\n");
|
||||||
|
+ cli_classic_abort_usage();
|
||||||
|
+ }
|
||||||
|
+ layout_use_ifd();
|
||||||
|
+ ifd = 1;
|
||||||
|
+ break;
|
||||||
|
case 'i':
|
||||||
|
tempstr = strdup(optarg);
|
||||||
|
if (register_include_arg(tempstr)) {
|
||||||
|
@@ -374,7 +388,7 @@ int main(int argc, char *argv[])
|
||||||
|
ret = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
- if (process_include_args()) {
|
||||||
|
+ if (!ifd && process_include_args()) {
|
||||||
|
ret = 1;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
diff --git a/flash.h b/flash.h
|
||||||
|
index 1857cc0..36b1e0d 100644
|
||||||
|
--- a/flash.h
|
||||||
|
+++ b/flash.h
|
||||||
|
@@ -306,11 +306,21 @@ int print(enum msglevel level, const char *fmt, ...) __attribute__((format(print
|
||||||
|
#define msg_cspew(...) print(MSG_SPEW, __VA_ARGS__) /* chip debug spew */
|
||||||
|
|
||||||
|
/* layout.c */
|
||||||
|
+typedef struct {
|
||||||
|
+ unsigned int start;
|
||||||
|
+ unsigned int end;
|
||||||
|
+ unsigned int included;
|
||||||
|
+ char name[256];
|
||||||
|
+} romlayout_t;
|
||||||
|
+void layout_use_ifd(void);
|
||||||
|
int register_include_arg(char *name);
|
||||||
|
int process_include_args(void);
|
||||||
|
int read_romlayout(char *name);
|
||||||
|
int handle_romentries(const struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents);
|
||||||
|
|
||||||
|
+/* ifd.c */
|
||||||
|
+int ifd_read_romlayout(const uint8_t *oldcontents, const uint8_t *newcontents, unsigned flash_size, romlayout_t *entries, int *n_entries);
|
||||||
|
+
|
||||||
|
/* spi.c */
|
||||||
|
struct spi_command {
|
||||||
|
unsigned int writecnt;
|
||||||
|
diff --git a/flashrom.8 b/flashrom.8
|
||||||
|
index 4e6ab55..82afb10 100644
|
||||||
|
--- a/flashrom.8
|
||||||
|
+++ b/flashrom.8
|
||||||
|
@@ -6,7 +6,7 @@ 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\-f\fR]]
|
||||||
|
+ [(\fB\-l\fR <file>|\fB\-d\fR) [\fB\-i\fR <image>]] [\fB\-n\fR] [\fB\-f\fR]]
|
||||||
|
[\fB\-V\fR[\fBV\fR[\fBV\fR]]] [\fB-o\fR <logfile>]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B flashrom
|
||||||
|
@@ -137,6 +137,22 @@ To update only the images named
|
||||||
|
.sp
|
||||||
|
Overlapping sections are not supported.
|
||||||
|
.TP
|
||||||
|
+.B "\-d, \-\-ifd"
|
||||||
|
+Read ROM layout from Intel Firmware Descriptor.
|
||||||
|
+.sp
|
||||||
|
+flashrom supports ROM layouts given by an Intel Firmware Descriptor
|
||||||
|
+(IFD). Both, the current flash ROM chips contents and the file's
|
||||||
|
+contents which are to be flashed, must contain an IFD with the same ROM
|
||||||
|
+regions.
|
||||||
|
+.sp
|
||||||
|
+The following ROM images may be present in an IFD:
|
||||||
|
+.sp
|
||||||
|
+ Flash_Descriptor the IFD itself
|
||||||
|
+ BIOS the host firmware aka. BIOS
|
||||||
|
+ Intel_ME Intel Management Engine firmware
|
||||||
|
+ GbE Gigabit Ethernet firmware
|
||||||
|
+ Platform_Data platform specific data
|
||||||
|
+.TP
|
||||||
|
.B "\-i, \-\-image <imagename>"
|
||||||
|
Only flash region/image
|
||||||
|
.B <imagename>
|
||||||
|
diff --git a/flashrom.c b/flashrom.c
|
||||||
|
index c11f723..bf690dc 100644
|
||||||
|
--- a/flashrom.c
|
||||||
|
+++ b/flashrom.c
|
||||||
|
@@ -1958,7 +1958,10 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it,
|
||||||
|
|
||||||
|
// This should be moved into each flash part's code to do it
|
||||||
|
// cleanly. This does the job.
|
||||||
|
- handle_romentries(flash, oldcontents, newcontents);
|
||||||
|
+ if (handle_romentries(flash, oldcontents, newcontents)) {
|
||||||
|
+ ret = 1;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
// ////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
diff --git a/ifd.c b/ifd.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..fd31f4f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/ifd.c
|
||||||
|
@@ -0,0 +1,155 @@
|
||||||
|
+/*
|
||||||
|
+ * This file is part of the flashrom project.
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2013 secunet Security Networks AG
|
||||||
|
+ *
|
||||||
|
+ * ifd reading code borrowed from coreboot's ifdtool:
|
||||||
|
+ * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation; version 2 of the License.
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * You should have received a copy of the GNU General Public License
|
||||||
|
+ * along with this program; if not, write to the Free Software
|
||||||
|
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <stdint.h>
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include "flash.h"
|
||||||
|
+
|
||||||
|
+/* flash descriptor */
|
||||||
|
+typedef struct {
|
||||||
|
+ uint32_t flvalsig;
|
||||||
|
+ uint32_t flmap0;
|
||||||
|
+ uint32_t flmap1;
|
||||||
|
+ uint32_t flmap2;
|
||||||
|
+ uint8_t reserved[0xefc - 0x20];
|
||||||
|
+ uint32_t flumap1;
|
||||||
|
+} __attribute__((packed)) fdbar_t;
|
||||||
|
+
|
||||||
|
+/* regions */
|
||||||
|
+typedef struct {
|
||||||
|
+ uint32_t flreg0;
|
||||||
|
+ uint32_t flreg1;
|
||||||
|
+ uint32_t flreg2;
|
||||||
|
+ uint32_t flreg3;
|
||||||
|
+ uint32_t flreg4;
|
||||||
|
+} __attribute__((packed)) frba_t;
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ int base, limit, size;
|
||||||
|
+} region_t;
|
||||||
|
+
|
||||||
|
+static fdbar_t *find_fd(const uint8_t *image, int size)
|
||||||
|
+{
|
||||||
|
+ int i, found = 0;
|
||||||
|
+
|
||||||
|
+ /* Scan for FD signature */
|
||||||
|
+ for (i = 0; i <= (size - sizeof(fdbar_t)); i += 4) {
|
||||||
|
+ if (*(uint32_t *) (image + i) == 0x0FF0A55A) {
|
||||||
|
+ found = 1;
|
||||||
|
+ break; // signature found.
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!found)
|
||||||
|
+ return NULL;
|
||||||
|
+
|
||||||
|
+ msg_ginfo("Found Flash Descriptor signature at 0x%08x\n", i);
|
||||||
|
+
|
||||||
|
+ return (fdbar_t *) (image + i);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static region_t get_region(const frba_t *frba, int region_type)
|
||||||
|
+{
|
||||||
|
+ region_t region;
|
||||||
|
+ region.base = 0, region.limit = 0, region.size = 0;
|
||||||
|
+
|
||||||
|
+ switch (region_type) {
|
||||||
|
+ case 0:
|
||||||
|
+ region.base = (frba->flreg0 & 0x00000fff) << 12;
|
||||||
|
+ region.limit = ((frba->flreg0 & 0x0fff0000) >> 4) | 0xfff;
|
||||||
|
+ break;
|
||||||
|
+ case 1:
|
||||||
|
+ region.base = (frba->flreg1 & 0x00000fff) << 12;
|
||||||
|
+ region.limit = ((frba->flreg1 & 0x0fff0000) >> 4) | 0xfff;
|
||||||
|
+ break;
|
||||||
|
+ case 2:
|
||||||
|
+ region.base = (frba->flreg2 & 0x00000fff) << 12;
|
||||||
|
+ region.limit = ((frba->flreg2 & 0x0fff0000) >> 4) | 0xfff;
|
||||||
|
+ break;
|
||||||
|
+ case 3:
|
||||||
|
+ region.base = (frba->flreg3 & 0x00000fff) << 12;
|
||||||
|
+ region.limit = ((frba->flreg3 & 0x0fff0000) >> 4) | 0xfff;
|
||||||
|
+ break;
|
||||||
|
+ case 4:
|
||||||
|
+ region.base = (frba->flreg4 & 0x00000fff) << 12;
|
||||||
|
+ region.limit = ((frba->flreg4 & 0x0fff0000) >> 4) | 0xfff;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ region.size = region.limit - region.base + 1;
|
||||||
|
+
|
||||||
|
+ return region;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int ifd_read_romlayout(const uint8_t *const oldcontents, const uint8_t *const newcontents,
|
||||||
|
+ const unsigned flash_size, romlayout_t *const entries, int *const n_entries)
|
||||||
|
+{
|
||||||
|
+ static const char *regions[5] = {
|
||||||
|
+ "Flash_Descriptor",
|
||||||
|
+ "BIOS",
|
||||||
|
+ "Intel_ME",
|
||||||
|
+ "GbE",
|
||||||
|
+ "Platform_Data"
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ const int max_entries = *n_entries;
|
||||||
|
+ *n_entries = 0;
|
||||||
|
+
|
||||||
|
+ const fdbar_t *const fdb_old = find_fd(oldcontents, flash_size);
|
||||||
|
+ if (!fdb_old) {
|
||||||
|
+ msg_gerr("No IFD found in old flash contents.\n");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ const fdbar_t *const fdb_new = find_fd(newcontents, flash_size);
|
||||||
|
+ if (!fdb_old) {
|
||||||
|
+ msg_gerr("No IFD found in new flash contents.\n");
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ const frba_t *const fr_old = (frba_t *)(oldcontents + (((fdb_old->flmap0 >> 16) & 0xff) << 4));
|
||||||
|
+ const frba_t *const fr_new = (frba_t *)(newcontents + (((fdb_new->flmap0 >> 16) & 0xff) << 4));
|
||||||
|
+ int i;
|
||||||
|
+ for (i = 0; i < 5; ++i) {
|
||||||
|
+ const region_t reg_old = get_region(fr_old, i);
|
||||||
|
+ const region_t reg_new = get_region(fr_new, i);
|
||||||
|
+ if (reg_old.base != reg_new.base || reg_old.limit != reg_new.limit) {
|
||||||
|
+ msg_gerr("Image '%s' doesn't match in old and new IFD, won't flash.\n", regions[i]);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ if (reg_old.size <= 0)
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (*n_entries >= max_entries) {
|
||||||
|
+ msg_gerr("Maximum number of ROM images (%i) in layout reached.\n", max_entries);
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+ entries[*n_entries].start = reg_old.base;
|
||||||
|
+ entries[*n_entries].end = reg_old.limit;
|
||||||
|
+ snprintf(entries[*n_entries].name, sizeof(entries[*n_entries].name), "%s", regions[i]);
|
||||||
|
+ msg_ginfo("Found flash region [%08x:%08x] %s\n",
|
||||||
|
+ entries[*n_entries].start, entries[*n_entries].end, entries[*n_entries].name);
|
||||||
|
+ ++*n_entries;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
diff --git a/layout.c b/layout.c
|
||||||
|
index 1bd3152..81058f3 100644
|
||||||
|
--- a/layout.c
|
||||||
|
+++ b/layout.c
|
||||||
|
@@ -26,16 +26,10 @@
|
||||||
|
#include "programmer.h"
|
||||||
|
|
||||||
|
static int romimages = 0;
|
||||||
|
+static int use_ifd = 0;
|
||||||
|
|
||||||
|
#define MAX_ROMLAYOUT 32
|
||||||
|
|
||||||
|
-typedef struct {
|
||||||
|
- unsigned int start;
|
||||||
|
- unsigned int end;
|
||||||
|
- unsigned int included;
|
||||||
|
- char name[256];
|
||||||
|
-} romlayout_t;
|
||||||
|
-
|
||||||
|
/* include_args lists arguments specified at the command line with -i. They
|
||||||
|
* must be processed at some point so that desired regions are marked as
|
||||||
|
* "included" in the rom_entries list.
|
||||||
|
@@ -44,6 +38,11 @@ static char *include_args[MAX_ROMLAYOUT];
|
||||||
|
static int num_include_args = 0; /* the number of valid entries. */
|
||||||
|
static romlayout_t rom_entries[MAX_ROMLAYOUT];
|
||||||
|
|
||||||
|
+void layout_use_ifd(void)
|
||||||
|
+{
|
||||||
|
+ use_ifd = 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#ifndef __LIBPAYLOAD__
|
||||||
|
int read_romlayout(char *name)
|
||||||
|
{
|
||||||
|
@@ -223,6 +222,16 @@ int handle_romentries(const struct flashctx *flash, uint8_t *oldcontents, uint8_
|
||||||
|
romlayout_t *entry;
|
||||||
|
unsigned int size = flash->chip->total_size * 1024;
|
||||||
|
|
||||||
|
+ if (use_ifd) {
|
||||||
|
+ romimages = MAX_ROMLAYOUT;
|
||||||
|
+ if (ifd_read_romlayout(oldcontents, newcontents, size, rom_entries, &romimages))
|
||||||
|
+ return 1;
|
||||||
|
+ /* Call process_include_args() late, as we only
|
||||||
|
+ just got to know the names of available images. */
|
||||||
|
+ if (process_include_args())
|
||||||
|
+ return 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* If no regions were specified for inclusion, assume
|
||||||
|
* that the user wants to write the complete new image.
|
||||||
|
*/
|
||||||
|
--
|
Loading…
Reference in new issue