summaryrefslogtreecommitdiffstats
path: root/util/ifdtool
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2015-06-22 11:14:48 -0700
committerAaron Durbin <adurbin@chromium.org>2015-08-19 14:03:26 +0000
commit1f7fd720c81755144423f2d4062c39cc651adc0a (patch)
tree95d3392f688d428bcec3db90b500a59d69fefdd6 /util/ifdtool
parente0334e82960aa72c602686f1f8a840002bc3a73a (diff)
downloadcoreboot-staging-1f7fd720c81755144423f2d4062c39cc651adc0a.zip
coreboot-staging-1f7fd720c81755144423f2d4062c39cc651adc0a.tar.gz
ifdtool: Update to support Skylake+ descriptor format
The descriptor format has changed with Skylake and some fields have moved or been expanded. This includes new SPI frequencies and chip densities, though unfortunately 30MHz in the new format conflicts with 50MHz in the old format... There are also new regions with a few reserved regions inserted before a new embedded controller region. Unfortunately there does not seem to be a documented version field so there does not seem to be an official way to determine if a specific descriptor is new or old. To work around this ifdtool checks the hardcoded "SPI Read Frequency" to see if it set for 20MHz (old descriptor) or 17MHz (new descriptor). BUG=chrome-os-partner:40635 BUG=chrome-os-partner:43461 BRANCH=none TEST=run ifdtool on skylake and broadwell images Original-Change-Id: I0561b3c65fcb3e77c0a24be58b01db9b3a36e5a9 Original-Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/281001 Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org> Original-Commit-Queue: Aaron Durbin <adurbin@chromium.org> Change-Id: I9a08c26432e13c4000afc50de9d8473e6f911805 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/293240 Reviewed-on: http://review.coreboot.org/11228 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'util/ifdtool')
-rw-r--r--util/ifdtool/ifdtool.c223
-rw-r--r--util/ifdtool/ifdtool.h22
2 files changed, 201 insertions, 44 deletions
diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c
index 8d5d059..6856400 100644
--- a/util/ifdtool/ifdtool.c
+++ b/util/ifdtool/ifdtool.c
@@ -31,14 +31,18 @@
#define O_BINARY 0
#endif
-#define NUM_REGIONS 5
+static int ifd_version;
-static const struct region_name region_names[NUM_REGIONS] = {
+static const struct region_name region_names[MAX_REGIONS] = {
{ "Flash Descriptor", "fd" },
{ "BIOS", "bios" },
{ "Intel ME", "me" },
{ "GbE", "gbe" },
- { "Platform Data", "pd" }
+ { "Platform Data", "pd" },
+ { "Reserved", "res1" },
+ { "Reserved", "res2" },
+ { "Reserved", "res3" },
+ { "EC" "ec" },
};
static fdbar_t *find_fd(char *image, int size)
@@ -58,11 +62,43 @@ static fdbar_t *find_fd(char *image, int size)
return NULL;
}
- printf("Found Flash Descriptor signature at 0x%08x\n", i);
-
return (fdbar_t *) (image + i);
}
+/*
+ * There is no version field in the descriptor so to determine
+ * if this is a new descriptor format we check the hardcoded SPI
+ * read frequency to see if it is fixed at 20MHz or 17MHz.
+ */
+static void check_ifd_version(char *image, int size)
+{
+ fdbar_t *fdb = find_fd(image, size);
+ fcba_t *fcba;
+ int read_freq;
+
+ if (!fdb)
+ exit(EXIT_FAILURE);
+
+ fcba = (fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4));
+ if (!fcba)
+ exit(EXIT_FAILURE);
+
+ read_freq = (fcba->flcomp >> 17) & 7;
+
+ switch (read_freq) {
+ case SPI_FREQUENCY_20MHZ:
+ ifd_version = IFD_VERSION_1;
+ break;
+ case SPI_FREQUENCY_17MHZ:
+ ifd_version = IFD_VERSION_2;
+ break;
+ default:
+ fprintf(stderr, "Unknown descriptor version: %d\n",
+ read_freq);
+ exit(EXIT_FAILURE);
+ }
+}
+
static region_t get_region(frba_t *frba, int region_type)
{
region_t region;
@@ -89,8 +125,24 @@ static region_t get_region(frba_t *frba, int region_type)
region.base = (frba->flreg4 & 0x00000fff) << 12;
region.limit = ((frba->flreg4 & 0x0fff0000) >> 4) | 0xfff;
break;
+ case 5:
+ region.base = (frba->flreg5 & 0x00000fff) << 12;
+ region.limit = ((frba->flreg5 & 0x0fff0000) >> 4) | 0xfff;
+ break;
+ case 6:
+ region.base = (frba->flreg6 & 0x00000fff) << 12;
+ region.limit = ((frba->flreg6 & 0x0fff0000) >> 4) | 0xfff;
+ break;
+ case 7:
+ region.base = (frba->flreg7 & 0x00000fff) << 12;
+ region.limit = ((frba->flreg7 & 0x0fff0000) >> 4) | 0xfff;
+ break;
+ case 8:
+ region.base = (frba->flreg8 & 0x00000fff) << 12;
+ region.limit = ((frba->flreg8 & 0x0fff0000) >> 4) | 0xfff;
+ break;
default:
- fprintf(stderr, "Invalid region type.\n");
+ fprintf(stderr, "Invalid region type %d.\n", region_type);
exit (EXIT_FAILURE);
}
@@ -132,7 +184,7 @@ static void set_region(frba_t *frba, int region_type, region_t region)
static const char *region_name(int region_type)
{
- if (region_type < 0 || region_type >= NUM_REGIONS) {
+ if (region_type < 0 || region_type >= MAX_REGIONS) {
fprintf(stderr, "Invalid region type.\n");
exit (EXIT_FAILURE);
}
@@ -142,7 +194,7 @@ static const char *region_name(int region_type)
static const char *region_name_short(int region_type)
{
- if (region_type < 0 || region_type >= NUM_REGIONS) {
+ if (region_type < 0 || region_type >= MAX_REGIONS) {
fprintf(stderr, "Invalid region type.\n");
exit (EXIT_FAILURE);
}
@@ -154,7 +206,7 @@ static int region_num(const char *name)
{
int i;
- for (i = 0; i < NUM_REGIONS; i++) {
+ for (i = 0; i < MAX_REGIONS; i++) {
if (strcasecmp(name, region_names[i].pretty) == 0)
return i;
if (strcasecmp(name, region_names[i].terse) == 0)
@@ -166,16 +218,20 @@ static int region_num(const char *name)
static const char *region_filename(int region_type)
{
- static const char *region_filenames[NUM_REGIONS] = {
+ static const char *region_filenames[MAX_REGIONS] = {
"flashregion_0_flashdescriptor.bin",
"flashregion_1_bios.bin",
"flashregion_2_intel_me.bin",
"flashregion_3_gbe.bin",
- "flashregion_4_platform_data.bin"
+ "flashregion_4_platform_data.bin",
+ "flashregion_5_reserved.bin",
+ "flashregion_6_reserved.bin",
+ "flashregion_7_reserved.bin",
+ "flashregion_8_ec.bin",
};
- if (region_type < 0 || region_type >= NUM_REGIONS) {
- fprintf(stderr, "Invalid region type.\n");
+ if (region_type < 0 || region_type >= MAX_REGIONS) {
+ fprintf(stderr, "Invalid region type %d.\n", region_type);
exit (EXIT_FAILURE);
}
@@ -210,6 +266,17 @@ static void dump_frba(frba_t * frba)
dump_region(3, frba);
printf("FLREG4: 0x%08x\n", frba->flreg4);
dump_region(4, frba);
+
+ if (ifd_version >= IFD_VERSION_2) {
+ printf("FLREG5: 0x%08x\n", frba->flreg5);
+ dump_region(5, frba);
+ printf("FLREG6: 0x%08x\n", frba->flreg6);
+ dump_region(6, frba);
+ printf("FLREG7: 0x%08x\n", frba->flreg7);
+ dump_region(7, frba);
+ printf("FLREG8: 0x%08x\n", frba->flreg8);
+ dump_region(8, frba);
+ }
}
static void dump_frba_layout(frba_t * frba, char *layout_fname)
@@ -225,7 +292,7 @@ static void dump_frba_layout(frba_t * frba, char *layout_fname)
exit(EXIT_FAILURE);
}
- for (i = 0; i < NUM_REGIONS; i++) {
+ for (i = 0; i < MAX_REGIONS; i++) {
dump_region_layout(buf, bufsize, i, frba);
if (write(layout_fd, buf, strlen(buf)) < 0) {
perror("Could not write to file");
@@ -245,8 +312,21 @@ static void decode_spi_frequency(unsigned int freq)
case SPI_FREQUENCY_33MHZ:
printf("33MHz");
break;
- case SPI_FREQUENCY_50MHZ:
- printf("50MHz");
+ case SPI_FREQUENCY_48MHZ:
+ printf("48MHz");
+ break;
+ case SPI_FREQUENCY_50MHZ_30MHZ:
+ switch (ifd_version) {
+ case IFD_VERSION_1:
+ printf("50MHz");
+ break;
+ case IFD_VERSION_2:
+ printf("30MHz");
+ break;
+ }
+ break;
+ case SPI_FREQUENCY_17MHZ:
+ printf("17MHz");
break;
default:
printf("unknown<%x>MHz", freq);
@@ -274,6 +354,15 @@ static void decode_component_density(unsigned int density)
case COMPONENT_DENSITY_16MB:
printf("16MB");
break;
+ case COMPONENT_DENSITY_32MB:
+ printf("32MB");
+ break;
+ case COMPONENT_DENSITY_64MB:
+ printf("64MB");
+ break;
+ case COMPONENT_DENSITY_UNUSED:
+ printf("UNUSED");
+ break;
default:
printf("unknown<%x>MB", density);
}
@@ -295,10 +384,22 @@ static void dump_fcba(fcba_t * fcba)
(fcba->flcomp & (1 << 20))?"":"not ");
printf("\n Read Clock Frequency: ");
decode_spi_frequency((fcba->flcomp >> 17) & 7);
- printf("\n Component 2 Density: ");
- decode_component_density((fcba->flcomp >> 3) & 7);
- printf("\n Component 1 Density: ");
- decode_component_density(fcba->flcomp & 7);
+
+ switch (ifd_version) {
+ case IFD_VERSION_1:
+ printf("\n Component 2 Density: ");
+ decode_component_density((fcba->flcomp >> 3) & 7);
+ printf("\n Component 1 Density: ");
+ decode_component_density(fcba->flcomp & 7);
+ break;
+ case IFD_VERSION_2:
+ printf("\n Component 2 Density: ");
+ decode_component_density((fcba->flcomp >> 4) & 0xf);
+ printf("\n Component 1 Density: ");
+ decode_component_density(fcba->flcomp & 0xf);
+ break;
+ }
+
printf("\n");
printf("FLILL 0x%08x\n", fcba->flill);
printf(" Invalid Instruction 3: 0x%02x\n",
@@ -339,6 +440,9 @@ static void dump_fpsba(fpsba_t * fpsba)
static void decode_flmstr(uint32_t flmstr)
{
+ if (ifd_version >= IFD_VERSION_2)
+ printf(" EC Region Write Access: %s\n",
+ (flmstr & (1 << 29)) ? "enabled" : "disabled");
printf(" Platform Data Region Write Access: %s\n",
(flmstr & (1 << 28)) ? "enabled" : "disabled");
printf(" GbE Region Write Access: %s\n",
@@ -350,6 +454,9 @@ static void decode_flmstr(uint32_t flmstr)
printf(" Flash Descriptor Write Access: %s\n",
(flmstr & (1 << 24)) ? "enabled" : "disabled");
+ if (ifd_version >= IFD_VERSION_2)
+ printf(" EC Region Read Access: %s\n",
+ (flmstr & (1 << 21)) ? "enabled" : "disabled");
printf(" Platform Data Region Read Access: %s\n",
(flmstr & (1 << 20)) ? "enabled" : "disabled");
printf(" GbE Region Read Access: %s\n",
@@ -374,6 +481,10 @@ static void dump_fmba(fmba_t * fmba)
decode_flmstr(fmba->flmstr2);
printf("FLMSTR3: 0x%08x (GbE)\n", fmba->flmstr3);
decode_flmstr(fmba->flmstr3);
+ if (ifd_version >= IFD_VERSION_2) {
+ printf("FLMSTR5: 0x%08x (EC)\n", fmba->flmstr5);
+ decode_flmstr(fmba->flmstr5);
+ }
}
static void dump_fmsba(fmsba_t * fmsba)
@@ -528,6 +639,7 @@ static void dump_layout(char *image, int size, char *layout_fname)
static void write_regions(char *image, int size)
{
int i;
+ int max_regions = MAX_REGIONS;
fdbar_t *fdb = find_fd(image, size);
if (!fdb)
@@ -536,7 +648,11 @@ static void write_regions(char *image, int size)
frba_t *frba =
(frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
- for (i = 0; i < NUM_REGIONS; i++) {
+ /* Older descriptor images have fewer regions */
+ if (ifd_version < IFD_VERSION_2)
+ max_regions = MAX_REGIONS_OLD;
+
+ for (i = 0; i < max_regions; i++) {
region_t region = get_region(frba, i);
dump_region(i, frba);
if (region.size > 0) {
@@ -601,9 +717,19 @@ static void set_em100_mode(char *filename, char *image, int size)
{
fdbar_t *fdb = find_fd(image, size);
fcba_t *fcba = (fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4));
+ int freq;
+
+ switch (ifd_version) {
+ case IFD_VERSION_1:
+ freq = SPI_FREQUENCY_20MHZ;
+ break;
+ case IFD_VERSION_2:
+ freq = SPI_FREQUENCY_17MHZ;
+ break;
+ }
fcba->flcomp &= ~(1 << 30);
- set_spi_frequency(filename, image, size, SPI_FREQUENCY_20MHZ);
+ set_spi_frequency(filename, image, size, freq);
}
static void lock_descriptor(char *filename, char *image, int size)
@@ -736,8 +862,8 @@ void new_layout(char *filename, char *image, int size, char *layout_fname)
char layout_region_name[256];
int i, j;
int region_number;
- region_t current_regions[NUM_REGIONS];
- region_t new_regions[NUM_REGIONS];
+ region_t current_regions[MAX_REGIONS];
+ region_t new_regions[MAX_REGIONS];
int new_extent = 0;
char *new_image;
@@ -749,7 +875,7 @@ void new_layout(char *filename, char *image, int size, char *layout_fname)
frba_t *frba =
(frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
- for (i = 0; i < NUM_REGIONS; i++) {
+ for (i = 0; i < MAX_REGIONS; i++) {
current_regions[i] = get_region(frba, i);
new_regions[i] = get_region(frba, i);
}
@@ -793,7 +919,7 @@ void new_layout(char *filename, char *image, int size, char *layout_fname)
fclose(romlayout);
/* check new layout */
- for (i = 0; i < NUM_REGIONS; i++) {
+ for (i = 0; i < MAX_REGIONS; i++) {
if (new_regions[i].size == 0)
continue;
@@ -804,7 +930,7 @@ void new_layout(char *filename, char *image, int size, char *layout_fname)
printf(" This may result in an unusable image.\n");
}
- for (j = i + 1; j < NUM_REGIONS; j++) {
+ for (j = i + 1; j < MAX_REGIONS; j++) {
if (regions_collide(new_regions[i], new_regions[j])) {
fprintf(stderr, "Regions would overlap.\n");
exit(EXIT_FAILURE);
@@ -826,7 +952,7 @@ void new_layout(char *filename, char *image, int size, char *layout_fname)
/* copy regions to a new image */
new_image = malloc(new_extent);
memset(new_image, 0xff, new_extent);
- for (i = 0; i < NUM_REGIONS; i++) {
+ for (i = 0; i < MAX_REGIONS; i++) {
int copy_size = new_regions[i].size;
int offset_current = 0, offset_new = 0;
region_t current = current_regions[i];
@@ -864,7 +990,7 @@ void new_layout(char *filename, char *image, int size, char *layout_fname)
exit(EXIT_FAILURE);
frba = (frba_t *) (new_image + (((fdb->flmap0 >> 16) & 0xff) << 4));
- for (i = 1; i < NUM_REGIONS; i++) {
+ for (i = 1; i < MAX_REGIONS; i++) {
set_region(frba, i, new_regions[i]);
}
@@ -892,18 +1018,18 @@ 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"
- " -n | --newlayout <filename> update regions using a flashrom layout file\n"
- " -s | --spifreq <20|33|50> set the SPI frequency\n"
- " -e | --em100 set SPI frequency to 20MHz and disable\n"
- " Dual Output Fast Read Support\n"
- " -l | --lock Lock firmware descriptor and ME region\n"
- " -u | --unlock Unlock firmware descriptor and ME region\n"
- " -v | --version: print the version\n"
- " -h | --help: print this help\n\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"
+ " -n | --newlayout <filename> update regions using a flashrom layout file\n"
+ " -s | --spifreq <17|20|30|33|48|50> set the SPI frequency\n"
+ " -e | --em100 set SPI frequency to 20MHz and disable\n"
+ " Dual Output Fast Read Support\n"
+ " -l | --lock Lock firmware descriptor and ME region\n"
+ " -u | --unlock Unlock firmware descriptor and ME region\n"
+ " -v | --version: print the version\n"
+ " -h | --help: print this help\n\n"
"<region> is one of Descriptor, BIOS, ME, GbE, Platform\n"
"\n");
}
@@ -973,6 +1099,8 @@ int main(int argc, char *argv[])
region_type = 3;
else if (!strcasecmp("Platform", region_type_string))
region_type = 4;
+ else if (!strcasecmp("EC", region_type_string))
+ region_type = 8;
if (region_type == -1) {
fprintf(stderr, "No such region type: '%s'\n\n",
region_type_string);
@@ -994,14 +1122,23 @@ int main(int argc, char *argv[])
// Parse the requested SPI frequency
inputfreq = strtol(optarg, NULL, 0);
switch (inputfreq) {
+ case 17:
+ spifreq = SPI_FREQUENCY_17MHZ;
+ break;
case 20:
spifreq = SPI_FREQUENCY_20MHZ;
break;
+ case 30:
+ spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
+ break;
case 33:
spifreq = SPI_FREQUENCY_33MHZ;
break;
+ case 48:
+ spifreq = SPI_FREQUENCY_48MHZ;
+ break;
case 50:
- spifreq = SPI_FREQUENCY_50MHZ;
+ spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
break;
default:
fprintf(stderr, "Invalid SPI Frequency: %d\n",
@@ -1091,6 +1228,8 @@ int main(int argc, char *argv[])
close(bios_fd);
+ check_ifd_version(image, size);
+
if (mode_dump)
dump_fd(image, size);
diff --git a/util/ifdtool/ifdtool.h b/util/ifdtool/ifdtool.h
index b91c02d..8b13283 100644
--- a/util/ifdtool/ifdtool.h
+++ b/util/ifdtool/ifdtool.h
@@ -18,14 +18,21 @@
*/
#include <stdint.h>
-#define IFDTOOL_VERSION "1.1"
+#define IFDTOOL_VERSION "1.2"
+
+enum ifd_version {
+ IFD_VERSION_1,
+ IFD_VERSION_2,
+};
#define LAYOUT_LINELEN 80
enum spi_frequency {
SPI_FREQUENCY_20MHZ = 0,
SPI_FREQUENCY_33MHZ = 1,
- SPI_FREQUENCY_50MHZ = 4,
+ SPI_FREQUENCY_48MHZ = 2,
+ SPI_FREQUENCY_50MHZ_30MHZ = 4,
+ SPI_FREQUENCY_17MHZ = 6,
};
enum component_density {
@@ -35,6 +42,9 @@ enum component_density {
COMPONENT_DENSITY_4MB = 3,
COMPONENT_DENSITY_8MB = 4,
COMPONENT_DENSITY_16MB = 5,
+ COMPONENT_DENSITY_32MB = 6,
+ COMPONENT_DENSITY_64MB = 7,
+ COMPONENT_DENSITY_UNUSED = 0xf
};
// flash descriptor
@@ -48,12 +58,18 @@ typedef struct {
} __attribute__((packed)) fdbar_t;
// regions
+#define MAX_REGIONS 9
+#define MAX_REGIONS_OLD 5
typedef struct {
uint32_t flreg0;
uint32_t flreg1;
uint32_t flreg2;
uint32_t flreg3;
uint32_t flreg4;
+ uint32_t flreg5;
+ uint32_t flreg6;
+ uint32_t flreg7;
+ uint32_t flreg8;
} __attribute__((packed)) frba_t;
// component section
@@ -90,6 +106,8 @@ typedef struct {
uint32_t flmstr1;
uint32_t flmstr2;
uint32_t flmstr3;
+ uint32_t flmstr4;
+ uint32_t flmstr5;
} __attribute__((packed)) fmba_t;
// processor strap
OpenPOWER on IntegriCloud