diff options
-rw-r--r-- | futility/cmd_dump_fmap.c | 11 | ||||
-rw-r--r-- | futility/cmd_dump_kernel_config.c | 1 | ||||
-rw-r--r-- | futility/cmd_gbb_utility.c | 39 | ||||
-rw-r--r-- | futility/cmd_load_fmap.c | 1 | ||||
-rw-r--r-- | futility/cmd_pcr.c | 1 | ||||
-rw-r--r-- | futility/cmd_show.c | 2 | ||||
-rw-r--r-- | futility/cmd_sign.c | 1 | ||||
-rw-r--r-- | futility/cmd_vbutil_firmware.c | 1 | ||||
-rw-r--r-- | futility/cmd_vbutil_kernel.c | 1 | ||||
-rw-r--r-- | futility/cmd_vbutil_key.c | 1 | ||||
-rw-r--r-- | futility/cmd_vbutil_keyblock.c | 1 | ||||
-rw-r--r-- | futility/futility.c | 93 | ||||
-rw-r--r-- | futility/futility.h | 39 | ||||
-rwxr-xr-x | tests/futility/test_dump_fmap.sh | 2 | ||||
-rwxr-xr-x | tests/futility/test_gbb_utility.sh | 10 |
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} |