summaryrefslogtreecommitdiff
path: root/util/ifdtool/ifdtool.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/ifdtool/ifdtool.c')
-rw-r--r--util/ifdtool/ifdtool.c223
1 files changed, 181 insertions, 42 deletions
diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c
index 8d5d05904b..6856400939 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);