Denis 'GNUtoo' Carikli has uploaded this change for review.

View Change

[RFC] [WIP] ifdtool: rework command line interface

The command line interface has been very much inspired by
the one from cbfstool, as it easily allow to add more
functionality, such as the creation of new images with
valid or fake Intel flash descriptor.

This could be then implemented by merging the code and/or
functionality from ifdfake and ich9gen in this tool.

Change-Id: I6e463239c4f727a6296e4eca24682966b4160e3b
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
---
M util/ifdtool/ifdtool.c
M util/ifdtool/ifdtool.h
2 files changed, 379 insertions(+), 374 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/34/20434/1
diff --git a/util/ifdtool/ifdtool.c b/util/ifdtool/ifdtool.c
index 9382bc4..482f4e5 100644
--- a/util/ifdtool/ifdtool.c
+++ b/util/ifdtool/ifdtool.c
@@ -13,35 +13,56 @@
* GNU General Public License for more details.
*/

-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <getopt.h>
#include <fcntl.h>
-#include <sys/types.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include <sys/stat.h>
+#include <sys/types.h>
#include "ifdtool.h"

#ifndef O_BINARY
#define O_BINARY 0
#endif

+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
static int ifd_version;
static int max_regions = 0;
static int selected_chip = 0;
static int platform = -1;

+struct command {
+ const char *name;
+ const char *optstring;
+};
+
+static struct param {
+ const char *ifd_filename;
+ const char *region_name;
+ const char *region_filename;
+} param;
+
static const struct region_name region_names[MAX_REGIONS] = {
- { "Flash Descriptor", "fd" },
- { "BIOS", "bios" },
- { "Intel ME", "me" },
- { "GbE", "gbe" },
- { "Platform Data", "pd" },
- { "Reserved", "res1" },
- { "Reserved", "res2" },
- { "Reserved", "res3" },
- { "EC", "ec" },
+ { "Flash Descriptor", "fd" , "Descriptor"},
+ { "BIOS", "bios" , "BIOS"},
+ { "Intel ME", "me", "ME"},
+ { "GbE", "gbe", "GbE" },
+ { "Platform Data", "pd", "Platform" },
+ { "Reserved", "res1", NULL },
+ { "Reserved", "res2", NULL },
+ { "Reserved", "res3", NULL },
+ { "EC", "ec", "EC" },
+};
+
+static enum cmdline_action {
+ MODE_DUMP,
+ MODE_EXTRACT,
+ MODE_INJECT,
+ MODE_INVALID,
+ MODE_CONFIGURE,
};

static fdbar_t *find_fd(char *image, int size)
@@ -209,7 +230,7 @@
return region_names[region_type].terse;
}

-static int region_num(const char *name)
+static int region_num(const char *name, int max_regions)
{
int i;

@@ -218,6 +239,10 @@
return i;
if (strcasecmp(name, region_names[i].terse) == 0)
return i;
+ if (region_names[i].type) {
+ if (strcasecmp(name, region_names[i].type) == 0)
+ return i;
+ }
}

return -1;
@@ -249,15 +274,15 @@
{
region_t region = get_region(frba, num);
printf(" Flash Region %d (%s): %08x - %08x %s\n",
- num, region_name(num), region.base, region.limit,
- region.size < 1 ? "(unused)" : "");
+ num, region_name(num), region.base, region.limit,
+ region.size < 1 ? "(unused)" : "");
}

static void dump_region_layout(char *buf, size_t bufsize, int num, frba_t *frba)
{
region_t region = get_region(frba, num);
snprintf(buf, bufsize, "%08x:%08x %s\n",
- region.base, region.limit, region_name_short(num));
+ region.base, region.limit, region_name_short(num));
}

static void dump_frba(frba_t * frba)
@@ -293,7 +318,7 @@
int i;

int layout_fd = open(layout_fname, O_WRONLY | O_CREAT | O_TRUNC,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (layout_fd == -1) {
perror("Could not open file");
exit(EXIT_FAILURE);
@@ -345,6 +370,42 @@
}
}

+static unsigned int encode_component_density(unsigned int density)
+{
+ unsigned int new_density = COMPONENT_DENSITY_UNUSED;
+
+ switch(density) {
+ case 512:
+ new_density = COMPONENT_DENSITY_512KB;
+ break;
+ case 1:
+ new_density = COMPONENT_DENSITY_1MB;
+ break;
+ case 2:
+ new_density = COMPONENT_DENSITY_2MB;
+ break;
+ case 4:
+ new_density = COMPONENT_DENSITY_4MB;
+ break;
+ case 8:
+ new_density = COMPONENT_DENSITY_8MB;
+ break;
+ case 16:
+ new_density = COMPONENT_DENSITY_16MB;
+ break;
+ case 32:
+ new_density = COMPONENT_DENSITY_32MB;
+ break;
+ case 64:
+ new_density = COMPONENT_DENSITY_64MB;
+ break;
+ default:
+ printf("error: Unknown density\n");
+ }
+
+ return new_density;
+}
+
static void decode_component_density(unsigned int density)
{
switch (density) {
@@ -385,7 +446,7 @@
printf("\nFound Component Section\n");
printf("FLCOMP 0x%08x\n", fcba->flcomp);
printf(" Dual Output Fast Read Support: %ssupported\n",
- (fcba->flcomp & (1 << 30))?"":"not ");
+ (fcba->flcomp & (1 << 30))?"":"not ");
printf(" Read ID/Read Status Clock Frequency: ");
decode_spi_frequency((fcba->flcomp >> 27) & 7);
printf("\n Write/Erase Clock Frequency: ");
@@ -393,7 +454,7 @@
printf("\n Fast Read Clock Frequency: ");
decode_spi_frequency((fcba->flcomp >> 21) & 7);
printf("\n Fast Read Support: %ssupported",
- (fcba->flcomp & (1 << 20))?"":"not ");
+ (fcba->flcomp & (1 << 20))?"":"not ");
printf("\n Read Clock Frequency: ");
decode_spi_frequency((fcba->flcomp >> 17) & 7);

@@ -415,16 +476,16 @@
printf("\n");
printf("FLILL 0x%08x\n", fcba->flill);
printf(" Invalid Instruction 3: 0x%02x\n",
- (fcba->flill >> 24) & 0xff);
+ (fcba->flill >> 24) & 0xff);
printf(" Invalid Instruction 2: 0x%02x\n",
- (fcba->flill >> 16) & 0xff);
+ (fcba->flill >> 16) & 0xff);
printf(" Invalid Instruction 1: 0x%02x\n",
- (fcba->flill >> 8) & 0xff);
+ (fcba->flill >> 8) & 0xff);
printf(" Invalid Instruction 0: 0x%02x\n",
- fcba->flill & 0xff);
+ fcba->flill & 0xff);
printf("FLPB 0x%08x\n", fcba->flpb);
printf(" Flash Partition Boundary Address: 0x%06x\n\n",
- (fcba->flpb & 0xfff) << 12);
+ (fcba->flpb & 0xfff) << 12);
}

static void dump_fpsba(fpsba_t * fpsba)
@@ -467,35 +528,35 @@
(flmstr & (1 << (wr_shift + 8))) ?
"enabled" : "disabled");
printf(" Platform Data Region Write Access: %s\n",
- (flmstr & (1 << (wr_shift + 4))) ? "enabled" : "disabled");
+ (flmstr & (1 << (wr_shift + 4))) ? "enabled" : "disabled");
printf(" GbE Region Write Access: %s\n",
- (flmstr & (1 << (wr_shift + 3))) ? "enabled" : "disabled");
+ (flmstr & (1 << (wr_shift + 3))) ? "enabled" : "disabled");
printf(" Intel ME Region Write Access: %s\n",
- (flmstr & (1 << (wr_shift + 2))) ? "enabled" : "disabled");
+ (flmstr & (1 << (wr_shift + 2))) ? "enabled" : "disabled");
printf(" Host CPU/BIOS Region Write Access: %s\n",
- (flmstr & (1 << (wr_shift + 1))) ? "enabled" : "disabled");
+ (flmstr & (1 << (wr_shift + 1))) ? "enabled" : "disabled");
printf(" Flash Descriptor Write Access: %s\n",
- (flmstr & (1 << wr_shift)) ? "enabled" : "disabled");
+ (flmstr & (1 << wr_shift)) ? "enabled" : "disabled");

if (ifd_version >= IFD_VERSION_2)
printf(" EC Region Read Access: %s\n",
(flmstr & (1 << (rd_shift + 8))) ?
"enabled" : "disabled");
printf(" Platform Data Region Read Access: %s\n",
- (flmstr & (1 << (rd_shift + 4))) ? "enabled" : "disabled");
+ (flmstr & (1 << (rd_shift + 4))) ? "enabled" : "disabled");
printf(" GbE Region Read Access: %s\n",
- (flmstr & (1 << (rd_shift + 3))) ? "enabled" : "disabled");
+ (flmstr & (1 << (rd_shift + 3))) ? "enabled" : "disabled");
printf(" Intel ME Region Read Access: %s\n",
- (flmstr & (1 << (rd_shift + 2))) ? "enabled" : "disabled");
+ (flmstr & (1 << (rd_shift + 2))) ? "enabled" : "disabled");
printf(" Host CPU/BIOS Region Read Access: %s\n",
- (flmstr & (1 << (rd_shift + 1))) ? "enabled" : "disabled");
+ (flmstr & (1 << (rd_shift + 1))) ? "enabled" : "disabled");
printf(" Flash Descriptor Read Access: %s\n",
- (flmstr & (1 << rd_shift)) ? "enabled" : "disabled");
+ (flmstr & (1 << rd_shift)) ? "enabled" : "disabled");

/* Requestor ID doesn't exist for ifd 2 */
if (ifd_version < IFD_VERSION_2)
printf(" Requester ID: 0x%04x\n\n",
- flmstr & 0xffff);
+ flmstr & 0xffff);
}

static void dump_fmba(fmba_t * fmba)
@@ -525,23 +586,23 @@
static void dump_jid(uint32_t jid)
{
printf(" SPI Componend Device ID 1: 0x%02x\n",
- (jid >> 16) & 0xff);
+ (jid >> 16) & 0xff);
printf(" SPI Componend Device ID 0: 0x%02x\n",
- (jid >> 8) & 0xff);
+ (jid >> 8) & 0xff);
printf(" SPI Componend Vendor ID: 0x%02x\n",
- jid & 0xff);
+ jid & 0xff);
}

static void dump_vscc(uint32_t vscc)
{
printf(" Lower Erase Opcode: 0x%02x\n",
- vscc >> 24);
+ vscc >> 24);
printf(" Lower Write Enable on Write Status: 0x%02x\n",
- vscc & (1 << 20) ? 0x06 : 0x50);
+ vscc & (1 << 20) ? 0x06 : 0x50);
printf(" Lower Write Status Required: %s\n",
- vscc & (1 << 19) ? "Yes" : "No");
+ vscc & (1 << 19) ? "Yes" : "No");
printf(" Lower Write Granularity: %d bytes\n",
- vscc & (1 << 18) ? 64 : 1);
+ vscc & (1 << 18) ? 64 : 1);
printf(" Lower Block / Sector Erase Size: ");
switch ((vscc >> 16) & 0x3) {
case 0:
@@ -559,13 +620,13 @@
}

printf(" Upper Erase Opcode: 0x%02x\n",
- (vscc >> 8) & 0xff);
+ (vscc >> 8) & 0xff);
printf(" Upper Write Enable on Write Status: 0x%02x\n",
- vscc & (1 << 4) ? 0x06 : 0x50);
+ vscc & (1 << 4) ? 0x06 : 0x50);
printf(" Upper Write Status Required: %s\n",
- vscc & (1 << 3) ? "Yes" : "No");
+ vscc & (1 << 3) ? "Yes" : "No");
printf(" Upper Write Granularity: %d bytes\n",
- vscc & (1 << 2) ? 64 : 1);
+ vscc & (1 << 2) ? 64 : 1);
printf(" Upper Block / Sector Erase Size: ");
switch (vscc & 0x3) {
case 0:
@@ -635,18 +696,18 @@

printf("FLUMAP1: 0x%08x\n", fdb->flumap1);
printf(" Intel ME VSCC Table Length (VTL): %d\n",
- (fdb->flumap1 >> 8) & 0xff);
+ (fdb->flumap1 >> 8) & 0xff);
printf(" Intel ME VSCC Table Base Address (VTBA): 0x%06x\n\n",
- (fdb->flumap1 & 0xff) << 4);
+ (fdb->flumap1 & 0xff) << 4);
dump_vtba((vtba_t *)
- (image + ((fdb->flumap1 & 0xff) << 4)),
- (fdb->flumap1 >> 8) & 0xff);
+ (image + ((fdb->flumap1 & 0xff) << 4)),
+ (fdb->flumap1 >> 8) & 0xff);
dump_oem((uint8_t *)image + 0xf00);
dump_frba((frba_t *)
- (image + (((fdb->flmap0 >> 16) & 0xff) << 4)));
+ (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)));
+ (image + (((fdb->flmap1 >> 16) & 0xff) << 4)));
dump_fmba((fmba_t *) (image + (((fdb->flmap1) & 0xff) << 4)));
dump_fmsba((fmsba_t *) (image + (((fdb->flmap2) & 0xff) << 4)));
}
@@ -658,8 +719,8 @@
exit(EXIT_FAILURE);

dump_frba_layout((frba_t *)
- (image + (((fdb->flmap0 >> 16) & 0xff) << 4)),
- layout_fname);
+ (image + (((fdb->flmap0 >> 16) & 0xff) << 4)),
+ layout_fname);
}

static void write_regions(char *image, int size)
@@ -671,7 +732,7 @@
exit(EXIT_FAILURE);

frba_t *frba =
- (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
+ (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));

for (i = 0; i < max_regions; i++) {
region_t region = get_region(frba, i);
@@ -694,19 +755,14 @@

static void write_image(char *filename, char *image, int size)
{
- char new_filename[FILENAME_MAX]; // allow long file names
int new_fd;

- // - 5: leave room for ".new\0"
- strncpy(new_filename, filename, FILENAME_MAX - 5);
- strncat(new_filename, ".new", FILENAME_MAX - strlen(filename));
-
- printf("Writing new image to %s\n", new_filename);
+ printf("Writing image to %s\n", filename);

// Now write out new image
- new_fd = open(new_filename,
- O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ new_fd = open(filename,
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (new_fd < 0) {
perror("Error while trying to open file");
exit(EXIT_FAILURE);
@@ -886,6 +942,36 @@
write_image(filename, image, size);
}

+
+static void extract_region(char *image, int size, int region_type,
+ char *region_filename)
+{
+ 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));
+
+ region_t region = get_region(frba, region_type);
+ dump_region(region_type, frba);
+ if (region.size > 0) {
+ int region_fd;
+ region_fd = open(region_filename,
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (region_fd < 0) {
+ perror("Error while trying to open file");
+ exit(EXIT_FAILURE);
+ }
+ if (write(region_fd, image + region.base, region.size) != region.size)
+ perror("Error while writing");
+ close(region_fd);
+ }
+}
+
void inject_region(char *filename, char *image, int size, int region_type,
char *region_fname)
{
@@ -893,12 +979,12 @@
if (!fdb)
exit(EXIT_FAILURE);
frba_t *frba =
- (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
+ (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));
+ region_name(region_type));
exit(EXIT_FAILURE);
}

@@ -917,20 +1003,20 @@
printf("File %s is %d bytes\n", region_fname, region_size);

if ( (region_size > region.size) || ((region_type != 1) &&
- (region_size > region.size))) {
+ (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);
+ " 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);
+ " 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);
}
@@ -942,7 +1028,7 @@
}

if (read(region_fd, image + region.base + offset, region_size)
- != region_size) {
+ != region_size) {
perror("Could not read file");
exit(EXIT_FAILURE);
}
@@ -1002,7 +1088,7 @@
exit(EXIT_FAILURE);

frba_t *frba =
- (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));
+ (frba_t *) (image + (((fdb->flmap0 >> 16) & 0xff) << 4));

for (i = 0; i < max_regions; i++) {
current_regions[i] = get_region(frba, i);
@@ -1021,10 +1107,10 @@
char *tstr1, *tstr2;

if (2 != fscanf(romlayout, "%255s %255s\n", tempstr,
- layout_region_name))
+ layout_region_name))
continue;

- region_number = region_num(layout_region_name);
+ region_number = region_num(layout_region_name, max_regions);
if (region_number < 0)
continue;

@@ -1035,9 +1121,9 @@
exit(EXIT_FAILURE);
}
new_regions[region_number].base = strtol(tstr1,
- (char **)NULL, 16);
+ (char **)NULL, 16);
new_regions[region_number].limit = strtol(tstr2,
- (char **)NULL, 16);
+ (char **)NULL, 16);
new_regions[region_number].size =
new_regions[region_number].limit -
new_regions[region_number].base + 1;
@@ -1054,7 +1140,7 @@

if (new_regions[i].size < current_regions[i].size) {
printf("DANGER: Region %s is shrinking.\n",
- region_name(i));
+ region_name(i));
printf(" The region will be truncated to fit.\n");
printf(" This may result in an unusable image.\n");
}
@@ -1102,15 +1188,15 @@
}

printf("Copy Descriptor %d (%s) (%d bytes)\n", i,
- region_name(i), copy_size);
+ region_name(i), copy_size);
printf(" from %08x+%08x:%08x (%10d)\n", current.base,
- offset_current, current.limit, current.size);
+ offset_current, current.limit, current.size);
printf(" to %08x+%08x:%08x (%10d)\n", new.base,
- offset_new, new.limit, new.size);
+ offset_new, new.limit, new.size);

memcpy(new_image + new.base + offset_new,
- image + current.base + offset_current,
- copy_size);
+ image + current.base + offset_current,
+ copy_size);
}

/* update new descriptor regions */
@@ -1127,331 +1213,249 @@
free(new_image);
}

+void close_image(int bios_fd, char *image)
+{
+ close(bios_fd);
+ free(image);
+}
+
+int open_image(char *filename, int *bios_fd, char **image, int *image_size)
+{
+ struct stat buf;
+
+ *bios_fd = open(filename, O_RDONLY | O_BINARY);
+ if (*bios_fd == -1) {
+ perror("Could not open file");
+ return -1;
+ }
+
+ if (fstat(*bios_fd, &buf) == -1) {
+ perror("Could not stat file");
+ return -1;
+ }
+ *image_size = buf.st_size;
+
+ printf("File %s is %d bytes\n", filename, *image_size);
+
+ *image = malloc(*image_size);
+
+ if (!*image) {
+ printf("Out of memory.\n");
+ return -1;
+ }
+
+ printf("read(*bios_fd(%d), image(%p), *image_size(%d)) = %d\n",
+ *bios_fd, *image, *image_size, *image_size);
+
+ if (read(*bios_fd, *image, *image_size) != *image_size) {
+ perror("Could not read file");
+ free(*image);
+ return -1;
+ }
+
+ return 0;
+}
+
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");
+ ("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");
}
+
+static struct option long_options[] = {
+ {"file", required_argument, 0, 'f' },
+ {"name", required_argument, 0, 'n' },
+ {"size", required_argument, 0, 's' },
+ {"lock-all-regions", no_argument, 0, 'l' },
+ {"unlock-all-regions", no_argument, 0, 'u' },
+};
+
+static const struct command commands[] = {
+ {"print", ""},
+ {"inject-region", "f:n:"},
+ {"extract-region", "f:n:"},
+// {"create-layout", "f:"},
+ {"configure", "lus:"},
+};

static void print_usage(const char *name)
{
- printf("usage: %s [-vhdix?] <filename>\n", name);
+ printf("usage: %s [filename] [action] [option]\n", name);
+ printf(" %s help\n", name);
+ printf(" %s version\n", name);
printf("\n"
- " -d | --dump: dump intel firmware descriptor\n"
- " -f | --layout <filename> dump regions into a flashrom layout file\n"
- " -x | --extract: extract intel fd modules\n"
- " -i | --inject <region>:<module> inject file <module> into region <region>\n"
- " -n | --newlayout <filename> update regions using a flashrom layout file\n"
- " -s | --spifreq <17|20|30|33|48|50> set the SPI frequency\n"
- " -D | --density <512|1|2|4|8|16> set chip density (512 in KByte, others in MByte)\n"
- " -C | --chip <0|1|2> select spi chip on which to operate\n"
- " can only be used once per run:\n"
- " 0 - both chips (default), 1 - first chip, 2 - second chip\n"
- " -e | --em100 set SPI frequency to 20MHz and disable\n"
- " Dual Output Fast Read Support\n"
- " -l | --lock Lock firmware descriptor and ME region\n"
- " -u | --unlock Unlock firmware descriptor and ME region\n"
- " -p | --platform Add platform-specific quirks\n"
- " aplk - Apollo Lake\n"
- " -v | --version: print the version\n"
- " -h | --help: print this help\n\n"
- "<region> is one of Descriptor, BIOS, ME, GbE, Platform\n"
+ " Actions:\n"
+ " print\n"
+ " extract-region -n <region_name> -f <region_file>\n"
+ " inject-region -n <region_name> -f <region_file>\n"
+ /* " create-layout -f <layout_file>\n" */
+ " configure [parameters]\n"
+ "\n"
+ " Parameters:\n"
+ " -l | --lock-all-regions\n"
+ " -u | --unlock-all-regions\n"
+ " -s | --size\n"
+ /* " -s | --spifreq\n" */
+ /* " -c | --chip\n" */
+ /* " -e | --em100\n" */
+ /* " -p | --platform\n" */
+ "\n"
+ " Options:\n"
+ /* " --use-layout <layout_file>\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;
- int mode_em100 = 0, mode_locked = 0, mode_unlocked = 0;
- int mode_layout = 0, mode_newlayout = 0, mode_density = 0;
+ int option_size = 0, option_lock = 0, option_unlock = 0;
char *region_type_string = NULL, *region_fname = NULL, *layout_fname = NULL;
int region_type = -1, inputfreq = 0;
unsigned int new_density = 0;
+ enum cmdline_action mode = MODE_INVALID;
enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ;
+ size_t i;
+ int c;

- static struct option long_options[] = {
- {"dump", 0, NULL, 'd'},
- {"layout", 1, NULL, 'f'},
- {"extract", 0, NULL, 'x'},
- {"inject", 1, NULL, 'i'},
- {"newlayout", 1, NULL, 'n'},
- {"spifreq", 1, NULL, 's'},
- {"density", 1, NULL, 'D'},
- {"chip", 1, NULL, 'C'},
- {"em100", 0, NULL, 'e'},
- {"lock", 0, NULL, 'l'},
- {"unlock", 0, NULL, 'u'},
- {"version", 0, NULL, 'v'},
- {"help", 0, NULL, 'h'},
- {"platform", 0, NULL, 'p'},
- {0, 0, 0, 0}
- };
+ if (argc == 2 && !strcmp("version", argv[1])) {
+ print_version();
+ return 0;
+ } else if (argc == 2 && !strcmp("version", argv[1])) {
+ print_usage(argv[0]);
+ return 0;
+ } else if (argc < 3) {
+ print_usage(argv[0]);
+ return 1;
+ }

- while ((opt = getopt_long(argc, argv, "df:D:C:xi:n:s:p:eluvh?",
- long_options, &option_index)) != EOF) {
- switch (opt) {
- case 'd':
- mode_dump = 1;
- break;
- case 'f':
- mode_layout = 1;
- layout_fname = strdup(optarg);
- if (!layout_fname) {
- fprintf(stderr, "No layout file specified\n");
- print_usage(argv[0]);
- exit(EXIT_FAILURE);
+ char *filename = argv[1];
+ char *cmd = argv[2];
+ optind += 2;
+
+ for (i = 0; i < ARRAY_SIZE(commands); i++) {
+ if (strcmp(cmd, commands[i].name) != 0)
+ continue;
+
+ if (!strcmp("print", commands[i].name)) {
+ mode = MODE_DUMP;
+ } else if (!strcmp("inject-region", commands[i].name)) {
+ mode = MODE_INJECT;
+ } else if (!strcmp("extract-region", commands[i].name)) {
+ mode = MODE_EXTRACT;
+ } else if (!strcmp("configure", commands[i].name)) {
+ mode = MODE_CONFIGURE;
+ }
+
+ while (1) {
+ char *suffix = NULL;
+ int option_index = 0;
+ c = getopt_long(argc, argv, commands[i].optstring,
+ long_options, &option_index);
+ if (c == -1) {
+ /* if (optind < argc) { */
+ /* printf("%s: excessive argument -- '%s'" */
+ /* "\n", argv[0], argv[optind]); */
+ /* return 1; */
+ /* } */
+ break;
}
- 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;
- else if (!strcasecmp("EC", region_type_string))
- region_type = 8;
- if (region_type == -1) {
- fprintf(stderr, "No such region type: '%s'\n\n",
- region_type_string);
- print_usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- mode_inject = 1;
- break;
- case 'n':
- mode_newlayout = 1;
- layout_fname = strdup(optarg);
- if (!layout_fname) {
- fprintf(stderr, "No layout file specified\n");
- print_usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- break;
- case 'D':
- mode_density = 1;
- new_density = strtoul(optarg, NULL, 0);
- switch (new_density) {
- case 512:
- new_density = COMPONENT_DENSITY_512KB;
+
+ switch(c) {
+ case 'f':
+ param.region_filename = optarg;
break;
- case 1:
- new_density = COMPONENT_DENSITY_1MB;
+ case 'l':
+ if (option_unlock) {
+ fprintf(stderr,
+ "Locking/Unlocking FD and ME are mutually exclusive\n");
+ return -1;
+ }
+ option_lock = 1;
break;
- case 2:
- new_density = COMPONENT_DENSITY_2MB;
+ case 'n':
+ param.region_name = optarg;
break;
- case 4:
- new_density = COMPONENT_DENSITY_4MB;
+ case 's':
+ option_size = 1;
+ new_density = encode_component_density(strtoul(optarg, NULL, 0));
+ if (new_density == COMPONENT_DENSITY_UNUSED) {
+ return -1;
+ }
break;
- case 8:
- new_density = COMPONENT_DENSITY_8MB;
- break;
- case 16:
- new_density = COMPONENT_DENSITY_16MB;
- break;
- case 32:
- new_density = COMPONENT_DENSITY_32MB;
- break;
- case 64:
- new_density = COMPONENT_DENSITY_64MB;
- break;
- case 0:
- new_density = COMPONENT_DENSITY_UNUSED;
+ case 'u':
+ if (option_lock) {
+ fprintf(stderr,
+ "Locking/Unlocking FD and ME are mutually exclusive\n");
+ return -1;
+ }
+ option_unlock = 1;
break;
default:
- printf("error: Unknown density\n");
print_usage(argv[0]);
- exit(EXIT_FAILURE);
+ return -1;
}
- break;
- case 'C':
- selected_chip = strtol(optarg, NULL, 0);
- if (selected_chip > 2) {
- fprintf(stderr, "error: Invalid chip selection\n");
- print_usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- break;
- case 's':
- // Parse the requested SPI frequency
- inputfreq = strtol(optarg, NULL, 0);
- switch (inputfreq) {
- case 17:
- spifreq = SPI_FREQUENCY_17MHZ;
- break;
- case 20:
- spifreq = SPI_FREQUENCY_20MHZ;
- break;
- case 30:
- spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
- break;
- case 33:
- spifreq = SPI_FREQUENCY_33MHZ;
- break;
- case 48:
- spifreq = SPI_FREQUENCY_48MHZ;
- break;
- case 50:
- spifreq = SPI_FREQUENCY_50MHZ_30MHZ;
- break;
- default:
- fprintf(stderr, "Invalid SPI Frequency: %d\n",
- inputfreq);
- print_usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- mode_spifreq = 1;
- break;
- case 'e':
- mode_em100 = 1;
- break;
- case 'l':
- mode_locked = 1;
- if (mode_unlocked == 1) {
- fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
- exit(EXIT_FAILURE);
- }
- break;
- case 'u':
- mode_unlocked = 1;
- if (mode_locked == 1) {
- fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n");
- exit(EXIT_FAILURE);
- }
- break;
- case 'p':
- if (!strcmp(optarg, "aplk")) {
- platform = PLATFORM_APOLLOLAKE;
- } else {
- fprintf(stderr, "Unknown platform: %s\n", optarg);
- exit(EXIT_FAILURE);
- }
- 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_layout + mode_extract + mode_inject +
- mode_newlayout + (mode_spifreq | mode_em100 | mode_unlocked |
- mode_locked)) > 1) {
- fprintf(stderr, "You may not specify more than one mode.\n\n");
- print_usage(argv[0]);
- exit(EXIT_FAILURE);
+ if (mode == MODE_INVALID) {
+ printf("Invalid action '%s'\n", cmd);
+ return -1;
+ } else if (mode == MODE_INJECT || mode == MODE_EXTRACT) {
+ region_type_string = param.region_name;
+ region_fname = param.region_filename;
+
+ if (!region_fname) {
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
+ region_type = region_num(region_type_string, MAX_REGIONS);
+ if (region_type == -1) {
+ fprintf(stderr, "No such region type: '%s'\n\n",
+ region_type_string);
+ print_usage(argv[0]);
+ exit(EXIT_FAILURE);
+ }
}

- if ((mode_dump + mode_layout + mode_extract + mode_inject +
- mode_newlayout + mode_spifreq + mode_em100 + mode_locked +
- mode_unlocked + mode_density) == 0) {
- fprintf(stderr, "You need to specify a mode.\n\n");
- print_usage(argv[0]);
+ int bios_fd;
+ int image_size;
+ char* image;
+
+ bios_fd = open_image(filename, &bios_fd, &image, &image_size);
+ if (bios_fd < 0)
exit(EXIT_FAILURE);
+
+ check_ifd_version(image, image_size);
+
+ if (mode == MODE_DUMP) {
+ dump_fd(image, image_size);
+ } else if (mode == MODE_INJECT) {
+ inject_region(filename, image, image_size, region_type,
+ region_fname);
+ } else if (mode == MODE_EXTRACT) {
+ extract_region(image, image_size, region_type, region_fname);
+ } else if (mode == MODE_CONFIGURE) {
+ if (option_size) {
+ set_chipdensity(filename, image, image_size, new_density);
+ }
+ if (option_lock) {
+ lock_descriptor(filename, image, image_size);
+ }
+ if (option_unlock) {
+ unlock_descriptor(filename, image, image_size);
+ }
+
}

- 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 | O_BINARY);
- 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);
-
- check_ifd_version(image, size);
-
- if (mode_dump)
- dump_fd(image, size);
-
- if (mode_layout)
- dump_layout(image, size, layout_fname);
-
- if (mode_extract)
- write_regions(image, size);
-
- if (mode_inject)
- inject_region(filename, image, size, region_type,
- region_fname);
-
- if (mode_newlayout)
- new_layout(filename, image, size, layout_fname);
-
- if (mode_spifreq)
- set_spi_frequency(filename, image, size, spifreq);
-
- if (mode_density)
- set_chipdensity(filename, image, size, new_density);
-
- if (mode_em100)
- set_em100_mode(filename, image, size);
-
- if (mode_locked)
- lock_descriptor(filename, image, size);
-
- if (mode_unlocked)
- unlock_descriptor(filename, image, size);
-
- free(image);
+ close_image(bios_fd, image);

return 0;
}
diff --git a/util/ifdtool/ifdtool.h b/util/ifdtool/ifdtool.h
index fe98d6a..e4c383e 100644
--- a/util/ifdtool/ifdtool.h
+++ b/util/ifdtool/ifdtool.h
@@ -142,4 +142,5 @@
struct region_name {
char *pretty;
char *terse;
+ char *type;
};

To view, visit change 20434. To unsubscribe, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6e463239c4f727a6296e4eca24682966b4160e3b
Gerrit-Change-Number: 20434
Gerrit-PatchSet: 1
Gerrit-Owner: Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>