summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2015-02-05 12:36:15 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-02-28 00:56:13 +0000
commit1eae873b6194db25781233d7a4aaee6a34160eec (patch)
treece7ce14d2a62beb97fce1772ea2f53920bdbd2b3
parent822120106c963b43c3d303a791f8dd8731d0888e (diff)
downloadvboot-stabilize-6835.B.tar.gz
futility: Add global args to specify vboot API and formatstabilize-6842.Bstabilize-6835.B
The host-side futility tool will need to support all extant vboot implementations. Some legacy futility commands only support the original vb1 format, but others ("show" or "sign", for example) may need to be instructed which formats to expect or emit. This change adds some global args to specify the preferred formats. It also cleans up a few [unused AFAICT] one-letter args to avoid conflicts. BUG=chromium:231574 BRANCH=none TEST=make runtests Nothing makes use of this yet, except the "help" command. Change-Id: Ib79fa12af72b8860b9494e5d9e90b9572c006107 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/246765 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--futility/cmd_dump_fmap.c11
-rw-r--r--futility/cmd_dump_kernel_config.c1
-rw-r--r--futility/cmd_gbb_utility.c39
-rw-r--r--futility/cmd_load_fmap.c1
-rw-r--r--futility/cmd_pcr.c1
-rw-r--r--futility/cmd_show.c2
-rw-r--r--futility/cmd_sign.c1
-rw-r--r--futility/cmd_vbutil_firmware.c1
-rw-r--r--futility/cmd_vbutil_kernel.c1
-rw-r--r--futility/cmd_vbutil_key.c1
-rw-r--r--futility/cmd_vbutil_keyblock.c1
-rw-r--r--futility/futility.c93
-rw-r--r--futility/futility.h39
-rwxr-xr-xtests/futility/test_dump_fmap.sh2
-rwxr-xr-xtests/futility/test_gbb_utility.sh10
15 files changed, 157 insertions, 47 deletions
diff --git a/futility/cmd_dump_fmap.c b/futility/cmd_dump_fmap.c
index 4bc4bd26..1c233fda 100644
--- a/futility/cmd_dump_fmap.c
+++ b/futility/cmd_dump_fmap.c
@@ -398,11 +398,11 @@ static const char usage[] =
"Display (and extract) the FMAP components from a BIOS image.\n"
"\n"
"Options:\n"
- " -p Use a format easy to parse by scripts\n"
- " -f Use the format expected by flashrom\n"
+ " -x Extract the named sections from the file\n"
" -h Use a human-readable format\n"
" -H With -h, display any gaps\n"
- " -x Extract the named sections from the file\n"
+ " -p Use a format easy to parse by scripts\n"
+ " -F Use the format expected by flashrom\n"
"\n"
"Specify one or more NAMEs to dump only those sections.\n"
"\n";
@@ -424,7 +424,7 @@ static int do_dump_fmap(int argc, char *argv[])
progname = argv[0];
opterr = 0; /* quiet, you */
- while ((c = getopt(argc, argv, ":xpfhH")) != -1) {
+ while ((c = getopt(argc, argv, ":xpFhH")) != -1) {
switch (c) {
case 'x':
opt_extract = 1;
@@ -432,7 +432,7 @@ static int do_dump_fmap(int argc, char *argv[])
case 'p':
opt_format = FMT_PRETTY;
break;
- case 'f':
+ case 'F':
opt_format = FMT_FLASHROM;
break;
case 'H':
@@ -514,5 +514,6 @@ static int do_dump_fmap(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(dump_fmap, do_dump_fmap,
+ VBOOT_VERSION_ALL,
"Display FMAP contents from a firmware image",
print_help);
diff --git a/futility/cmd_dump_kernel_config.c b/futility/cmd_dump_kernel_config.c
index 520d2802..fad7e292 100644
--- a/futility/cmd_dump_kernel_config.c
+++ b/futility/cmd_dump_kernel_config.c
@@ -88,5 +88,6 @@ static int do_dump_kernel_config(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(dump_kernel_config, do_dump_kernel_config,
+ VBOOT_VERSION_ALL,
"Prints the kernel command line",
PrintHelp);
diff --git a/futility/cmd_gbb_utility.c b/futility/cmd_gbb_utility.c
index 9e608d1f..65d5f938 100644
--- a/futility/cmd_gbb_utility.c
+++ b/futility/cmd_gbb_utility.c
@@ -57,26 +57,39 @@ static void print_help(const char *prog)
}
enum {
- OPT_DIGEST = 1000,
+ OPT_HWID = 1000,
+ OPT_FLAGS,
+ OPT_DIGEST,
};
/* Command line options */
-static const struct option long_opts[] = {
- /* name hasarg *flag val */
+static struct option long_opts[] = {
+ /* name has_arg *flag val */
{"get", 0, NULL, 'g'},
{"set", 0, NULL, 's'},
{"create", 1, NULL, 'c'},
{"output", 1, NULL, 'o'},
{"rootkey", 1, NULL, 'k'},
{"bmpfv", 1, NULL, 'b'},
- {"recoverykey", 1, NULL, 'R'},
- {"hwid", 2, NULL, 'i'},
- {"flags", 2, NULL, 'L'},
+ {"recoverykey", 1, NULL, 'r'},
+ {"hwid", 0, NULL, OPT_HWID},
+ {"flags", 0, NULL, OPT_FLAGS},
{"digest", 0, NULL, OPT_DIGEST},
{NULL, 0, NULL, 0},
};
-static char *short_opts = ":gsc:o:k:b:R:r:h:i:L:f:";
+static char *short_opts = ":gsc:o:k:b:r:";
+
+/* Change the has_arg field of a long_opts entry */
+static void opt_has_arg(const char *name, int val)
+{
+ struct option *p;
+ for (p = long_opts; p->name; p++)
+ if (!strcmp(name, p->name)) {
+ p->has_arg = val;
+ break;
+ }
+}
static int errorcnt;
@@ -360,9 +373,13 @@ static int do_gbb_utility(int argc, char *argv[])
switch (i) {
case 'g':
mode = DO_GET;
+ opt_has_arg("flags", 0);
+ opt_has_arg("hwid", 0);
break;
case 's':
mode = DO_SET;
+ opt_has_arg("flags", 1);
+ opt_has_arg("hwid", 1);
break;
case 'c':
mode = DO_CREATE;
@@ -377,18 +394,15 @@ static int do_gbb_utility(int argc, char *argv[])
case 'b':
opt_bmpfv = optarg;
break;
- case 'R':
case 'r':
opt_recoverykey = optarg;
break;
- case 'i':
- case 'h':
+ case OPT_HWID:
/* --hwid is optional: null might be okay */
opt_hwid = optarg;
sel_hwid = 1;
break;
- case 'L':
- case 'f':
+ case OPT_FLAGS:
/* --flags is optional: null might be okay */
opt_flags = optarg;
sel_flags = 1;
@@ -624,5 +638,6 @@ static int do_gbb_utility(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(gbb_utility, do_gbb_utility,
+ VBOOT_VERSION_ALL,
"Manipulate the Google Binary Block (GBB)",
print_help);
diff --git a/futility/cmd_load_fmap.c b/futility/cmd_load_fmap.c
index 7922ad62..cd81b303 100644
--- a/futility/cmd_load_fmap.c
+++ b/futility/cmd_load_fmap.c
@@ -199,5 +199,6 @@ done_file:
}
DECLARE_FUTIL_COMMAND(load_fmap, do_load_fmap,
+ VBOOT_VERSION_ALL,
"Replace the contents of specified FMAP areas",
help_and_quit);
diff --git a/futility/cmd_pcr.c b/futility/cmd_pcr.c
index 9149ccfe..ef44453e 100644
--- a/futility/cmd_pcr.c
+++ b/futility/cmd_pcr.c
@@ -182,5 +182,6 @@ static int do_pcr(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(pcr, do_pcr,
+ VBOOT_VERSION_ALL,
"Simulate a TPM PCR extension operation",
help_and_quit);
diff --git a/futility/cmd_show.c b/futility/cmd_show.c
index b6c2574a..875689d5 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -730,6 +730,7 @@ done:
}
DECLARE_FUTIL_COMMAND(show, do_show,
+ VBOOT_VERSION_ALL,
"Display the content of various binary components",
print_help);
@@ -740,5 +741,6 @@ static int do_verify(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(verify, do_verify,
+ VBOOT_VERSION_ALL,
"Verify the signatures of various binary components",
print_help);
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c
index 2d247bcd..192305f7 100644
--- a/futility/cmd_sign.c
+++ b/futility/cmd_sign.c
@@ -1079,5 +1079,6 @@ done:
}
DECLARE_FUTIL_COMMAND(sign, do_sign,
+ VBOOT_VERSION_ALL,
"Sign / resign various binary components",
print_help);
diff --git a/futility/cmd_vbutil_firmware.c b/futility/cmd_vbutil_firmware.c
index dcb325e1..4f748e86 100644
--- a/futility/cmd_vbutil_firmware.c
+++ b/futility/cmd_vbutil_firmware.c
@@ -386,5 +386,6 @@ static int do_vbutil_firmware(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware,
+ VBOOT_VERSION_1_0,
"Verified boot firmware utility",
print_help);
diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c
index 3322e4b8..c7b3c78c 100644
--- a/futility/cmd_vbutil_kernel.c
+++ b/futility/cmd_vbutil_kernel.c
@@ -648,5 +648,6 @@ static int do_vbutil_kernel(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(vbutil_kernel, do_vbutil_kernel,
+ VBOOT_VERSION_1_0,
"Creates, signs, and verifies the kernel partition",
print_help);
diff --git a/futility/cmd_vbutil_key.c b/futility/cmd_vbutil_key.c
index ea8dea0b..de9f97ff 100644
--- a/futility/cmd_vbutil_key.c
+++ b/futility/cmd_vbutil_key.c
@@ -235,5 +235,6 @@ static int do_vbutil_key(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key,
+ VBOOT_VERSION_1_0,
"Wraps RSA keys with vboot headers",
print_help);
diff --git a/futility/cmd_vbutil_keyblock.c b/futility/cmd_vbutil_keyblock.c
index c73fd9ae..64a1760b 100644
--- a/futility/cmd_vbutil_keyblock.c
+++ b/futility/cmd_vbutil_keyblock.c
@@ -332,5 +332,6 @@ static int do_vbutil_keyblock(int argc, char *argv[])
}
DECLARE_FUTIL_COMMAND(vbutil_keyblock, do_vbutil_keyblock,
+ VBOOT_VERSION_1_0,
"Creates, signs, and verifies a keyblock",
print_help);
diff --git a/futility/futility.c b/futility/futility.c
index ba9fb163..02f61af9 100644
--- a/futility/futility.c
+++ b/futility/futility.c
@@ -6,6 +6,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <getopt.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
@@ -175,8 +176,11 @@ static void log_args(int argc, char *argv[])
/******************************************************************************/
+/* Default is to support everything we can */
+enum vboot_version vboot_version = VBOOT_VERSION_ALL;
+
static const char *const usage = "\n"
-"Usage: " MYNAME " COMMAND [args...]\n"
+"Usage: " MYNAME " [options] COMMAND [args...]\n"
"\n"
"This is the unified firmware utility, which will eventually replace\n"
"most of the distinct verified boot tools formerly produced by the\n"
@@ -187,10 +191,12 @@ static const char *const usage = "\n"
"as " MYNAME ", followed by the original name as the first argument.\n"
"\n";
-static void print_help(const char *cmd)
-{
- puts(usage);
-}
+static const char *const options =
+"Global options:\n"
+"\n"
+" --vb1 Use only vboot v1.0 binary formats\n"
+" --vb21 Use only vboot v2.1 binary formats\n"
+"\n";
static const struct futil_cmd_t *find_command(const char *name)
{
@@ -208,12 +214,15 @@ static void list_commands(void)
const struct futil_cmd_t *const *cmd;
for (cmd = futil_cmds; *cmd; cmd++)
- printf(" %-20s %s\n", (*cmd)->name, (*cmd)->shorthelp);
+ if (vboot_version & (*cmd)->version)
+ printf(" %-20s %s\n",
+ (*cmd)->name, (*cmd)->shorthelp);
}
static int do_help(int argc, char *argv[])
{
const struct futil_cmd_t *cmd;
+ const char *vstr;
if (argc >= 2) {
cmd = find_command(argv[1]);
@@ -227,16 +236,30 @@ static int do_help(int argc, char *argv[])
fputs(usage, stdout);
- printf("The following commands are built-in:\n\n");
+ if (vboot_version == VBOOT_VERSION_ALL)
+ fputs(options, stdout);
+
+ switch (vboot_version) {
+ case VBOOT_VERSION_1_0:
+ vstr = "version 1.0 ";
+ break;
+ case VBOOT_VERSION_2_1:
+ vstr = "version 2.1 ";
+ break;
+ case VBOOT_VERSION_ALL:
+ vstr = "";
+ break;
+ }
+ printf("The following %scommands are built-in:\n\n", vstr);
list_commands();
printf("\nUse \"" MYNAME " help COMMAND\" for more information.\n\n");
return 0;
}
-DECLARE_FUTIL_COMMAND(help, do_help,
+DECLARE_FUTIL_COMMAND(help, do_help, VBOOT_VERSION_ALL,
"Show a bit of help (you're looking at it)",
- print_help);
+ NULL);
static int do_version(int argc, char *argv[])
{
@@ -244,7 +267,7 @@ static int do_version(int argc, char *argv[])
return 0;
}
-DECLARE_FUTIL_COMMAND(version, do_version,
+DECLARE_FUTIL_COMMAND(version, do_version, VBOOT_VERSION_ALL,
"Show the futility source revision and build date",
NULL);
@@ -276,6 +299,13 @@ int main(int argc, char *argv[], char *envp[])
{
char *progname;
const struct futil_cmd_t *cmd;
+ int i, errorcnt = 0;
+ int vb_ver = VBOOT_VERSION_ALL;
+ struct option long_opts[] = {
+ {"vb1" , 0, &vb_ver, VBOOT_VERSION_1_0},
+ {"vb21", 0, &vb_ver, VBOOT_VERSION_2_1},
+ { 0, 0, 0, 0},
+ };
log_args(argc, argv);
@@ -285,23 +315,48 @@ int main(int argc, char *argv[], char *envp[])
/* See if the program name is a command we recognize */
cmd = find_command(progname);
if (cmd)
+ /* Yep, just do that */
return run_command(cmd, argc, argv);
- /* The program name means nothing, so we require an argument. */
- if (argc < 2) {
+ /* Parse the global options, stopping at the first non-option. */
+ opterr = 0; /* quiet, you. */
+ while ((i = getopt_long(argc, argv, "+:", long_opts, NULL)) != -1) {
+ switch (i) {
+ case '?':
+ if (optopt)
+ fprintf(stderr, "Unrecognized option: -%c\n",
+ optopt);
+ else
+ fprintf(stderr, "Unrecognized option: %s\n",
+ argv[optind - 1]);
+ errorcnt++;
+ break;
+ case ':':
+ fprintf(stderr, "Missing argument to -%c\n", optopt);
+ errorcnt++;
+ break;
+ case 0: /* handled option */
+ break;
+ default:
+ Debug("i=%d\n", i);
+ DIE;
+ }
+ }
+ vboot_version = vb_ver;
+
+ /* Reset the getopt state so commands can parse their own options. */
+ argc -= optind;
+ argv += optind;
+ optind = 0;
+
+ /* We require a command name. */
+ if (errorcnt || argc < 1) {
do_help(0, 0);
return 1;
}
- /* The first arg should be a command we recognize */
- argc--;
- argv++;
-
/* For reasons I've forgotten, treat /blah/blah/CMD the same as CMD */
progname = simple_basename(argv[0]);
- /* Oh, and treat "--foo" the same as "foo" */
- while (*progname == '-')
- progname++;
/* Do we recognize the command? */
cmd = find_command(progname);
diff --git a/futility/futility.h b/futility/futility.h
index 5f9a5b78..550e381e 100644
--- a/futility/futility.h
+++ b/futility/futility.h
@@ -17,21 +17,48 @@
/* Version string (autogenerated) */
extern const char futility_version[];
+/* Bitfields indicating the struct/format versions supported by a command */
+enum vboot_version {
+ /*
+ * v1.0 is the original structs used since the dawn of time.
+ * v2.0 can verify the firmware in smaller chunks, but there's
+ * no difference in the on-device structs, so it's only
+ * meaningful for the firmware API. Futility doesn't care.
+ */
+ VBOOT_VERSION_1_0 = 0x00000001,
+
+ /*
+ * v2.1 uses new and different structs, and is what v2.0 would have
+ * been if someone hadn't started using it before it was ready.
+ */
+ VBOOT_VERSION_2_1 = 0x00000002,
+
+ /*
+ * Everything we know about to date.
+ */
+ VBOOT_VERSION_ALL = 0x00000003,
+};
+
+/* What's our preferred API & data format? */
+enum vboot_version vboot_version;
+
/* Here's a structure to define the commands that futility implements. */
struct futil_cmd_t {
const char *const name;
int (*const handler) (int argc, char **argv);
+ enum vboot_version version;
const char *const shorthelp;
void (*longhelp) (const char *cmd);
};
/* Macro to define a command */
-#define DECLARE_FUTIL_COMMAND(NAME, HANDLER, SHORTHELP, LONGHELP) \
- const struct futil_cmd_t __cmd_##NAME = { \
- .name = #NAME, \
- .handler = HANDLER, \
- .shorthelp = SHORTHELP, \
- .longhelp = LONGHELP, \
+#define DECLARE_FUTIL_COMMAND(NAME, HANDLER, VERSION, SHORTHELP, LONGHELP) \
+ const struct futil_cmd_t __cmd_##NAME = { \
+ .name = #NAME, \
+ .handler = HANDLER, \
+ .version = VERSION, \
+ .shorthelp = SHORTHELP, \
+ .longhelp = LONGHELP, \
}
/* This is the list of pointers to all commands. */
diff --git a/tests/futility/test_dump_fmap.sh b/tests/futility/test_dump_fmap.sh
index bcdb27e6..5a58a0c8 100755
--- a/tests/futility/test_dump_fmap.sh
+++ b/tests/futility/test_dump_fmap.sh
@@ -10,7 +10,7 @@ TMP="$me.tmp"
cd "$OUTDIR"
# Good FMAP
-"$FUTILITY" dump_fmap -f "${SCRIPTDIR}/data_fmap.bin" > "$TMP"
+"$FUTILITY" dump_fmap -F "${SCRIPTDIR}/data_fmap.bin" > "$TMP"
cmp "${SCRIPTDIR}/data_fmap_expect_f.txt" "$TMP"
"$FUTILITY" dump_fmap -p "${SCRIPTDIR}/data_fmap.bin" > "$TMP"
diff --git a/tests/futility/test_gbb_utility.sh b/tests/futility/test_gbb_utility.sh
index 3d8e576b..3dc7d351 100755
--- a/tests/futility/test_gbb_utility.sh
+++ b/tests/futility/test_gbb_utility.sh
@@ -22,9 +22,11 @@ ${FUTILITY} gbb_utility -s --flags=0xdeadbeef ${TMP}.blob
${FUTILITY} gbb_utility -g --flags ${TMP}.blob | grep -i 0xdeadbeef
# HWID length should include the terminating null - this is too long
-if ${FUTILITY} gbb_utility -s -i "0123456789ABCDEF" ${TMP}.blob; then false; fi
+if ${FUTILITY} gbb_utility -s --hwid="0123456789ABCDEF" ${TMP}.blob; then
+ false;
+fi
# This works
-${FUTILITY} gbb_utility -s -i "0123456789ABCDE" ${TMP}.blob
+${FUTILITY} gbb_utility -s --hwid="0123456789ABCDE" ${TMP}.blob
# Read it back?
${FUTILITY} gbb_utility -g ${TMP}.blob | grep "0123456789ABCDE"
@@ -184,7 +186,7 @@ if ${FUTILITY} gbb_utility -g ${TMP}.blob.bad; then false; fi
# hwid_size == 0 doesn't complain, but can't be set
cat ${TMP}.blob | ${REPLACE} 0x14 0x00 > ${TMP}.blob.bad
${FUTILITY} gbb_utility -g ${TMP}.blob.bad
-if ${FUTILITY} gbb_utility -s -i "A" ${TMP}.blob.bad; then false; fi
+if ${FUTILITY} gbb_utility -s --hwid="A" ${TMP}.blob.bad; then false; fi
# rootkey_size == 0 gives warning, gets nothing, can't be set
cat ${TMP}.blob | ${REPLACE} 0x1c 0x00 > ${TMP}.blob.bad
@@ -213,7 +215,7 @@ if ${FUTILITY} gbb_utility -s --recoverykey ${TMP}.data2 ${TMP}.blob.bad; then f
# See that the digest is updated properly.
hwid="123456789ABCDEF"
-${FUTILITY} gbb_utility -s -i ${hwid} ${TMP}.blob
+${FUTILITY} gbb_utility -s --hwid=${hwid} ${TMP}.blob
expect=$(echo -n "$hwid" | sha256sum | cut -d ' ' -f 1)
[ $(echo -n ${expect} | wc -c) == "64" ]
${FUTILITY} gbb_utility -g --digest ${TMP}.blob | grep ${expect}