<p>Denis 'GNUtoo' Carikli has uploaded this change for <strong>review</strong>.</p><p><a href="https://review.coreboot.org/20434">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">[RFC] [WIP] ifdtool: rework command line interface<br><br>The command line interface has been very much inspired by<br>the one from cbfstool, as it easily allow to add more<br>functionality, such as the creation of new images with<br>valid or fake Intel flash descriptor.<br><br>This could be then implemented by merging the code and/or<br>functionality from ifdfake and ich9gen in this tool.<br><br>Change-Id: I6e463239c4f727a6296e4eca24682966b4160e3b<br>Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@no-log.org><br>---<br>M util/ifdtool/ifdtool.c<br>M util/ifdtool/ifdtool.h<br>2 files changed, 379 insertions(+), 374 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://review.coreboot.org:29418/coreboot refs/changes/34/20434/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c<br>index 9382bc4..482f4e5 100644<br>--- a/util/ifdtool/ifdtool.c<br>+++ b/util/ifdtool/ifdtool.c<br>@@ -13,35 +13,56 @@<br> * GNU General Public License for more details.<br> */<br> <br>-#include <unistd.h><br>-#include <stdlib.h><br>-#include <stdio.h><br>-#include <string.h><br>-#include <getopt.h><br> #include <fcntl.h><br>-#include <sys/types.h><br>+#include <getopt.h><br>+#include <stdio.h><br>+#include <stdlib.h><br>+#include <string.h><br>+#include <unistd.h><br> #include <sys/stat.h><br>+#include <sys/types.h><br> #include "ifdtool.h"<br> <br> #ifndef O_BINARY<br> #define O_BINARY 0<br> #endif<br> <br>+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))<br>+<br> static int ifd_version;<br> static int max_regions = 0;<br> static int selected_chip = 0;<br> static int platform = -1;<br> <br>+struct command {<br>+ const char *name;<br>+ const char *optstring;<br>+};<br>+<br>+static struct param {<br>+ const char *ifd_filename;<br>+ const char *region_name;<br>+ const char *region_filename;<br>+} param;<br>+<br> static const struct region_name region_names[MAX_REGIONS] = {<br>- { "Flash Descriptor", "fd" },<br>- { "BIOS", "bios" },<br>- { "Intel ME", "me" },<br>- { "GbE", "gbe" },<br>- { "Platform Data", "pd" },<br>- { "Reserved", "res1" },<br>- { "Reserved", "res2" },<br>- { "Reserved", "res3" },<br>- { "EC", "ec" },<br>+ { "Flash Descriptor", "fd" , "Descriptor"},<br>+ { "BIOS", "bios" , "BIOS"},<br>+ { "Intel ME", "me", "ME"},<br>+ { "GbE", "gbe", "GbE" },<br>+ { "Platform Data", "pd", "Platform" },<br>+ { "Reserved", "res1", NULL },<br>+ { "Reserved", "res2", NULL },<br>+ { "Reserved", "res3", NULL },<br>+ { "EC", "ec", "EC" },<br>+};<br>+<br>+static enum cmdline_action {<br>+ MODE_DUMP,<br>+ MODE_EXTRACT,<br>+ MODE_INJECT,<br>+ MODE_INVALID,<br>+ MODE_CONFIGURE,<br> };<br> <br> static fdbar_t *find_fd(char *image, int size)<br>@@ -209,7 +230,7 @@<br> return region_names[region_type].terse;<br> }<br> <br>-static int region_num(const char *name)<br>+static int region_num(const char *name, int max_regions)<br> {<br> int i;<br> <br>@@ -218,6 +239,10 @@<br> return i;<br> if (strcasecmp(name, region_names[i].terse) == 0)<br> return i;<br>+ if (region_names[i].type) {<br>+ if (strcasecmp(name, region_names[i].type) == 0)<br>+ return i;<br>+ }<br> }<br> <br> return -1;<br>@@ -249,15 +274,15 @@<br> {<br> region_t region = get_region(frba, num);<br> printf(" Flash Region %d (%s): %08x - %08x %s\n",<br>- num, region_name(num), region.base, region.limit,<br>- region.size < 1 ? "(unused)" : "");<br>+ num, region_name(num), region.base, region.limit,<br>+ region.size < 1 ? "(unused)" : "");<br> }<br> <br> static void dump_region_layout(char *buf, size_t bufsize, int num, frba_t *frba)<br> {<br> region_t region = get_region(frba, num);<br> snprintf(buf, bufsize, "%08x:%08x %s\n",<br>- region.base, region.limit, region_name_short(num));<br>+ region.base, region.limit, region_name_short(num));<br> }<br> <br> static void dump_frba(frba_t * frba)<br>@@ -293,7 +318,7 @@<br> int i;<br> <br> int layout_fd = open(layout_fname, O_WRONLY | O_CREAT | O_TRUNC,<br>- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);<br>+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);<br> if (layout_fd == -1) {<br> perror("Could not open file");<br> exit(EXIT_FAILURE);<br>@@ -345,6 +370,42 @@<br> }<br> }<br> <br>+static unsigned int encode_component_density(unsigned int density)<br>+{<br>+ unsigned int new_density = COMPONENT_DENSITY_UNUSED;<br>+<br>+ switch(density) {<br>+ case 512:<br>+ new_density = COMPONENT_DENSITY_512KB;<br>+ break;<br>+ case 1:<br>+ new_density = COMPONENT_DENSITY_1MB;<br>+ break;<br>+ case 2:<br>+ new_density = COMPONENT_DENSITY_2MB;<br>+ break;<br>+ case 4:<br>+ new_density = COMPONENT_DENSITY_4MB;<br>+ break;<br>+ case 8:<br>+ new_density = COMPONENT_DENSITY_8MB;<br>+ break;<br>+ case 16:<br>+ new_density = COMPONENT_DENSITY_16MB;<br>+ break;<br>+ case 32:<br>+ new_density = COMPONENT_DENSITY_32MB;<br>+ break;<br>+ case 64:<br>+ new_density = COMPONENT_DENSITY_64MB;<br>+ break;<br>+ default:<br>+ printf("error: Unknown density\n");<br>+ }<br>+<br>+ return new_density;<br>+}<br>+<br> static void decode_component_density(unsigned int density)<br> {<br> switch (density) {<br>@@ -385,7 +446,7 @@<br> printf("\nFound Component Section\n");<br> printf("FLCOMP 0x%08x\n", fcba->flcomp);<br> printf(" Dual Output Fast Read Support: %ssupported\n",<br>- (fcba->flcomp & (1 << 30))?"":"not ");<br>+ (fcba->flcomp & (1 << 30))?"":"not ");<br> printf(" Read ID/Read Status Clock Frequency: ");<br> decode_spi_frequency((fcba->flcomp >> 27) & 7);<br> printf("\n Write/Erase Clock Frequency: ");<br>@@ -393,7 +454,7 @@<br> printf("\n Fast Read Clock Frequency: ");<br> decode_spi_frequency((fcba->flcomp >> 21) & 7);<br> printf("\n Fast Read Support: %ssupported",<br>- (fcba->flcomp & (1 << 20))?"":"not ");<br>+ (fcba->flcomp & (1 << 20))?"":"not ");<br> printf("\n Read Clock Frequency: ");<br> decode_spi_frequency((fcba->flcomp >> 17) & 7);<br> <br>@@ -415,16 +476,16 @@<br> printf("\n");<br> printf("FLILL 0x%08x\n", fcba->flill);<br> printf(" Invalid Instruction 3: 0x%02x\n",<br>- (fcba->flill >> 24) & 0xff);<br>+ (fcba->flill >> 24) & 0xff);<br> printf(" Invalid Instruction 2: 0x%02x\n",<br>- (fcba->flill >> 16) & 0xff);<br>+ (fcba->flill >> 16) & 0xff);<br> printf(" Invalid Instruction 1: 0x%02x\n",<br>- (fcba->flill >> 8) & 0xff);<br>+ (fcba->flill >> 8) & 0xff);<br> printf(" Invalid Instruction 0: 0x%02x\n",<br>- fcba->flill & 0xff);<br>+ fcba->flill & 0xff);<br> printf("FLPB 0x%08x\n", fcba->flpb);<br> printf(" Flash Partition Boundary Address: 0x%06x\n\n",<br>- (fcba->flpb & 0xfff) << 12);<br>+ (fcba->flpb & 0xfff) << 12);<br> }<br> <br> static void dump_fpsba(fpsba_t * fpsba)<br>@@ -467,35 +528,35 @@<br> (flmstr & (1 << (wr_shift + 8))) ?<br> "enabled" : "disabled");<br> printf(" Platform Data Region Write Access: %s\n",<br>- (flmstr & (1 << (wr_shift + 4))) ? "enabled" : "disabled");<br>+ (flmstr & (1 << (wr_shift + 4))) ? "enabled" : "disabled");<br> printf(" GbE Region Write Access: %s\n",<br>- (flmstr & (1 << (wr_shift + 3))) ? "enabled" : "disabled");<br>+ (flmstr & (1 << (wr_shift + 3))) ? "enabled" : "disabled");<br> printf(" Intel ME Region Write Access: %s\n",<br>- (flmstr & (1 << (wr_shift + 2))) ? "enabled" : "disabled");<br>+ (flmstr & (1 << (wr_shift + 2))) ? "enabled" : "disabled");<br> printf(" Host CPU/BIOS Region Write Access: %s\n",<br>- (flmstr & (1 << (wr_shift + 1))) ? "enabled" : "disabled");<br>+ (flmstr & (1 << (wr_shift + 1))) ? "enabled" : "disabled");<br> printf(" Flash Descriptor Write Access: %s\n",<br>- (flmstr & (1 << wr_shift)) ? "enabled" : "disabled");<br>+ (flmstr & (1 << wr_shift)) ? "enabled" : "disabled");<br> <br> if (ifd_version >= IFD_VERSION_2)<br> printf(" EC Region Read Access: %s\n",<br> (flmstr & (1 << (rd_shift + 8))) ?<br> "enabled" : "disabled");<br> printf(" Platform Data Region Read Access: %s\n",<br>- (flmstr & (1 << (rd_shift + 4))) ? "enabled" : "disabled");<br>+ (flmstr & (1 << (rd_shift + 4))) ? "enabled" : "disabled");<br> printf(" GbE Region Read Access: %s\n",<br>- (flmstr & (1 << (rd_shift + 3))) ? "enabled" : "disabled");<br>+ (flmstr & (1 << (rd_shift + 3))) ? "enabled" : "disabled");<br> printf(" Intel ME Region Read Access: %s\n",<br>- (flmstr & (1 << (rd_shift + 2))) ? "enabled" : "disabled");<br>+ (flmstr & (1 << (rd_shift + 2))) ? "enabled" : "disabled");<br> printf(" Host CPU/BIOS Region Read Access: %s\n",<br>- (flmstr & (1 << (rd_shift + 1))) ? "enabled" : "disabled");<br>+ (flmstr & (1 << (rd_shift + 1))) ? "enabled" : "disabled");<br> printf(" Flash Descriptor Read Access: %s\n",<br>- (flmstr & (1 << rd_shift)) ? "enabled" : "disabled");<br>+ (flmstr & (1 << rd_shift)) ? "enabled" : "disabled");<br> <br> /* Requestor ID doesn't exist for ifd 2 */<br> if (ifd_version < IFD_VERSION_2)<br> printf(" Requester ID: 0x%04x\n\n",<br>- flmstr & 0xffff);<br>+ flmstr & 0xffff);<br> }<br> <br> static void dump_fmba(fmba_t * fmba)<br>@@ -525,23 +586,23 @@<br> static void dump_jid(uint32_t jid)<br> {<br> printf(" SPI Componend Device ID 1: 0x%02x\n",<br>- (jid >> 16) & 0xff);<br>+ (jid >> 16) & 0xff);<br> printf(" SPI Componend Device ID 0: 0x%02x\n",<br>- (jid >> 8) & 0xff);<br>+ (jid >> 8) & 0xff);<br> printf(" SPI Componend Vendor ID: 0x%02x\n",<br>- jid & 0xff);<br>+ jid & 0xff);<br> }<br> <br> static void dump_vscc(uint32_t vscc)<br> {<br> printf(" Lower Erase Opcode: 0x%02x\n",<br>- vscc >> 24);<br>+ vscc >> 24);<br> printf(" Lower Write Enable on Write Status: 0x%02x\n",<br>- vscc & (1 << 20) ? 0x06 : 0x50);<br>+ vscc & (1 << 20) ? 0x06 : 0x50);<br> printf(" Lower Write Status Required: %s\n",<br>- vscc & (1 << 19) ? "Yes" : "No");<br>+ vscc & (1 << 19) ? "Yes" : "No");<br> printf(" Lower Write Granularity: %d bytes\n",<br>- vscc & (1 << 18) ? 64 : 1);<br>+ vscc & (1 << 18) ? 64 : 1);<br> printf(" Lower Block / Sector Erase Size: ");<br> switch ((vscc >> 16) & 0x3) {<br> case 0:<br>@@ -559,13 +620,13 @@<br> }<br> <br> printf(" Upper Erase Opcode: 0x%02x\n",<br>- (vscc >> 8) & 0xff);<br>+ (vscc >> 8) & 0xff);<br> printf(" Upper Write Enable on Write Status: 0x%02x\n",<br>- vscc & (1 << 4) ? 0x06 : 0x50);<br>+ vscc & (1 << 4) ? 0x06 : 0x50);<br> printf(" Upper Write Status Required: %s\n",<br>- vscc & (1 << 3) ? "Yes" : "No");<br>+ vscc & (1 << 3) ? "Yes" : "No");<br> printf(" Upper Write Granularity: %d bytes\n",<br>- vscc & (1 << 2) ? 64 : 1);<br>+ vscc & (1 << 2) ? 64 : 1);<br> printf(" Upper Block / Sector Erase Size: ");<br> switch (vscc & 0x3) {<br> case 0:<br>@@ -635,18 +696,18 @@<br> <br> printf("FLUMAP1: 0x%08x\n", fdb->flumap1);<br> printf(" Intel ME VSCC Table Length (VTL): %d\n",<br>- (fdb->flumap1 >> 8) & 0xff);<br>+ (fdb->flumap1 >> 8) & 0xff);<br> printf(" Intel ME VSCC Table Base Address (VTBA): 0x%06x\n\n",<br>- (fdb->flumap1 & 0xff) << 4);<br>+ (fdb->flumap1 & 0xff) << 4);<br> dump_vtba((vtba_t *)<br>- (image + ((fdb->flumap1 & 0xff) << 4)),<br>- (fdb->flumap1 >> 8) & 0xff);<br>+ (image + ((fdb->flumap1 & 0xff) << 4)),<br>+ (fdb->flumap1 >> 8) & 0xff);<br> dump_oem((uint8_t *)image + 0xf00);<br> dump_frba((frba_t *)<br>- (image + (((fdb->flmap0 >> 16) & 0xff) << 4)));<br>+ (image + (((fdb->flmap0 >> 16) & 0xff) << 4)));<br> dump_fcba((fcba_t *) (image + (((fdb->flmap0) & 0xff) << 4)));<br> dump_fpsba((fpsba_t *)<br>- (image + (((fdb->flmap1 >> 16) & 0xff) << 4)));<br>+ (image + (((fdb->flmap1 >> 16) & 0xff) << 4)));<br> dump_fmba((fmba_t *) (image + (((fdb->flmap1) & 0xff) << 4)));<br> dump_fmsba((fmsba_t *) (image + (((fdb->flmap2) & 0xff) << 4)));<br> }<br>@@ -658,8 +719,8 @@<br> exit(EXIT_FAILURE);<br> <br> dump_frba_layout((frba_t *)<br>- (image + (((fdb->flmap0 >> 16) & 0xff) << 4)),<br>- layout_fname);<br>+ (image + (((fdb->flmap0 >> 16) & 0xff) << 4)),<br>+ layout_fname);<br> }<br> <br> static void write_regions(char *image, int size)<br>@@ -671,7 +732,7 @@<br> exit(EXIT_FAILURE);<br> <br> frba_t *frba =<br>- (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));<br>+ (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));<br> <br> for (i = 0; i < max_regions; i++) {<br> region_t region = get_region(frba, i);<br>@@ -694,19 +755,14 @@<br> <br> static void write_image(char *filename, char *image, int size)<br> {<br>- char new_filename[FILENAME_MAX]; // allow long file names<br> int new_fd;<br> <br>- // - 5: leave room for ".new\0"<br>- strncpy(new_filename, filename, FILENAME_MAX - 5);<br>- strncat(new_filename, ".new", FILENAME_MAX - strlen(filename));<br>-<br>- printf("Writing new image to %s\n", new_filename);<br>+ printf("Writing image to %s\n", filename);<br> <br> // Now write out new image<br>- new_fd = open(new_filename,<br>- O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,<br>- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);<br>+ new_fd = open(filename,<br>+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,<br>+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);<br> if (new_fd < 0) {<br> perror("Error while trying to open file");<br> exit(EXIT_FAILURE);<br>@@ -886,6 +942,36 @@<br> write_image(filename, image, size);<br> }<br> <br>+<br>+static void extract_region(char *image, int size, int region_type,<br>+ char *region_filename)<br>+{<br>+ int i;<br>+<br>+ fdbar_t *fdb = find_fd(image, size);<br>+ if (!fdb)<br>+ exit(EXIT_FAILURE);<br>+<br>+ frba_t *frba =<br>+ (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));<br>+<br>+ region_t region = get_region(frba, region_type);<br>+ dump_region(region_type, frba);<br>+ if (region.size > 0) {<br>+ int region_fd;<br>+ region_fd = open(region_filename,<br>+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,<br>+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);<br>+ if (region_fd < 0) {<br>+ perror("Error while trying to open file");<br>+ exit(EXIT_FAILURE);<br>+ }<br>+ if (write(region_fd, image + region.base, region.size) != region.size)<br>+ perror("Error while writing");<br>+ close(region_fd);<br>+ }<br>+}<br>+<br> void inject_region(char *filename, char *image, int size, int region_type,<br> char *region_fname)<br> {<br>@@ -893,12 +979,12 @@<br> if (!fdb)<br> exit(EXIT_FAILURE);<br> frba_t *frba =<br>- (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));<br>+ (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));<br> <br> region_t region = get_region(frba, region_type);<br> if (region.size <= 0xfff) {<br> fprintf(stderr, "Region %s is disabled in target. Not injecting.\n",<br>- region_name(region_type));<br>+ region_name(region_type));<br> exit(EXIT_FAILURE);<br> }<br> <br>@@ -917,20 +1003,20 @@<br> printf("File %s is %d bytes\n", region_fname, region_size);<br> <br> if ( (region_size > region.size) || ((region_type != 1) &&<br>- (region_size > region.size))) {<br>+ (region_size > region.size))) {<br> fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"<br>- " bytes. Not injecting.\n",<br>- region_name(region_type), region.size,<br>- region.size, region_size, region_size);<br>+ " bytes. Not injecting.\n",<br>+ region_name(region_type), region.size,<br>+ region.size, region_size, region_size);<br> exit(EXIT_FAILURE);<br> }<br> <br> int offset = 0;<br> if ((region_type == 1) && (region_size < region.size)) {<br> fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x)"<br>- " bytes. Padding before injecting.\n",<br>- region_name(region_type), region.size,<br>- region.size, region_size, region_size);<br>+ " bytes. Padding before injecting.\n",<br>+ region_name(region_type), region.size,<br>+ region.size, region_size, region_size);<br> offset = region.size - region_size;<br> memset(image + region.base, 0xff, offset);<br> }<br>@@ -942,7 +1028,7 @@<br> }<br> <br> if (read(region_fd, image + region.base + offset, region_size)<br>- != region_size) {<br>+ != region_size) {<br> perror("Could not read file");<br> exit(EXIT_FAILURE);<br> }<br>@@ -1002,7 +1088,7 @@<br> exit(EXIT_FAILURE);<br> <br> frba_t *frba =<br>- (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));<br>+ (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));<br> <br> for (i = 0; i < max_regions; i++) {<br> current_regions[i] = get_region(frba, i);<br>@@ -1021,10 +1107,10 @@<br> char *tstr1, *tstr2;<br> <br> if (2 != fscanf(romlayout, "%255s %255s\n", tempstr,<br>- layout_region_name))<br>+ layout_region_name))<br> continue;<br> <br>- region_number = region_num(layout_region_name);<br>+ region_number = region_num(layout_region_name, max_regions);<br> if (region_number < 0)<br> continue;<br> <br>@@ -1035,9 +1121,9 @@<br> exit(EXIT_FAILURE);<br> }<br> new_regions[region_number].base = strtol(tstr1,<br>- (char **)NULL, 16);<br>+ (char **)NULL, 16);<br> new_regions[region_number].limit = strtol(tstr2,<br>- (char **)NULL, 16);<br>+ (char **)NULL, 16);<br> new_regions[region_number].size =<br> new_regions[region_number].limit -<br> new_regions[region_number].base + 1;<br>@@ -1054,7 +1140,7 @@<br> <br> if (new_regions[i].size < current_regions[i].size) {<br> printf("DANGER: Region %s is shrinking.\n",<br>- region_name(i));<br>+ region_name(i));<br> printf(" The region will be truncated to fit.\n");<br> printf(" This may result in an unusable image.\n");<br> }<br>@@ -1102,15 +1188,15 @@<br> }<br> <br> printf("Copy Descriptor %d (%s) (%d bytes)\n", i,<br>- region_name(i), copy_size);<br>+ region_name(i), copy_size);<br> printf(" from %08x+%08x:%08x (%10d)\n", current.base,<br>- offset_current, current.limit, current.size);<br>+ offset_current, current.limit, current.size);<br> printf(" to %08x+%08x:%08x (%10d)\n", new.base,<br>- offset_new, new.limit, new.size);<br>+ offset_new, new.limit, new.size);<br> <br> memcpy(new_image + new.base + offset_new,<br>- image + current.base + offset_current,<br>- copy_size);<br>+ image + current.base + offset_current,<br>+ copy_size);<br> }<br> <br> /* update new descriptor regions */<br>@@ -1127,331 +1213,249 @@<br> free(new_image);<br> }<br> <br>+void close_image(int bios_fd, char *image)<br>+{<br>+ close(bios_fd);<br>+ free(image);<br>+}<br>+<br>+int open_image(char *filename, int *bios_fd, char **image, int *image_size)<br>+{<br>+ struct stat buf;<br>+<br>+ *bios_fd = open(filename, O_RDONLY | O_BINARY);<br>+ if (*bios_fd == -1) {<br>+ perror("Could not open file");<br>+ return -1;<br>+ }<br>+<br>+ if (fstat(*bios_fd, &buf) == -1) {<br>+ perror("Could not stat file");<br>+ return -1;<br>+ }<br>+ *image_size = buf.st_size;<br>+<br>+ printf("File %s is %d bytes\n", filename, *image_size);<br>+<br>+ *image = malloc(*image_size);<br>+<br>+ if (!*image) {<br>+ printf("Out of memory.\n");<br>+ return -1;<br>+ }<br>+<br>+ printf("read(*bios_fd(%d), image(%p), *image_size(%d)) = %d\n",<br>+ *bios_fd, *image, *image_size, *image_size);<br>+<br>+ if (read(*bios_fd, *image, *image_size) != *image_size) {<br>+ perror("Could not read file");<br>+ free(*image);<br>+ return -1;<br>+ }<br>+<br>+ return 0;<br>+}<br>+<br> static void print_version(void)<br> {<br> printf("ifdtool v%s -- ", IFDTOOL_VERSION);<br> printf("Copyright (C) 2011 Google Inc.\n\n");<br> printf<br>- ("This program is free software: you can redistribute it and/or modify\n"<br>- "it under the terms of the GNU General Public License as published by\n"<br>- "the Free Software Foundation, version 2 of the License.\n\n"<br>- "This program is distributed in the hope that it will be useful,\n"<br>- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"<br>- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"<br>- "GNU General Public License for more details.\n\n");<br>+ ("This program is free software: you can redistribute it and/or modify\n"<br>+ "it under the terms of the GNU General Public License as published by\n"<br>+ "the Free Software Foundation, version 2 of the License.\n\n"<br>+ "This program is distributed in the hope that it will be useful,\n"<br>+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"<br>+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"<br>+ "GNU General Public License for more details.\n\n");<br> }<br>+<br>+static struct option long_options[] = {<br>+ {"file", required_argument, 0, 'f' },<br>+ {"name", required_argument, 0, 'n' },<br>+ {"size", required_argument, 0, 's' },<br>+ {"lock-all-regions", no_argument, 0, 'l' },<br>+ {"unlock-all-regions", no_argument, 0, 'u' },<br>+};<br>+<br>+static const struct command commands[] = {<br>+ {"print", ""},<br>+ {"inject-region", "f:n:"},<br>+ {"extract-region", "f:n:"},<br>+// {"create-layout", "f:"},<br>+ {"configure", "lus:"},<br>+};<br> <br> static void print_usage(const char *name)<br> {<br>- printf("usage: %s [-vhdix?] <filename>\n", name);<br>+ printf("usage: %s [filename] [action] [option]\n", name);<br>+ printf(" %s help\n", name);<br>+ printf(" %s version\n", name);<br> printf("\n"<br>- " -d | --dump: dump intel firmware descriptor\n"<br>- " -f | --layout <filename> dump regions into a flashrom layout file\n"<br>- " -x | --extract: extract intel fd modules\n"<br>- " -i | --inject <region>:<module> inject file <module> into region <region>\n"<br>- " -n | --newlayout <filename> update regions using a flashrom layout file\n"<br>- " -s | --spifreq <17|20|30|33|48|50> set the SPI frequency\n"<br>- " -D | --density <512|1|2|4|8|16> set chip density (512 in KByte, others in MByte)\n"<br>- " -C | --chip <0|1|2> select spi chip on which to operate\n"<br>- " can only be used once per run:\n"<br>- " 0 - both chips (default), 1 - first chip, 2 - second chip\n"<br>- " -e | --em100 set SPI frequency to 20MHz and disable\n"<br>- " Dual Output Fast Read Support\n"<br>- " -l | --lock Lock firmware descriptor and ME region\n"<br>- " -u | --unlock Unlock firmware descriptor and ME region\n"<br>- " -p | --platform Add platform-specific quirks\n"<br>- " aplk - Apollo Lake\n"<br>- " -v | --version: print the version\n"<br>- " -h | --help: print this help\n\n"<br>- "<region> is one of Descriptor, BIOS, ME, GbE, Platform\n"<br>+ " Actions:\n"<br>+ " print\n"<br>+ " extract-region -n <region_name> -f <region_file>\n"<br>+ " inject-region -n <region_name> -f <region_file>\n"<br>+ /* " create-layout -f <layout_file>\n" */<br>+ " configure [parameters]\n"<br>+ "\n"<br>+ " Parameters:\n"<br>+ " -l | --lock-all-regions\n"<br>+ " -u | --unlock-all-regions\n"<br>+ " -s | --size\n"<br>+ /* " -s | --spifreq\n" */<br>+ /* " -c | --chip\n" */<br>+ /* " -e | --em100\n" */<br>+ /* " -p | --platform\n" */<br>+ "\n"<br>+ " Options:\n"<br>+ /* " --use-layout <layout_file>\n" */<br> "\n");<br> }<br> <br> int main(int argc, char *argv[])<br> {<br> int opt, option_index = 0;<br>- int mode_dump = 0, mode_extract = 0, mode_inject = 0, mode_spifreq = 0;<br>- int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0;<br>- int mode_layout = 0, mode_newlayout = 0, mode_density = 0;<br>+ int option_size = 0, option_lock = 0, option_unlock = 0;<br> char *region_type_string = NULL, *region_fname = NULL, *layout_fname = NULL;<br> int region_type = -1, inputfreq = 0;<br> unsigned int new_density = 0;<br>+ enum cmdline_action mode = MODE_INVALID;<br> enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;<br>+ size_t i;<br>+ int c;<br> <br>- static struct option long_options[] = {<br>- {"dump", 0, NULL, 'd'},<br>- {"layout", 1, NULL, 'f'},<br>- {"extract", 0, NULL, 'x'},<br>- {"inject", 1, NULL, 'i'},<br>- {"newlayout", 1, NULL, 'n'},<br>- {"spifreq", 1, NULL, 's'},<br>- {"density", 1, NULL, 'D'},<br>- {"chip", 1, NULL, 'C'},<br>- {"em100", 0, NULL, 'e'},<br>- {"lock", 0, NULL, 'l'},<br>- {"unlock", 0, NULL, 'u'},<br>- {"version", 0, NULL, 'v'},<br>- {"help", 0, NULL, 'h'},<br>- {"platform", 0, NULL, 'p'},<br>- {0, 0, 0, 0}<br>- };<br>+ if (argc == 2 && !strcmp("version", argv[1])) {<br>+ print_version();<br>+ return 0;<br>+ } else if (argc == 2 && !strcmp("version", argv[1])) {<br>+ print_usage(argv[0]);<br>+ return 0;<br>+ } else if (argc < 3) {<br>+ print_usage(argv[0]);<br>+ return 1;<br>+ }<br> <br>- while ((opt = getopt_long(argc, argv, "df:D:C:xi:n:s:p:eluvh?",<br>- long_options, &option_index)) != EOF) {<br>- switch (opt) {<br>- case 'd':<br>- mode_dump = 1;<br>- break;<br>- case 'f':<br>- mode_layout = 1;<br>- layout_fname = strdup(optarg);<br>- if (!layout_fname) {<br>- fprintf(stderr, "No layout file specified\n");<br>- print_usage(argv[0]);<br>- exit(EXIT_FAILURE);<br>+ char *filename = argv[1];<br>+ char *cmd = argv[2];<br>+ optind += 2;<br>+<br>+ for (i = 0; i < ARRAY_SIZE(commands); i++) {<br>+ if (strcmp(cmd, commands[i].name) != 0)<br>+ continue;<br>+<br>+ if (!strcmp("print", commands[i].name)) {<br>+ mode = MODE_DUMP;<br>+ } else if (!strcmp("inject-region", commands[i].name)) {<br>+ mode = MODE_INJECT;<br>+ } else if (!strcmp("extract-region", commands[i].name)) {<br>+ mode = MODE_EXTRACT;<br>+ } else if (!strcmp("configure", commands[i].name)) {<br>+ mode = MODE_CONFIGURE;<br>+ }<br>+<br>+ while (1) {<br>+ char *suffix = NULL;<br>+ int option_index = 0;<br>+ c = getopt_long(argc, argv, commands[i].optstring,<br>+ long_options, &option_index);<br>+ if (c == -1) {<br>+ /* if (optind < argc) { */<br>+ /* printf("%s: excessive argument -- '%s'" */<br>+ /* "\n", argv[0], argv[optind]); */<br>+ /* return 1; */<br>+ /* } */<br>+ break;<br> }<br>- break;<br>- case 'x':<br>- mode_extract = 1;<br>- break;<br>- case 'i':<br>- // separate type and file name<br>- region_type_string = strdup(optarg);<br>- region_fname = strchr(region_type_string, ':');<br>- if (!region_fname) {<br>- print_usage(argv[0]);<br>- exit(EXIT_FAILURE);<br>- }<br>- region_fname[0] = '\0';<br>- region_fname++;<br>- // Descriptor, BIOS, ME, GbE, Platform<br>- // valid type?<br>- if (!strcasecmp("Descriptor", region_type_string))<br>- region_type = 0;<br>- else if (!strcasecmp("BIOS", region_type_string))<br>- region_type = 1;<br>- else if (!strcasecmp("ME", region_type_string))<br>- region_type = 2;<br>- else if (!strcasecmp("GbE", region_type_string))<br>- region_type = 3;<br>- else if (!strcasecmp("Platform", region_type_string))<br>- region_type = 4;<br>- else if (!strcasecmp("EC", region_type_string))<br>- region_type = 8;<br>- if (region_type == -1) {<br>- fprintf(stderr, "No such region type: '%s'\n\n",<br>- region_type_string);<br>- print_usage(argv[0]);<br>- exit(EXIT_FAILURE);<br>- }<br>- mode_inject = 1;<br>- break;<br>- case 'n':<br>- mode_newlayout = 1;<br>- layout_fname = strdup(optarg);<br>- if (!layout_fname) {<br>- fprintf(stderr, "No layout file specified\n");<br>- print_usage(argv[0]);<br>- exit(EXIT_FAILURE);<br>- }<br>- break;<br>- case 'D':<br>- mode_density = 1;<br>- new_density = strtoul(optarg, NULL, 0);<br>- switch (new_density) {<br>- case 512:<br>- new_density = COMPONENT_DENSITY_512KB;<br>+<br>+ switch(c) {<br>+ case 'f':<br>+ param.region_filename = optarg;<br> break;<br>- case 1:<br>- new_density = COMPONENT_DENSITY_1MB;<br>+ case 'l':<br>+ if (option_unlock) {<br>+ fprintf(stderr,<br>+ "Locking/Unlocking FD and ME are mutually exclusive\n");<br>+ return -1;<br>+ }<br>+ option_lock = 1;<br> break;<br>- case 2:<br>- new_density = COMPONENT_DENSITY_2MB;<br>+ case 'n':<br>+ param.region_name = optarg;<br> break;<br>- case 4:<br>- new_density = COMPONENT_DENSITY_4MB;<br>+ case 's':<br>+ option_size = 1;<br>+ new_density = encode_component_density(strtoul(optarg, NULL, 0));<br>+ if (new_density == COMPONENT_DENSITY_UNUSED) {<br>+ return -1;<br>+ }<br> break;<br>- case 8:<br>- new_density = COMPONENT_DENSITY_8MB;<br>- break;<br>- case 16:<br>- new_density = COMPONENT_DENSITY_16MB;<br>- break;<br>- case 32:<br>- new_density = COMPONENT_DENSITY_32MB;<br>- break;<br>- case 64:<br>- new_density = COMPONENT_DENSITY_64MB;<br>- break;<br>- case 0:<br>- new_density = COMPONENT_DENSITY_UNUSED;<br>+ case 'u':<br>+ if (option_lock) {<br>+ fprintf(stderr,<br>+ "Locking/Unlocking FD and ME are mutually exclusive\n");<br>+ return -1;<br>+ }<br>+ option_unlock = 1;<br> break;<br> default:<br>- printf("error: Unknown density\n");<br> print_usage(argv[0]);<br>- exit(EXIT_FAILURE);<br>+ return -1;<br> }<br>- break;<br>- case 'C':<br>- selected_chip = strtol(optarg, NULL, 0);<br>- if (selected_chip > 2) {<br>- fprintf(stderr, "error: Invalid chip selection\n");<br>- print_usage(argv[0]);<br>- exit(EXIT_FAILURE);<br>- }<br>- break;<br>- case 's':<br>- // Parse the requested SPI frequency<br>- inputfreq = strtol(optarg, NULL, 0);<br>- switch (inputfreq) {<br>- case 17:<br>- spifreq = SPI_FREQUENCY_17MHZ;<br>- break;<br>- case 20:<br>- spifreq = SPI_FREQUENCY_20MHZ;<br>- break;<br>- case 30:<br>- spifreq = SPI_FREQUENCY_50MHZ_30MHZ;<br>- break;<br>- case 33:<br>- spifreq = SPI_FREQUENCY_33MHZ;<br>- break;<br>- case 48:<br>- spifreq = SPI_FREQUENCY_48MHZ;<br>- break;<br>- case 50:<br>- spifreq = SPI_FREQUENCY_50MHZ_30MHZ;<br>- break;<br>- default:<br>- fprintf(stderr, "Invalid SPI Frequency: %d\n",<br>- inputfreq);<br>- print_usage(argv[0]);<br>- exit(EXIT_FAILURE);<br>- }<br>- mode_spifreq = 1;<br>- break;<br>- case 'e':<br>- mode_em100 = 1;<br>- break;<br>- case 'l':<br>- mode_locked = 1;<br>- if (mode_unlocked == 1) {<br>- fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");<br>- exit(EXIT_FAILURE);<br>- }<br>- break;<br>- case 'u':<br>- mode_unlocked = 1;<br>- if (mode_locked == 1) {<br>- fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");<br>- exit(EXIT_FAILURE);<br>- }<br>- break;<br>- case 'p':<br>- if (!strcmp(optarg, "aplk")) {<br>- platform = PLATFORM_APOLLOLAKE;<br>- } else {<br>- fprintf(stderr, "Unknown platform: %s\n", optarg);<br>- exit(EXIT_FAILURE);<br>- }<br>- break;<br>- case 'v':<br>- print_version();<br>- exit(EXIT_SUCCESS);<br>- break;<br>- case 'h':<br>- case '?':<br>- default:<br>- print_usage(argv[0]);<br>- exit(EXIT_SUCCESS);<br>- break;<br> }<br> }<br> <br>- if ((mode_dump + mode_layout + mode_extract + mode_inject +<br>- mode_newlayout + (mode_spifreq | mode_em100 | mode_unlocked |<br>- mode_locked)) > 1) {<br>- fprintf(stderr, "You may not specify more than one mode.\n\n");<br>- print_usage(argv[0]);<br>- exit(EXIT_FAILURE);<br>+ if (mode == MODE_INVALID) {<br>+ printf("Invalid action '%s'\n", cmd);<br>+ return -1;<br>+ } else if (mode == MODE_INJECT || mode == MODE_EXTRACT) {<br>+ region_type_string = param.region_name;<br>+ region_fname = param.region_filename;<br>+<br>+ if (!region_fname) {<br>+ print_usage(argv[0]);<br>+ exit(EXIT_FAILURE);<br>+ }<br>+ region_type = region_num(region_type_string, MAX_REGIONS);<br>+ if (region_type == -1) {<br>+ fprintf(stderr, "No such region type: '%s'\n\n",<br>+ region_type_string);<br>+ print_usage(argv[0]);<br>+ exit(EXIT_FAILURE);<br>+ }<br> }<br> <br>- if ((mode_dump + mode_layout + mode_extract + mode_inject +<br>- mode_newlayout + mode_spifreq + mode_em100 + mode_locked +<br>- mode_unlocked + mode_density) == 0) {<br>- fprintf(stderr, "You need to specify a mode.\n\n");<br>- print_usage(argv[0]);<br>+ int bios_fd;<br>+ int image_size;<br>+ char* image;<br>+<br>+ bios_fd = open_image(filename, &bios_fd, &image, &image_size);<br>+ if (bios_fd < 0)<br> exit(EXIT_FAILURE);<br>+<br>+ check_ifd_version(image, image_size);<br>+<br>+ if (mode == MODE_DUMP) {<br>+ dump_fd(image, image_size);<br>+ } else if (mode == MODE_INJECT) {<br>+ inject_region(filename, image, image_size, region_type,<br>+ region_fname);<br>+ } else if (mode == MODE_EXTRACT) {<br>+ extract_region(image, image_size, region_type, region_fname);<br>+ } else if (mode == MODE_CONFIGURE) {<br>+ if (option_size) {<br>+ set_chipdensity(filename, image, image_size, new_density);<br>+ }<br>+ if (option_lock) {<br>+ lock_descriptor(filename, image, image_size);<br>+ }<br>+ if (option_unlock) {<br>+ unlock_descriptor(filename, image, image_size);<br>+ }<br>+<br> }<br> <br>- if (optind + 1 != argc) {<br>- fprintf(stderr, "You need to specify a file.\n\n");<br>- print_usage(argv[0]);<br>- exit(EXIT_FAILURE);<br>- }<br>-<br>- char *filename = argv[optind];<br>- int bios_fd = open(filename, O_RDONLY | O_BINARY);<br>- if (bios_fd == -1) {<br>- perror("Could not open file");<br>- exit(EXIT_FAILURE);<br>- }<br>- struct stat buf;<br>- if (fstat(bios_fd, &buf) == -1) {<br>- perror("Could not stat file");<br>- exit(EXIT_FAILURE);<br>- }<br>- int size = buf.st_size;<br>-<br>- printf("File %s is %d bytes\n", filename, size);<br>-<br>- char *image = malloc(size);<br>- if (!image) {<br>- printf("Out of memory.\n");<br>- exit(EXIT_FAILURE);<br>- }<br>-<br>- if (read(bios_fd, image, size) != size) {<br>- perror("Could not read file");<br>- exit(EXIT_FAILURE);<br>- }<br>-<br>- close(bios_fd);<br>-<br>- check_ifd_version(image, size);<br>-<br>- if (mode_dump)<br>- dump_fd(image, size);<br>-<br>- if (mode_layout)<br>- dump_layout(image, size, layout_fname);<br>-<br>- if (mode_extract)<br>- write_regions(image, size);<br>-<br>- if (mode_inject)<br>- inject_region(filename, image, size, region_type,<br>- region_fname);<br>-<br>- if (mode_newlayout)<br>- new_layout(filename, image, size, layout_fname);<br>-<br>- if (mode_spifreq)<br>- set_spi_frequency(filename, image, size, spifreq);<br>-<br>- if (mode_density)<br>- set_chipdensity(filename, image, size, new_density);<br>-<br>- if (mode_em100)<br>- set_em100_mode(filename, image, size);<br>-<br>- if (mode_locked)<br>- lock_descriptor(filename, image, size);<br>-<br>- if (mode_unlocked)<br>- unlock_descriptor(filename, image, size);<br>-<br>- free(image);<br>+ close_image(bios_fd, image);<br> <br> return 0;<br> }<br>diff --git a/util/ifdtool/ifdtool.h b/util/ifdtool/ifdtool.h<br>index fe98d6a..e4c383e 100644<br>--- a/util/ifdtool/ifdtool.h<br>+++ b/util/ifdtool/ifdtool.h<br>@@ -142,4 +142,5 @@<br> struct region_name {<br> char *pretty;<br> char *terse;<br>+ char *type;<br> };<br></pre><p>To view, visit <a href="https://review.coreboot.org/20434">change 20434</a>. To unsubscribe, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/20434"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I6e463239c4f727a6296e4eca24682966b4160e3b </div>
<div style="display:none"> Gerrit-Change-Number: 20434 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Denis 'GNUtoo' Carikli <GNUtoo@no-log.org> </div>