<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>