aboutsummaryrefslogtreecommitdiff
path: root/util/ifdtool
diff options
context:
space:
mode:
authorStefan Reinauer <reinauer@chromium.org>2011-10-14 12:49:41 -0700
committerPatrick Georgi <patrick@georgi-clan.de>2011-10-22 10:40:18 +0200
commit1c795ad109bd382ff75e92d83f5721b8ed7c3be1 (patch)
treea1db7ff85704000af2b3916bb689a17454e79216 /util/ifdtool
parentc31c4de681738fc264333cb12aecdb995b119a94 (diff)
Add ifdtool, utility to read / modify Intel Firmware Descriptor images
Change-Id: Ie78b97bf573d238d0dff9a663e774deb1b7dea44 Signed-off-by: Stefan Reinauer <reinauer@google.com> Reviewed-on: http://review.coreboot.org/272 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Diffstat (limited to 'util/ifdtool')
-rw-r--r--util/ifdtool/Makefile53
-rw-r--r--util/ifdtool/ifdtool.c551
-rw-r--r--util/ifdtool/ifdtool.h87
3 files changed, 691 insertions, 0 deletions
diff --git a/util/ifdtool/Makefile b/util/ifdtool/Makefile
new file mode 100644
index 0000000000..fc8581f280
--- /dev/null
+++ b/util/ifdtool/Makefile
@@ -0,0 +1,53 @@
+#
+# ifdtool - dump Intel Firmware Descriptor information
+#
+# 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
+#
+
+PROGRAM = ifdtool
+
+CC = gcc
+INSTALL = /usr/bin/install
+PREFIX = /usr/local
+CFLAGS = -O2 -g -Wall -W
+LDFLAGS =
+
+OBJS = ifdtool.o
+
+all: dep $(PROGRAM)
+
+$(PROGRAM): $(OBJS)
+ $(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
+
+clean:
+ rm -f $(PROGRAM) *.o *~
+
+distclean: clean
+ rm -f .dependencies
+
+dep:
+ @$(CC) $(CFLAGS) -MM *.c > .dependencies
+
+install: $(PROGRAM)
+ mkdir -p $(DESTDIR)$(PREFIX)/bin
+ $(INSTALL) $(PROGRAM) $(DESTDIR)$(PREFIX)/bin
+ mkdir -p $(DESTDIR)$(PREFIX)/share/man/man8
+ $(INSTALL) $(PROGRAM).8 $(DESTDIR)$(PREFIX)/share/man/man8
+
+.PHONY: all clean distclean dep
+
+-include .dependencies
+
diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c
new file mode 100644
index 0000000000..204c4492dc
--- /dev/null
+++ b/util/ifdtool/ifdtool.c
@@ -0,0 +1,551 @@
+/*
+ * ifdtool - dump Intel Firmware Descriptor information
+ *
+ * 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 <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "ifdtool.h"
+
+static fdbar_t *find_fd(char *image, int size)
+{
+ int i, found = 0;
+
+ /* Scan for FD signature */
+ for (i = 0; i < (size - 4); i += 4) {
+ if (*(uint32_t *) (image + i) == 0x0FF0A55A) {
+ found = 1;
+ break; // signature found.
+ }
+ }
+
+ if (!found) {
+ printf("No Flash Descriptor found in this image\n");
+ return NULL;
+ }
+
+ printf("Found Flash Descriptor signature at 0x%08x\n", i);
+
+ return (fdbar_t *) (image + i);
+}
+
+typedef struct {
+ int base, limit, size;
+} region_t;
+
+static region_t get_region(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:
+ fprintf(stderr, "Invalid region type.\n");
+ exit (EXIT_FAILURE);
+ }
+
+ region.size = region.limit - region.base + 1;
+
+ return region;
+}
+
+static const char *region_name(int region_type)
+{
+ static const char *regions[5] = {
+ "Flash Descriptor",
+ "BIOS",
+ "Intel ME",
+ "GbE",
+ "Platform Data"
+ };
+
+ if (region_type < 0 || region_type > 4) {
+ fprintf(stderr, "Invalid region type.\n");
+ exit (EXIT_FAILURE);
+ }
+
+ return regions[region_type];
+}
+
+static const char *region_filename(int region_type)
+{
+ static const char *region_filenames[5] = {
+ "flashregion_0_flashdescriptor.bin",
+ "flashregion_1_bios.bin",
+ "flashregion_2_intel_me.bin",
+ "flashregion_3_gbe.bin",
+ "flashregion_4_platform_data.bin"
+ };
+
+ if (region_type < 0 || region_type > 4) {
+ fprintf(stderr, "Invalid region type.\n");
+ exit (EXIT_FAILURE);
+ }
+
+ return region_filenames[region_type];
+}
+
+static void dump_frba(frba_t * frba)
+{
+ printf("\nFound Region Section\n");
+ printf("FLREG0: 0x%08x\n", frba->flreg0);
+ printf("FLREG1: 0x%08x\n", frba->flreg1);
+ printf("FLREG2: 0x%08x\n", frba->flreg2);
+ printf("FLREG3: 0x%08x\n", frba->flreg3);
+ printf("FLREG4: 0x%08x\n", frba->flreg4);
+}
+
+static void decode_spi_frequency(unsigned int freq)
+{
+ switch (freq) {
+ case SPI_FREQUENCY_20MHZ:
+ printf("20MHz");
+ break;
+ case SPI_FREQUENCY_33MHZ:
+ printf("33MHz");
+ break;
+ case SPI_FREQUENCY_50MHZ:
+ printf("50MHz");
+ break;
+ default:
+ printf("unknown<%x>MHz", freq);
+ }
+}
+
+static void dump_fcba(fcba_t * fcba)
+{
+ printf("\nFound Component Section\n");
+ printf("FLCOMP 0x%08x\n", fcba->flcomp);
+ printf(" Read ID/Read Status Clock Frequency: ");
+ decode_spi_frequency((fcba->flcomp >> 27) & 7);
+ printf("\n Write/Erase Clock Frequency: ");
+ decode_spi_frequency((fcba->flcomp >> 24) & 7);
+ printf("\n Fast Read Clock Frequency: ");
+ decode_spi_frequency((fcba->flcomp >> 21) & 7);
+ printf("\n");
+ printf("FLILL 0x%08x\n", fcba->flill);
+ printf("FLPB 0x%08x\n", fcba->flpb);
+}
+
+static void dump_fpsba(fpsba_t * fpsba)
+{
+ printf("\nFound PCH Strap Section\n");
+ printf("PCHSTRP0: 0x%08x\n", fpsba->pchstrp0);
+ printf("PCHSTRP1: 0x%08x\n", fpsba->pchstrp1);
+ printf("PCHSTRP2: 0x%08x\n", fpsba->pchstrp2);
+ printf("PCHSTRP3: 0x%08x\n", fpsba->pchstrp3);
+ printf("PCHSTRP4: 0x%08x\n", fpsba->pchstrp4);
+ printf("PCHSTRP5: 0x%08x\n", fpsba->pchstrp5);
+ printf("PCHSTRP6: 0x%08x\n", fpsba->pchstrp6);
+ printf("PCHSTRP7: 0x%08x\n", fpsba->pchstrp7);
+ printf("PCHSTRP8: 0x%08x\n", fpsba->pchstrp8);
+ printf("PCHSTRP9: 0x%08x\n", fpsba->pchstrp9);
+ printf("PCHSTRP10: 0x%08x\n", fpsba->pchstrp10);
+ printf("PCHSTRP11: 0x%08x\n", fpsba->pchstrp11);
+ printf("PCHSTRP12: 0x%08x\n", fpsba->pchstrp12);
+ printf("PCHSTRP13: 0x%08x\n", fpsba->pchstrp13);
+ printf("PCHSTRP14: 0x%08x\n", fpsba->pchstrp14);
+ printf("PCHSTRP15: 0x%08x\n", fpsba->pchstrp15);
+}
+
+static void dump_fmba(fmba_t * fmba)
+{
+ printf("\nFound Master Section\n");
+ printf("FLMSTR1: 0x%08x\n", fmba->flmstr1);
+ printf("FLMSTR2: 0x%08x\n", fmba->flmstr2);
+ printf("FLMSTR3: 0x%08x\n", fmba->flmstr3);
+}
+
+static void dump_fmsba(fmsba_t * fmsba)
+{
+ printf("\nFound Processor Strap Section\n");
+ printf("????: 0x%08x\n", fmsba->data[0]);
+ printf("????: 0x%08x\n", fmsba->data[1]);
+ printf("????: 0x%08x\n", fmsba->data[2]);
+ printf("????: 0x%08x\n", fmsba->data[3]);
+}
+
+static void dump_fd(char *image, int size)
+{
+ fdbar_t *fdb = find_fd(image, size);
+ if (!fdb)
+ exit(EXIT_FAILURE);
+
+ printf("FLMAP0: 0x%08x\n", fdb->flmap0);
+ printf(" NR: %d\n", (fdb->flmap0 >> 24) & 7);
+ printf(" FRBA: 0x%x\n", ((fdb->flmap0 >> 16) & 0xff) << 4);
+ printf(" NC: %d\n", ((fdb->flmap0 >> 8) & 3) + 1);
+ printf(" FCBA: 0x%x\n", ((fdb->flmap0) & 0xff) << 4);
+
+ printf("FLMAP1: 0x%08x\n", fdb->flmap1);
+ printf(" ISL: 0x%02x\n", (fdb->flmap1 >> 24) & 0xff);
+ printf(" FPSBA: 0x%x\n", ((fdb->flmap1 >> 16) & 0xff) << 4);
+ printf(" NM: %d\n", (fdb->flmap1 >> 8) & 3);
+ printf(" FMBA: 0x%x\n", ((fdb->flmap1) & 0xff) << 4);
+
+ printf("FLMAP2: 0x%08x\n", fdb->flmap2);
+ printf(" PSL: 0x%04x\n", (fdb->flmap2 >> 8) & 0xffff);
+ printf(" FMSBA: 0x%x\n", ((fdb->flmap2) & 0xff) << 4);
+
+ printf("FLUMAP1: 0x%08x\n", fdb->flumap1);
+
+ dump_frba((frba_t *)
+ (image + (((fdb->flmap0 >> 16) & 0xff) << 4)));
+ dump_fcba((fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4)));
+ dump_fpsba((fpsba_t *)
+ (image + (((fdb->flmap1 >> 16) & 0xff) << 4)));
+ dump_fmba((fmba_t *) (image + (((fdb->flmap1) & 0xff) << 4)));
+ dump_fmsba((fmsba_t *) (image + (((fdb->flmap2) & 0xff) << 4)));
+}
+
+static void write_regions(char *image, int size)
+{
+ int i;
+
+ fdbar_t *fdb = find_fd(image, size);
+ if (!fdb)
+ exit(EXIT_FAILURE);
+
+ frba_t *frba =
+ (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
+
+ for (i = 0; i<5; i++) {
+ region_t region = get_region(frba, i);
+ printf("Flash Region %d (%s): %08x - %08x %s\n",
+ i, region_name(i), region.base, region.limit,
+ region.size < 1 ? "(unused)" : "");
+ if (region.size > 0) {
+ int region_fd;
+ region_fd = open(region_filename(i),
+ O_WRONLY | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (write(region_fd, image + region.base, region.size) != region.size)
+ printf("Error while writing.");
+ close(region_fd);
+ }
+ }
+}
+
+static void write_image(char *filename, char *image, int size)
+{
+ char new_filename[FILENAME_MAX]; // allow long file names
+ int new_fd;
+
+ strncpy(new_filename, filename, FILENAME_MAX);
+ strncat(new_filename, ".new", FILENAME_MAX - strlen(filename));
+
+ printf("Writing new image to %s\n", new_filename);
+
+ // Now write out new image
+ new_fd = open(new_filename,
+ O_WRONLY | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (write(new_fd, image, size) != size)
+ printf("Error while writing.");
+ close(new_fd);
+}
+
+static void set_spi_frequency(char *filename, char *image, int size,
+ enum spi_frequency freq)
+{
+ fdbar_t *fdb = find_fd(image, size);
+ fcba_t *fcba = (fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4));
+
+ /* clear bits 21-29 */
+ fcba->flcomp &= ~0x3fe00000;
+ /* Read ID and Read Status Clock Frequency */
+ fcba->flcomp |= freq << 27;
+ /* Write and Erase Clock Frequency */
+ fcba->flcomp |= freq << 24;
+ /* Fast Read Clock Frequency */
+ fcba->flcomp |= freq << 21;
+
+ write_image(filename, image, size);
+}
+
+void inject_region(char *filename, char *image, int size, int region_type,
+ char *region_fname)
+{
+ fdbar_t *fdb = find_fd(image, size);
+ if (!fdb)
+ exit(EXIT_FAILURE);
+ frba_t *frba =
+ (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
+
+ region_t region = get_region(frba, region_type);
+ if (region.size <= 0xfff) {
+ fprintf(stderr, "Region %s is disabled in target. Not injecting.\n",
+ region_name(region_type));
+ exit(EXIT_FAILURE);
+ }
+
+ int region_fd = open(region_fname, O_RDONLY);
+ if (region_fd == -1) {
+ perror("Could not open file");
+ exit(EXIT_FAILURE);
+ }
+ struct stat buf;
+ if (fstat(region_fd, &buf) == -1) {
+ perror("Could not stat file");
+ exit(EXIT_FAILURE);
+ }
+ int region_size = buf.st_size;
+
+ printf("File %s is %d bytes\n", region_fname, region_size);
+
+ if ( (region_size > region.size) || ((region_type != 1) &&
+ (region_size != region.size))) {
+ fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
+ " bytes. Not injecting.\n",
+ region_name(region_type), region.size,
+ region.size, region_size, region_size);
+ exit(EXIT_FAILURE);
+ }
+
+ int offset = 0;
+ if ((region_type == 1) && (region_size < region.size)) {
+ fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"
+ " bytes. Padding before injecting.\n",
+ region_name(region_type), region.size,
+ region.size, region_size, region_size);
+ offset = region.size - region_size;
+ memset(image + region.base, 0xff, offset);
+ }
+
+ if (read(region_fd, image + region.base + offset, region_size)
+ != region_size) {
+ perror("Could not read file");
+ exit(EXIT_FAILURE);
+ }
+
+ close(region_fd);
+
+ printf("Adding %s as the %s section of %s\n",
+ region_fname, region_name(region_type), filename);
+ write_image(filename, image, size);
+}
+
+static void print_version(void)
+{
+ printf("ifdtool v%s -- ", IFDTOOL_VERSION);
+ printf("Copyright (C) 2011 Google Inc.\n\n");
+ printf
+ ("This program is free software: you can redistribute it and/or modify\n"
+ "it under the terms of the GNU General Public License as published by\n"
+ "the Free Software Foundation, version 2 of the License.\n\n"
+ "This program is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n\n"
+ "You should have received a copy of the GNU General Public License\n"
+ "along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n");
+}
+
+static void print_usage(const char *name)
+{
+ printf("usage: %s [-vhdix?] <filename>\n", name);
+ printf("\n"
+ " -d | --dump: dump intel firmware descriptor\n"
+ " -x | --extract: extract intel fd modules\n"
+ " -i | --inject <region>:<module> inject file <module> into region <region>\n"
+ " -s | --spifreq <20|33|50> set the SPI frequency\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");
+}
+
+int main(int argc, char *argv[])
+{
+ int opt, option_index = 0;
+ int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;
+ char *region_type_string = NULL, *region_fname = NULL;
+ int region_type = -1, inputfreq = 0;
+ enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
+
+ static struct option long_options[] = {
+ {"dump", 0, NULL, 'd'},
+ {"extract", 0, NULL, 'x'},
+ {"inject", 1, NULL, 'i'},
+ {"spifreq", 1, NULL, 's'},
+ {"version", 0, NULL, 'v'},
+ {"help", 0, NULL, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ while ((opt = getopt_long(argc, argv, "dxi:s:vh?",
+ long_options, &option_index)) != EOF) {
+ switch (opt) {
+ case 'd':
+ mode_dump = 1;
+ break;
+ case 'x':
+ mode_extract = 1;
+ break;
+ case 'i':
+ // separate type and file name
+ region_type_string = strdup(optarg);
+ region_fname = strchr(region_type_string, ':');
+ if (!region_fname) {
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ region_fname[0] = '\0';
+ region_fname++;
+ // Descriptor, BIOS, ME, GbE, Platform
+ // valid type?
+ if (!strcasecmp("Descriptor", region_type_string))
+ region_type = 0;
+ else if (!strcasecmp("BIOS", region_type_string))
+ region_type = 1;
+ else if (!strcasecmp("ME", region_type_string))
+ region_type = 2;
+ else if (!strcasecmp("GbE", region_type_string))
+ region_type = 3;
+ else if (!strcasecmp("Platform", region_type_string))
+ region_type = 4;
+ if (region_type == -1) {
+ fprintf(stderr, "No such region type: '%s'\n\n",
+ region_type_string);
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ mode_inject = 1;
+ break;
+ case 's':
+ // Parse the requested SPI frequency
+ inputfreq = strtol(optarg, NULL, 0);
+ switch (inputfreq) {
+ case 20:
+ spifreq = SPI_FREQUENCY_20MHZ;
+ break;
+ case 33:
+ spifreq = SPI_FREQUENCY_33MHZ;
+ break;
+ case 50:
+ spifreq = SPI_FREQUENCY_50MHZ;
+ break;
+ default:
+ fprintf(stderr, "Invalid SPI Frequency: %d\n",
+ inputfreq);
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ mode_spifreq = 1;
+ break;
+ case 'v':
+ print_version();
+ exit(EXIT_SUCCESS);
+ break;
+ case 'h':
+ case '?':
+ default:
+ print_usage(argv[0]);
+ exit(EXIT_SUCCESS);
+ break;
+ }
+ }
+
+ if ((mode_dump + mode_extract + mode_inject + mode_spifreq) > 1) {
+ fprintf(stderr, "Only one mode allowed.\n\n");
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if ((mode_dump + mode_extract + mode_inject + mode_spifreq) == 0) {
+ fprintf(stderr, "You need to specify a mode.\n\n");
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (optind + 1 != argc) {
+ fprintf(stderr, "You need to specify a file.\n\n");
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ char *filename = argv[optind];
+ int bios_fd = open(filename, O_RDONLY);
+ if (bios_fd == -1) {
+ perror("Could not open file");
+ exit(EXIT_FAILURE);
+ }
+ struct stat buf;
+ if (fstat(bios_fd, &buf) == -1) {
+ perror("Could not stat file");
+ exit(EXIT_FAILURE);
+ }
+ int size = buf.st_size;
+
+ printf("File %s is %d bytes\n", filename, size);
+
+ char *image = malloc(size);
+ if (!image) {
+ printf("Out of memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (read(bios_fd, image, size) != size) {
+ perror("Could not read file");
+ exit(EXIT_FAILURE);
+ }
+
+ close(bios_fd);
+
+ if (mode_dump)
+ dump_fd(image, size);
+
+ if (mode_extract)
+ write_regions(image, size);
+
+ if (mode_inject)
+ inject_region(filename, image, size, region_type,
+ region_fname);
+
+ if (mode_spifreq)
+ set_spi_frequency(filename, image, size, spifreq);
+
+ free(image);
+
+ return 0;
+}
diff --git a/util/ifdtool/ifdtool.h b/util/ifdtool/ifdtool.h
new file mode 100644
index 0000000000..057153434d
--- /dev/null
+++ b/util/ifdtool/ifdtool.h
@@ -0,0 +1,87 @@
+/*
+ * ifdtool - dump Intel Firmware Descriptor information
+ *
+ * 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>
+#define IFDTOOL_VERSION "1.0"
+
+enum spi_frequency {
+ SPI_FREQUENCY_20MHZ = 0,
+ SPI_FREQUENCY_33MHZ = 1,
+ SPI_FREQUENCY_50MHZ = 4,
+};
+
+// 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;
+
+// component section
+typedef struct {
+ uint32_t flcomp;
+ uint32_t flill;
+ uint32_t flpb;
+} __attribute__((packed)) fcba_t;
+
+// pch strap
+typedef struct {
+ uint32_t pchstrp0;
+ uint32_t pchstrp1;
+ uint32_t pchstrp2;
+ uint32_t pchstrp3;
+ uint32_t pchstrp4;
+ uint32_t pchstrp5;
+ uint32_t pchstrp6;
+ uint32_t pchstrp7;
+ uint32_t pchstrp8;
+ uint32_t pchstrp9;
+ uint32_t pchstrp10;
+ uint32_t pchstrp11;
+ uint32_t pchstrp12;
+ uint32_t pchstrp13;
+ uint32_t pchstrp14;
+ uint32_t pchstrp15;
+} __attribute__((packed)) fpsba_t;
+
+// master
+typedef struct {
+ uint32_t flmstr1;
+ uint32_t flmstr2;
+ uint32_t flmstr3;
+} __attribute__((packed)) fmba_t;
+
+// processor strap
+typedef struct {
+ uint32_t data[8];
+} __attribute__((packed)) fmsba_t;
+
+