diff options
author | Bill Richardson <wfrichar@chromium.org> | 2015-03-26 16:34:28 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-03-31 06:28:18 +0000 |
commit | 1e35c3a51176edbe924acb8b9bcb68ae7b155ab4 (patch) | |
tree | 49d1af5d7f0592481e78e87d614d3735c852d16f /futility | |
parent | 453ecd19560af8efe3e518ba745dc6e8bfecac90 (diff) | |
download | vboot-1e35c3a51176edbe924acb8b9bcb68ae7b155ab4.tar.gz |
futility: export options for the sign and show commands
This declares the options for the sign and show commands in a
header file.
We want to split the code for logically separate file types into
separate source files, but we don't want to have multiple
option-parsing routines, so that we can be sure we're using the
same option names consistently (for example, --hash_alg always
takes the same args and means the same thing).
BUG=chromium:231574
BRANCH=none
TEST=make runtests
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Change-Id: I939bd19ba199b4c44eb41cff3571cff88df9a181
Reviewed-on: https://chromium-review.googlesource.com/262896
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'futility')
-rw-r--r-- | futility/cmd_show.c | 77 | ||||
-rw-r--r-- | futility/cmd_sign.c | 373 | ||||
-rw-r--r-- | futility/futility_options.h | 59 |
3 files changed, 277 insertions, 232 deletions
diff --git a/futility/cmd_show.c b/futility/cmd_show.c index f00f2224..714b0e58 100644 --- a/futility/cmd_show.c +++ b/futility/cmd_show.c @@ -24,6 +24,7 @@ #include "file_type.h" #include "fmap.h" #include "futility.h" +#include "futility_options.h" #include "gbb_header.h" #include "host_common.h" #include "traversal.h" @@ -31,16 +32,8 @@ #include "vb1_helper.h" #include "vboot_common.h" -/* Local structure for args, etc. */ -static struct local_data_s { - VbPublicKey *k; - uint8_t *fv; - uint64_t fv_size; - uint32_t padding; - int strict; - int t_flag; - enum futil_file_type type; -} option = { +/* Options */ +struct show_option_s show_option = { .padding = 65536, .type = FILE_TYPE_UNKNOWN, }; @@ -278,7 +271,7 @@ int ft_show_gbb(const char *name, uint8_t *buf, uint32_t len, void *data) int ft_show_keyblock(const char *name, uint8_t *buf, uint32_t len, void *data) { VbKeyBlockHeader *block = (VbKeyBlockHeader *)buf; - VbPublicKey *sign_key = option.k; + VbPublicKey *sign_key = show_option.k; int good_sig = 0; int retval = 0; @@ -293,7 +286,7 @@ int ft_show_keyblock(const char *name, uint8_t *buf, uint32_t len, void *data) KeyBlockVerify(block, len, sign_key, 0)) good_sig = 1; - if (option.strict && (!sign_key || !good_sig)) + if (show_option.strict && (!sign_key || !good_sig)) retval = 1; show_keyblock(block, name, !!sign_key, good_sig); @@ -333,9 +326,9 @@ int ft_show_fw_preamble(const char *name, uint8_t *buf, uint32_t len, { VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf; struct show_state_s *state = (struct show_state_s *)data; - VbPublicKey *sign_key = option.k; - uint8_t *fv_data = option.fv; - uint64_t fv_size = option.fv_size; + VbPublicKey *sign_key = show_option.k; + uint8_t *fv_data = show_option.fv; + uint64_t fv_size = show_option.fv_size; struct bios_area_s *fw_body_area = 0; int good_sig = 0; int retval = 0; @@ -371,7 +364,7 @@ int ft_show_fw_preamble(const char *name, uint8_t *buf, uint32_t len, show_keyblock(key_block, name, !!sign_key, good_sig); - if (option.strict && (!sign_key || !good_sig)) + if (show_option.strict && (!sign_key || !good_sig)) retval = 1; RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key); @@ -428,7 +421,7 @@ int ft_show_fw_preamble(const char *name, uint8_t *buf, uint32_t len, if (!fv_data) { printf("No firmware body available to verify.\n"); - if (option.strict) + if (show_option.strict) return 1; return 0; } @@ -449,7 +442,7 @@ done: state->area[state->c].is_valid = 1; } else { printf("Seems legit, but the signature is unverified.\n"); - if (option.strict) + if (show_option.strict) retval = 1; } @@ -509,7 +502,7 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len, void *data) { VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf; - VbPublicKey *sign_key = option.k; + VbPublicKey *sign_key = show_option.k; uint8_t *kernel_blob = 0; uint64_t kernel_size = 0; int good_sig = 0; @@ -532,7 +525,7 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len, printf("Kernel partition: %s\n", name); show_keyblock(key_block, NULL, !!sign_key, good_sig); - if (option.strict && (!sign_key || !good_sig)) + if (show_option.strict && (!sign_key || !good_sig)) retval = 1; RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key); @@ -586,14 +579,14 @@ int ft_show_kernel_preamble(const char *name, uint8_t *buf, uint32_t len, printf(" Flags: 0x%" PRIx32 "\n", flags); /* Verify kernel body */ - if (option.fv) { + if (show_option.fv) { /* It's in a separate file, which we've already read in */ - kernel_blob = option.fv; - kernel_size = option.fv_size; - } else if (len > option.padding) { + kernel_blob = show_option.fv; + kernel_size = show_option.fv_size; + } else if (len > show_option.padding) { /* It should be at an offset within the input file. */ - kernel_blob = buf + option.padding; - kernel_size = len - option.padding; + kernel_blob = buf + show_option.padding; + kernel_size = len - show_option.padding; } if (!kernel_blob) { @@ -661,7 +654,7 @@ static const struct option long_opts[] = { {"fv", 1, 0, 'f'}, {"pad", 1, NULL, OPT_PADDING}, {"type", 1, NULL, OPT_TYPE}, - {"strict", 0, &option.strict, 1}, + {"strict", 0, &show_option.strict, 1}, {"help", 0, NULL, OPT_HELP}, {NULL, 0, NULL, 0}, }; @@ -712,25 +705,26 @@ static int do_show(int argc, char *argv[]) while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { switch (i) { case 'f': - option.fv = ReadFile(optarg, &option.fv_size); - if (!option.fv) { + show_option.fv = ReadFile(optarg, + &show_option.fv_size); + if (!show_option.fv) { fprintf(stderr, "Error reading %s: %s\n", optarg, strerror(errno)); errorcnt++; } break; case 'k': - option.k = PublicKeyRead(optarg); - if (!option.k) { + show_option.k = PublicKeyRead(optarg); + if (!show_option.k) { fprintf(stderr, "Error reading %s\n", optarg); errorcnt++; } break; case 't': - option.t_flag = 1; + show_option.t_flag = 1; break; case OPT_PADDING: - option.padding = strtoul(optarg, &e, 0); + show_option.padding = strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { fprintf(stderr, "Invalid --padding \"%s\"\n", optarg); @@ -738,7 +732,8 @@ static int do_show(int argc, char *argv[]) } break; case OPT_TYPE: - if (!futil_str_to_file_type(optarg, &option.type)) { + if (!futil_str_to_file_type(optarg, + &show_option.type)) { if (!strcasecmp("help", optarg)) print_file_types_and_exit(errorcnt); fprintf(stderr, @@ -781,7 +776,7 @@ static int do_show(int argc, char *argv[]) return 1; } - if (option.t_flag) { + if (show_option.t_flag) { for (i = optind; i < argc; i++) errorcnt += show_type(argv[i]); goto done; @@ -804,7 +799,7 @@ static int do_show(int argc, char *argv[]) /* Allow the user to override the type */ if (type_override) - type = option.type; + type = show_option.type; else type = futil_file_type_buf(buf, len); @@ -820,10 +815,10 @@ boo: } done: - if (option.k) - free(option.k); - if (option.fv) - free(option.fv); + if (show_option.k) + free(show_option.k); + if (show_option.fv) + free(show_option.fv); return !!errorcnt; } @@ -833,7 +828,7 @@ DECLARE_FUTIL_COMMAND(show, do_show, VBOOT_VERSION_ALL, static int do_verify(int argc, char *argv[]) { - option.strict = 1; + show_option.strict = 1; return do_show(argc, argv); } diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c index 98a197e0..3020215c 100644 --- a/futility/cmd_sign.c +++ b/futility/cmd_sign.c @@ -21,6 +21,7 @@ #include "file_type.h" #include "fmap.h" #include "futility.h" +#include "futility_options.h" #include "gbb_header.h" #include "host_common.h" #include "kernel_blob.h" @@ -29,36 +30,8 @@ #include "vb1_helper.h" #include "vboot_common.h" -/* Local structure for args, etc. */ -static struct local_data_s { - VbPrivateKey *signprivate; - VbKeyBlockHeader *keyblock; - VbPublicKey *kernel_subkey; - VbPrivateKey *devsignprivate; - VbKeyBlockHeader *devkeyblock; - uint32_t version; - int version_specified; - uint32_t flags; - int flags_specified; - char *loemdir; - char *loemid; - uint8_t *bootloader_data; - uint64_t bootloader_size; - uint8_t *config_data; - uint64_t config_size; - enum arch_t arch; - int fv_specified; - uint32_t kloadaddr; - uint32_t padding; - int vblockonly; - char *outfile; - int create_new_outfile; - char *pem_signpriv; - int pem_algo_specified; - uint32_t pem_algo; - char *pem_external; - enum futil_file_type type; -} option = { +/* Options */ +struct sign_option_s sign_option = { .version = 1, .arch = ARCH_UNSPECIFIED, .kloadaddr = CROS_32BIT_ENTRY_ADDR, @@ -66,7 +39,6 @@ static struct local_data_s { .type = FILE_TYPE_UNKNOWN, }; - /* Helper to complain about invalid args. Returns num errors discovered */ static int no_opt_if(int expr, const char *optname) { @@ -118,34 +90,36 @@ int ft_sign_pubkey(const char *name, uint8_t *buf, uint32_t len, void *data) VbPublicKey *data_key = (VbPublicKey *)buf; VbKeyBlockHeader *vblock; - if (option.pem_signpriv) { - if (option.pem_external) { + if (sign_option.pem_signpriv) { + if (sign_option.pem_external) { /* External signing uses the PEM file directly. */ vblock = KeyBlockCreate_external( data_key, - option.pem_signpriv, - option.pem_algo, option.flags, - option.pem_external); + sign_option.pem_signpriv, + sign_option.pem_algo, sign_option.flags, + sign_option.pem_external); } else { - option.signprivate = PrivateKeyReadPem( - option.pem_signpriv, option.pem_algo); - if (!option.signprivate) { + sign_option.signprivate = PrivateKeyReadPem( + sign_option.pem_signpriv, + sign_option.pem_algo); + if (!sign_option.signprivate) { fprintf(stderr, "Unable to read PEM signing key: %s\n", strerror(errno)); return 1; } - vblock = KeyBlockCreate(data_key, option.signprivate, - option.flags); + vblock = KeyBlockCreate(data_key, + sign_option.signprivate, + sign_option.flags); } } else { /* Not PEM. Should already have a signing key. */ - vblock = KeyBlockCreate(data_key, option.signprivate, - option.flags); + vblock = KeyBlockCreate(data_key, sign_option.signprivate, + sign_option.flags); } /* Write it out */ - return WriteSomeParts(option.outfile, + return WriteSomeParts(sign_option.outfile, vblock, vblock->key_block_size, NULL, 0); } @@ -203,8 +177,8 @@ static int fmap_fw_preamble(const char *name, uint8_t *buf, uint32_t len, case BIOS_FMAP_VBLOCK_A: fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_A]; /* Preserve the flags if they're not specified */ - if (!option.flags_specified) - option.flags = preamble->flags; + if (!sign_option.flags_specified) + sign_option.flags = preamble->flags; break; case BIOS_FMAP_VBLOCK_B: fw_body_area = &state->area[BIOS_FMAP_FW_MAIN_B]; @@ -241,9 +215,9 @@ int ft_sign_raw_kernel(const char *name, uint8_t *buf, uint32_t len, kblob_data = CreateKernelBlob( vmlinuz_data, vmlinuz_size, - option.arch, option.kloadaddr, - option.config_data, option.config_size, - option.bootloader_data, option.bootloader_size, + sign_option.arch, sign_option.kloadaddr, + sign_option.config_data, sign_option.config_size, + sign_option.bootloader_data, sign_option.bootloader_size, &kblob_size); if (!kblob_data) { fprintf(stderr, "Unable to create kernel blob\n"); @@ -251,10 +225,13 @@ int ft_sign_raw_kernel(const char *name, uint8_t *buf, uint32_t len, } Debug("kblob_size = 0x%" PRIx64 "\n", kblob_size); - vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, - option.version, option.kloadaddr, - option.keyblock, option.signprivate, - option.flags, &vblock_size); + vblock_data = SignKernelBlob(kblob_data, kblob_size, + sign_option.padding, + sign_option.version, + sign_option.kloadaddr, + sign_option.keyblock, + sign_option.signprivate, + sign_option.flags, &vblock_size); if (!vblock_data) { fprintf(stderr, "Unable to sign kernel blob\n"); free(kblob_data); @@ -264,15 +241,15 @@ int ft_sign_raw_kernel(const char *name, uint8_t *buf, uint32_t len, /* We should be creating a completely new output file. * If not, something's wrong. */ - if (!option.create_new_outfile) + if (!sign_option.create_new_outfile) DIE; - if (option.vblockonly) - rv = WriteSomeParts(option.outfile, + if (sign_option.vblockonly) + rv = WriteSomeParts(sign_option.outfile, vblock_data, vblock_size, NULL, 0); else - rv = WriteSomeParts(option.outfile, + rv = WriteSomeParts(sign_option.outfile, vblock_data, vblock_size, kblob_data, kblob_size); @@ -294,7 +271,7 @@ int ft_sign_kern_preamble(const char *name, uint8_t *buf, uint32_t len, kpart_size = len; /* Note: This just sets some static pointers. It doesn't malloc. */ - kblob_data = UnpackKPart(kpart_data, kpart_size, option.padding, + kblob_data = UnpackKPart(kpart_data, kpart_size, sign_option.padding, &keyblock, &preamble, &kblob_size); if (!kblob_data) { @@ -309,50 +286,54 @@ int ft_sign_kern_preamble(const char *name, uint8_t *buf, uint32_t len, * it here either. To enable it, we'd need to update the zeropage * table's cmd_line_ptr as well as the preamble. */ - option.kloadaddr = preamble->body_load_address; + sign_option.kloadaddr = preamble->body_load_address; /* Replace the config if asked */ - if (option.config_data && + if (sign_option.config_data && 0 != UpdateKernelBlobConfig(kblob_data, kblob_size, - option.config_data, - option.config_size)) { + sign_option.config_data, + sign_option.config_size)) { fprintf(stderr, "Unable to update config\n"); return 1; } /* Preserve the version unless a new one is given */ - if (!option.version_specified) - option.version = preamble->kernel_version; + if (!sign_option.version_specified) + sign_option.version = preamble->kernel_version; /* Preserve the flags if not specified */ if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS) { - if (option.flags_specified == 0) - option.flags = preamble->flags; + if (sign_option.flags_specified == 0) + sign_option.flags = preamble->flags; } /* Replace the keyblock if asked */ - if (option.keyblock) - keyblock = option.keyblock; + if (sign_option.keyblock) + keyblock = sign_option.keyblock; /* Compute the new signature */ - vblock_data = SignKernelBlob(kblob_data, kblob_size, option.padding, - option.version, option.kloadaddr, - keyblock, option.signprivate, - option.flags, &vblock_size); + vblock_data = SignKernelBlob(kblob_data, kblob_size, + sign_option.padding, + sign_option.version, + sign_option.kloadaddr, + keyblock, + sign_option.signprivate, + sign_option.flags, + &vblock_size); if (!vblock_data) { fprintf(stderr, "Unable to sign kernel blob\n"); return 1; } Debug("vblock_size = 0x%" PRIx64 "\n", vblock_size); - if (option.create_new_outfile) { + if (sign_option.create_new_outfile) { /* Write out what we've been asked for */ - if (option.vblockonly) - rv = WriteSomeParts(option.outfile, + if (sign_option.vblockonly) + rv = WriteSomeParts(sign_option.outfile, vblock_data, vblock_size, NULL, 0); else - rv = WriteSomeParts(option.outfile, + rv = WriteSomeParts(sign_option.outfile, vblock_data, vblock_size, kblob_data, kblob_size); } else { @@ -374,25 +355,26 @@ int ft_sign_raw_firmware(const char *name, uint8_t *buf, uint32_t len, VbFirmwarePreambleHeader *preamble; int rv; - body_sig = CalculateSignature(buf, len, option.signprivate); + body_sig = CalculateSignature(buf, len, sign_option.signprivate); if (!body_sig) { fprintf(stderr, "Error calculating body signature\n"); return 1; } - preamble = CreateFirmwarePreamble(option.version, - option.kernel_subkey, + preamble = CreateFirmwarePreamble(sign_option.version, + sign_option.kernel_subkey, body_sig, - option.signprivate, - option.flags); + sign_option.signprivate, + sign_option.flags); if (!preamble) { fprintf(stderr, "Error creating firmware preamble.\n"); free(body_sig); return 1; } - rv = WriteSomeParts(option.outfile, - option.keyblock, option.keyblock->key_block_size, + rv = WriteSomeParts(sign_option.outfile, + sign_option.keyblock, + sign_option.keyblock->key_block_size, preamble, preamble->preamble_size); free(preamble); @@ -416,11 +398,11 @@ static int write_new_preamble(struct bios_area_s *vblock, return 1; } - preamble = CreateFirmwarePreamble(option.version, - option.kernel_subkey, + preamble = CreateFirmwarePreamble(sign_option.version, + sign_option.kernel_subkey, body_sig, signkey, - option.flags); + sign_option.flags); if (!preamble) { fprintf(stderr, "Error creating firmware preamble.\n"); free(body_sig); @@ -444,8 +426,8 @@ static int write_loem(const char *ab, struct bios_area_s *vblock) char filename[PATH_MAX]; int n; n = snprintf(filename, sizeof(filename), "%s/vblock_%s.%s", - option.loemdir ? option.loemdir : ".", - ab, option.loemid); + sign_option.loemdir ? sign_option.loemdir : ".", + ab, sign_option.loemid); if (n >= sizeof(filename)) { fprintf(stderr, "LOEM args produce bogus filename\n"); return 1; @@ -492,29 +474,29 @@ static int sign_bios_at_end(struct sign_state_s *state) if (fw_a->len != fw_b->len || memcmp(fw_a->buf, fw_b->buf, fw_a->len)) { /* Yes, must use DEV keys for A */ - if (!option.devsignprivate || !option.devkeyblock) { + if (!sign_option.devsignprivate || !sign_option.devkeyblock) { fprintf(stderr, "FW A & B differ. DEV keys are required.\n"); return 1; } retval |= write_new_preamble(vblock_a, fw_a, - option.devsignprivate, - option.devkeyblock); + sign_option.devsignprivate, + sign_option.devkeyblock); } else { retval |= write_new_preamble(vblock_a, fw_a, - option.signprivate, - option.keyblock); + sign_option.signprivate, + sign_option.keyblock); } /* FW B is always normal keys */ retval |= write_new_preamble(vblock_b, fw_b, - option.signprivate, - option.keyblock); + sign_option.signprivate, + sign_option.keyblock); - if (option.loemid) { + if (sign_option.loemid) { retval |= write_loem("A", vblock_a); retval |= write_loem("B", vblock_b); } @@ -717,14 +699,14 @@ static void print_help(int argc, char *argv[]) puts(usage_fw_main); return; case FILE_TYPE_BIOS_IMAGE: - printf(usage_bios, option.version); + printf(usage_bios, sign_option.version); return; case FILE_TYPE_RAW_KERNEL: - printf(usage_new_kpart, option.kloadaddr, - option.padding); + printf(usage_new_kpart, sign_option.kloadaddr, + sign_option.padding); return; case FILE_TYPE_KERN_PREAMBLE: - printf(usage_old_kpart, option.padding); + printf(usage_old_kpart, sign_option.padding); return; default: break; @@ -779,7 +761,7 @@ static const struct option long_opts[] = { {"pem_algo", 1, NULL, OPT_PEM_ALGO}, {"pem_external", 1, NULL, OPT_PEM_EXTERNAL}, {"type", 1, NULL, OPT_TYPE}, - {"vblockonly", 0, &option.vblockonly, 1}, + {"vblockonly", 0, &sign_option.vblockonly, 1}, {"help", 0, NULL, OPT_HELP}, {NULL, 0, NULL, 0}, }; @@ -802,43 +784,43 @@ static int do_sign(int argc, char *argv[]) while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) { switch (i) { case 's': - option.signprivate = PrivateKeyRead(optarg); - if (!option.signprivate) { + sign_option.signprivate = PrivateKeyRead(optarg); + if (!sign_option.signprivate) { fprintf(stderr, "Error reading %s\n", optarg); errorcnt++; } break; case 'b': - option.keyblock = KeyBlockRead(optarg); - if (!option.keyblock) { + sign_option.keyblock = KeyBlockRead(optarg); + if (!sign_option.keyblock) { fprintf(stderr, "Error reading %s\n", optarg); errorcnt++; } break; case 'k': - option.kernel_subkey = PublicKeyRead(optarg); - if (!option.kernel_subkey) { + sign_option.kernel_subkey = PublicKeyRead(optarg); + if (!sign_option.kernel_subkey) { fprintf(stderr, "Error reading %s\n", optarg); errorcnt++; } break; case 'S': - option.devsignprivate = PrivateKeyRead(optarg); - if (!option.devsignprivate) { + sign_option.devsignprivate = PrivateKeyRead(optarg); + if (!sign_option.devsignprivate) { fprintf(stderr, "Error reading %s\n", optarg); errorcnt++; } break; case 'B': - option.devkeyblock = KeyBlockRead(optarg); - if (!option.devkeyblock) { + sign_option.devkeyblock = KeyBlockRead(optarg); + if (!sign_option.devkeyblock) { fprintf(stderr, "Error reading %s\n", optarg); errorcnt++; } break; case 'v': - option.version_specified = 1; - option.version = strtoul(optarg, &e, 0); + sign_option.version_specified = 1; + sign_option.version = strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { fprintf(stderr, "Invalid --version \"%s\"\n", optarg); @@ -847,8 +829,8 @@ static int do_sign(int argc, char *argv[]) break; case 'f': - option.flags_specified = 1; - option.flags = strtoul(optarg, &e, 0); + sign_option.flags_specified = 1; + sign_option.flags = strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { fprintf(stderr, "Invalid --flags \"%s\"\n", optarg); @@ -856,13 +838,13 @@ static int do_sign(int argc, char *argv[]) } break; case 'd': - option.loemdir = optarg; + sign_option.loemdir = optarg; break; case 'l': - option.loemid = optarg; + sign_option.loemid = optarg; break; case OPT_FV: - option.fv_specified = 1; + sign_option.fv_specified = 1; /* fallthrough */ case OPT_INFILE: inout_file_count++; @@ -870,24 +852,24 @@ static int do_sign(int argc, char *argv[]) break; case OPT_OUTFILE: inout_file_count++; - option.outfile = optarg; + sign_option.outfile = optarg; break; case OPT_BOOTLOADER: - option.bootloader_data = ReadFile( - optarg, &option.bootloader_size); - if (!option.bootloader_data) { + sign_option.bootloader_data = ReadFile( + optarg, &sign_option.bootloader_size); + if (!sign_option.bootloader_data) { fprintf(stderr, "Error reading bootloader file: %s\n", strerror(errno)); errorcnt++; } Debug("bootloader file size=0x%" PRIx64 "\n", - option.bootloader_size); + sign_option.bootloader_size); break; case OPT_CONFIG: - option.config_data = ReadConfigFile( - optarg, &option.config_size); - if (!option.config_data) { + sign_option.config_data = ReadConfigFile( + optarg, &sign_option.config_size); + if (!sign_option.config_data) { fprintf(stderr, "Error reading config file: %s\n", strerror(errno)); @@ -898,12 +880,12 @@ static int do_sign(int argc, char *argv[]) /* check the first 3 characters to also match x86_64 */ if ((!strncasecmp(optarg, "x86", 3)) || (!strcasecmp(optarg, "amd64"))) - option.arch = ARCH_X86; + sign_option.arch = ARCH_X86; else if ((!strcasecmp(optarg, "arm")) || (!strcasecmp(optarg, "aarch64"))) - option.arch = ARCH_ARM; + sign_option.arch = ARCH_ARM; else if (!strcasecmp(optarg, "mips")) - option.arch = ARCH_MIPS; + sign_option.arch = ARCH_MIPS; else { fprintf(stderr, "Unknown architecture: \"%s\"\n", @@ -912,7 +894,7 @@ static int do_sign(int argc, char *argv[]) } break; case OPT_KLOADADDR: - option.kloadaddr = strtoul(optarg, &e, 0); + sign_option.kloadaddr = strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { fprintf(stderr, "Invalid --kloadaddr \"%s\"\n", optarg); @@ -920,7 +902,7 @@ static int do_sign(int argc, char *argv[]) } break; case OPT_PADDING: - option.padding = strtoul(optarg, &e, 0); + sign_option.padding = strtoul(optarg, &e, 0); if (!*optarg || (e && *e)) { fprintf(stderr, "Invalid --padding \"%s\"\n", optarg); @@ -928,23 +910,24 @@ static int do_sign(int argc, char *argv[]) } break; case OPT_PEM_SIGNPRIV: - option.pem_signpriv = optarg; + sign_option.pem_signpriv = optarg; break; case OPT_PEM_ALGO: - option.pem_algo_specified = 1; - option.pem_algo = strtoul(optarg, &e, 0); + sign_option.pem_algo_specified = 1; + sign_option.pem_algo = strtoul(optarg, &e, 0); if (!*optarg || (e && *e) || - (option.pem_algo >= kNumAlgorithms)) { + (sign_option.pem_algo >= kNumAlgorithms)) { fprintf(stderr, "Invalid --pem_algo \"%s\"\n", optarg); errorcnt++; } break; case OPT_PEM_EXTERNAL: - option.pem_external = optarg; + sign_option.pem_external = optarg; break; case OPT_TYPE: - if (!futil_str_to_file_type(optarg, &option.type)) { + if (!futil_str_to_file_type(optarg, + &sign_option.type)) { if (!strcasecmp("help", optarg)) print_file_types_and_exit(errorcnt); fprintf(stderr, @@ -1000,46 +983,48 @@ static int do_sign(int argc, char *argv[]) } /* Look for an output file if we don't have one, just in case. */ - if (!option.outfile && argc - optind > 0) { + if (!sign_option.outfile && argc - optind > 0) { inout_file_count++; - option.outfile = argv[optind++]; + sign_option.outfile = argv[optind++]; } /* What are we looking at? */ - if (option.type == FILE_TYPE_UNKNOWN && - futil_file_type(infile, &option.type)) { + if (sign_option.type == FILE_TYPE_UNKNOWN && + futil_file_type(infile, &sign_option.type)) { errorcnt++; goto done; } /* We may be able to infer the type based on the other args */ - if (option.type == FILE_TYPE_UNKNOWN) { - if (option.bootloader_data || option.config_data - || option.arch != ARCH_UNSPECIFIED) - option.type = FILE_TYPE_RAW_KERNEL; - else if (option.kernel_subkey || option.fv_specified) - option.type = FILE_TYPE_RAW_FIRMWARE; + if (sign_option.type == FILE_TYPE_UNKNOWN) { + if (sign_option.bootloader_data || sign_option.config_data + || sign_option.arch != ARCH_UNSPECIFIED) + sign_option.type = FILE_TYPE_RAW_KERNEL; + else if (sign_option.kernel_subkey || sign_option.fv_specified) + sign_option.type = FILE_TYPE_RAW_FIRMWARE; } - Debug("type=%s\n", futil_file_type_name(option.type)); + Debug("type=%s\n", futil_file_type_name(sign_option.type)); /* Check the arguments for the type of thing we want to sign */ - switch (option.type) { + switch (sign_option.type) { case FILE_TYPE_PUBKEY: - option.create_new_outfile = 1; - if (option.signprivate && option.pem_signpriv) { + sign_option.create_new_outfile = 1; + if (sign_option.signprivate && sign_option.pem_signpriv) { fprintf(stderr, "Only one of --signprivate and --pem_signpriv" " can be specified\n"); errorcnt++; } - if ((option.signprivate && option.pem_algo_specified) || - (option.pem_signpriv && !option.pem_algo_specified)) { + if ((sign_option.signprivate && + sign_option.pem_algo_specified) || + (sign_option.pem_signpriv && + !sign_option.pem_algo_specified)) { fprintf(stderr, "--pem_algo must be used with" " --pem_signpriv\n"); errorcnt++; } - if (option.pem_external && !option.pem_signpriv) { + if (sign_option.pem_external && !sign_option.pem_signpriv) { fprintf(stderr, "--pem_external must be used with" " --pem_signpriv\n"); errorcnt++; @@ -1049,53 +1034,58 @@ static int do_sign(int argc, char *argv[]) break; case FILE_TYPE_BIOS_IMAGE: case FILE_TYPE_OLD_BIOS_IMAGE: - errorcnt += no_opt_if(!option.signprivate, "signprivate"); - errorcnt += no_opt_if(!option.keyblock, "keyblock"); - errorcnt += no_opt_if(!option.kernel_subkey, "kernelkey"); + errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); + errorcnt += no_opt_if(!sign_option.keyblock, "keyblock"); + errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey"); break; case FILE_TYPE_KERN_PREAMBLE: - errorcnt += no_opt_if(!option.signprivate, "signprivate"); - if (option.vblockonly || inout_file_count > 1) - option.create_new_outfile = 1; + errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); + if (sign_option.vblockonly || inout_file_count > 1) + sign_option.create_new_outfile = 1; break; case FILE_TYPE_RAW_FIRMWARE: - option.create_new_outfile = 1; - errorcnt += no_opt_if(!option.signprivate, "signprivate"); - errorcnt += no_opt_if(!option.keyblock, "keyblock"); - errorcnt += no_opt_if(!option.kernel_subkey, "kernelkey"); - errorcnt += no_opt_if(!option.version_specified, "version"); + sign_option.create_new_outfile = 1; + errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); + errorcnt += no_opt_if(!sign_option.keyblock, "keyblock"); + errorcnt += no_opt_if(!sign_option.kernel_subkey, "kernelkey"); + errorcnt += no_opt_if(!sign_option.version_specified, + "version"); break; case FILE_TYPE_RAW_KERNEL: - option.create_new_outfile = 1; - errorcnt += no_opt_if(!option.signprivate, "signprivate"); - errorcnt += no_opt_if(!option.keyblock, "keyblock"); - errorcnt += no_opt_if(!option.version_specified, "version"); - errorcnt += no_opt_if(!option.bootloader_data, "bootloader"); - errorcnt += no_opt_if(!option.config_data, "config"); - errorcnt += no_opt_if(option.arch == ARCH_UNSPECIFIED, "arch"); + sign_option.create_new_outfile = 1; + errorcnt += no_opt_if(!sign_option.signprivate, "signprivate"); + errorcnt += no_opt_if(!sign_option.keyblock, "keyblock"); + errorcnt += no_opt_if(!sign_option.version_specified, + "version"); + errorcnt += no_opt_if(!sign_option.bootloader_data, + "bootloader"); + errorcnt += no_opt_if(!sign_option.config_data, "config"); + errorcnt += no_opt_if(sign_option.arch == ARCH_UNSPECIFIED, + "arch"); break; default: fprintf(stderr, "Unable to sign type %s\n", - futil_file_type_name(option.type)); + futil_file_type_name(sign_option.type)); errorcnt++; } Debug("infile=%s\n", infile); Debug("inout_file_count=%d\n", inout_file_count); - Debug("option.create_new_outfile=%d\n", option.create_new_outfile); + Debug("sign_option.create_new_outfile=%d\n", + sign_option.create_new_outfile); /* Make sure we have an output file if one is needed */ - if (!option.outfile) { - if (option.create_new_outfile) { + if (!sign_option.outfile) { + if (sign_option.create_new_outfile) { errorcnt++; fprintf(stderr, "Missing output filename\n"); goto done; } else { - option.outfile = infile; + sign_option.outfile = infile; } } - Debug("option.outfile=%s\n", option.outfile); + Debug("sign_option.outfile=%s\n", sign_option.outfile); if (argc - optind > 0) { errorcnt++; @@ -1105,7 +1095,7 @@ static int do_sign(int argc, char *argv[]) if (errorcnt) goto done; - if (option.create_new_outfile) { + if (sign_option.create_new_outfile) { /* The input is read-only, the output is write-only. */ mapping = MAP_RO; Debug("open RO %s\n", infile); @@ -1120,14 +1110,14 @@ static int do_sign(int argc, char *argv[]) /* We'll read-modify-write the output file */ mapping = MAP_RW; if (inout_file_count > 1) - futil_copy_file_or_die(infile, option.outfile); - Debug("open RW %s\n", option.outfile); - infile = option.outfile; - ifd = open(option.outfile, O_RDWR); + futil_copy_file_or_die(infile, sign_option.outfile); + Debug("open RW %s\n", sign_option.outfile); + infile = sign_option.outfile; + ifd = open(sign_option.outfile, O_RDWR); if (ifd < 0) { errorcnt++; fprintf(stderr, "Can't open %s for writing: %s\n", - option.outfile, strerror(errno)); + sign_option.outfile, strerror(errno)); goto done; } } @@ -1137,7 +1127,8 @@ static int do_sign(int argc, char *argv[]) goto done; } - errorcnt += futil_file_type_sign(option.type, infile, buf, buf_len); + errorcnt += futil_file_type_sign(sign_option.type, infile, + buf, buf_len); errorcnt += futil_unmap_file(ifd, MAP_RW, buf, buf_len); @@ -1148,12 +1139,12 @@ done: strerror(errno)); } - if (option.signprivate) - free(option.signprivate); - if (option.keyblock) - free(option.keyblock); - if (option.kernel_subkey) - free(option.kernel_subkey); + if (sign_option.signprivate) + free(sign_option.signprivate); + if (sign_option.keyblock) + free(sign_option.keyblock); + if (sign_option.kernel_subkey) + free(sign_option.kernel_subkey); if (errorcnt) fprintf(stderr, "Use --help for usage instructions\n"); diff --git a/futility/futility_options.h b/futility/futility_options.h new file mode 100644 index 00000000..3d416d5b --- /dev/null +++ b/futility/futility_options.h @@ -0,0 +1,59 @@ +/* + * Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * We centralize option parsing but may split operations into multiple files, + * so let's declare the option structures in a single place (here). + */ + +#ifndef VBOOT_REFERENCE_FUTILITY_OPTIONS_H_ +#define VBOOT_REFERENCE_FUTILITY_OPTIONS_H_ +#include <stdint.h> +#include "vboot_common.h" + +struct show_option_s { + VbPublicKey *k; + uint8_t *fv; + uint64_t fv_size; + uint32_t padding; + int strict; + int t_flag; + enum futil_file_type type; +}; +extern struct show_option_s show_option; + +struct sign_option_s { + VbPrivateKey *signprivate; + VbKeyBlockHeader *keyblock; + VbPublicKey *kernel_subkey; + VbPrivateKey *devsignprivate; + VbKeyBlockHeader *devkeyblock; + uint32_t version; + int version_specified; + uint32_t flags; + int flags_specified; + char *loemdir; + char *loemid; + uint8_t *bootloader_data; + uint64_t bootloader_size; + uint8_t *config_data; + uint64_t config_size; + enum arch_t arch; + int fv_specified; + uint32_t kloadaddr; + uint32_t padding; + int vblockonly; + char *outfile; + int create_new_outfile; + char *pem_signpriv; + int pem_algo_specified; + uint32_t pem_algo; + char *pem_external; + enum futil_file_type type; +}; +extern struct sign_option_s sign_option; + +#endif /* VBOOT_REFERENCE_FUTILITY_OPTIONS_H_ */ |