diff options
Diffstat (limited to 'util/ifdtool/ifdtool.c')
-rw-r--r-- | util/ifdtool/ifdtool.c | 223 |
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); |