summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2014-08-24 22:07:17 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-08-25 20:52:39 +0000
commit31d95c2386df8d3d5ec619a077960645d052fa38 (patch)
tree9fdcb739d3f8de0c0d7479bf20401886864c3ff6
parent8f15d74fd64e4a4d98471221948cc8f1fde127e2 (diff)
downloadvboot-31d95c2386df8d3d5ec619a077960645d052fa38.tar.gz
futility: Reformat to use kernel coding style
This just reformats the futility sources to conform to the Linux kernel coding style. No functional changes. BUG=chromium:224734 BRANCH=ToT TEST=make runtests Change-Id: I82df07dd3f8be2ad2f3df24cebe00a9a378b13f4 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/213915 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--futility/cmd_dev_sign_file.c633
-rw-r--r--futility/cmd_dump_fmap.c775
-rw-r--r--futility/cmd_dump_kernel_config.c129
-rw-r--r--futility/cmd_gbb_utility.c1122
-rw-r--r--futility/cmd_vbutil_firmware.c686
-rw-r--r--futility/cmd_vbutil_kernel.c1675
-rw-r--r--futility/cmd_vbutil_key.c407
-rw-r--r--futility/cmd_vbutil_keyblock.c592
-rw-r--r--futility/dump_kernel_config_lib.c195
-rw-r--r--futility/futility.c336
-rw-r--r--futility/futility.h8
-rw-r--r--futility/kernel_blob.h85
12 files changed, 3372 insertions, 3271 deletions
diff --git a/futility/cmd_dev_sign_file.c b/futility/cmd_dev_sign_file.c
index f377ff47..134339eb 100644
--- a/futility/cmd_dev_sign_file.c
+++ b/futility/cmd_dev_sign_file.c
@@ -7,7 +7,7 @@
#include <errno.h>
#include <getopt.h>
-#include <inttypes.h> /* For PRIu64 */
+#include <inttypes.h> /* For PRIu64 */
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
@@ -23,336 +23,351 @@
#include "kernel_blob.h"
#include "vboot_common.h"
-
/* Global opt */
static int opt_debug = 0;
/* Command line options */
enum {
- OPT_MODE_SIGN = 1000,
- OPT_MODE_VERIFY,
- OPT_KEYBLOCK,
- OPT_SIGNPRIVATE,
- OPT_VBLOCK,
+ OPT_MODE_SIGN = 1000,
+ OPT_MODE_VERIFY,
+ OPT_KEYBLOCK,
+ OPT_SIGNPRIVATE,
+ OPT_VBLOCK,
};
static const struct option long_opts[] = {
- {"sign", 1, 0, OPT_MODE_SIGN },
- {"verify", 1, 0, OPT_MODE_VERIFY },
- {"keyblock", 1, 0, OPT_KEYBLOCK },
- {"signprivate", 1, 0, OPT_SIGNPRIVATE },
- {"vblock", 1, 0, OPT_VBLOCK },
- {"debug", 0, &opt_debug, 1 },
- {NULL, 0, 0, 0}
+ {"sign", 1, 0, OPT_MODE_SIGN},
+ {"verify", 1, 0, OPT_MODE_VERIFY},
+ {"keyblock", 1, 0, OPT_KEYBLOCK},
+ {"signprivate", 1, 0, OPT_SIGNPRIVATE},
+ {"vblock", 1, 0, OPT_VBLOCK},
+ {"debug", 0, &opt_debug, 1},
+ {NULL, 0, 0, 0}
};
-
/* Print help and return error */
-static int PrintHelp(const char *progname) {
- fprintf(stderr,
- "This program is used to sign and verify developer-mode files\n");
- fprintf(stderr,
- "\n"
- "Usage: %s --sign <file> [PARAMETERS]\n"
- "\n"
- " Required parameters:\n"
- " --keyblock <file> Key block in .keyblock format\n"
- " --signprivate <file>"
- " Private key to sign file data, in .vbprivk format\n"
- " --vblock <file> Output signature in .vblock format\n"
- "\n",
- progname);
- fprintf(stderr,
- "OR\n\n"
- "Usage: %s --verify <file> [PARAMETERS]\n"
- "\n"
- " Required parameters:\n"
- " --vblock <file> Signature file in .vblock format\n"
- "\n"
- " Optional parameters:\n"
- " --keyblock <file>"
- " Extract .keyblock to file if verification succeeds\n"
- "\n",
- progname);
- return 1;
+static int PrintHelp(const char *progname)
+{
+ fprintf(stderr,
+ "This is used to sign and verify developer-mode files\n");
+ fprintf(stderr,
+ "\n"
+ "Usage: %s --sign <file> [PARAMETERS]\n"
+ "\n"
+ " Required parameters:\n"
+ " --keyblock <file> Key block in .keyblock format\n"
+ " --signprivate <file>"
+ " Private key to sign file data, in .vbprivk format\n"
+ " --vblock <file>"
+ " Output signature in .vblock format\n"
+ "\n", progname);
+ fprintf(stderr,
+ "OR\n\n"
+ "Usage: %s --verify <file> [PARAMETERS]\n"
+ "\n"
+ " Required parameters:\n"
+ " --vblock <file>"
+ " Signature file in .vblock format\n"
+ "\n"
+ " Optional parameters:\n"
+ " --keyblock <file>"
+ " Extract .keyblock to file if verification succeeds\n"
+ "\n", progname);
+ return 1;
}
-static void Debug(const char *format, ...) {
- if (!opt_debug)
- return;
+static void Debug(const char *format, ...)
+{
+ if (!opt_debug)
+ return;
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "DEBUG: ");
- vfprintf(stderr, format, ap);
- va_end(ap);
+ va_list ap;
+ va_start(ap, format);
+ fprintf(stderr, "DEBUG: ");
+ vfprintf(stderr, format, ap);
+ va_end(ap);
}
-
/* Sign a file. We'll reuse the same structs used to sign kernels, to avoid
having to declare yet another one for just this purpose. */
-static int Sign(const char* filename, const char* keyblock_file,
- const char* signprivate_file, const char* outfile) {
- uint8_t* file_data;
- uint64_t file_size;
- VbKeyBlockHeader* key_block;
- uint64_t key_block_size;
- VbPrivateKey* signing_key;
- VbSignature* body_sig;
- VbKernelPreambleHeader* preamble;
- FILE* output_fp;
-
- /* Read the file that we're going to sign. */
- file_data = ReadFile(filename, &file_size);
- if (!file_data) {
- VbExError("Error reading file to sign.\n");
- return 1;
- }
-
- /* Get the key block and read the private key corresponding to it. */
- key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size);
- if (!key_block) {
- VbExError("Error reading key block.\n");
- return 1;
- }
- signing_key = PrivateKeyRead(signprivate_file);
- if (!signing_key) {
- VbExError("Error reading signing key.\n");
- return 1;
- }
-
- /* Sign the file data */
- body_sig = CalculateSignature(file_data, file_size, signing_key);
- if (!body_sig) {
- VbExError("Error calculating body signature\n");
- return 1;
- }
-
- /* Create preamble */
- preamble = CreateKernelPreamble((uint64_t)0,
- (uint64_t)0,
- (uint64_t)0,
- (uint64_t)0,
- body_sig,
- (uint64_t)0,
- signing_key);
- if (!preamble) {
- VbExError("Error creating preamble.\n");
- return 1;
- }
-
- /* Write the output file */
- Debug("writing %s...\n", outfile);
- output_fp = fopen(outfile, "wb");
- if (!output_fp) {
- VbExError("Can't open output file %s\n", outfile);
- return 1;
- }
- Debug("0x%" PRIx64 " bytes of key_block\n", key_block_size);
- Debug("0x%" PRIx64 " bytes of preamble\n", preamble->preamble_size);
- if ((1 != fwrite(key_block, key_block_size, 1, output_fp)) ||
- (1 != fwrite(preamble, preamble->preamble_size, 1, output_fp))) {
- VbExError("Can't write output file %s\n", outfile);
- fclose(output_fp);
- unlink(outfile);
- return 1;
- }
- fclose(output_fp);
-
- /* Done */
- free(preamble);
- free(body_sig);
- free(signing_key);
- free(key_block);
- free(file_data);
-
- /* Success */
- return 0;
+static int Sign(const char *filename, const char *keyblock_file,
+ const char *signprivate_file, const char *outfile)
+{
+ uint8_t *file_data;
+ uint64_t file_size;
+ VbKeyBlockHeader *key_block;
+ uint64_t key_block_size;
+ VbPrivateKey *signing_key;
+ VbSignature *body_sig;
+ VbKernelPreambleHeader *preamble;
+ FILE *output_fp;
+
+ /* Read the file that we're going to sign. */
+ file_data = ReadFile(filename, &file_size);
+ if (!file_data) {
+ VbExError("Error reading file to sign.\n");
+ return 1;
+ }
+
+ /* Get the key block and read the private key corresponding to it. */
+ key_block =
+ (VbKeyBlockHeader *) ReadFile(keyblock_file, &key_block_size);
+ if (!key_block) {
+ VbExError("Error reading key block.\n");
+ return 1;
+ }
+ signing_key = PrivateKeyRead(signprivate_file);
+ if (!signing_key) {
+ VbExError("Error reading signing key.\n");
+ return 1;
+ }
+
+ /* Sign the file data */
+ body_sig = CalculateSignature(file_data, file_size, signing_key);
+ if (!body_sig) {
+ VbExError("Error calculating body signature\n");
+ return 1;
+ }
+
+ /* Create preamble */
+ preamble = CreateKernelPreamble((uint64_t) 0,
+ (uint64_t) 0,
+ (uint64_t) 0,
+ (uint64_t) 0,
+ body_sig, (uint64_t) 0, signing_key);
+ if (!preamble) {
+ VbExError("Error creating preamble.\n");
+ return 1;
+ }
+
+ /* Write the output file */
+ Debug("writing %s...\n", outfile);
+ output_fp = fopen(outfile, "wb");
+ if (!output_fp) {
+ VbExError("Can't open output file %s\n", outfile);
+ return 1;
+ }
+ Debug("0x%" PRIx64 " bytes of key_block\n", key_block_size);
+ Debug("0x%" PRIx64 " bytes of preamble\n", preamble->preamble_size);
+ if ((1 != fwrite(key_block, key_block_size, 1, output_fp)) ||
+ (1 != fwrite(preamble, preamble->preamble_size, 1, output_fp))) {
+ VbExError("Can't write output file %s\n", outfile);
+ fclose(output_fp);
+ unlink(outfile);
+ return 1;
+ }
+ fclose(output_fp);
+
+ /* Done */
+ free(preamble);
+ free(body_sig);
+ free(signing_key);
+ free(key_block);
+ free(file_data);
+
+ /* Success */
+ return 0;
}
-static int Verify(const char* filename, const char* vblock_file,
- const char* keyblock_file) {
- uint8_t* file_data;
- uint64_t file_size;
- uint8_t* buf;
- uint64_t buf_size;
- VbKeyBlockHeader* key_block;
- VbKernelPreambleHeader* preamble;
- VbPublicKey* data_key;
- RSAPublicKey* rsa;
- uint64_t current_buf_offset = 0;
-
- /* Read the file that we're going to verify. */
- file_data = ReadFile(filename, &file_size);
- if (!file_data) {
- VbExError("Error reading file to sign.\n");
- return 1;
- }
-
- /* Read the vblock that we're going to use on it */
- buf = ReadFile(vblock_file, &buf_size);
- if (!buf) {
- VbExError("Error reading vblock_file.\n");
- return 1;
- }
-
- /* Find the key block */
- key_block = (VbKeyBlockHeader*)buf;
- Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
- current_buf_offset += key_block->key_block_size;
- if (current_buf_offset > buf_size) {
- VbExError("key_block_size advances past the end of the buffer\n");
- return 1;
- }
-
- /* Find the preamble */
- preamble = (VbKernelPreambleHeader*)(buf + current_buf_offset);
- Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
- current_buf_offset += preamble->preamble_size;
- if (current_buf_offset > buf_size ) {
- VbExError("preamble_size advances past the end of the buffer\n");
- return 1;
- }
-
- Debug("Current buf offset is at 0x%" PRIx64 " bytes\n", current_buf_offset);
-
- /* Check the key block (hash only) */
- if (0 != KeyBlockVerify(key_block, key_block->key_block_size, NULL, 1)) {
- VbExError("Error verifying key block.\n");
- return 1;
- }
-
- printf("Key block:\n");
- data_key = &key_block->data_key;
- printf(" Size: 0x%" PRIx64 "\n", key_block->key_block_size);
- printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
- (data_key->algorithm < kNumAlgorithms ?
- algo_strings[data_key->algorithm] : "(invalid)"));
- printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
- printf(" Flags: %" PRIu64 "\n", key_block->key_block_flags);
-
-
- /* Verify preamble */
- rsa = PublicKeyToRSA(&key_block->data_key);
- if (!rsa) {
- VbExError("Error parsing data key.\n");
- return 1;
- }
- if (0 != VerifyKernelPreamble(preamble, preamble->preamble_size, rsa)) {
- VbExError("Error verifying preamble.\n");
- return 1;
- }
-
- printf("Preamble:\n");
- printf(" Size: 0x%" PRIx64 "\n", preamble->preamble_size);
- printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
- preamble->header_version_major, preamble->header_version_minor);
- printf(" Kernel version: %" PRIu64 "\n", preamble->kernel_version);
- printf(" Body load address: 0x%" PRIx64 "\n", preamble->body_load_address);
- printf(" Body size: 0x%" PRIx64 "\n",
- preamble->body_signature.data_size);
- printf(" Bootloader address: 0x%" PRIx64 "\n",
- preamble->bootloader_address);
- printf(" Bootloader size: 0x%" PRIx64 "\n", preamble->bootloader_size);
-
- /* Verify body */
- if (0 != VerifyData(file_data, file_size, &preamble->body_signature, rsa)) {
- VbExError("Error verifying kernel body.\n");
- return 1;
- }
- printf("Body verification succeeded.\n");
-
- if (keyblock_file) {
- if (0 != WriteFile(keyblock_file, key_block, key_block->key_block_size)) {
- VbExError("Unable to export keyblock file\n");
- return 1;
- }
- printf("Key block exported to %s\n", keyblock_file);
- }
-
- return 0;
+static int Verify(const char *filename, const char *vblock_file,
+ const char *keyblock_file)
+{
+ uint8_t *file_data;
+ uint64_t file_size;
+ uint8_t *buf;
+ uint64_t buf_size;
+ VbKeyBlockHeader *key_block;
+ VbKernelPreambleHeader *preamble;
+ VbPublicKey *data_key;
+ RSAPublicKey *rsa;
+ uint64_t current_buf_offset = 0;
+
+ /* Read the file that we're going to verify. */
+ file_data = ReadFile(filename, &file_size);
+ if (!file_data) {
+ VbExError("Error reading file to sign.\n");
+ return 1;
+ }
+
+ /* Read the vblock that we're going to use on it */
+ buf = ReadFile(vblock_file, &buf_size);
+ if (!buf) {
+ VbExError("Error reading vblock_file.\n");
+ return 1;
+ }
+
+ /* Find the key block */
+ key_block = (VbKeyBlockHeader *) buf;
+ Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
+ current_buf_offset += key_block->key_block_size;
+ if (current_buf_offset > buf_size) {
+ VbExError
+ ("key_block_size advances past the end of the buffer\n");
+ return 1;
+ }
+
+ /* Find the preamble */
+ preamble = (VbKernelPreambleHeader *) (buf + current_buf_offset);
+ Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
+ current_buf_offset += preamble->preamble_size;
+ if (current_buf_offset > buf_size) {
+ VbExError
+ ("preamble_size advances past the end of the buffer\n");
+ return 1;
+ }
+
+ Debug("Current buf offset is at 0x%" PRIx64 " bytes\n",
+ current_buf_offset);
+
+ /* Check the key block (hash only) */
+ if (0 != KeyBlockVerify(key_block, key_block->key_block_size,
+ NULL, 1)) {
+ VbExError("Error verifying key block.\n");
+ return 1;
+ }
+
+ printf("Key block:\n");
+ data_key = &key_block->data_key;
+ printf(" Size: 0x%" PRIx64 "\n",
+ key_block->key_block_size);
+ printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
+ (data_key->algorithm <
+ kNumAlgorithms ? algo_strings[data_key->
+ algorithm] : "(invalid)"));
+ printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
+ printf(" Flags: %" PRIu64 "\n",
+ key_block->key_block_flags);
+
+ /* Verify preamble */
+ rsa = PublicKeyToRSA(&key_block->data_key);
+ if (!rsa) {
+ VbExError("Error parsing data key.\n");
+ return 1;
+ }
+ if (0 != VerifyKernelPreamble(preamble, preamble->preamble_size, rsa)) {
+ VbExError("Error verifying preamble.\n");
+ return 1;
+ }
+
+ printf("Preamble:\n");
+ printf(" Size: 0x%" PRIx64 "\n",
+ preamble->preamble_size);
+ printf(" Header version: %" PRIu32 ".%" PRIu32 "\n",
+ preamble->header_version_major, preamble->header_version_minor);
+ printf(" Kernel version: %" PRIu64 "\n",
+ preamble->kernel_version);
+ printf(" Body load address: 0x%" PRIx64 "\n",
+ preamble->body_load_address);
+ printf(" Body size: 0x%" PRIx64 "\n",
+ preamble->body_signature.data_size);
+ printf(" Bootloader address: 0x%" PRIx64 "\n",
+ preamble->bootloader_address);
+ printf(" Bootloader size: 0x%" PRIx64 "\n",
+ preamble->bootloader_size);
+
+ /* Verify body */
+ if (0 !=
+ VerifyData(file_data, file_size, &preamble->body_signature, rsa)) {
+ VbExError("Error verifying kernel body.\n");
+ return 1;
+ }
+ printf("Body verification succeeded.\n");
+
+ if (keyblock_file) {
+ if (0 !=
+ WriteFile(keyblock_file, key_block,
+ key_block->key_block_size)) {
+ VbExError("Unable to export keyblock file\n");
+ return 1;
+ }
+ printf("Key block exported to %s\n", keyblock_file);
+ }
+
+ return 0;
}
-
-static int do_dev_sign_file(int argc, char* argv[]) {
- char* filename = NULL;
- char* keyblock_file = NULL;
- char* signprivate_file = NULL;
- char* vblock_file = NULL;
- int mode = 0;
- int parse_error = 0;
- int option_index;
-
- char *progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- while ((option_index = getopt_long(argc, argv, ":", long_opts, NULL)) != -1 &&
- !parse_error) {
- switch (option_index) {
- default:
- case '?':
- /* Unhandled option */
- parse_error = 1;
- break;
-
- case 0:
- /* silently handled option */
- break;
-
- case OPT_MODE_SIGN:
- case OPT_MODE_VERIFY:
- if (mode && (mode != option_index)) {
- fprintf(stderr, "Only a single mode can be specified\n");
- parse_error = 1;
- break;
- }
- mode = option_index;
- filename = optarg;
- break;
-
- case OPT_KEYBLOCK:
- keyblock_file = optarg;
- break;
-
- case OPT_SIGNPRIVATE:
- signprivate_file = optarg;
- break;
-
- case OPT_VBLOCK:
- vblock_file = optarg;
- break;
- }
- }
-
- if (parse_error)
- return PrintHelp(progname);
-
- switch(mode) {
- case OPT_MODE_SIGN:
- if (!keyblock_file || !signprivate_file || !vblock_file) {
- fprintf(stderr, "Some required options are missing\n");
- return PrintHelp(progname);
- }
- return Sign(filename, keyblock_file, signprivate_file, vblock_file);
-
- case OPT_MODE_VERIFY:
- if (!vblock_file) {
- fprintf(stderr, "Some required options are missing\n");
- return PrintHelp(progname);
- }
- return Verify(filename, vblock_file, keyblock_file);
-
- default:
- fprintf(stderr,
- "You must specify either --sign or --verify\n");
- return PrintHelp(progname);
- }
-
- /* NOTREACHED */
- return 1;
+static int do_dev_sign_file(int argc, char *argv[])
+{
+ char *filename = NULL;
+ char *keyblock_file = NULL;
+ char *signprivate_file = NULL;
+ char *vblock_file = NULL;
+ int mode = 0;
+ int parse_error = 0;
+ int option_index;
+
+ char *progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ while ((option_index =
+ getopt_long(argc, argv, ":", long_opts, NULL)) != -1
+ && !parse_error) {
+ switch (option_index) {
+ default:
+ case '?':
+ /* Unhandled option */
+ parse_error = 1;
+ break;
+
+ case 0:
+ /* silently handled option */
+ break;
+
+ case OPT_MODE_SIGN:
+ case OPT_MODE_VERIFY:
+ if (mode && (mode != option_index)) {
+ fprintf(stderr,
+ "Only one mode can be specified\n");
+ parse_error = 1;
+ break;
+ }
+ mode = option_index;
+ filename = optarg;
+ break;
+
+ case OPT_KEYBLOCK:
+ keyblock_file = optarg;
+ break;
+
+ case OPT_SIGNPRIVATE:
+ signprivate_file = optarg;
+ break;
+
+ case OPT_VBLOCK:
+ vblock_file = optarg;
+ break;
+ }
+ }
+
+ if (parse_error)
+ return PrintHelp(progname);
+
+ switch (mode) {
+ case OPT_MODE_SIGN:
+ if (!keyblock_file || !signprivate_file || !vblock_file) {
+ fprintf(stderr, "Some required options are missing\n");
+ return PrintHelp(progname);
+ }
+ return Sign(filename, keyblock_file, signprivate_file,
+ vblock_file);
+
+ case OPT_MODE_VERIFY:
+ if (!vblock_file) {
+ fprintf(stderr, "Some required options are missing\n");
+ return PrintHelp(progname);
+ }
+ return Verify(filename, vblock_file, keyblock_file);
+
+ default:
+ fprintf(stderr, "You must specify either --sign or --verify\n");
+ return PrintHelp(progname);
+ }
+
+ /* NOTREACHED */
+ return 1;
}
DECLARE_FUTIL_COMMAND(dev_sign_file, do_dev_sign_file,
diff --git a/futility/cmd_dump_fmap.c b/futility/cmd_dump_fmap.c
index bf9e7afd..14bedac6 100644
--- a/futility/cmd_dump_fmap.c
+++ b/futility/cmd_dump_fmap.c
@@ -29,452 +29,459 @@ static void *base_of_rom;
static size_t size_of_rom;
static int opt_gaps = 0;
-
/* Return 0 if successful */
static int dump_fmap(const void *ptr, int argc, char *argv[])
{
- int i, retval = 0;
- char buf[80]; // DWR: magic number
- const FmapHeader *fmh = (const FmapHeader*)ptr;
- const FmapAreaHeader *ah = (const FmapAreaHeader*)(ptr + sizeof(FmapHeader));
-
- if (FMT_NORMAL == opt_format) {
- snprintf(buf, FMAP_SIGNATURE_SIZE+1, "%s", fmh->fmap_signature);
- printf("fmap_signature %s\n", buf);
- printf("fmap_version: %d.%d\n",
- fmh->fmap_ver_major, fmh->fmap_ver_minor);
- printf("fmap_base: 0x%" PRIx64 "\n", fmh->fmap_base);
- printf("fmap_size: 0x%08x (%d)\n", fmh->fmap_size, fmh->fmap_size);
- snprintf(buf, FMAP_NAMELEN+1, "%s", fmh->fmap_name);
- printf("fmap_name: %s\n", buf);
- printf("fmap_nareas: %d\n", fmh->fmap_nareas);
- }
-
- for (i = 0; i < fmh->fmap_nareas; i++, ah++) {
- snprintf(buf, FMAP_NAMELEN+1, "%s", ah->area_name);
-
- if (argc) {
- int j, found=0;
- for (j = 0; j < argc; j++)
- if (!strcmp(argv[j], buf)) {
- found = 1;
- break;
- }
- if (!found) {
- continue;
- }
- }
-
- switch (opt_format) {
- case FMT_PRETTY:
- printf("%s %d %d\n", buf, ah->area_offset, ah->area_size);
- break;
- case FMT_FLASHROM:
- if (ah->area_size)
- printf("0x%08x:0x%08x %s\n", ah->area_offset,
- ah->area_offset + ah->area_size - 1, buf);
- break;
- default:
- printf("area: %d\n", i+1);
- printf("area_offset: 0x%08x\n", ah->area_offset);
- printf("area_size: 0x%08x (%d)\n", ah->area_size, ah->area_size);
- printf("area_name: %s\n", buf);
- }
-
- if (opt_extract) {
- char *s;
- for (s = buf; *s; s++)
- if (*s == ' ')
- *s = '_';
- FILE *fp = fopen(buf,"wb");
- if (!fp) {
- fprintf(stderr, "%s: can't open %s: %s\n",
- progname, buf, strerror(errno));
- retval = 1;
- } else if (!ah->area_size) {
- fprintf(stderr, "%s: section %s has zero size\n", progname, buf);
- } else if (ah->area_offset + ah->area_size > size_of_rom) {
- fprintf(stderr, "%s: section %s is larger than the image\n",
- progname, buf);
- retval = 1;
- } else if (1 != fwrite(base_of_rom + ah->area_offset,
- ah->area_size, 1, fp)) {
- fprintf(stderr, "%s: can't write %s: %s\n",
- progname, buf, strerror(errno));
- retval = 1;
- } else {
- if (FMT_NORMAL == opt_format)
- printf("saved as \"%s\"\n", buf);
- }
- fclose(fp);
- }
- }
-
- return retval;
+ int i, retval = 0;
+ char buf[80]; /* DWR: magic number */
+ const FmapHeader *fmh = (const FmapHeader *)ptr;
+ const FmapAreaHeader *ah =
+ (const FmapAreaHeader *)(ptr + sizeof(FmapHeader));
+
+ if (FMT_NORMAL == opt_format) {
+ snprintf(buf, FMAP_SIGNATURE_SIZE + 1, "%s",
+ fmh->fmap_signature);
+ printf("fmap_signature %s\n", buf);
+ printf("fmap_version: %d.%d\n",
+ fmh->fmap_ver_major, fmh->fmap_ver_minor);
+ printf("fmap_base: 0x%" PRIx64 "\n", fmh->fmap_base);
+ printf("fmap_size: 0x%08x (%d)\n", fmh->fmap_size,
+ fmh->fmap_size);
+ snprintf(buf, FMAP_NAMELEN + 1, "%s", fmh->fmap_name);
+ printf("fmap_name: %s\n", buf);
+ printf("fmap_nareas: %d\n", fmh->fmap_nareas);
+ }
+
+ for (i = 0; i < fmh->fmap_nareas; i++, ah++) {
+ snprintf(buf, FMAP_NAMELEN + 1, "%s", ah->area_name);
+
+ if (argc) {
+ int j, found = 0;
+ for (j = 0; j < argc; j++)
+ if (!strcmp(argv[j], buf)) {
+ found = 1;
+ break;
+ }
+ if (!found) {
+ continue;
+ }
+ }
+
+ switch (opt_format) {
+ case FMT_PRETTY:
+ printf("%s %d %d\n", buf, ah->area_offset,
+ ah->area_size);
+ break;
+ case FMT_FLASHROM:
+ if (ah->area_size)
+ printf("0x%08x:0x%08x %s\n", ah->area_offset,
+ ah->area_offset + ah->area_size - 1,
+ buf);
+ break;
+ default:
+ printf("area: %d\n", i + 1);
+ printf("area_offset: 0x%08x\n", ah->area_offset);
+ printf("area_size: 0x%08x (%d)\n", ah->area_size,
+ ah->area_size);
+ printf("area_name: %s\n", buf);
+ }
+
+ if (opt_extract) {
+ char *s;
+ for (s = buf; *s; s++)
+ if (*s == ' ')
+ *s = '_';
+ FILE *fp = fopen(buf, "wb");
+ if (!fp) {
+ fprintf(stderr, "%s: can't open %s: %s\n",
+ progname, buf, strerror(errno));
+ retval = 1;
+ } else if (!ah->area_size) {
+ fprintf(stderr,
+ "%s: section %s has zero size\n",
+ progname, buf);
+ } else if (ah->area_offset + ah->area_size >
+ size_of_rom) {
+ fprintf(stderr, "%s: section %s is larger"
+ " than the image\n", progname, buf);
+ retval = 1;
+ } else if (1 != fwrite(base_of_rom + ah->area_offset,
+ ah->area_size, 1, fp)) {
+ fprintf(stderr, "%s: can't write %s: %s\n",
+ progname, buf, strerror(errno));
+ retval = 1;
+ } else {
+ if (FMT_NORMAL == opt_format)
+ printf("saved as \"%s\"\n", buf);
+ }
+ fclose(fp);
+ }
+ }
+
+ return retval;
}
-
/****************************************************************************/
/* Stuff for human-readable form */
typedef struct dup_s {
- char *name;
- struct dup_s *next;
+ char *name;
+ struct dup_s *next;
} dupe_t;
typedef struct node_s {
- char *name;
- uint32_t start;
- uint32_t size;
- uint32_t end;
- struct node_s *parent;
- int num_children;
- struct node_s **child;
- dupe_t *alias;
+ char *name;
+ uint32_t start;
+ uint32_t size;
+ uint32_t end;
+ struct node_s *parent;
+ int num_children;
+ struct node_s **child;
+ dupe_t *alias;
} node_t;
static node_t *all_nodes;
-static void sort_nodes(int num, node_t *ary[])
+static void sort_nodes(int num, node_t * ary[])
{
- int i, j;
- node_t *tmp;
-
- /* bubble-sort is quick enough with only a few entries */
- for (i = 0; i < num; i++) {
- for (j = i + 1; j < num; j++) {
- if (ary[j]->start > ary[i]->start) {
- tmp = ary[i];
- ary[i] = ary[j];
- ary[j] = tmp;
- }
- }
- }
+ int i, j;
+ node_t *tmp;
+
+ /* bubble-sort is quick enough with only a few entries */
+ for (i = 0; i < num; i++) {
+ for (j = i + 1; j < num; j++) {
+ if (ary[j]->start > ary[i]->start) {
+ tmp = ary[i];
+ ary[i] = ary[j];
+ ary[j] = tmp;
+ }
+ }
+ }
}
-
static void line(int indent, char *name,
- uint32_t start, uint32_t end, uint32_t size, char *append)
+ uint32_t start, uint32_t end, uint32_t size, char *append)
{
- int i;
- for (i = 0; i < indent; i++)
- printf(" ");
- printf("%-25s %08x %08x %08x%s\n", name, start, end, size,
- append ? append : "");
+ int i;
+ for (i = 0; i < indent; i++)
+ printf(" ");
+ printf("%-25s %08x %08x %08x%s\n", name, start, end, size,
+ append ? append : "");
}
static int gapcount;
static void empty(int indent, uint32_t start, uint32_t end, char *name)
{
- char buf[80];
- if (opt_gaps) {
- sprintf(buf, " // gap in %s", name);
- line(indent + 1, "", start, end, end - start, buf);
- }
- gapcount++;
+ char buf[80];
+ if (opt_gaps) {
+ sprintf(buf, " // gap in %s", name);
+ line(indent + 1, "", start, end, end - start, buf);
+ }
+ gapcount++;
}
-static void show(node_t *p, int indent, int show_first)
+static void show(node_t * p, int indent, int show_first)
{
- int i;
- dupe_t *alias;
- if (show_first) {
- line(indent, p->name, p->start, p->end, p->size, 0);
- for (alias = p->alias; alias; alias = alias->next)
- line(indent, alias->name, p->start, p->end, p->size, " // DUPLICATE");
- }
- sort_nodes(p->num_children, p->child);
- for (i = 0; i < p->num_children; i++) {
- if (i == 0 && p->end != p->child[i]->end)
- empty(indent, p->child[i]->end, p->end, p->name);
- show(p->child[i], indent + show_first, 1);
- if (i < p->num_children - 1 && p->child[i]->start != p->child[i+1]->end)
- empty(indent, p->child[i+1]->end, p->child[i]->start, p->name);
- if (i == p->num_children - 1 && p->child[i]->start != p->start)
- empty(indent, p->start, p->child[i]->start, p->name);
- }
+ int i;
+ dupe_t *alias;
+ if (show_first) {
+ line(indent, p->name, p->start, p->end, p->size, 0);
+ for (alias = p->alias; alias; alias = alias->next)
+ line(indent, alias->name, p->start, p->end, p->size,
+ " // DUPLICATE");
+ }
+ sort_nodes(p->num_children, p->child);
+ for (i = 0; i < p->num_children; i++) {
+ if (i == 0 && p->end != p->child[i]->end)
+ empty(indent, p->child[i]->end, p->end, p->name);
+ show(p->child[i], indent + show_first, 1);
+ if (i < p->num_children - 1
+ && p->child[i]->start != p->child[i + 1]->end)
+ empty(indent, p->child[i + 1]->end, p->child[i]->start,
+ p->name);
+ if (i == p->num_children - 1 && p->child[i]->start != p->start)
+ empty(indent, p->start, p->child[i]->start, p->name);
+ }
}
static int overlaps(int i, int j)
{
- node_t *a = all_nodes + i;
- node_t *b = all_nodes + j;
+ node_t *a = all_nodes + i;
+ node_t *b = all_nodes + j;
- return ((a->start < b->start) && (b->start < a->end) &&
- (b->start < a->end) && (a->end < b->end));
+ return ((a->start < b->start) && (b->start < a->end) &&
+ (b->start < a->end) && (a->end < b->end));
}
static int encloses(int i, int j)
{
- node_t *a = all_nodes + i;
- node_t *b = all_nodes + j;
+ node_t *a = all_nodes + i;
+ node_t *b = all_nodes + j;
- return ((a->start <= b->start) &&
- (a->end >= b->end));
+ return ((a->start <= b->start) && (a->end >= b->end));
}
static int duplicates(int i, int j)
{
- node_t *a = all_nodes + i;
- node_t *b = all_nodes + j;
+ node_t *a = all_nodes + i;
+ node_t *b = all_nodes + j;
- return ((a->start == b->start) &&
- (a->end == b->end));
+ return ((a->start == b->start) && (a->end == b->end));
}
static void add_dupe(int i, int j, int numnodes)
{
- int k;
- dupe_t *alias;
-
- alias = (dupe_t *)malloc(sizeof(dupe_t));
- alias->name = all_nodes[j].name;
- alias->next = all_nodes[i].alias;
- all_nodes[i].alias = alias;
- for (k = j; k < numnodes; k++ )
- all_nodes[k] = all_nodes[k + 1];
+ int k;
+ dupe_t *alias;
+
+ alias = (dupe_t *) malloc(sizeof(dupe_t));
+ alias->name = all_nodes[j].name;
+ alias->next = all_nodes[i].alias;
+ all_nodes[i].alias = alias;
+ for (k = j; k < numnodes; k++)
+ all_nodes[k] = all_nodes[k + 1];
}
-static void add_child(node_t *p, int n)
+static void add_child(node_t * p, int n)
{
- int i;
- if (p->num_children && !p->child) {
- p->child = (struct node_s **)calloc(p->num_children, sizeof(node_t *));
- if (!p->child) {
- perror("calloc failed");
- exit(1);
- }
- }
- for (i = 0; i < p->num_children; i++)
- if (!p->child[i]) {
- p->child[i] = all_nodes + n;
- return;
- }
+ int i;
+ if (p->num_children && !p->child) {
+ p->child =
+ (struct node_s **)calloc(p->num_children, sizeof(node_t *));
+ if (!p->child) {
+ perror("calloc failed");
+ exit(1);
+ }
+ }
+ for (i = 0; i < p->num_children; i++)
+ if (!p->child[i]) {
+ p->child[i] = all_nodes + n;
+ return;
+ }
}
static int human_fmap(void *p)
{
- FmapHeader *fmh;
- FmapAreaHeader *ah;
- int i, j, errorcnt=0;
- int numnodes;
-
- fmh = (FmapHeader *)p;
- ah = (FmapAreaHeader *)(fmh + 1);
-
- /* The challenge here is to generate a directed graph from the
- * arbitrarily-ordered FMAP entries, and then to prune it until it's as
- * simple (and deep) as possible. Overlapping regions are not allowed.
- * Duplicate regions are okay, but may require special handling. */
-
- /* Convert the FMAP info into our format. */
- numnodes = fmh->fmap_nareas;
-
- /* plus one for the all-enclosing "root" */
- all_nodes = (node_t *)calloc(numnodes+1, sizeof(node_t));
- if (!all_nodes) {
- perror("calloc failed");
- exit(1);
- }
- for (i = 0; i < numnodes; i++) {
- char buf[FMAP_NAMELEN+1];
- strncpy(buf, ah[i].area_name, FMAP_NAMELEN);
- buf[FMAP_NAMELEN] = '\0';
- if (!(all_nodes[i].name = strdup(buf))) {
- perror("strdup failed");
- exit(1);
- }
- all_nodes[i].start = ah[i].area_offset;
- all_nodes[i].size = ah[i].area_size;
- all_nodes[i].end = ah[i].area_offset + ah[i].area_size;
- }
- /* Now add the root node */
- all_nodes[numnodes].name = strdup("-entire flash-");
- all_nodes[numnodes].start = fmh->fmap_base;
- all_nodes[numnodes].size = fmh->fmap_size;
- all_nodes[numnodes].end = fmh->fmap_base + fmh->fmap_size;
-
-
- /* First, coalesce any duplicates */
- for (i = 0; i < numnodes; i++) {
- for (j = i + 1; j < numnodes; j++) {
- if (duplicates(i, j)) {
- add_dupe(i, j, numnodes);
- numnodes--;
- }
- }
- }
-
- /* Each node should have at most one parent, which is the smallest enclosing
- * node. Duplicate nodes "enclose" each other, but if there's already a
- * relationship in one direction, we won't create another. */
- for (i = 0; i < numnodes; i++) {
- /* Find the smallest parent, which might be the root node. */
- int k = numnodes;
- for (j = 0; j < numnodes; j++) { /* full O(N^2), not triangular */
- if (i == j)
- continue;
- if (overlaps(i, j)) {
- printf("ERROR: %s and %s overlap\n",
- all_nodes[i].name, all_nodes[j].name);
- printf(" %s: 0x%x - 0x%x\n", all_nodes[i].name,
- all_nodes[i].start, all_nodes[i].end);
- printf(" %s: 0x%x - 0x%x\n", all_nodes[j].name,
- all_nodes[j].start, all_nodes[j].end);
- if (opt_overlap < 2) {
- printf("Use more -h args to ignore this error\n");
- errorcnt++;
- }
- continue;
- }
- if (encloses(j, i) && all_nodes[j].size < all_nodes[k].size)
- k = j;
- }
- all_nodes[i].parent = all_nodes + k;
- }
- if (errorcnt)
- return 1;
-
- /* Force those deadbeat parents to recognize their children */
- for (i = 0; i < numnodes; i++) /* how many */
- if (all_nodes[i].parent)
- all_nodes[i].parent->num_children++;
- for (i = 0; i < numnodes; i++) /* here they are */
- if (all_nodes[i].parent)
- add_child(all_nodes[i].parent, i);
-
- /* Ready to go */
- printf("# name start end size\n");
- show(all_nodes + numnodes, 0, opt_gaps);
-
- if (gapcount && !opt_gaps)
- printf("\nWARNING: unused regions found. Use -H to see them\n");
-
- return 0;
+ FmapHeader *fmh;
+ FmapAreaHeader *ah;
+ int i, j, errorcnt = 0;
+ int numnodes;
+
+ fmh = (FmapHeader *) p;
+ ah = (FmapAreaHeader *) (fmh + 1);
+
+ /* The challenge here is to generate a directed graph from the
+ * arbitrarily-ordered FMAP entries, and then to prune it until it's as
+ * simple (and deep) as possible. Overlapping regions are not allowed.
+ * Duplicate regions are okay, but may require special handling. */
+
+ /* Convert the FMAP info into our format. */
+ numnodes = fmh->fmap_nareas;
+
+ /* plus one for the all-enclosing "root" */
+ all_nodes = (node_t *) calloc(numnodes + 1, sizeof(node_t));
+ if (!all_nodes) {
+ perror("calloc failed");
+ exit(1);
+ }
+ for (i = 0; i < numnodes; i++) {
+ char buf[FMAP_NAMELEN + 1];
+ strncpy(buf, ah[i].area_name, FMAP_NAMELEN);
+ buf[FMAP_NAMELEN] = '\0';
+ if (!(all_nodes[i].name = strdup(buf))) {
+ perror("strdup failed");
+ exit(1);
+ }
+ all_nodes[i].start = ah[i].area_offset;
+ all_nodes[i].size = ah[i].area_size;
+ all_nodes[i].end = ah[i].area_offset + ah[i].area_size;
+ }
+ /* Now add the root node */
+ all_nodes[numnodes].name = strdup("-entire flash-");
+ all_nodes[numnodes].start = fmh->fmap_base;
+ all_nodes[numnodes].size = fmh->fmap_size;
+ all_nodes[numnodes].end = fmh->fmap_base + fmh->fmap_size;
+
+ /* First, coalesce any duplicates */
+ for (i = 0; i < numnodes; i++) {
+ for (j = i + 1; j < numnodes; j++) {
+ if (duplicates(i, j)) {
+ add_dupe(i, j, numnodes);
+ numnodes--;
+ }
+ }
+ }
+
+ /* Each node should have at most one parent, which is the smallest
+ * enclosing node. Duplicate nodes "enclose" each other, but if there's
+ * already a relationship in one direction, we won't create another.
+ */
+ for (i = 0; i < numnodes; i++) {
+ /* Find the smallest parent, which might be the root node. */
+ int k = numnodes;
+ for (j = 0; j < numnodes; j++) { /* full O(N^2) comparison */
+ if (i == j)
+ continue;
+ if (overlaps(i, j)) {
+ printf("ERROR: %s and %s overlap\n",
+ all_nodes[i].name, all_nodes[j].name);
+ printf(" %s: 0x%x - 0x%x\n", all_nodes[i].name,
+ all_nodes[i].start, all_nodes[i].end);
+ printf(" %s: 0x%x - 0x%x\n", all_nodes[j].name,
+ all_nodes[j].start, all_nodes[j].end);
+ if (opt_overlap < 2) {
+ printf("Use more -h args to ignore"
+ " this error\n");
+ errorcnt++;
+ }
+ continue;
+ }
+ if (encloses(j, i)
+ && all_nodes[j].size < all_nodes[k].size)
+ k = j;
+ }
+ all_nodes[i].parent = all_nodes + k;
+ }
+ if (errorcnt)
+ return 1;
+
+ /* Force those deadbeat parents to recognize their children */
+ for (i = 0; i < numnodes; i++) /* how many */
+ if (all_nodes[i].parent)
+ all_nodes[i].parent->num_children++;
+ for (i = 0; i < numnodes; i++) /* here they are */
+ if (all_nodes[i].parent)
+ add_child(all_nodes[i].parent, i);
+
+ /* Ready to go */
+ printf("# name start end size\n");
+ show(all_nodes + numnodes, 0, opt_gaps);
+
+ if (gapcount && !opt_gaps)
+ printf("\nWARNING: unused regions found. Use -H to see them\n");
+
+ return 0;
}
/* End of human-reable stuff */
/****************************************************************************/
+static const char usage[] =
+ "\nUsage: %s [-x] [-p|-f|-h] FLASHIMAGE [NAME...]\n\n"
+ "Display (and extract with -x) the FMAP components from a BIOS image.\n"
+ "The -p option makes the output easier to parse by scripts.\n"
+ "The -f option emits the FMAP in the format used by flashrom.\n"
+ "\n"
+ "Specify one or more NAMEs to only print sections that exactly match.\n"
+ "\n"
+ "The -h option shows the whole FMAP in human-readable form.\n"
+ " Use -H to also display any gaps.\n"
+ "\n";
+
static int do_dump_fmap(int argc, char *argv[])
{
- int c;
- int errorcnt = 0;
- struct stat sb;
- int fd;
- const char *fmap;
- int retval = 1;
-
- progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- opterr = 0; /* quiet, you */
- while ((c = getopt(argc, argv, ":xpfhH")) != -1) {
- switch (c) {
- case 'x':
- opt_extract = 1;
- break;
- case 'p':
- opt_format = FMT_PRETTY;
- break;
- case 'f':
- opt_format = FMT_FLASHROM;
- break;
- case 'H':
- opt_gaps = 1;
- /* fallthrough */
- case 'h':
- opt_format = FMT_HUMAN;
- opt_overlap++;
- break;
- case '?':
- fprintf(stderr, "%s: unrecognized switch: -%c\n",
- progname, optopt);
- errorcnt++;
- break;
- case ':':
- fprintf(stderr, "%s: missing argument to -%c\n",
- progname, optopt);
- errorcnt++;
- break;
- default:
- errorcnt++;
- break;
- }
- }
-
- if (errorcnt || optind >= argc) {
- fprintf(stderr,
- "\nUsage: %s [-x] [-p|-f|-h] FLASHIMAGE [NAME...]\n\n"
- "Display (and extract with -x) the FMAP components from a BIOS image.\n"
- "The -p option makes the output easier to parse by scripts.\n"
- "The -f option emits the FMAP in the format used by flashrom.\n"
- "\n"
- "Specify one or more NAMEs to only print sections that exactly match.\n"
- "\n"
- "The -h option shows the whole FMAP in human-readable form.\n"
- " Use -H to also display any gaps.\n"
- "\n",
- progname);
- return 1;
- }
-
- if (0 != stat(argv[optind], &sb)) {
- fprintf(stderr, "%s: can't stat %s: %s\n",
- progname,
- argv[optind],
- strerror(errno));
- return 1;
- }
-
- fd = open(argv[optind], O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "%s: can't open %s: %s\n",
- progname,
- argv[optind],
- strerror(errno));
- return 1;
- }
-
- base_of_rom = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
- if (base_of_rom == (char*)-1) {
- fprintf(stderr, "%s: can't mmap %s: %s\n",
- progname,
- argv[optind],
- strerror(errno));
- close(fd);
- return 1;
- }
- close(fd); /* done with this now */
- size_of_rom = sb.st_size;
-
- fmap = FmapFind((char*) base_of_rom, size_of_rom);
- if (fmap) {
- switch (opt_format) {
- case FMT_HUMAN:
- retval = human_fmap((void *)fmap);
- break;
- case FMT_NORMAL:
- printf("hit at 0x%08x\n", (uint32_t) (fmap - (char*) base_of_rom));
- /* fallthrough */
- default:
- retval = dump_fmap(fmap, argc-optind-1, argv+optind+1);
- }
- }
-
- if (0 != munmap(base_of_rom, sb.st_size)) {
- fprintf(stderr, "%s: can't munmap %s: %s\n",
- progname,
- argv[optind],
- strerror(errno));
- return 1;
- }
-
- return retval;
+ int c;
+ int errorcnt = 0;
+ struct stat sb;
+ int fd;
+ const char *fmap;
+ int retval = 1;
+
+ progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ opterr = 0; /* quiet, you */
+ while ((c = getopt(argc, argv, ":xpfhH")) != -1) {
+ switch (c) {
+ case 'x':
+ opt_extract = 1;
+ break;
+ case 'p':
+ opt_format = FMT_PRETTY;
+ break;
+ case 'f':
+ opt_format = FMT_FLASHROM;
+ break;
+ case 'H':
+ opt_gaps = 1;
+ /* fallthrough */
+ case 'h':
+ opt_format = FMT_HUMAN;
+ opt_overlap++;
+ break;
+ case '?':
+ fprintf(stderr, "%s: unrecognized switch: -%c\n",
+ progname, optopt);
+ errorcnt++;
+ break;
+ case ':':
+ fprintf(stderr, "%s: missing argument to -%c\n",
+ progname, optopt);
+ errorcnt++;
+ break;
+ default:
+ errorcnt++;
+ break;
+ }
+ }
+
+ if (errorcnt || optind >= argc) {
+ fprintf(stderr, usage, progname);
+ return 1;
+ }
+
+ if (0 != stat(argv[optind], &sb)) {
+ fprintf(stderr, "%s: can't stat %s: %s\n",
+ progname, argv[optind], strerror(errno));
+ return 1;
+ }
+
+ fd = open(argv[optind], O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "%s: can't open %s: %s\n",
+ progname, argv[optind], strerror(errno));
+ return 1;
+ }
+
+ base_of_rom =
+ mmap(0, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+ if (base_of_rom == (char *)-1) {
+ fprintf(stderr, "%s: can't mmap %s: %s\n",
+ progname, argv[optind], strerror(errno));
+ close(fd);
+ return 1;
+ }
+ close(fd); /* done with this now */
+ size_of_rom = sb.st_size;
+
+ fmap = FmapFind((char *)base_of_rom, size_of_rom);
+ if (fmap) {
+ switch (opt_format) {
+ case FMT_HUMAN:
+ retval = human_fmap((void *)fmap);
+ break;
+ case FMT_NORMAL:
+ printf("hit at 0x%08x\n",
+ (uint32_t) (fmap - (char *)base_of_rom));
+ /* fallthrough */
+ default:
+ retval =
+ dump_fmap(fmap, argc - optind - 1,
+ argv + optind + 1);
+ }
+ }
+
+ if (0 != munmap(base_of_rom, sb.st_size)) {
+ fprintf(stderr, "%s: can't munmap %s: %s\n",
+ progname, argv[optind], strerror(errno));
+ return 1;
+ }
+
+ return retval;
}
DECLARE_FUTIL_COMMAND(dump_fmap, do_dump_fmap,
- "Display FMAP contents from a firmware image");
+ "Display FMAP contents from a firmware image");
diff --git a/futility/cmd_dump_kernel_config.c b/futility/cmd_dump_kernel_config.c
index a6e987e2..1bf411b2 100644
--- a/futility/cmd_dump_kernel_config.c
+++ b/futility/cmd_dump_kernel_config.c
@@ -5,7 +5,6 @@
* Exports the kernel commandline from a given partition/image.
*/
-
#include <getopt.h>
#include <stdio.h>
#include <sys/mman.h>
@@ -15,78 +14,78 @@
#include "vboot_host.h"
enum {
- OPT_KLOADADDR = 1000,
+ OPT_KLOADADDR = 1000,
};
static const struct option long_opts[] = {
- { "kloadaddr", 1, NULL, OPT_KLOADADDR },
- { NULL, 0, NULL, 0 }
+ {"kloadaddr", 1, NULL, OPT_KLOADADDR},
+ {NULL, 0, NULL, 0}
};
/* Print help and return error */
-static int PrintHelp(void) {
- puts("dump_kernel_config - Prints the kernel command line\n"
- "\n"
- "Usage: dump_kernel_config [--kloadaddr <ADDRESS>] "
- "<image/blockdevice>\n"
- "\n"
- "");
- return 1;
+static int PrintHelp(void)
+{
+ puts("dump_kernel_config - Prints the kernel command line\n"
+ "\n"
+ "Usage: dump_kernel_config [--kloadaddr <ADDRESS>] "
+ "<image/blockdevice>\n" "\n" "");
+ return 1;
}
-static int do_dump_kernel_config(int argc, char* argv[]) {
- char *infile = NULL;
- char *config = NULL;
- uint64_t kernel_body_load_address = USE_PREAMBLE_LOAD_ADDR;
- int parse_error = 0;
- char *e;
- int i;
-
- while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
- !parse_error) {
- switch (i) {
- default:
- case '?':
- /* Unhandled option */
- parse_error = 1;
- break;
-
- case 0:
- /* silently handled option */
- break;
-
- case OPT_KLOADADDR:
- kernel_body_load_address = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr, "Invalid --kloadaddr\n");
- parse_error = 1;
- }
- break;
- }
- }
-
- if (optind >= argc) {
- fprintf(stderr, "Expected argument after options\n");
- parse_error = 1;
- } else
- infile = argv[optind];
-
- if (parse_error)
- return PrintHelp();
-
- if (!infile || !*infile) {
- fprintf(stderr, "Must specify filename\n");
- return 1;
- }
-
- config = FindKernelConfig(infile, kernel_body_load_address);
- if (!config)
- return 1;
-
- printf("%s", config);
-
- free(config);
- return 0;
+static int do_dump_kernel_config(int argc, char *argv[])
+{
+ char *infile = NULL;
+ char *config = NULL;
+ uint64_t kernel_body_load_address = USE_PREAMBLE_LOAD_ADDR;
+ int parse_error = 0;
+ char *e;
+ int i;
+
+ while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
+ !parse_error) {
+ switch (i) {
+ default:
+ case '?':
+ /* Unhandled option */
+ parse_error = 1;
+ break;
+
+ case 0:
+ /* silently handled option */
+ break;
+
+ case OPT_KLOADADDR:
+ kernel_body_load_address = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ fprintf(stderr, "Invalid --kloadaddr\n");
+ parse_error = 1;
+ }
+ break;
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "Expected argument after options\n");
+ parse_error = 1;
+ } else
+ infile = argv[optind];
+
+ if (parse_error)
+ return PrintHelp();
+
+ if (!infile || !*infile) {
+ fprintf(stderr, "Must specify filename\n");
+ return 1;
+ }
+
+ config = FindKernelConfig(infile, kernel_body_load_address);
+ if (!config)
+ return 1;
+
+ printf("%s", config);
+
+ free(config);
+ return 0;
}
DECLARE_FUTIL_COMMAND(dump_kernel_config, do_dump_kernel_config,
diff --git a/futility/cmd_gbb_utility.c b/futility/cmd_gbb_utility.c
index 966b7445..9810058d 100644
--- a/futility/cmd_gbb_utility.c
+++ b/futility/cmd_gbb_utility.c
@@ -18,593 +18,623 @@
#include "futility.h"
#include "gbb_header.h"
-static void help_and_quit(const char *prog) {
- fprintf(stderr, "\n"
- "Usage: %s [-g|-s|-c] [OPTIONS] bios_file [output_file]\n"
- "\n"
- "GET MODE:\n"
- "-g, --get (default)\tGet (read) from bios_file, "
- "with following options:\n"
- " --hwid \tReport hardware id (default).\n"
- " --flags \tReport header flags.\n"
- " -k, --rootkey=FILE \tFile name to export Root Key.\n"
- " -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n"
- " -r --recoverykey=FILE\tFile name to export Recovery Key.\n"
- "\n"
- "SET MODE:\n"
- "-s, --set \tSet (write) to bios_file, "
- "with following options:\n"
- " -o, --output=FILE \tNew file name for ouptput.\n"
- " --hwid=HWID \tThe new hardware id to be changed.\n"
- " --flags=FLAGS \tThe new (numeric) flags value.\n"
- " -k, --rootkey=FILE \tFile name of new Root Key.\n"
- " -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n"
- " -r --recoverykey=FILE\tFile name of new Recovery Key.\n"
- "\n"
- "CREATE MODE:\n"
- "-c, --create=hwid_size,rootkey_size,bmpfv_size,recoverykey_size\n"
- " \tCreate a GBB blob by given size list.\n"
- "SAMPLE:\n"
- " %s -g bios.bin\n"
- " %s --set --hwid='New Model' -k key.bin bios.bin newbios.bin\n"
- " %s -c 0x100,0x1000,0x03DE80,0x1000 gbb.blob\n\n",
- prog, prog, prog, prog);
- exit(1);
+static void help_and_quit(const char *prog)
+{
+ fprintf(stderr, "\n"
+ "Usage: %s [-g|-s|-c] [OPTIONS] bios_file [output_file]\n"
+ "\n"
+ "GET MODE:\n"
+ "-g, --get (default)\tGet (read) from bios_file, "
+ "with following options:\n"
+ " --hwid \tReport hardware id (default).\n"
+ " --flags \tReport header flags.\n"
+ " -k, --rootkey=FILE \tFile name to export Root Key.\n"
+ " -b, --bmpfv=FILE \tFile name to export Bitmap FV.\n"
+ " -r --recoverykey=FILE\tFile name to export Recovery Key.\n"
+ "\n"
+ "SET MODE:\n"
+ "-s, --set \tSet (write) to bios_file, "
+ "with following options:\n"
+ " -o, --output=FILE \tNew file name for ouptput.\n"
+ " --hwid=HWID \tThe new hardware id to be changed.\n"
+ " --flags=FLAGS \tThe new (numeric) flags value.\n"
+ " -k, --rootkey=FILE \tFile name of new Root Key.\n"
+ " -b, --bmpfv=FILE \tFile name of new Bitmap FV.\n"
+ " -r --recoverykey=FILE\tFile name of new Recovery Key.\n"
+ "\n"
+ "CREATE MODE:\n"
+ "-c, --create=hwid_size,rootkey_size,bmpfv_size,"
+ "recoverykey_size\n"
+ " \tCreate a GBB blob by given size list.\n"
+ "SAMPLE:\n"
+ " %s -g bios.bin\n"
+ " %s --set --hwid='New Model' -k key.bin"
+ " bios.bin newbios.bin\n"
+ " %s -c 0x100,0x1000,0x03DE80,0x1000 gbb.blob\n\n",
+ prog, prog, prog, prog);
+ exit(1);
}
/* Command line options */
static const struct option long_opts[] = {
- /* name hasarg *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' },
- { NULL, 0, NULL, 0 },
+ /* name hasarg *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'},
+ {NULL, 0, NULL, 0},
};
+
static char *short_opts = ":gsc:o:k:b:R:r:h:i:L:f:";
static int errorcnt;
-static int ValidGBB(GoogleBinaryBlockHeader *gbb, size_t maxlen)
+static int ValidGBB(GoogleBinaryBlockHeader * gbb, size_t maxlen)
{
- uint32_t i;
- char *s;
-
- if (gbb->major_version != GBB_MAJOR_VER)
- goto bad;
- if (gbb->header_size != GBB_HEADER_SIZE || gbb->header_size > maxlen)
- goto bad;
- if (gbb->hwid_offset < GBB_HEADER_SIZE)
- goto bad;
- if (gbb->hwid_offset + gbb->hwid_size > maxlen)
- goto bad;
- if (gbb->hwid_size) {
- /* Make sure the HWID is null-terminated (assumes ASCII, not unicode). */
- s = (char *)((char *)gbb + gbb->hwid_offset);
- for (i = 0; i < gbb->hwid_size; i++)
- if (*s++ == '\0')
- break;
- if (i >= gbb->hwid_size)
- goto bad;
- }
- if (gbb->rootkey_offset < GBB_HEADER_SIZE)
- goto bad;
- if (gbb->rootkey_offset + gbb->rootkey_size > maxlen)
- goto bad;
- if (gbb->bmpfv_offset < GBB_HEADER_SIZE)
- goto bad;
- if (gbb->bmpfv_offset + gbb->bmpfv_size > maxlen)
- goto bad;
- if (gbb->recovery_key_offset < GBB_HEADER_SIZE)
- goto bad;
- if (gbb->recovery_key_offset + gbb->recovery_key_size > maxlen)
- goto bad;
-
- return 1;
+ uint32_t i;
+ char *s;
+
+ if (gbb->major_version != GBB_MAJOR_VER)
+ goto bad;
+ if (gbb->header_size != GBB_HEADER_SIZE || gbb->header_size > maxlen)
+ goto bad;
+ if (gbb->hwid_offset < GBB_HEADER_SIZE)
+ goto bad;
+ if (gbb->hwid_offset + gbb->hwid_size > maxlen)
+ goto bad;
+ if (gbb->hwid_size) {
+ /* Make sure the HWID is null-terminated (ASCII, not unicode) */
+ s = (char *)((char *)gbb + gbb->hwid_offset);
+ for (i = 0; i < gbb->hwid_size; i++)
+ if (*s++ == '\0')
+ break;
+ if (i >= gbb->hwid_size)
+ goto bad;
+ }
+ if (gbb->rootkey_offset < GBB_HEADER_SIZE)
+ goto bad;
+ if (gbb->rootkey_offset + gbb->rootkey_size > maxlen)
+ goto bad;
+ if (gbb->bmpfv_offset < GBB_HEADER_SIZE)
+ goto bad;
+ if (gbb->bmpfv_offset + gbb->bmpfv_size > maxlen)
+ goto bad;
+ if (gbb->recovery_key_offset < GBB_HEADER_SIZE)
+ goto bad;
+ if (gbb->recovery_key_offset + gbb->recovery_key_size > maxlen)
+ goto bad;
+
+ return 1;
bad:
- errorcnt++;
- return 0;
+ errorcnt++;
+ return 0;
}
#define GBB_SEARCH_STRIDE 4
-GoogleBinaryBlockHeader *FindGbbHeader(uint8_t *ptr, size_t size)
+GoogleBinaryBlockHeader *FindGbbHeader(uint8_t * ptr, size_t size)
{
- size_t i;
- GoogleBinaryBlockHeader *tmp, *gbb_header = NULL;
- int count = 0;
-
- for (i = 0;
- i <= size - GBB_SEARCH_STRIDE;
- i += GBB_SEARCH_STRIDE) {
- if (0 != memcmp(ptr + i, GBB_SIGNATURE, GBB_SIGNATURE_SIZE))
- continue;
-
- /* Found something. See if it's any good. */
- tmp = (GoogleBinaryBlockHeader *)(ptr + i);
- if (ValidGBB(tmp, size - i))
- if (!count++)
- gbb_header = tmp;
- }
-
- switch (count) {
- case 0:
- errorcnt++;
- return NULL;
- case 1:
- return gbb_header;
- default:
- fprintf(stderr, "ERROR: multiple GBB headers found\n");
- errorcnt++;
- return NULL;
- }
+ size_t i;
+ GoogleBinaryBlockHeader *tmp, *gbb_header = NULL;
+ int count = 0;
+
+ for (i = 0; i <= size - GBB_SEARCH_STRIDE; i += GBB_SEARCH_STRIDE) {
+ if (0 != memcmp(ptr + i, GBB_SIGNATURE, GBB_SIGNATURE_SIZE))
+ continue;
+
+ /* Found something. See if it's any good. */
+ tmp = (GoogleBinaryBlockHeader *) (ptr + i);
+ if (ValidGBB(tmp, size - i))
+ if (!count++)
+ gbb_header = tmp;
+ }
+
+ switch (count) {
+ case 0:
+ errorcnt++;
+ return NULL;
+ case 1:
+ return gbb_header;
+ default:
+ fprintf(stderr, "ERROR: multiple GBB headers found\n");
+ errorcnt++;
+ return NULL;
+ }
}
-static uint8_t *create_gbb(const char *desc, off_t *sizeptr)
+static uint8_t *create_gbb(const char *desc, off_t * sizeptr)
{
- char *str, *sizes, *param, *e = NULL;
- size_t size = GBB_HEADER_SIZE;
- int i = 0;
- /* Danger Will Robinson! four entries ==> four paramater blocks */
- uint32_t val[] = {0, 0, 0, 0};
- uint8_t *buf;
- GoogleBinaryBlockHeader *gbb;
-
- sizes = strdup(desc);
- if (!sizes) {
- errorcnt++;
- fprintf(stderr, "ERROR: strdup() failed: %s\n", strerror(errno));
- return NULL;
- }
-
- for (str = sizes; (param = strtok(str, ", ")) != NULL; str = NULL) {
- val[i] = (uint32_t)strtoul(param, &e, 0);
- if (e && *e) {
- errorcnt++;
- fprintf(stderr, "ERROR: invalid creation parameter: \"%s\"\n", param);
- free(sizes);
- return NULL;
- }
- size += val[i++];
- if (i > ARRAY_SIZE(val))
- break;
- }
-
- buf = (uint8_t *)calloc(1, size);
- if (!buf) {
- errorcnt++;
- fprintf(stderr, "ERROR: can't malloc %zu bytes: %s\n",
- size, strerror(errno));
- free(sizes);
- return NULL;
- } else if (sizeptr) {
- *sizeptr = size;
- }
-
- gbb = (GoogleBinaryBlockHeader *)buf;
- memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE);
- gbb->major_version = GBB_MAJOR_VER;
- gbb->minor_version = GBB_MINOR_VER;
- gbb->header_size = GBB_HEADER_SIZE;
- gbb->flags = 0;
-
- i = GBB_HEADER_SIZE;
- gbb->hwid_offset = i;
- gbb->hwid_size = val[0];
- i += val[0];
-
- gbb->rootkey_offset = i;
- gbb->rootkey_size = val[1];
- i += val[1];
-
- gbb->bmpfv_offset = i;
- gbb->bmpfv_size = val[2];
- i += val[2];
-
- gbb->recovery_key_offset = i;
- gbb->recovery_key_size = val[3];
- i += val[1];
-
- free(sizes);
- return buf;
+ char *str, *sizes, *param, *e = NULL;
+ size_t size = GBB_HEADER_SIZE;
+ int i = 0;
+ /* Danger Will Robinson! four entries ==> four paramater blocks */
+ uint32_t val[] = { 0, 0, 0, 0 };
+ uint8_t *buf;
+ GoogleBinaryBlockHeader *gbb;
+
+ sizes = strdup(desc);
+ if (!sizes) {
+ errorcnt++;
+ fprintf(stderr, "ERROR: strdup() failed: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ for (str = sizes; (param = strtok(str, ", ")) != NULL; str = NULL) {
+ val[i] = (uint32_t) strtoul(param, &e, 0);
+ if (e && *e) {
+ errorcnt++;
+ fprintf(stderr,
+ "ERROR: invalid creation parameter: \"%s\"\n",
+ param);
+ free(sizes);
+ return NULL;
+ }
+ size += val[i++];
+ if (i > ARRAY_SIZE(val))
+ break;
+ }
+
+ buf = (uint8_t *) calloc(1, size);
+ if (!buf) {
+ errorcnt++;
+ fprintf(stderr, "ERROR: can't malloc %zu bytes: %s\n",
+ size, strerror(errno));
+ free(sizes);
+ return NULL;
+ } else if (sizeptr) {
+ *sizeptr = size;
+ }
+
+ gbb = (GoogleBinaryBlockHeader *) buf;
+ memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE);
+ gbb->major_version = GBB_MAJOR_VER;
+ gbb->minor_version = GBB_MINOR_VER;
+ gbb->header_size = GBB_HEADER_SIZE;
+ gbb->flags = 0;
+
+ i = GBB_HEADER_SIZE;
+ gbb->hwid_offset = i;
+ gbb->hwid_size = val[0];
+ i += val[0];
+
+ gbb->rootkey_offset = i;
+ gbb->rootkey_size = val[1];
+ i += val[1];
+
+ gbb->bmpfv_offset = i;
+ gbb->bmpfv_size = val[2];
+ i += val[2];
+
+ gbb->recovery_key_offset = i;
+ gbb->recovery_key_size = val[3];
+ i += val[1];
+
+ free(sizes);
+ return buf;
}
-uint8_t *read_entire_file(const char *filename, off_t *sizeptr)
+uint8_t *read_entire_file(const char *filename, off_t * sizeptr)
{
- FILE *fp = NULL;
- uint8_t *buf = NULL;
- struct stat sb;
-
- fp = fopen(filename, "rb");
- if (!fp) {
- fprintf(stderr, "ERROR: Unable to open %s for reading: %s\n",
- filename, strerror(errno));
- goto fail;
- }
-
- if (0 != fstat(fileno(fp), &sb)) {
- fprintf(stderr, "ERROR: can't fstat %s: %s\n",
- filename, strerror(errno));
- goto fail;
- }
- if (sizeptr)
- *sizeptr = sb.st_size;
-
- buf = (uint8_t *)malloc(sb.st_size);
- if (!buf) {
- fprintf(stderr, "ERROR: can't malloc %" PRIi64 " bytes: %s\n",
- sb.st_size, strerror(errno));
- goto fail;
- }
-
- if (1 != fread(buf, sb.st_size, 1, fp)) {
- fprintf(stderr, "ERROR: Unable to read from %s: %s\n",
- filename, strerror(errno));
- goto fail;
- }
-
- if (fp && 0 != fclose(fp)) {
- fprintf(stderr, "ERROR: Unable to close %s: %s\n",
- filename, strerror(errno));
- goto fail;
- }
-
- return buf;
+ FILE *fp = NULL;
+ uint8_t *buf = NULL;
+ struct stat sb;
+
+ fp = fopen(filename, "rb");
+ if (!fp) {
+ fprintf(stderr, "ERROR: Unable to open %s for reading: %s\n",
+ filename, strerror(errno));
+ goto fail;
+ }
+
+ if (0 != fstat(fileno(fp), &sb)) {
+ fprintf(stderr, "ERROR: can't fstat %s: %s\n",
+ filename, strerror(errno));
+ goto fail;
+ }
+ if (sizeptr)
+ *sizeptr = sb.st_size;
+
+ buf = (uint8_t *) malloc(sb.st_size);
+ if (!buf) {
+ fprintf(stderr, "ERROR: can't malloc %" PRIi64 " bytes: %s\n",
+ sb.st_size, strerror(errno));
+ goto fail;
+ }
+
+ if (1 != fread(buf, sb.st_size, 1, fp)) {
+ fprintf(stderr, "ERROR: Unable to read from %s: %s\n",
+ filename, strerror(errno));
+ goto fail;
+ }
+
+ if (fp && 0 != fclose(fp)) {
+ fprintf(stderr, "ERROR: Unable to close %s: %s\n",
+ filename, strerror(errno));
+ goto fail;
+ }
+
+ return buf;
fail:
- errorcnt++;
+ errorcnt++;
- if (buf)
- free(buf);
+ if (buf)
+ free(buf);
- if (fp && 0 != fclose(fp))
- fprintf(stderr, "ERROR: Unable to close %s: %s\n",
- filename, strerror(errno));
- return NULL;
+ if (fp && 0 != fclose(fp))
+ fprintf(stderr, "ERROR: Unable to close %s: %s\n",
+ filename, strerror(errno));
+ return NULL;
}
static int write_to_file(const char *msg, const char *filename,
- uint8_t *start, size_t size)
+ uint8_t * start, size_t size)
{
- FILE *fp;
- int r = 0;
-
- fp = fopen(filename, "wb");
- if (!fp) {
- fprintf(stderr, "ERROR: Unable to open %s for writing: %s\n",
- filename, strerror(errno));
- errorcnt++;
- return errno;
- }
-
- /* Don't write zero bytes */
- if (size && 1 != fwrite(start, size, 1, fp)) {
- fprintf(stderr, "ERROR: Unable to write to %s: %s\n",
- filename, strerror(errno));
- errorcnt++;
- r = errno;
- }
-
- if (0 != fclose(fp)) {
- fprintf(stderr, "ERROR: Unable to close %s: %s\n",
- filename, strerror(errno));
- errorcnt++;
- if (!r)
- r = errno;
- }
-
- if (!r && msg)
- printf("%s %s\n", msg, filename);
-
- return r;
+ FILE *fp;
+ int r = 0;
+
+ fp = fopen(filename, "wb");
+ if (!fp) {
+ fprintf(stderr, "ERROR: Unable to open %s for writing: %s\n",
+ filename, strerror(errno));
+ errorcnt++;
+ return errno;
+ }
+
+ /* Don't write zero bytes */
+ if (size && 1 != fwrite(start, size, 1, fp)) {
+ fprintf(stderr, "ERROR: Unable to write to %s: %s\n",
+ filename, strerror(errno));
+ errorcnt++;
+ r = errno;
+ }
+
+ if (0 != fclose(fp)) {
+ fprintf(stderr, "ERROR: Unable to close %s: %s\n",
+ filename, strerror(errno));
+ errorcnt++;
+ if (!r)
+ r = errno;
+ }
+
+ if (!r && msg)
+ printf("%s %s\n", msg, filename);
+
+ return r;
}
static int read_from_file(const char *msg, const char *filename,
- uint8_t *start, uint32_t size)
+ uint8_t * start, uint32_t size)
{
- FILE *fp;
- struct stat sb;
- size_t count;
- int r = 0;
-
- fp = fopen(filename, "rb");
- if (!fp) {
- fprintf(stderr, "ERROR: Unable to open %s for reading: %s\n",
- filename, strerror(errno));
- errorcnt++;
- return errno;
- }
-
- if (0 != fstat(fileno(fp), &sb)) {
- fprintf(stderr, "ERROR: can't fstat %s: %s\n",
- filename, strerror(errno));
- errorcnt++;
- r = errno;
- goto done_close;
- }
-
- if (sb.st_size > size) {
- fprintf(stderr, "ERROR: file %s exceeds capacity (%" PRIu32 ")\n",
- filename, size);
- errorcnt++;
- r = errno;
- goto done_close;
- }
-
- /* It's okay if we read less than size. That's just the max. */
- count = fread(start, 1, size, fp);
- if (ferror(fp)) {
- fprintf(stderr, "ERROR: Read %zu/%" PRIi64 " bytes from %s: %s\n",
- count, sb.st_size, filename, strerror(errno));
- errorcnt++;
- r = errno;
- }
+ FILE *fp;
+ struct stat sb;
+ size_t count;
+ int r = 0;
+
+ fp = fopen(filename, "rb");
+ if (!fp) {
+ fprintf(stderr, "ERROR: Unable to open %s for reading: %s\n",
+ filename, strerror(errno));
+ errorcnt++;
+ return errno;
+ }
+
+ if (0 != fstat(fileno(fp), &sb)) {
+ fprintf(stderr, "ERROR: can't fstat %s: %s\n",
+ filename, strerror(errno));
+ errorcnt++;
+ r = errno;
+ goto done_close;
+ }
+
+ if (sb.st_size > size) {
+ fprintf(stderr,
+ "ERROR: file %s exceeds capacity (%" PRIu32 ")\n",
+ filename, size);
+ errorcnt++;
+ r = errno;
+ goto done_close;
+ }
+
+ /* It's okay if we read less than size. That's just the max. */
+ count = fread(start, 1, size, fp);
+ if (ferror(fp)) {
+ fprintf(stderr,
+ "ERROR: Read %zu/%" PRIi64 " bytes from %s: %s\n",
+ count, sb.st_size, filename, strerror(errno));
+ errorcnt++;
+ r = errno;
+ }
done_close:
- if (0 != fclose(fp)) {
- fprintf(stderr, "ERROR: Unable to close %s: %s\n",
- filename, strerror(errno));
- errorcnt++;
- if (!r)
- r = errno;
- }
-
- if (!r && msg)
- printf(" - import %s from %s: success\n", msg, filename);
-
- return r;
+ if (0 != fclose(fp)) {
+ fprintf(stderr, "ERROR: Unable to close %s: %s\n",
+ filename, strerror(errno));
+ errorcnt++;
+ if (!r)
+ r = errno;
+ }
+
+ if (!r && msg)
+ printf(" - import %s from %s: success\n", msg, filename);
+
+ return r;
}
static int do_gbb_utility(int argc, char *argv[])
{
- enum do_what_now {DO_GET, DO_SET, DO_CREATE} mode = DO_GET;
- char *infile = NULL;
- char *outfile = NULL;
- char *opt_create = NULL;
- char *opt_rootkey = NULL;
- char *opt_bmpfv = NULL;
- char *opt_recoverykey = NULL;
- char *opt_hwid = NULL;
- char *opt_flags = NULL;
- int sel_hwid = 0;
- int sel_flags = 0;
- uint8_t *inbuf = NULL;
- off_t filesize;
- uint8_t *outbuf = NULL;
- GoogleBinaryBlockHeader *gbb;
- uint8_t *gbb_base;
- int i;
-
- opterr = 0; /* quiet, you */
- while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
- switch (i) {
- case 'g':
- mode = DO_GET;
- break;
- case 's':
- mode = DO_SET;
- break;
- case 'c':
- mode = DO_CREATE;
- opt_create = optarg;
- break;
- case 'o':
- outfile = optarg;
- break;
- case 'k':
- opt_rootkey = optarg;
- break;
- case 'b':
- opt_bmpfv = optarg;
- break;
- case 'R': case 'r':
- opt_recoverykey = optarg;
- break;
- case 'i': case 'h':
- /* --hwid is optional: might be null, which could be okay */
- opt_hwid = optarg;
- sel_hwid = 1;
- break;
- case 'L': case 'f':
- /* --flags is optional: might be null, which could be okay */
- opt_flags = optarg;
- sel_flags = 1;
- break;
- case '?':
- errorcnt++;
- if (optopt)
- fprintf(stderr, "ERROR: unrecognized option: -%c\n", optopt);
- else if (argv[optind - 1] )
- fprintf(stderr, "ERROR: unrecognized option (possibly \"%s\")\n",
- argv[optind - 1]);
- else
- fprintf(stderr, "ERROR: unrecognized option\n");
- break;
- case ':':
- errorcnt++;
- if (argv[optind - 1])
- fprintf(stderr, "ERROR: missing argument to -%c (%s)\n",
- optopt, argv[optind - 1]);
- else
- fprintf(stderr, "ERROR: missing argument to -%c\n", optopt);
- break;
- default:
- errorcnt++;
- fprintf(stderr, "ERROR: unexpected error while parsing options\n");
- }
- }
-
- /* Problems? */
- if (errorcnt)
- help_and_quit(argv[0]);
-
- /* Now try to do something */
- switch (mode) {
- case DO_GET:
- if (argc - optind < 1) {
- fprintf(stderr, "\nERROR: missing input filename\n");
- help_and_quit(argv[0]);
- } else {
- infile = argv[optind++];
- }
-
- /* With no args, show the HWID */
- if (!opt_rootkey && !opt_bmpfv && !opt_recoverykey && !sel_flags)
- sel_hwid = 1;
-
- inbuf = read_entire_file(infile, &filesize);
- if (!inbuf)
- break;
-
- gbb = FindGbbHeader(inbuf, filesize);
- if (!gbb) {
- fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
- break;
- }
- gbb_base = (uint8_t *)gbb;
-
- /* Get the stuff */
- if (sel_hwid)
- printf("hardware_id: %s\n",
- gbb->hwid_size ? (char *)(gbb_base + gbb->hwid_offset) : "");
- if (sel_flags)
- printf("flags: 0x%08x\n", gbb->flags);
- if (opt_rootkey)
- write_to_file(" - exported root_key to file:", opt_rootkey,
- gbb_base + gbb->rootkey_offset,
- gbb->rootkey_size);
- if (opt_bmpfv)
- write_to_file(" - exported bmp_fv to file:", opt_bmpfv,
- gbb_base + gbb->bmpfv_offset,
- gbb->bmpfv_size);
- if (opt_recoverykey)
- write_to_file(" - exported recovery_key to file:", opt_recoverykey,
- gbb_base + gbb->recovery_key_offset,
- gbb->recovery_key_size);
- break;
-
- case DO_SET:
- if (argc - optind < 1) {
- fprintf(stderr, "\nERROR: missing input filename\n");
- help_and_quit(argv[0]);
- }
- infile = argv[optind++];
- if (!outfile)
- outfile = (argc - optind < 1) ? infile : argv[optind++];
-
- if (sel_hwid && !opt_hwid) {
- fprintf(stderr, "\nERROR: missing new HWID value\n");
- help_and_quit(argv[0]);
- }
- if (sel_flags && (!opt_flags || !*opt_flags)) {
- fprintf(stderr, "\nERROR: missing new flags value\n");
- help_and_quit(argv[0]);
- }
-
- /* With no args, we'll either copy it unchanged or do nothing */
- inbuf = read_entire_file(infile, &filesize);
- if (!inbuf)
- break;
-
- gbb = FindGbbHeader(inbuf, filesize);
- if (!gbb) {
- fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
- break;
- }
- gbb_base = (uint8_t *)gbb;
-
- outbuf = (uint8_t *)malloc(filesize);
- if (!outbuf) {
- errorcnt++;
- fprintf(stderr, "ERROR: can't malloc %" PRIi64 " bytes: %s\n",
- filesize, strerror(errno));
- break;
- }
-
- /* Switch pointers to outbuf */
- memcpy(outbuf, inbuf, filesize);
- gbb = FindGbbHeader(outbuf, filesize);
- if (!gbb) {
- fprintf(stderr, "INTERNAL ERROR: No GBB found in outbuf\n");
- exit(1);
- }
- gbb_base = (uint8_t *)gbb;
-
- if (opt_hwid) {
- if (strlen(opt_hwid) + 1 > gbb->hwid_size) {
- fprintf(stderr,
- "ERROR: null-terminated HWID exceeds capacity (%d)\n",
- gbb->hwid_size);
- errorcnt++;
- } else {
- strcpy((char *)(gbb_base + gbb->hwid_offset), opt_hwid);
- }
- }
-
- if (opt_flags) {
- char *e = NULL;
- uint32_t val;
- val = (uint32_t)strtoul(opt_flags, &e, 0);
- if (e && *e) {
- fprintf(stderr, "ERROR: invalid flags value: %s\n", opt_flags);
- errorcnt++;
- } else {
- gbb->flags = val;
- }
- }
-
- if (opt_rootkey)
- read_from_file("root_key", opt_rootkey,
- gbb_base + gbb->rootkey_offset,
- gbb->rootkey_size);
- if (opt_bmpfv)
- read_from_file("bmp_fv", opt_bmpfv,
- gbb_base + gbb->bmpfv_offset,
- gbb->bmpfv_size);
- if (opt_recoverykey)
- read_from_file("recovery_key", opt_recoverykey,
- gbb_base + gbb->recovery_key_offset,
- gbb->recovery_key_size);
-
- /* Write it out if there are no problems. */
- if (!errorcnt)
- write_to_file("successfully saved new image to:",
- outfile, outbuf, filesize);
-
- break;
-
- case DO_CREATE:
- if (!outfile) {
- if (argc - optind < 1) {
- fprintf(stderr, "\nERROR: missing output filename\n");
- help_and_quit(argv[0]);
+ enum do_what_now { DO_GET, DO_SET, DO_CREATE } mode = DO_GET;
+ char *infile = NULL;
+ char *outfile = NULL;
+ char *opt_create = NULL;
+ char *opt_rootkey = NULL;
+ char *opt_bmpfv = NULL;
+ char *opt_recoverykey = NULL;
+ char *opt_hwid = NULL;
+ char *opt_flags = NULL;
+ int sel_hwid = 0;
+ int sel_flags = 0;
+ uint8_t *inbuf = NULL;
+ off_t filesize;
+ uint8_t *outbuf = NULL;
+ GoogleBinaryBlockHeader *gbb;
+ uint8_t *gbb_base;
+ int i;
+
+ opterr = 0; /* quiet, you */
+ while ((i = getopt_long(argc, argv, short_opts, long_opts, 0)) != -1) {
+ switch (i) {
+ case 'g':
+ mode = DO_GET;
+ break;
+ case 's':
+ mode = DO_SET;
+ break;
+ case 'c':
+ mode = DO_CREATE;
+ opt_create = optarg;
+ break;
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'k':
+ opt_rootkey = optarg;
+ break;
+ case 'b':
+ opt_bmpfv = optarg;
+ break;
+ case 'R':
+ case 'r':
+ opt_recoverykey = optarg;
+ break;
+ case 'i':
+ case 'h':
+ /* --hwid is optional: null might be okay */
+ opt_hwid = optarg;
+ sel_hwid = 1;
+ break;
+ case 'L':
+ case 'f':
+ /* --flags is optional: null might be okay */
+ opt_flags = optarg;
+ sel_flags = 1;
+ break;
+ case '?':
+ errorcnt++;
+ if (optopt)
+ fprintf(stderr,
+ "ERROR: unrecognized option: -%c\n",
+ optopt);
+ else if (argv[optind - 1])
+ fprintf(stderr,
+ "ERROR: unrecognized option "
+ "(possibly \"%s\")\n",
+ argv[optind - 1]);
+ else
+ fprintf(stderr, "ERROR: unrecognized option\n");
+ break;
+ case ':':
+ errorcnt++;
+ if (argv[optind - 1])
+ fprintf(stderr,
+ "ERROR: missing argument to -%c (%s)\n",
+ optopt, argv[optind - 1]);
+ else
+ fprintf(stderr,
+ "ERROR: missing argument to -%c\n",
+ optopt);
+ break;
+ default:
+ errorcnt++;
+ fprintf(stderr,
+ "ERROR: error while parsing options\n");
+ }
}
- outfile = argv[optind++];
- }
- /* Parse the creation args */
- outbuf = create_gbb(opt_create, &filesize);
- if (!outbuf) {
- fprintf(stderr,
- "\nERROR: unable to parse creation spec (%s)\n", opt_create);
- help_and_quit(argv[0]);
- }
- if (!errorcnt)
- write_to_file("successfully created new GBB to:",
- outfile, outbuf, filesize);
- break;
- }
-
-
- if (inbuf)
- free(inbuf);
- if (outbuf)
- free(outbuf);
- return !!errorcnt;
+
+ /* Problems? */
+ if (errorcnt)
+ help_and_quit(argv[0]);
+
+ /* Now try to do something */
+ switch (mode) {
+ case DO_GET:
+ if (argc - optind < 1) {
+ fprintf(stderr, "\nERROR: missing input filename\n");
+ help_and_quit(argv[0]);
+ } else {
+ infile = argv[optind++];
+ }
+
+ /* With no args, show the HWID */
+ if (!opt_rootkey && !opt_bmpfv && !opt_recoverykey
+ && !sel_flags)
+ sel_hwid = 1;
+
+ inbuf = read_entire_file(infile, &filesize);
+ if (!inbuf)
+ break;
+
+ gbb = FindGbbHeader(inbuf, filesize);
+ if (!gbb) {
+ fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
+ break;
+ }
+ gbb_base = (uint8_t *) gbb;
+
+ /* Get the stuff */
+ if (sel_hwid)
+ printf("hardware_id: %s\n",
+ gbb->hwid_size ? (char *)(gbb_base +
+ gbb->
+ hwid_offset) : "");
+ if (sel_flags)
+ printf("flags: 0x%08x\n", gbb->flags);
+ if (opt_rootkey)
+ write_to_file(" - exported root_key to file:",
+ opt_rootkey,
+ gbb_base + gbb->rootkey_offset,
+ gbb->rootkey_size);
+ if (opt_bmpfv)
+ write_to_file(" - exported bmp_fv to file:", opt_bmpfv,
+ gbb_base + gbb->bmpfv_offset,
+ gbb->bmpfv_size);
+ if (opt_recoverykey)
+ write_to_file(" - exported recovery_key to file:",
+ opt_recoverykey,
+ gbb_base + gbb->recovery_key_offset,
+ gbb->recovery_key_size);
+ break;
+
+ case DO_SET:
+ if (argc - optind < 1) {
+ fprintf(stderr, "\nERROR: missing input filename\n");
+ help_and_quit(argv[0]);
+ }
+ infile = argv[optind++];
+ if (!outfile)
+ outfile = (argc - optind < 1) ? infile : argv[optind++];
+
+ if (sel_hwid && !opt_hwid) {
+ fprintf(stderr, "\nERROR: missing new HWID value\n");
+ help_and_quit(argv[0]);
+ }
+ if (sel_flags && (!opt_flags || !*opt_flags)) {
+ fprintf(stderr, "\nERROR: missing new flags value\n");
+ help_and_quit(argv[0]);
+ }
+
+ /* With no args, we'll either copy it unchanged or do nothing */
+ inbuf = read_entire_file(infile, &filesize);
+ if (!inbuf)
+ break;
+
+ gbb = FindGbbHeader(inbuf, filesize);
+ if (!gbb) {
+ fprintf(stderr, "ERROR: No GBB found in %s\n", infile);
+ break;
+ }
+ gbb_base = (uint8_t *) gbb;
+
+ outbuf = (uint8_t *) malloc(filesize);
+ if (!outbuf) {
+ errorcnt++;
+ fprintf(stderr,
+ "ERROR: can't malloc %" PRIi64 " bytes: %s\n",
+ filesize, strerror(errno));
+ break;
+ }
+
+ /* Switch pointers to outbuf */
+ memcpy(outbuf, inbuf, filesize);
+ gbb = FindGbbHeader(outbuf, filesize);
+ if (!gbb) {
+ fprintf(stderr,
+ "INTERNAL ERROR: No GBB found in outbuf\n");
+ exit(1);
+ }
+ gbb_base = (uint8_t *) gbb;
+
+ if (opt_hwid) {
+ if (strlen(opt_hwid) + 1 > gbb->hwid_size) {
+ fprintf(stderr,
+ "ERROR: null-terminated HWID"
+ " exceeds capacity (%d)\n",
+ gbb->hwid_size);
+ errorcnt++;
+ } else {
+ strcpy((char *)(gbb_base + gbb->hwid_offset),
+ opt_hwid);
+ }
+ }
+
+ if (opt_flags) {
+ char *e = NULL;
+ uint32_t val;
+ val = (uint32_t) strtoul(opt_flags, &e, 0);
+ if (e && *e) {
+ fprintf(stderr,
+ "ERROR: invalid flags value: %s\n",
+ opt_flags);
+ errorcnt++;
+ } else {
+ gbb->flags = val;
+ }
+ }
+
+ if (opt_rootkey)
+ read_from_file("root_key", opt_rootkey,
+ gbb_base + gbb->rootkey_offset,
+ gbb->rootkey_size);
+ if (opt_bmpfv)
+ read_from_file("bmp_fv", opt_bmpfv,
+ gbb_base + gbb->bmpfv_offset,
+ gbb->bmpfv_size);
+ if (opt_recoverykey)
+ read_from_file("recovery_key", opt_recoverykey,
+ gbb_base + gbb->recovery_key_offset,
+ gbb->recovery_key_size);
+
+ /* Write it out if there are no problems. */
+ if (!errorcnt)
+ write_to_file("successfully saved new image to:",
+ outfile, outbuf, filesize);
+
+ break;
+
+ case DO_CREATE:
+ if (!outfile) {
+ if (argc - optind < 1) {
+ fprintf(stderr,
+ "\nERROR: missing output filename\n");
+ help_and_quit(argv[0]);
+ }
+ outfile = argv[optind++];
+ }
+ /* Parse the creation args */
+ outbuf = create_gbb(opt_create, &filesize);
+ if (!outbuf) {
+ fprintf(stderr,
+ "\nERROR: unable to parse creation spec (%s)\n",
+ opt_create);
+ help_and_quit(argv[0]);
+ }
+ if (!errorcnt)
+ write_to_file("successfully created new GBB to:",
+ outfile, outbuf, filesize);
+ break;
+ }
+
+ if (inbuf)
+ free(inbuf);
+ if (outbuf)
+ free(outbuf);
+ return ! !errorcnt;
}
DECLARE_FUTIL_COMMAND(gbb_utility, do_gbb_utility,
diff --git a/futility/cmd_vbutil_firmware.c b/futility/cmd_vbutil_firmware.c
index 7eea6c84..95cae28d 100644
--- a/futility/cmd_vbutil_firmware.c
+++ b/futility/cmd_vbutil_firmware.c
@@ -6,7 +6,7 @@
*/
#include <getopt.h>
-#include <inttypes.h> /* For PRIu64 */
+#include <inttypes.h> /* For PRIu64 */
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -19,358 +19,368 @@
#include "util_misc.h"
#include "vboot_common.h"
-
/* Command line options */
enum {
- OPT_MODE_VBLOCK = 1000,
- OPT_MODE_VERIFY,
- OPT_KEYBLOCK,
- OPT_SIGNPUBKEY,
- OPT_SIGNPRIVATE,
- OPT_VERSION,
- OPT_FV,
- OPT_KERNELKEY,
- OPT_FLAGS,
+ OPT_MODE_VBLOCK = 1000,
+ OPT_MODE_VERIFY,
+ OPT_KEYBLOCK,
+ OPT_SIGNPUBKEY,
+ OPT_SIGNPRIVATE,
+ OPT_VERSION,
+ OPT_FV,
+ OPT_KERNELKEY,
+ OPT_FLAGS,
};
static const struct option long_opts[] = {
- {"vblock", 1, 0, OPT_MODE_VBLOCK },
- {"verify", 1, 0, OPT_MODE_VERIFY },
- {"keyblock", 1, 0, OPT_KEYBLOCK },
- {"signpubkey", 1, 0, OPT_SIGNPUBKEY },
- {"signprivate", 1, 0, OPT_SIGNPRIVATE },
- {"version", 1, 0, OPT_VERSION },
- {"fv", 1, 0, OPT_FV },
- {"kernelkey", 1, 0, OPT_KERNELKEY },
- {"flags", 1, 0, OPT_FLAGS },
- {NULL, 0, 0, 0}
+ {"vblock", 1, 0, OPT_MODE_VBLOCK},
+ {"verify", 1, 0, OPT_MODE_VERIFY},
+ {"keyblock", 1, 0, OPT_KEYBLOCK},
+ {"signpubkey", 1, 0, OPT_SIGNPUBKEY},
+ {"signprivate", 1, 0, OPT_SIGNPRIVATE},
+ {"version", 1, 0, OPT_VERSION},
+ {"fv", 1, 0, OPT_FV},
+ {"kernelkey", 1, 0, OPT_KERNELKEY},
+ {"flags", 1, 0, OPT_FLAGS},
+ {NULL, 0, 0, 0}
};
-
/* Print help and return error */
-static int PrintHelp(void) {
-
- puts("vbutil_firmware - Verified boot key block utility\n"
- "\n"
- "Usage: vbutil_firmware <--vblock|--verify> <file> [OPTIONS]\n"
- "\n"
- "For '--vblock <file>', required OPTIONS are:\n"
- " --keyblock <file> Key block in .keyblock format\n"
- " --signprivate <file> Signing private key in .vbprivk format\n"
- " --version <number> Firmware version\n"
- " --fv <file> Firmware volume to sign\n"
- " --kernelkey <file> Kernel subkey in .vbpubk format\n"
- "optional OPTIONS are:\n"
- " --flags <number> Preamble flags (defaults to 0)\n"
- "\n"
- "For '--verify <file>', required OPTIONS are:\n"
- " --signpubkey <file> Signing public key in .vbpubk format\n"
- " --fv <file> Firmware volume to verify\n"
- "\n"
- "For '--verify <file>', optional OPTIONS are:\n"
- " --kernelkey <file> Write the kernel subkey to this file\n"
- "");
- return 1;
+static int PrintHelp(void)
+{
+
+ puts("vbutil_firmware - Verified boot key block utility\n"
+ "\n"
+ "Usage: vbutil_firmware <--vblock|--verify> <file> [OPTIONS]\n"
+ "\n"
+ "For '--vblock <file>', required OPTIONS are:\n"
+ " --keyblock <file> Key block in .keyblock format\n"
+ " --signprivate <file>"
+ " Signing private key in .vbprivk format\n"
+ " --version <number> Firmware version\n"
+ " --fv <file> Firmware volume to sign\n"
+ " --kernelkey <file> Kernel subkey in .vbpubk format\n"
+ "optional OPTIONS are:\n"
+ " --flags <number> Preamble flags (defaults to 0)\n"
+ "\n"
+ "For '--verify <file>', required OPTIONS are:\n"
+ " --signpubkey <file>"
+ " Signing public key in .vbpubk format\n"
+ " --fv <file> Firmware volume to verify\n"
+ "\n"
+ "For '--verify <file>', optional OPTIONS are:\n"
+ " --kernelkey <file>"
+ " Write the kernel subkey to this file\n"
+ "");
+ return 1;
}
-
/* Create a firmware .vblock */
-static int Vblock(const char* outfile, const char* keyblock_file,
- const char* signprivate, uint64_t version,
- const char* fv_file, const char* kernelkey_file,
- uint32_t preamble_flags) {
-
- VbPrivateKey* signing_key;
- VbPublicKey* kernel_subkey;
- VbSignature* body_sig;
- VbFirmwarePreambleHeader* preamble;
- VbKeyBlockHeader* key_block;
- uint64_t key_block_size;
- uint8_t* fv_data;
- uint64_t fv_size;
- FILE* f;
- uint64_t i;
-
- if (!outfile) {
- VbExError("Must specify output filename\n");
- return 1;
- }
- if (!keyblock_file || !signprivate || !kernelkey_file) {
- VbExError("Must specify all keys\n");
- return 1;
- }
- if (!fv_file) {
- VbExError("Must specify firmware volume\n");
- return 1;
- }
-
- /* Read the key block and keys */
- key_block = (VbKeyBlockHeader*)ReadFile(keyblock_file, &key_block_size);
- if (!key_block) {
- VbExError("Error reading key block.\n");
- return 1;
- }
-
- signing_key = PrivateKeyRead(signprivate);
- if (!signing_key) {
- VbExError("Error reading signing key.\n");
- return 1;
- }
-
- kernel_subkey = PublicKeyRead(kernelkey_file);
- if (!kernel_subkey) {
- VbExError("Error reading kernel subkey.\n");
- return 1;
- }
-
- /* Read and sign the firmware volume */
- fv_data = ReadFile(fv_file, &fv_size);
- if (!fv_data)
- return 1;
- if (!fv_size) {
- VbExError("Empty firmware volume file\n");
- return 1;
- }
- body_sig = CalculateSignature(fv_data, fv_size, signing_key);
- if (!body_sig) {
- VbExError("Error calculating body signature\n");
- return 1;
- }
- free(fv_data);
-
- /* Create preamble */
- preamble = CreateFirmwarePreamble(version,
- kernel_subkey,
- body_sig,
- signing_key,
- preamble_flags);
- if (!preamble) {
- VbExError("Error creating preamble.\n");
- return 1;
- }
-
- /* Write the output file */
- f = fopen(outfile, "wb");
- if (!f) {
- VbExError("Can't open output file %s\n", outfile);
- return 1;
- }
- i = ((1 != fwrite(key_block, key_block_size, 1, f)) ||
- (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
- fclose(f);
- if (i) {
- VbExError("Can't write output file %s\n", outfile);
- unlink(outfile);
- return 1;
- }
-
- /* Success */
- return 0;
+static int Vblock(const char *outfile, const char *keyblock_file,
+ const char *signprivate, uint64_t version,
+ const char *fv_file, const char *kernelkey_file,
+ uint32_t preamble_flags)
+{
+
+ VbPrivateKey *signing_key;
+ VbPublicKey *kernel_subkey;
+ VbSignature *body_sig;
+ VbFirmwarePreambleHeader *preamble;
+ VbKeyBlockHeader *key_block;
+ uint64_t key_block_size;
+ uint8_t *fv_data;
+ uint64_t fv_size;
+ FILE *f;
+ uint64_t i;
+
+ if (!outfile) {
+ VbExError("Must specify output filename\n");
+ return 1;
+ }
+ if (!keyblock_file || !signprivate || !kernelkey_file) {
+ VbExError("Must specify all keys\n");
+ return 1;
+ }
+ if (!fv_file) {
+ VbExError("Must specify firmware volume\n");
+ return 1;
+ }
+
+ /* Read the key block and keys */
+ key_block =
+ (VbKeyBlockHeader *) ReadFile(keyblock_file, &key_block_size);
+ if (!key_block) {
+ VbExError("Error reading key block.\n");
+ return 1;
+ }
+
+ signing_key = PrivateKeyRead(signprivate);
+ if (!signing_key) {
+ VbExError("Error reading signing key.\n");
+ return 1;
+ }
+
+ kernel_subkey = PublicKeyRead(kernelkey_file);
+ if (!kernel_subkey) {
+ VbExError("Error reading kernel subkey.\n");
+ return 1;
+ }
+
+ /* Read and sign the firmware volume */
+ fv_data = ReadFile(fv_file, &fv_size);
+ if (!fv_data)
+ return 1;
+ if (!fv_size) {
+ VbExError("Empty firmware volume file\n");
+ return 1;
+ }
+ body_sig = CalculateSignature(fv_data, fv_size, signing_key);
+ if (!body_sig) {
+ VbExError("Error calculating body signature\n");
+ return 1;
+ }
+ free(fv_data);
+
+ /* Create preamble */
+ preamble = CreateFirmwarePreamble(version,
+ kernel_subkey,
+ body_sig,
+ signing_key, preamble_flags);
+ if (!preamble) {
+ VbExError("Error creating preamble.\n");
+ return 1;
+ }
+
+ /* Write the output file */
+ f = fopen(outfile, "wb");
+ if (!f) {
+ VbExError("Can't open output file %s\n", outfile);
+ return 1;
+ }
+ i = ((1 != fwrite(key_block, key_block_size, 1, f)) ||
+ (1 != fwrite(preamble, preamble->preamble_size, 1, f)));
+ fclose(f);
+ if (i) {
+ VbExError("Can't write output file %s\n", outfile);
+ unlink(outfile);
+ return 1;
+ }
+
+ /* Success */
+ return 0;
}
-static int Verify(const char* infile, const char* signpubkey,
- const char* fv_file, const char* kernelkey_file) {
-
- VbKeyBlockHeader* key_block;
- VbFirmwarePreambleHeader* preamble;
- VbPublicKey* data_key;
- VbPublicKey* sign_key;
- VbPublicKey* kernel_subkey;
- RSAPublicKey* rsa;
- uint8_t* blob;
- uint64_t blob_size;
- uint8_t* fv_data;
- uint64_t fv_size;
- uint64_t now = 0;
- uint32_t flags;
-
- if (!infile || !signpubkey || !fv_file) {
- VbExError("Must specify filename, signpubkey, and fv\n");
- return 1;
- }
-
- /* Read public signing key */
- sign_key = PublicKeyRead(signpubkey);
- if (!sign_key) {
- VbExError("Error reading signpubkey.\n");
- return 1;
- }
-
- /* Read blob */
- blob = ReadFile(infile, &blob_size);
- if (!blob) {
- VbExError("Error reading input file\n");
- return 1;
- }
-
- /* Read firmware volume */
- fv_data = ReadFile(fv_file, &fv_size);
- if (!fv_data) {
- VbExError("Error reading firmware volume\n");
- return 1;
- }
-
- /* Verify key block */
- key_block = (VbKeyBlockHeader*)blob;
- if (0 != KeyBlockVerify(key_block, blob_size, sign_key, 0)) {
- VbExError("Error verifying key block.\n");
- return 1;
- }
- free(sign_key);
- now += key_block->key_block_size;
-
- printf("Key block:\n");
- data_key = &key_block->data_key;
- printf(" Size: %" PRIu64 "\n", key_block->key_block_size);
- printf(" Flags: %" PRIu64 " (ignored)\n",
- key_block->key_block_flags);
- printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
- (data_key->algorithm < kNumAlgorithms ?
- algo_strings[data_key->algorithm] : "(invalid)"));
- printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
- printf(" Data key sha1sum: ");
- PrintPubKeySha1Sum(data_key);
- printf("\n");
-
- rsa = PublicKeyToRSA(&key_block->data_key);
- if (!rsa) {
- VbExError("Error parsing data key.\n");
- return 1;
- }
-
- /* Verify preamble */
- preamble = (VbFirmwarePreambleHeader*)(blob + now);
- if (0 != VerifyFirmwarePreamble(preamble, blob_size - now, rsa)) {
- VbExError("Error verifying preamble.\n");
- return 1;
- }
- now += preamble->preamble_size;
-
- flags = VbGetFirmwarePreambleFlags(preamble);
- printf("Preamble:\n");
- printf(" Size: %" PRIu64 "\n", preamble->preamble_size);
- printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
- preamble->header_version_major, preamble->header_version_minor);
- printf(" Firmware version: %" PRIu64 "\n", preamble->firmware_version);
- kernel_subkey = &preamble->kernel_subkey;
- printf(" Kernel key algorithm: %" PRIu64 " %s\n",
- kernel_subkey->algorithm,
- (kernel_subkey->algorithm < kNumAlgorithms ?
- algo_strings[kernel_subkey->algorithm] : "(invalid)"));
- printf(" Kernel key version: %" PRIu64 "\n",
- kernel_subkey->key_version);
- printf(" Kernel key sha1sum: ");
- PrintPubKeySha1Sum(kernel_subkey);
- printf("\n");
- printf(" Firmware body size: %" PRIu64 "\n",
- preamble->body_signature.data_size);
- printf(" Preamble flags: %" PRIu32 "\n", flags);
-
- /* TODO: verify body size same as signature size */
-
- /* Verify body */
- if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
- printf("Preamble requests USE_RO_NORMAL; skipping body verification.\n");
- } else {
- if (0 != VerifyData(fv_data, fv_size, &preamble->body_signature, rsa)) {
- VbExError("Error verifying firmware body.\n");
- return 1;
- }
- printf("Body verification succeeded.\n");
- }
-
- if (kernelkey_file) {
- if (0 != PublicKeyWrite(kernelkey_file, kernel_subkey)) {
- fprintf(stderr,
- "vbutil_firmware: unable to write kernel subkey\n");
- return 1;
- }
- }
-
- return 0;
+static int Verify(const char *infile, const char *signpubkey,
+ const char *fv_file, const char *kernelkey_file)
+{
+
+ VbKeyBlockHeader *key_block;
+ VbFirmwarePreambleHeader *preamble;
+ VbPublicKey *data_key;
+ VbPublicKey *sign_key;
+ VbPublicKey *kernel_subkey;
+ RSAPublicKey *rsa;
+ uint8_t *blob;
+ uint64_t blob_size;
+ uint8_t *fv_data;
+ uint64_t fv_size;
+ uint64_t now = 0;
+ uint32_t flags;
+
+ if (!infile || !signpubkey || !fv_file) {
+ VbExError("Must specify filename, signpubkey, and fv\n");
+ return 1;
+ }
+
+ /* Read public signing key */
+ sign_key = PublicKeyRead(signpubkey);
+ if (!sign_key) {
+ VbExError("Error reading signpubkey.\n");
+ return 1;
+ }
+
+ /* Read blob */
+ blob = ReadFile(infile, &blob_size);
+ if (!blob) {
+ VbExError("Error reading input file\n");
+ return 1;
+ }
+
+ /* Read firmware volume */
+ fv_data = ReadFile(fv_file, &fv_size);
+ if (!fv_data) {
+ VbExError("Error reading firmware volume\n");
+ return 1;
+ }
+
+ /* Verify key block */
+ key_block = (VbKeyBlockHeader *) blob;
+ if (0 != KeyBlockVerify(key_block, blob_size, sign_key, 0)) {
+ VbExError("Error verifying key block.\n");
+ return 1;
+ }
+ free(sign_key);
+ now += key_block->key_block_size;
+
+ printf("Key block:\n");
+ data_key = &key_block->data_key;
+ printf(" Size: %" PRIu64 "\n",
+ key_block->key_block_size);
+ printf(" Flags: %" PRIu64 " (ignored)\n",
+ key_block->key_block_flags);
+ printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
+ (data_key->algorithm <
+ kNumAlgorithms ? algo_strings[data_key->
+ algorithm] : "(invalid)"));
+ printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
+ printf(" Data key sha1sum: ");
+ PrintPubKeySha1Sum(data_key);
+ printf("\n");
+
+ rsa = PublicKeyToRSA(&key_block->data_key);
+ if (!rsa) {
+ VbExError("Error parsing data key.\n");
+ return 1;
+ }
+
+ /* Verify preamble */
+ preamble = (VbFirmwarePreambleHeader *) (blob + now);
+ if (0 != VerifyFirmwarePreamble(preamble, blob_size - now, rsa)) {
+ VbExError("Error verifying preamble.\n");
+ return 1;
+ }
+ now += preamble->preamble_size;
+
+ flags = VbGetFirmwarePreambleFlags(preamble);
+ printf("Preamble:\n");
+ printf(" Size: %" PRIu64 "\n",
+ preamble->preamble_size);
+ printf(" Header version: %" PRIu32 ".%" PRIu32 "\n",
+ preamble->header_version_major, preamble->header_version_minor);
+ printf(" Firmware version: %" PRIu64 "\n",
+ preamble->firmware_version);
+ kernel_subkey = &preamble->kernel_subkey;
+ printf(" Kernel key algorithm: %" PRIu64 " %s\n",
+ kernel_subkey->algorithm,
+ (kernel_subkey->algorithm < kNumAlgorithms ?
+ algo_strings[kernel_subkey->algorithm] : "(invalid)"));
+ printf(" Kernel key version: %" PRIu64 "\n",
+ kernel_subkey->key_version);
+ printf(" Kernel key sha1sum: ");
+ PrintPubKeySha1Sum(kernel_subkey);
+ printf("\n");
+ printf(" Firmware body size: %" PRIu64 "\n",
+ preamble->body_signature.data_size);
+ printf(" Preamble flags: %" PRIu32 "\n", flags);
+
+ /* TODO: verify body size same as signature size */
+
+ /* Verify body */
+ if (flags & VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) {
+ printf
+ ("Preamble requests USE_RO_NORMAL;"
+ " skipping body verification.\n");
+ } else {
+ if (0 !=
+ VerifyData(fv_data, fv_size, &preamble->body_signature,
+ rsa)) {
+ VbExError("Error verifying firmware body.\n");
+ return 1;
+ }
+ printf("Body verification succeeded.\n");
+ }
+
+ if (kernelkey_file) {
+ if (0 != PublicKeyWrite(kernelkey_file, kernel_subkey)) {
+ VbExError("Unable to write kernel subkey\n");
+ return 1;
+ }
+ }
+
+ return 0;
}
-
-static int do_vbutil_firmware(int argc, char* argv[]) {
-
- char* filename = NULL;
- char* key_block_file = NULL;
- char* signpubkey = NULL;
- char* signprivate = NULL;
- uint64_t version = 0;
- char* fv_file = NULL;
- char* kernelkey_file = NULL;
- uint32_t preamble_flags = 0;
- int mode = 0;
- int parse_error = 0;
- char* e;
- int i;
-
- while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
- switch (i) {
- case '?':
- /* Unhandled option */
- printf("Unknown option\n");
- parse_error = 1;
- break;
-
- case OPT_MODE_VBLOCK:
- case OPT_MODE_VERIFY:
- mode = i;
- filename = optarg;
- break;
-
- case OPT_KEYBLOCK:
- key_block_file = optarg;
- break;
-
- case OPT_SIGNPUBKEY:
- signpubkey = optarg;
- break;
-
- case OPT_SIGNPRIVATE:
- signprivate = optarg;
- break;
-
- case OPT_FV:
- fv_file = optarg;
- break;
-
- case OPT_KERNELKEY:
- kernelkey_file = optarg;
- break;
-
- case OPT_VERSION:
- version = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- printf("Invalid --version\n");
- parse_error = 1;
- }
- break;
-
- case OPT_FLAGS:
- preamble_flags = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- printf("Invalid --flags\n");
- parse_error = 1;
- }
- break;
- }
- }
-
- if (parse_error)
- return PrintHelp();
-
- switch(mode) {
- case OPT_MODE_VBLOCK:
- return Vblock(filename, key_block_file, signprivate, version, fv_file,
- kernelkey_file, preamble_flags);
- case OPT_MODE_VERIFY:
- return Verify(filename, signpubkey, fv_file, kernelkey_file);
- default:
- printf("Must specify a mode.\n");
- return PrintHelp();
- }
+static int do_vbutil_firmware(int argc, char *argv[])
+{
+
+ char *filename = NULL;
+ char *key_block_file = NULL;
+ char *signpubkey = NULL;
+ char *signprivate = NULL;
+ uint64_t version = 0;
+ char *fv_file = NULL;
+ char *kernelkey_file = NULL;
+ uint32_t preamble_flags = 0;
+ int mode = 0;
+ int parse_error = 0;
+ char *e;
+ int i;
+
+ while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
+ switch (i) {
+ case '?':
+ /* Unhandled option */
+ printf("Unknown option\n");
+ parse_error = 1;
+ break;
+
+ case OPT_MODE_VBLOCK:
+ case OPT_MODE_VERIFY:
+ mode = i;
+ filename = optarg;
+ break;
+
+ case OPT_KEYBLOCK:
+ key_block_file = optarg;
+ break;
+
+ case OPT_SIGNPUBKEY:
+ signpubkey = optarg;
+ break;
+
+ case OPT_SIGNPRIVATE:
+ signprivate = optarg;
+ break;
+
+ case OPT_FV:
+ fv_file = optarg;
+ break;
+
+ case OPT_KERNELKEY:
+ kernelkey_file = optarg;
+ break;
+
+ case OPT_VERSION:
+ version = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ printf("Invalid --version\n");
+ parse_error = 1;
+ }
+ break;
+
+ case OPT_FLAGS:
+ preamble_flags = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ printf("Invalid --flags\n");
+ parse_error = 1;
+ }
+ break;
+ }
+ }
+
+ if (parse_error)
+ return PrintHelp();
+
+ switch (mode) {
+ case OPT_MODE_VBLOCK:
+ return Vblock(filename, key_block_file, signprivate, version,
+ fv_file, kernelkey_file, preamble_flags);
+ case OPT_MODE_VERIFY:
+ return Verify(filename, signpubkey, fv_file, kernelkey_file);
+ default:
+ printf("Must specify a mode.\n");
+ return PrintHelp();
+ }
}
DECLARE_FUTIL_COMMAND(vbutil_firmware, do_vbutil_firmware,
diff --git a/futility/cmd_vbutil_kernel.c b/futility/cmd_vbutil_kernel.c
index 420e3b57..ebb4510e 100644
--- a/futility/cmd_vbutil_kernel.c
+++ b/futility/cmd_vbutil_kernel.c
@@ -8,9 +8,9 @@
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
-#include <inttypes.h> /* For PRIu64 */
+#include <inttypes.h> /* For PRIu64 */
#include <sys/ioctl.h>
-#include <linux/fs.h> /* For BLKGETSIZE64 */
+#include <linux/fs.h> /* For BLKGETSIZE64 */
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
@@ -33,181 +33,183 @@ static int opt_verbose = 0;
static int opt_vblockonly = 0;
static uint64_t opt_pad = 65536;
-
/* Command line options */
enum {
- OPT_MODE_PACK = 1000,
- OPT_MODE_REPACK,
- OPT_MODE_VERIFY,
- OPT_ARCH,
- OPT_OLDBLOB,
- OPT_KLOADADDR,
- OPT_KEYBLOCK,
- OPT_SIGNPUBKEY,
- OPT_SIGNPRIVATE,
- OPT_VERSION,
- OPT_VMLINUZ,
- OPT_BOOTLOADER,
- OPT_CONFIG,
- OPT_VBLOCKONLY,
- OPT_PAD,
- OPT_VERBOSE,
- OPT_MINVERSION,
+ OPT_MODE_PACK = 1000,
+ OPT_MODE_REPACK,
+ OPT_MODE_VERIFY,
+ OPT_ARCH,
+ OPT_OLDBLOB,
+ OPT_KLOADADDR,
+ OPT_KEYBLOCK,
+ OPT_SIGNPUBKEY,
+ OPT_SIGNPRIVATE,
+ OPT_VERSION,
+ OPT_VMLINUZ,
+ OPT_BOOTLOADER,
+ OPT_CONFIG,
+ OPT_VBLOCKONLY,
+ OPT_PAD,
+ OPT_VERBOSE,
+ OPT_MINVERSION,
};
typedef enum {
- ARCH_ARM,
- ARCH_X86, /* default */
- ARCH_MIPS
+ ARCH_ARM,
+ ARCH_X86, /* default */
+ ARCH_MIPS
} arch_t;
static const struct option long_opts[] = {
- {"pack", 1, 0, OPT_MODE_PACK },
- {"repack", 1, 0, OPT_MODE_REPACK },
- {"verify", 1, 0, OPT_MODE_VERIFY },
- {"arch", 1, 0, OPT_ARCH },
- {"oldblob", 1, 0, OPT_OLDBLOB },
- {"kloadaddr", 1, 0, OPT_KLOADADDR },
- {"keyblock", 1, 0, OPT_KEYBLOCK },
- {"signpubkey", 1, 0, OPT_SIGNPUBKEY },
- {"signprivate", 1, 0, OPT_SIGNPRIVATE },
- {"version", 1, 0, OPT_VERSION },
- {"minversion", 1, 0, OPT_MINVERSION },
- {"vmlinuz", 1, 0, OPT_VMLINUZ },
- {"bootloader", 1, 0, OPT_BOOTLOADER },
- {"config", 1, 0, OPT_CONFIG },
- {"vblockonly", 0, 0, OPT_VBLOCKONLY },
- {"pad", 1, 0, OPT_PAD },
- {"verbose", 0, &opt_verbose, 1 },
- {"debug", 0, &opt_debug, 1 },
- {NULL, 0, 0, 0}
+ {"pack", 1, 0, OPT_MODE_PACK},
+ {"repack", 1, 0, OPT_MODE_REPACK},
+ {"verify", 1, 0, OPT_MODE_VERIFY},
+ {"arch", 1, 0, OPT_ARCH},
+ {"oldblob", 1, 0, OPT_OLDBLOB},
+ {"kloadaddr", 1, 0, OPT_KLOADADDR},
+ {"keyblock", 1, 0, OPT_KEYBLOCK},
+ {"signpubkey", 1, 0, OPT_SIGNPUBKEY},
+ {"signprivate", 1, 0, OPT_SIGNPRIVATE},
+ {"version", 1, 0, OPT_VERSION},
+ {"minversion", 1, 0, OPT_MINVERSION},
+ {"vmlinuz", 1, 0, OPT_VMLINUZ},
+ {"bootloader", 1, 0, OPT_BOOTLOADER},
+ {"config", 1, 0, OPT_CONFIG},
+ {"vblockonly", 0, 0, OPT_VBLOCKONLY},
+ {"pad", 1, 0, OPT_PAD},
+ {"verbose", 0, &opt_verbose, 1},
+ {"debug", 0, &opt_debug, 1},
+ {NULL, 0, 0, 0}
};
+
+static const char usage[] =
+ "This program creates, signs, and verifies the kernel blob\n"
+ "\n"
+ "Usage: %s --pack <file> [PARAMETERS]\n"
+ "\n"
+ " Required parameters:\n"
+ " --keyblock <file> Key block in .keyblock format\n"
+ " --signprivate <file> Private key to sign kernel data,\n"
+ " in .vbprivk format\n"
+ " --version <number> Kernel version\n"
+ " --vmlinuz <file> Linux kernel bzImage file\n"
+ " --bootloader <file> Bootloader stub\n"
+ " --config <file> Command line file\n"
+ " --arch <arch> Cpu architecture (default x86)\n"
+ "\n"
+ " Optional:\n"
+ " --kloadaddr <address> Assign kernel body load address\n"
+ " --pad <number> Verification padding size in bytes\n"
+ " --vblockonly Emit just the verification blob\n"
+ "\nOR\n\n"
+ "Usage: %s --repack <file> [PARAMETERS]\n"
+ "\n"
+ " Required parameters:\n"
+ " --signprivate <file> Private key to sign kernel data,\n"
+ " in .vbprivk format\n"
+ " --oldblob <file> Previously packed kernel blob\n"
+ " (including verfication blob)\n"
+ "\n"
+ " Optional:\n"
+ " --keyblock <file> Key block in .keyblock format\n"
+ " --config <file> New command line file\n"
+ " --version <number> Kernel version\n"
+ " --kloadaddr <address> Assign kernel body load address\n"
+ " --pad <number> Verification blob size in bytes\n"
+ " --vblockonly Emit just the verification blob\n"
+ "\nOR\n\n"
+ "Usage: %s --verify <file> [PARAMETERS]\n"
+ "\n"
+ " Optional:\n"
+ " --signpubkey <file>"
+ " Public key to verify kernel keyblock,\n"
+ " in .vbpubk format\n"
+ " --verbose Print a more detailed report\n"
+ " --keyblock <file> Outputs the verified key block,\n"
+ " in .keyblock format\n"
+ " --pad <number> Verification padding size in bytes\n"
+ " --minversion <number> Minimum combined kernel key version\n"
+ " and kernel version\n"
+ "\n";
+
+
/* Print help and return error */
-static int PrintHelp(char *progname) {
- fprintf(stderr,
- "This program creates, signs, and verifies the kernel blob\n");
- fprintf(stderr,
- "\n"
- "Usage: %s --pack <file> [PARAMETERS]\n"
- "\n"
- " Required parameters:\n"
- " --keyblock <file> Key block in .keyblock format\n"
- " --signprivate <file> Private key to sign kernel data,\n"
- " in .vbprivk format\n"
- " --version <number> Kernel version\n"
- " --vmlinuz <file> Linux kernel bzImage file\n"
- " --bootloader <file> Bootloader stub\n"
- " --config <file> Command line file\n"
- " --arch <arch> Cpu architecture (default x86)\n"
- "\n"
- " Optional:\n"
- " --kloadaddr <address> Assign kernel body load address\n"
- " --pad <number> Verification padding size in bytes\n"
- " --vblockonly Emit just the verification blob\n",
- progname);
- fprintf(stderr,
- "\nOR\n\n"
- "Usage: %s --repack <file> [PARAMETERS]\n"
- "\n"
- " Required parameters:\n"
- " --signprivate <file> Private key to sign kernel data,\n"
- " in .vbprivk format\n"
- " --oldblob <file> Previously packed kernel blob\n"
- " (including verfication blob)\n"
- "\n"
- " Optional:\n"
- " --keyblock <file> Key block in .keyblock format\n"
- " --config <file> New command line file\n"
- " --version <number> Kernel version\n"
- " --kloadaddr <address> Assign kernel body load address\n"
- " --pad <number> Verification blob size in bytes\n"
- " --vblockonly Emit just the verification blob\n",
- progname);
- fprintf(stderr,
- "\nOR\n\n"
- "Usage: %s --verify <file> [PARAMETERS]\n"
- "\n"
- " Optional:\n"
- " --signpubkey <file>"
- " Public key to verify kernel keyblock,\n"
- " in .vbpubk format\n"
- " --verbose Print a more detailed report\n"
- " --keyblock <file> Outputs the verified key block,\n"
- " in .keyblock format\n"
- " --pad <number> Verification padding size in bytes\n"
- " --minversion <number> Minimum combined kernel key version\n"
- " and kernel version\n"
- "\n",
- progname);
- return 1;
+static int PrintHelp(char *progname)
+{
+ fprintf(stderr, usage, progname, progname, progname);
+ return 1;
}
-static void Debug(const char *format, ...) {
- if (!opt_debug)
- return;
-
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "DEBUG: ");
- vfprintf(stderr, format, ap);
- va_end(ap);
+static void Debug(const char *format, ...)
+{
+ if (!opt_debug)
+ return;
+
+ va_list ap;
+ va_start(ap, format);
+ fprintf(stderr, "DEBUG: ");
+ vfprintf(stderr, format, ap);
+ va_end(ap);
}
-static void Fatal(const char *format, ...) {
- va_list ap;
- va_start(ap, format);
- fprintf(stderr, "ERROR: ");
- vfprintf(stderr, format, ap);
- va_end(ap);
- exit(1);
+static void Fatal(const char *format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ fprintf(stderr, "ERROR: ");
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ exit(1);
}
/* Return an explanation when fread() fails. */
-static const char *error_fread(FILE *fp) {
- const char *retval = "beats me why";
- if (feof(fp))
- retval = "EOF";
- else if (ferror(fp))
- retval = strerror(errno);
- clearerr(fp);
- return retval;
+static const char *error_fread(FILE * fp)
+{
+ const char *retval = "beats me why";
+ if (feof(fp))
+ retval = "EOF";
+ else if (ferror(fp))
+ retval = strerror(errno);
+ clearerr(fp);
+ return retval;
}
/* Return the smallest integral multiple of [alignment] that is equal
* to or greater than [val]. Used to determine the number of
* pages/sectors/blocks/whatever needed to contain [val]
* items/bytes/etc. */
-static uint64_t roundup(uint64_t val, uint64_t alignment) {
- uint64_t rem = val % alignment;
- if ( rem )
- return val + (alignment - rem);
- return val;
+static uint64_t roundup(uint64_t val, uint64_t alignment)
+{
+ uint64_t rem = val % alignment;
+ if (rem)
+ return val + (alignment - rem);
+ return val;
}
-
/* Match regexp /\b--\b/ to delimit the start of the kernel commandline. If we
* don't find one, we'll use the whole thing. */
-static unsigned int find_cmdline_start(char *input, unsigned int max_len) {
- int start = 0;
- int i;
- for(i = 0; i < max_len - 1 && input[i]; i++) {
- if ('-' == input[i] && '-' == input[i + 1]) { /* found a "--" */
- if ((i == 0 || ' ' == input[i - 1]) && /* nothing before it */
- (i + 2 >= max_len || ' ' == input[i+2])) { /* nothing after it */
- start = i+2; /* note: hope there's a trailing '\0' */
- break;
- }
- }
- }
- while(' ' == input[start]) /* skip leading spaces */
- start++;
-
- return start;
+static unsigned int find_cmdline_start(char *input, unsigned int max_len)
+{
+ int start = 0;
+ int i;
+ for (i = 0; i < max_len - 1 && input[i]; i++) {
+ if ('-' == input[i] && '-' == input[i + 1]) {
+ if ((i == 0 || ' ' == input[i - 1]) &&
+ (i + 2 >= max_len || ' ' == input[i + 2])) {
+ /* found "--" with nothing before or after it */
+ start = i + 2; /* hope for a trailing '\0' */
+ break;
+ }
+ }
+ }
+ while (' ' == input[start]) /* skip leading spaces */
+ start++;
+
+ return start;
}
-
/****************************************************************************/
/* Here are globals containing all the bits & pieces I'm working on. */
@@ -222,11 +224,10 @@ static uint8_t *g_bootloader_data;
static uint64_t g_bootloader_size;
static uint64_t g_bootloader_address;
-
/* The individual parts of the verification blob (including the data that
* immediately follows the headers) */
-static VbKeyBlockHeader* g_keyblock;
-static VbKernelPreambleHeader* g_preamble;
+static VbKeyBlockHeader *g_keyblock;
+static VbKernelPreambleHeader *g_preamble;
/****************************************************************************/
@@ -237,736 +238,760 @@ static VbKernelPreambleHeader* g_preamble;
* Return the buffer contaning the line on success (and set the line length
* using the passed in parameter), or NULL in case something goes wrong.
*/
-static uint8_t* ReadConfigFile(const char* config_file, uint64_t* config_size)
+static uint8_t *ReadConfigFile(const char *config_file, uint64_t * config_size)
{
- uint8_t* config_buf;
- int ii;
-
- config_buf = ReadFile(config_file, config_size);
- Debug(" config file size=0x%" PRIx64 "\n", *config_size);
- if (CROS_CONFIG_SIZE <= *config_size) { /* need room for trailing '\0' */
- VbExError("Config file %s is too large (>= %d bytes)\n",
- config_file, CROS_CONFIG_SIZE);
- return NULL;
- }
-
- /* Replace newlines with spaces */
- for (ii = 0; ii < *config_size; ii++) {
- if ('\n' == config_buf[ii]) {
- config_buf[ii] = ' ';
- }
- }
- return config_buf;
+ uint8_t *config_buf;
+ int ii;
+
+ config_buf = ReadFile(config_file, config_size);
+ Debug(" config file size=0x%" PRIx64 "\n", *config_size);
+ if (CROS_CONFIG_SIZE <= *config_size) { /* room for trailing '\0' */
+ VbExError("Config file %s is too large (>= %d bytes)\n",
+ config_file, CROS_CONFIG_SIZE);
+ return NULL;
+ }
+
+ /* Replace newlines with spaces */
+ for (ii = 0; ii < *config_size; ii++) {
+ if ('\n' == config_buf[ii]) {
+ config_buf[ii] = ' ';
+ }
+ }
+ return config_buf;
}
-
/* Offset of kernel command line string from start of packed kernel blob */
-static uint64_t CmdLineOffset(VbKernelPreambleHeader *preamble) {
- return preamble->bootloader_address - preamble->body_load_address -
- CROS_CONFIG_SIZE - CROS_PARAMS_SIZE;
+static uint64_t CmdLineOffset(VbKernelPreambleHeader * preamble)
+{
+ return preamble->bootloader_address - preamble->body_load_address -
+ CROS_CONFIG_SIZE - CROS_PARAMS_SIZE;
}
/* This initializes g_vmlinuz and g_param from a standard vmlinuz file.
* It returns 0 on error. */
static int ImportVmlinuzFile(const char *vmlinuz_file, arch_t arch,
- uint64_t kernel_body_load_address) {
- uint8_t *kernel_buf;
- uint64_t kernel_size;
- uint64_t kernel32_start = 0;
- uint64_t kernel32_size = 0;
- struct linux_kernel_params *params = NULL, *lh = NULL;
-
- /* Read the kernel */
- Debug("Reading %s\n", vmlinuz_file);
- kernel_buf = ReadFile(vmlinuz_file, &kernel_size);
- if (!kernel_buf)
- return 0;
- Debug(" kernel file size=0x%" PRIx64 "\n", kernel_size);
- if (!kernel_size)
- Fatal("Empty kernel file\n");
-
- /* Go ahead and allocate the param region anyway. I don't think we need it
- * for non-x86, but let's keep it for now. */
- g_param_size = CROS_PARAMS_SIZE;
- g_param_data= VbExMalloc(g_param_size);
- Memset(g_param_data, 0, g_param_size);
-
- /* Unless we're handling x86, the kernel is the kernel, so we're done. */
- if (arch != ARCH_X86) {
- g_kernel_data = kernel_buf;
- g_kernel_size = kernel_size;
- return 1;
- }
-
- /* The first part of the x86 vmlinuz is a header, followed by a real-mode
- * boot stub. We only want the 32-bit part. */
- lh = (struct linux_kernel_params *)kernel_buf;
- kernel32_start = (lh->setup_sects + 1) << 9;
- if (kernel32_start >= kernel_size)
- Fatal("Malformed kernel\n");
- kernel32_size = kernel_size - kernel32_start;
-
- Debug(" kernel32_start=0x%" PRIx64 "\n", kernel32_start);
- Debug(" kernel32_size=0x%" PRIx64 "\n", kernel32_size);
-
- /* Keep just the 32-bit kernel. */
- if (kernel32_size) {
- g_kernel_size = kernel32_size;
- g_kernel_data = VbExMalloc(g_kernel_size);
- Memcpy(g_kernel_data, kernel_buf + kernel32_start, kernel32_size);
- }
-
- /* Copy the original zeropage data from kernel_buf into g_param_data, then
- * tweak a few fields for our purposes */
- params = (struct linux_kernel_params *)(g_param_data);
- Memcpy(&(params->setup_sects), &(lh->setup_sects),
- offsetof(struct linux_kernel_params, e820_entries)
- - offsetof(struct linux_kernel_params, setup_sects));
- params->boot_flag = 0;
- params->ramdisk_image = 0; /* we don't support initrd */
- params->ramdisk_size = 0;
- params->type_of_loader = 0xff;
- /* We need to point to the kernel commandline arg. On disk, it will come
- * right after the 32-bit part of the kernel. */
- params->cmd_line_ptr = kernel_body_load_address +
- roundup(kernel32_size, CROS_ALIGN) +
- find_cmdline_start((char *)g_config_data, g_config_size);
- Debug(" cmdline_addr=0x%x\n", params->cmd_line_ptr);
- Debug(" version=0x%x\n", params->version);
- Debug(" kernel_alignment=0x%x\n", params->kernel_alignment);
- Debug(" relocatable_kernel=0x%x\n", params->relocatable_kernel);
- /* A fake e820 memory map with 2 entries */
- params->n_e820_entry = 2;
- params->e820_entries[0].start_addr = 0x00000000;
- params->e820_entries[0].segment_size = 0x00001000;
- params->e820_entries[0].segment_type = E820_TYPE_RAM;
- params->e820_entries[1].start_addr = 0xfffff000;
- params->e820_entries[1].segment_size = 0x00001000;
- params->e820_entries[1].segment_type = E820_TYPE_RESERVED;
-
- /* done */
- free(kernel_buf);
- return 1;
+ uint64_t kernel_body_load_address)
+{
+ uint8_t *kernel_buf;
+ uint64_t kernel_size;
+ uint64_t kernel32_start = 0;
+ uint64_t kernel32_size = 0;
+ struct linux_kernel_params *params = NULL, *lh = NULL;
+
+ /* Read the kernel */
+ Debug("Reading %s\n", vmlinuz_file);
+ kernel_buf = ReadFile(vmlinuz_file, &kernel_size);
+ if (!kernel_buf)
+ return 0;
+ Debug(" kernel file size=0x%" PRIx64 "\n", kernel_size);
+ if (!kernel_size)
+ Fatal("Empty kernel file\n");
+
+ /* Go ahead and allocate the param region anyway. I don't think we need
+ * it for non-x86, but let's keep it for now. */
+ g_param_size = CROS_PARAMS_SIZE;
+ g_param_data = VbExMalloc(g_param_size);
+ Memset(g_param_data, 0, g_param_size);
+
+ /* Unless we're handling x86, the kernel is the kernel; we're done. */
+ if (arch != ARCH_X86) {
+ g_kernel_data = kernel_buf;
+ g_kernel_size = kernel_size;
+ return 1;
+ }
+
+ /* The first part of the x86 vmlinuz is a header, followed by a
+ * real-mode boot stub. We only want the 32-bit part. */
+ lh = (struct linux_kernel_params *)kernel_buf;
+ kernel32_start = (lh->setup_sects + 1) << 9;
+ if (kernel32_start >= kernel_size)
+ Fatal("Malformed kernel\n");
+ kernel32_size = kernel_size - kernel32_start;
+
+ Debug(" kernel32_start=0x%" PRIx64 "\n", kernel32_start);
+ Debug(" kernel32_size=0x%" PRIx64 "\n", kernel32_size);
+
+ /* Keep just the 32-bit kernel. */
+ if (kernel32_size) {
+ g_kernel_size = kernel32_size;
+ g_kernel_data = VbExMalloc(g_kernel_size);
+ Memcpy(g_kernel_data, kernel_buf + kernel32_start,
+ kernel32_size);
+ }
+
+ /* Copy the original zeropage data from kernel_buf into g_param_data,
+ * then tweak a few fields for our purposes */
+ params = (struct linux_kernel_params *)(g_param_data);
+ Memcpy(&(params->setup_sects), &(lh->setup_sects),
+ offsetof(struct linux_kernel_params, e820_entries)
+ - offsetof(struct linux_kernel_params, setup_sects));
+ params->boot_flag = 0;
+ params->ramdisk_image = 0; /* we don't support initrd */
+ params->ramdisk_size = 0;
+ params->type_of_loader = 0xff;
+ /* We need to point to the kernel commandline arg. On disk, it will come
+ * right after the 32-bit part of the kernel. */
+ params->cmd_line_ptr = kernel_body_load_address +
+ roundup(kernel32_size, CROS_ALIGN) +
+ find_cmdline_start((char *)g_config_data, g_config_size);
+ Debug(" cmdline_addr=0x%x\n", params->cmd_line_ptr);
+ Debug(" version=0x%x\n", params->version);
+ Debug(" kernel_alignment=0x%x\n", params->kernel_alignment);
+ Debug(" relocatable_kernel=0x%x\n", params->relocatable_kernel);
+ /* A fake e820 memory map with 2 entries */
+ params->n_e820_entry = 2;
+ params->e820_entries[0].start_addr = 0x00000000;
+ params->e820_entries[0].segment_size = 0x00001000;
+ params->e820_entries[0].segment_type = E820_TYPE_RAM;
+ params->e820_entries[1].start_addr = 0xfffff000;
+ params->e820_entries[1].segment_size = 0x00001000;
+ params->e820_entries[1].segment_type = E820_TYPE_RESERVED;
+
+ /* done */
+ free(kernel_buf);
+ return 1;
}
/* This returns just the kernel blob, with the verification blob separated
* and copied to new memory in g_keyblock and g_preamble. */
-static uint8_t* ReadOldBlobFromFileOrDie(const char *filename,
- uint64_t* size_ptr) {
- FILE* fp = NULL;
- struct stat statbuf;
- VbKeyBlockHeader* key_block;
- VbKernelPreambleHeader* preamble;
- uint64_t now = 0;
- uint8_t* buf;
- uint8_t* kernel_blob_data;
- uint64_t kernel_blob_size;
- uint64_t file_size = 0;
-
- if (0 != stat(filename, &statbuf))
- Fatal("Unable to stat %s: %s\n", filename, strerror(errno));
-
- if (S_ISBLK(statbuf.st_mode)) {
- int fd;
-
- if ((fd = open(filename, O_RDONLY)) >= 0) {
- ioctl(fd, BLKGETSIZE64, &file_size);
- close(fd);
- }
- } else {
- file_size = statbuf.st_size;
- }
- Debug("%s size is 0x%" PRIx64 "\n", filename, file_size);
- if (file_size < opt_pad)
- Fatal("%s is too small to be a valid kernel blob\n");
-
- Debug("Reading %s\n", filename);
- fp = fopen(filename, "rb");
- if (!fp)
- Fatal("Unable to open file %s: %s\n", filename, strerror(errno));
-
- buf = VbExMalloc(opt_pad);
- if (1 != fread(buf, opt_pad, 1, fp))
- Fatal("Unable to read header from %s: %s\n", filename, error_fread(fp));
-
- /* Sanity-check the key_block */
- key_block = (VbKeyBlockHeader*)buf;
- Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
- now += key_block->key_block_size;
- if (now > file_size)
- Fatal("key_block_size advances past the end of the blob\n");
- if (now > opt_pad)
- Fatal("key_block_size advances past %" PRIu64 " byte padding\n",
- opt_pad);
- /* LGTM */
- g_keyblock = (VbKeyBlockHeader*)VbExMalloc(key_block->key_block_size);
- Memcpy(g_keyblock, key_block, key_block->key_block_size);
-
- /* And the preamble */
- preamble = (VbKernelPreambleHeader*)(buf + now);
- Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
- now += preamble->preamble_size;
- if (now > file_size)
- Fatal("preamble_size advances past the end of the blob\n");
- if (now > opt_pad)
- Fatal("preamble_size advances past %" PRIu64 " byte padding\n",
- opt_pad);
- /* LGTM */
- Debug(" kernel_version = %d\n", preamble->kernel_version);
- Debug(" bootloader_address = 0x%" PRIx64 "\n", preamble->bootloader_address);
- Debug(" bootloader_size = 0x%" PRIx64 "\n", preamble->bootloader_size);
- Debug(" kern_blob_size = 0x%" PRIx64 "\n",
- preamble->body_signature.data_size);
- g_preamble = (VbKernelPreambleHeader*)VbExMalloc(preamble->preamble_size);
- Memcpy(g_preamble, preamble, preamble->preamble_size);
-
- /* Now for the kernel blob */
- Debug("kernel blob is at offset 0x%" PRIx64 "\n", now);
- if (0 != fseek(fp, now, SEEK_SET))
- Fatal("Unable to seek to 0x%" PRIx64 " in %s: %s\n", now, filename,
- strerror(errno));
-
- /* Sanity check */
- kernel_blob_size = file_size - now;
- if (!kernel_blob_size)
- Fatal("No kernel blob found\n");
- if (kernel_blob_size < preamble->body_signature.data_size)
- fprintf(stderr, "Warning: kernel file only has 0x%" PRIx64 " bytes\n",
- kernel_blob_size);
- kernel_blob_data = VbExMalloc(kernel_blob_size);
-
- /* Read it in */
- if (1 != fread(kernel_blob_data, kernel_blob_size, 1, fp))
- Fatal("Unable to read kernel blob from %s: %s\n", filename,
- error_fread(fp));
-
- /* Done */
- VbExFree(buf);
-
- if (size_ptr)
- *size_ptr = kernel_blob_size;
-
- return kernel_blob_data;
+static uint8_t *ReadOldBlobFromFileOrDie(const char *filename,
+ uint64_t * size_ptr)
+{
+ FILE *fp = NULL;
+ struct stat statbuf;
+ VbKeyBlockHeader *key_block;
+ VbKernelPreambleHeader *preamble;
+ uint64_t now = 0;
+ uint8_t *buf;
+ uint8_t *kernel_blob_data;
+ uint64_t kernel_blob_size;
+ uint64_t file_size = 0;
+
+ if (0 != stat(filename, &statbuf))
+ Fatal("Unable to stat %s: %s\n", filename, strerror(errno));
+
+ if (S_ISBLK(statbuf.st_mode)) {
+ int fd;
+
+ if ((fd = open(filename, O_RDONLY)) >= 0) {
+ ioctl(fd, BLKGETSIZE64, &file_size);
+ close(fd);
+ }
+ } else {
+ file_size = statbuf.st_size;
+ }
+ Debug("%s size is 0x%" PRIx64 "\n", filename, file_size);
+ if (file_size < opt_pad)
+ Fatal("%s is too small to be a valid kernel blob\n");
+
+ Debug("Reading %s\n", filename);
+ fp = fopen(filename, "rb");
+ if (!fp)
+ Fatal("Unable to open file %s: %s\n", filename,
+ strerror(errno));
+
+ buf = VbExMalloc(opt_pad);
+ if (1 != fread(buf, opt_pad, 1, fp))
+ Fatal("Unable to read header from %s: %s\n", filename,
+ error_fread(fp));
+
+ /* Sanity-check the key_block */
+ key_block = (VbKeyBlockHeader *) buf;
+ Debug("Keyblock is 0x%" PRIx64 " bytes\n", key_block->key_block_size);
+ now += key_block->key_block_size;
+ if (now > file_size)
+ Fatal("key_block_size advances past the end of the blob\n");
+ if (now > opt_pad)
+ Fatal("key_block_size advances past %" PRIu64 " byte padding\n",
+ opt_pad);
+ /* LGTM */
+ g_keyblock = (VbKeyBlockHeader *) VbExMalloc(key_block->key_block_size);
+ Memcpy(g_keyblock, key_block, key_block->key_block_size);
+
+ /* And the preamble */
+ preamble = (VbKernelPreambleHeader *) (buf + now);
+ Debug("Preamble is 0x%" PRIx64 " bytes\n", preamble->preamble_size);
+ now += preamble->preamble_size;
+ if (now > file_size)
+ Fatal("preamble_size advances past the end of the blob\n");
+ if (now > opt_pad)
+ Fatal("preamble_size advances past %" PRIu64 " byte padding\n",
+ opt_pad);
+ /* LGTM */
+ Debug(" kernel_version = %d\n", preamble->kernel_version);
+ Debug(" bootloader_address = 0x%" PRIx64 "\n",
+ preamble->bootloader_address);
+ Debug(" bootloader_size = 0x%" PRIx64 "\n", preamble->bootloader_size);
+ Debug(" kern_blob_size = 0x%" PRIx64 "\n",
+ preamble->body_signature.data_size);
+ g_preamble =
+ (VbKernelPreambleHeader *) VbExMalloc(preamble->preamble_size);
+ Memcpy(g_preamble, preamble, preamble->preamble_size);
+
+ /* Now for the kernel blob */
+ Debug("kernel blob is at offset 0x%" PRIx64 "\n", now);
+ if (0 != fseek(fp, now, SEEK_SET))
+ Fatal("Unable to seek to 0x%" PRIx64 " in %s: %s\n", now,
+ filename, strerror(errno));
+
+ /* Sanity check */
+ kernel_blob_size = file_size - now;
+ if (!kernel_blob_size)
+ Fatal("No kernel blob found\n");
+ if (kernel_blob_size < preamble->body_signature.data_size)
+ fprintf(stderr,
+ "Warning: kernel file only has 0x%" PRIx64 " bytes\n",
+ kernel_blob_size);
+ kernel_blob_data = VbExMalloc(kernel_blob_size);
+
+ /* Read it in */
+ if (1 != fread(kernel_blob_data, kernel_blob_size, 1, fp))
+ Fatal("Unable to read kernel blob from %s: %s\n", filename,
+ error_fread(fp));
+
+ /* Done */
+ VbExFree(buf);
+
+ if (size_ptr)
+ *size_ptr = kernel_blob_size;
+
+ return kernel_blob_data;
}
-
/* Split a kernel blob into separate g_kernel, g_param, g_config, and
* g_bootloader parts. */
-static void UnpackKernelBlob(uint8_t *kernel_blob_data,
- uint64_t kernel_blob_size) {
-
- uint64_t k_blob_size = g_preamble->body_signature.data_size;
- uint64_t k_blob_ofs = 0;
- uint64_t b_size = g_preamble->bootloader_size;
- uint64_t b_ofs = k_blob_ofs + g_preamble->bootloader_address -
- g_preamble->body_load_address;
- uint64_t p_ofs = b_ofs - CROS_CONFIG_SIZE;
- uint64_t c_ofs = p_ofs - CROS_PARAMS_SIZE;
-
- Debug("k_blob_size = 0x%" PRIx64 "\n", k_blob_size );
- Debug("k_blob_ofs = 0x%" PRIx64 "\n", k_blob_ofs );
- Debug("b_size = 0x%" PRIx64 "\n", b_size );
- Debug("b_ofs = 0x%" PRIx64 "\n", b_ofs );
- Debug("p_ofs = 0x%" PRIx64 "\n", p_ofs );
- Debug("c_ofs = 0x%" PRIx64 "\n", c_ofs );
-
- g_kernel_size = c_ofs;
- g_kernel_data = VbExMalloc(g_kernel_size);
- Memcpy(g_kernel_data, kernel_blob_data, g_kernel_size);
-
- g_param_size = CROS_PARAMS_SIZE;
- g_param_data = VbExMalloc(g_param_size);
- Memcpy(g_param_data, kernel_blob_data + p_ofs, g_param_size);
-
- g_config_size = CROS_CONFIG_SIZE;
- g_config_data = VbExMalloc(g_config_size);
- Memcpy(g_config_data, kernel_blob_data + c_ofs, g_config_size);
-
- g_bootloader_size = b_size;
- g_bootloader_data = VbExMalloc(g_bootloader_size);
- Memcpy(g_bootloader_data, kernel_blob_data + b_ofs, g_bootloader_size);
-}
-
+static void UnpackKernelBlob(uint8_t * kernel_blob_data,
+ uint64_t kernel_blob_size)
+{
+ uint64_t k_blob_size = g_preamble->body_signature.data_size;
+ uint64_t k_blob_ofs = 0;
+ uint64_t b_size = g_preamble->bootloader_size;
+ uint64_t b_ofs = k_blob_ofs + g_preamble->bootloader_address -
+ g_preamble->body_load_address;
+ uint64_t p_ofs = b_ofs - CROS_CONFIG_SIZE;
+ uint64_t c_ofs = p_ofs - CROS_PARAMS_SIZE;
+
+ Debug("k_blob_size = 0x%" PRIx64 "\n", k_blob_size);
+ Debug("k_blob_ofs = 0x%" PRIx64 "\n", k_blob_ofs);
+ Debug("b_size = 0x%" PRIx64 "\n", b_size);
+ Debug("b_ofs = 0x%" PRIx64 "\n", b_ofs);
+ Debug("p_ofs = 0x%" PRIx64 "\n", p_ofs);
+ Debug("c_ofs = 0x%" PRIx64 "\n", c_ofs);
+
+ g_kernel_size = c_ofs;
+ g_kernel_data = VbExMalloc(g_kernel_size);
+ Memcpy(g_kernel_data, kernel_blob_data, g_kernel_size);
+
+ g_param_size = CROS_PARAMS_SIZE;
+ g_param_data = VbExMalloc(g_param_size);
+ Memcpy(g_param_data, kernel_blob_data + p_ofs, g_param_size);
+
+ g_config_size = CROS_CONFIG_SIZE;
+ g_config_data = VbExMalloc(g_config_size);
+ Memcpy(g_config_data, kernel_blob_data + c_ofs, g_config_size);
+
+ g_bootloader_size = b_size;
+ g_bootloader_data = VbExMalloc(g_bootloader_size);
+ Memcpy(g_bootloader_data, kernel_blob_data + b_ofs, g_bootloader_size);
+}
/****************************************************************************/
-static uint8_t* CreateKernelBlob(uint64_t kernel_body_load_address,
- arch_t arch,
- uint64_t *size_ptr) {
- uint8_t *kern_blob;
- uint64_t kern_blob_size;
- uint64_t now;
- uint64_t bootloader_size = roundup(g_bootloader_size, CROS_ALIGN);
-
- /* Put the kernel blob together */
- kern_blob_size = roundup(g_kernel_size, CROS_ALIGN) +
- CROS_CONFIG_SIZE + CROS_PARAMS_SIZE + bootloader_size;
- Debug("kern_blob_size=0x%" PRIx64 "\n", kern_blob_size);
- kern_blob = VbExMalloc(kern_blob_size);
- Memset(kern_blob, 0, kern_blob_size);
- now = 0;
-
- Debug("kernel goes at kern_blob+0x%" PRIx64 "\n", now);
-
- Memcpy(kern_blob+now, g_kernel_data, g_kernel_size);
- now += roundup(g_kernel_size, CROS_ALIGN);
-
- Debug("config goes at kern_blob+0x%" PRIx64 "\n", now);
- if (g_config_size)
- Memcpy(kern_blob + now, g_config_data, g_config_size);
- now += CROS_CONFIG_SIZE;
-
- Debug("params goes at kern_blob+0x%" PRIx64 "\n", now);
- if (g_param_size) {
- Memcpy(kern_blob + now, g_param_data, g_param_size);
- }
- now += CROS_PARAMS_SIZE;
-
- Debug("bootloader goes at kern_blob+0x%" PRIx64 "\n", now);
- g_bootloader_address = kernel_body_load_address + now;
- Debug(" bootloader_address=0x%" PRIx64 "\n", g_bootloader_address);
- Debug(" bootloader_size=0x%" PRIx64 "\n", bootloader_size);
- if (bootloader_size)
- Memcpy(kern_blob + now, g_bootloader_data, g_bootloader_size);
- now += bootloader_size;
- Debug("end of kern_blob at kern_blob+0x%" PRIx64 "\n", now);
-
- /* Done */
- if (size_ptr)
- *size_ptr = kern_blob_size;
-
- return kern_blob;
+static uint8_t *CreateKernelBlob(uint64_t kernel_body_load_address,
+ arch_t arch, uint64_t * size_ptr)
+{
+ uint8_t *kern_blob;
+ uint64_t kern_blob_size;
+ uint64_t now;
+ uint64_t bootloader_size = roundup(g_bootloader_size, CROS_ALIGN);
+
+ /* Put the kernel blob together */
+ kern_blob_size = roundup(g_kernel_size, CROS_ALIGN) +
+ CROS_CONFIG_SIZE + CROS_PARAMS_SIZE + bootloader_size;
+ Debug("kern_blob_size=0x%" PRIx64 "\n", kern_blob_size);
+ kern_blob = VbExMalloc(kern_blob_size);
+ Memset(kern_blob, 0, kern_blob_size);
+ now = 0;
+
+ Debug("kernel goes at kern_blob+0x%" PRIx64 "\n", now);
+
+ Memcpy(kern_blob + now, g_kernel_data, g_kernel_size);
+ now += roundup(g_kernel_size, CROS_ALIGN);
+
+ Debug("config goes at kern_blob+0x%" PRIx64 "\n", now);
+ if (g_config_size)
+ Memcpy(kern_blob + now, g_config_data, g_config_size);
+ now += CROS_CONFIG_SIZE;
+
+ Debug("params goes at kern_blob+0x%" PRIx64 "\n", now);
+ if (g_param_size) {
+ Memcpy(kern_blob + now, g_param_data, g_param_size);
+ }
+ now += CROS_PARAMS_SIZE;
+
+ Debug("bootloader goes at kern_blob+0x%" PRIx64 "\n", now);
+ g_bootloader_address = kernel_body_load_address + now;
+ Debug(" bootloader_address=0x%" PRIx64 "\n", g_bootloader_address);
+ Debug(" bootloader_size=0x%" PRIx64 "\n", bootloader_size);
+ if (bootloader_size)
+ Memcpy(kern_blob + now, g_bootloader_data, g_bootloader_size);
+ now += bootloader_size;
+ Debug("end of kern_blob at kern_blob+0x%" PRIx64 "\n", now);
+
+ /* Done */
+ if (size_ptr)
+ *size_ptr = kern_blob_size;
+
+ return kern_blob;
}
-static int Pack(const char* outfile,
- uint8_t *kernel_blob,
- uint64_t kernel_size,
- int version,
- uint64_t kernel_body_load_address,
- VbPrivateKey* signpriv_key) {
- VbSignature* body_sig;
- FILE* f;
- uint64_t i;
- uint64_t written = 0;
-
- /* Sign the kernel data */
- body_sig = CalculateSignature(kernel_blob, kernel_size, signpriv_key);
- if (!body_sig)
- Fatal("Error calculating body signature\n");
-
- /* Create preamble */
- g_preamble = CreateKernelPreamble(version,
- kernel_body_load_address,
- g_bootloader_address,
- roundup(g_bootloader_size, CROS_ALIGN),
- body_sig,
- opt_pad - g_keyblock->key_block_size,
- signpriv_key);
- if (!g_preamble) {
- VbExError("Error creating preamble.\n");
- return 1;
- }
- /* Write the output file */
- Debug("writing %s...\n", outfile);
- f = fopen(outfile, "wb");
- if (!f) {
- VbExError("Can't open output file %s\n", outfile);
- return 1;
- }
- Debug("0x%" PRIx64 " bytes of key_block\n", g_keyblock->key_block_size);
- Debug("0x%" PRIx64 " bytes of preamble\n", g_preamble->preamble_size);
- i = ((1 != fwrite(g_keyblock, g_keyblock->key_block_size, 1, f)) ||
- (1 != fwrite(g_preamble, g_preamble->preamble_size, 1, f)));
- if (i) {
- VbExError("Can't write output file %s\n", outfile);
- fclose(f);
- unlink(outfile);
- return 1;
- }
- written += g_keyblock->key_block_size;
- written += g_preamble->preamble_size;
-
- if (!opt_vblockonly) {
- Debug("0x%" PRIx64 " bytes of kern_blob\n", kernel_size);
- i = (1 != fwrite(kernel_blob, kernel_size, 1, f));
- if (i) {
- fclose(f);
- unlink(outfile);
- Fatal("Can't write output file %s\n", outfile);
- }
- written += kernel_size;
- }
- Debug("0x%" PRIx64 " bytes total\n", written);
- fclose(f);
-
- /* Success */
- return 0;
+static int Pack(const char *outfile,
+ uint8_t * kernel_blob,
+ uint64_t kernel_size,
+ int version,
+ uint64_t kernel_body_load_address, VbPrivateKey * signpriv_key)
+{
+ VbSignature *body_sig;
+ FILE *f;
+ uint64_t i;
+ uint64_t written = 0;
+
+ /* Sign the kernel data */
+ body_sig = CalculateSignature(kernel_blob, kernel_size, signpriv_key);
+ if (!body_sig)
+ Fatal("Error calculating body signature\n");
+
+ /* Create preamble */
+ g_preamble = CreateKernelPreamble(version,
+ kernel_body_load_address,
+ g_bootloader_address,
+ roundup(g_bootloader_size,
+ CROS_ALIGN), body_sig,
+ opt_pad - g_keyblock->key_block_size,
+ signpriv_key);
+ if (!g_preamble) {
+ VbExError("Error creating preamble.\n");
+ return 1;
+ }
+ /* Write the output file */
+ Debug("writing %s...\n", outfile);
+ f = fopen(outfile, "wb");
+ if (!f) {
+ VbExError("Can't open output file %s\n", outfile);
+ return 1;
+ }
+ Debug("0x%" PRIx64 " bytes of key_block\n", g_keyblock->key_block_size);
+ Debug("0x%" PRIx64 " bytes of preamble\n", g_preamble->preamble_size);
+ i = ((1 != fwrite(g_keyblock, g_keyblock->key_block_size, 1, f)) ||
+ (1 != fwrite(g_preamble, g_preamble->preamble_size, 1, f)));
+ if (i) {
+ VbExError("Can't write output file %s\n", outfile);
+ fclose(f);
+ unlink(outfile);
+ return 1;
+ }
+ written += g_keyblock->key_block_size;
+ written += g_preamble->preamble_size;
+
+ if (!opt_vblockonly) {
+ Debug("0x%" PRIx64 " bytes of kern_blob\n", kernel_size);
+ i = (1 != fwrite(kernel_blob, kernel_size, 1, f));
+ if (i) {
+ fclose(f);
+ unlink(outfile);
+ Fatal("Can't write output file %s\n", outfile);
+ }
+ written += kernel_size;
+ }
+ Debug("0x%" PRIx64 " bytes total\n", written);
+ fclose(f);
+
+ /* Success */
+ return 0;
}
-static int Verify(uint8_t* kernel_blob,
- uint64_t kernel_size,
- VbPublicKey* signpub_key,
- const char* keyblock_outfile,
- uint64_t min_version) {
- VbPublicKey* data_key;
- RSAPublicKey* rsa;
-
- if (0 != KeyBlockVerify(g_keyblock, g_keyblock->key_block_size,
- signpub_key, (0 == signpub_key)))
- Fatal("Error verifying key block.\n");
-
- printf("Key block:\n");
- data_key = &g_keyblock->data_key;
- if (opt_verbose)
- printf(" Signature: %s\n", signpub_key ? "valid" : "ignored");
- printf(" Size: 0x%" PRIx64 "\n", g_keyblock->key_block_size);
- printf(" Flags: %" PRIu64 " ", g_keyblock->key_block_flags);
- if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
- printf(" !DEV");
- if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
- printf(" DEV");
- if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
- printf(" !REC");
- if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
- printf(" REC");
- printf("\n");
- printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
- (data_key->algorithm < kNumAlgorithms ?
- algo_strings[data_key->algorithm] : "(invalid)"));
- printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
- printf(" Data key sha1sum: ");
- PrintPubKeySha1Sum(data_key);
- printf("\n");
-
- if (keyblock_outfile) {
- FILE* f = NULL;
- f = fopen(keyblock_outfile, "wb");
- if (!f)
- Fatal("Can't open key block file %s\n", keyblock_outfile);
- if (1 != fwrite(g_keyblock, g_keyblock->key_block_size, 1, f))
- Fatal("Can't write key block file %s\n", keyblock_outfile);
- fclose(f);
- }
-
- if (data_key->key_version < (min_version >> 16))
- Fatal("Data key version %" PRIu64
- " is lower than minimum %" PRIu64".\n",
- data_key->key_version, (min_version >> 16));
-
- rsa = PublicKeyToRSA(data_key);
- if (!rsa)
- Fatal("Error parsing data key.\n");
-
- /* Verify preamble */
- if (0 != VerifyKernelPreamble(
- g_preamble, g_preamble->preamble_size, rsa))
- Fatal("Error verifying preamble.\n");
-
- printf("Preamble:\n");
- printf(" Size: 0x%" PRIx64 "\n", g_preamble->preamble_size);
- printf(" Header version: %" PRIu32 ".%" PRIu32"\n",
- g_preamble->header_version_major, g_preamble->header_version_minor);
- printf(" Kernel version: %" PRIu64 "\n", g_preamble->kernel_version);
- printf(" Body load address: 0x%" PRIx64 "\n",
- g_preamble->body_load_address);
- printf(" Body size: 0x%" PRIx64 "\n",
- g_preamble->body_signature.data_size);
- printf(" Bootloader address: 0x%" PRIx64 "\n",
- g_preamble->bootloader_address);
- printf(" Bootloader size: 0x%" PRIx64 "\n",
- g_preamble->bootloader_size);
-
- if (g_preamble->kernel_version < (min_version & 0xFFFF))
- Fatal("Kernel version %" PRIu64 " is lower than minimum %" PRIu64 ".\n",
- g_preamble->kernel_version, (min_version & 0xFFFF));
-
- /* Verify body */
- if (0 != VerifyData(kernel_blob, kernel_size,
- &g_preamble->body_signature, rsa))
- Fatal("Error verifying kernel body.\n");
- printf("Body verification succeeded.\n");
-
-
- if (opt_verbose)
- printf("Config:\n%s\n", kernel_blob + CmdLineOffset(g_preamble));
-
- return 0;
+static int Verify(uint8_t * kernel_blob,
+ uint64_t kernel_size,
+ VbPublicKey * signpub_key,
+ const char *keyblock_outfile, uint64_t min_version)
+{
+ VbPublicKey *data_key;
+ RSAPublicKey *rsa;
+
+ if (0 != KeyBlockVerify(g_keyblock, g_keyblock->key_block_size,
+ signpub_key, (0 == signpub_key)))
+ Fatal("Error verifying key block.\n");
+
+ printf("Key block:\n");
+ data_key = &g_keyblock->data_key;
+ if (opt_verbose)
+ printf(" Signature: %s\n",
+ signpub_key ? "valid" : "ignored");
+ printf(" Size: 0x%" PRIx64 "\n",
+ g_keyblock->key_block_size);
+ printf(" Flags: %" PRIu64 " ",
+ g_keyblock->key_block_flags);
+ if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
+ printf(" !DEV");
+ if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
+ printf(" DEV");
+ if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
+ printf(" !REC");
+ if (g_keyblock->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
+ printf(" REC");
+ printf("\n");
+ printf(" Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
+ (data_key->algorithm < kNumAlgorithms ?
+ algo_strings[data_key->algorithm] : "(invalid)"));
+ printf(" Data key version: %" PRIu64 "\n", data_key->key_version);
+ printf(" Data key sha1sum: ");
+ PrintPubKeySha1Sum(data_key);
+ printf("\n");
+
+ if (keyblock_outfile) {
+ FILE *f = NULL;
+ f = fopen(keyblock_outfile, "wb");
+ if (!f)
+ Fatal("Can't open key block file %s\n",
+ keyblock_outfile);
+ if (1 != fwrite(g_keyblock, g_keyblock->key_block_size, 1, f))
+ Fatal("Can't write key block file %s\n",
+ keyblock_outfile);
+ fclose(f);
+ }
+
+ if (data_key->key_version < (min_version >> 16))
+ Fatal("Data key version %" PRIu64
+ " is lower than minimum %" PRIu64 ".\n",
+ data_key->key_version, (min_version >> 16));
+
+ rsa = PublicKeyToRSA(data_key);
+ if (!rsa)
+ Fatal("Error parsing data key.\n");
+
+ /* Verify preamble */
+ if (0 !=
+ VerifyKernelPreamble(g_preamble, g_preamble->preamble_size, rsa))
+ Fatal("Error verifying preamble.\n");
+
+ printf("Preamble:\n");
+ printf(" Size: 0x%" PRIx64 "\n",
+ g_preamble->preamble_size);
+ printf(" Header version: %" PRIu32 ".%" PRIu32 "\n",
+ g_preamble->header_version_major,
+ g_preamble->header_version_minor);
+ printf(" Kernel version: %" PRIu64 "\n",
+ g_preamble->kernel_version);
+ printf(" Body load address: 0x%" PRIx64 "\n",
+ g_preamble->body_load_address);
+ printf(" Body size: 0x%" PRIx64 "\n",
+ g_preamble->body_signature.data_size);
+ printf(" Bootloader address: 0x%" PRIx64 "\n",
+ g_preamble->bootloader_address);
+ printf(" Bootloader size: 0x%" PRIx64 "\n",
+ g_preamble->bootloader_size);
+
+ if (g_preamble->kernel_version < (min_version & 0xFFFF))
+ Fatal("Kernel version %" PRIu64 " is lower than minimum %"
+ PRIu64 ".\n", g_preamble->kernel_version,
+ (min_version & 0xFFFF));
+
+ /* Verify body */
+ if (0 != VerifyData(kernel_blob, kernel_size,
+ &g_preamble->body_signature, rsa))
+ Fatal("Error verifying kernel body.\n");
+ printf("Body verification succeeded.\n");
+
+ if (opt_verbose)
+ printf("Config:\n%s\n",
+ kernel_blob + CmdLineOffset(g_preamble));
+
+ return 0;
}
/****************************************************************************/
-static int do_vbutil_kernel(int argc, char* argv[]) {
- char* filename = NULL;
- char* oldfile = NULL;
- char* keyblock_file = NULL;
- char* signpubkey_file = NULL;
- char* signprivkey_file = NULL;
- char* version_str = NULL;
- int version = -1;
- char* vmlinuz_file = NULL;
- char* bootloader_file = NULL;
- char* config_file = NULL;
- arch_t arch = ARCH_X86;
- char *address_str = NULL;
- uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_ADDR;
- int mode = 0;
- int parse_error = 0;
- uint64_t min_version = 0;
- char* e;
- int i;
- VbPrivateKey* signpriv_key = NULL;
- VbPublicKey* signpub_key = NULL;
- uint8_t* kernel_blob = NULL;
- uint64_t kernel_size = 0;
-
- char *progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
- !parse_error) {
- switch (i) {
- default:
- case '?':
- /* Unhandled option */
- parse_error = 1;
- break;
-
- case 0:
- /* silently handled option */
- break;
-
- case OPT_MODE_PACK:
- case OPT_MODE_REPACK:
- case OPT_MODE_VERIFY:
- if (mode && (mode != i)) {
- fprintf(stderr, "Only a single mode can be specified\n");
- parse_error = 1;
- break;
- }
- mode = i;
- filename = optarg;
- break;
-
- case OPT_ARCH:
- /* check the first 3 characters to also detect x86_64 */
- if ((!strncasecmp(optarg, "x86", 3)) ||
- (!strcasecmp(optarg, "amd64")))
- arch = ARCH_X86;
- else if ((!strcasecmp(optarg, "arm")) ||
- (!strcasecmp(optarg, "aarch64")))
- arch = ARCH_ARM;
- else if (!strcasecmp(optarg, "mips"))
- arch = ARCH_MIPS;
- else {
- fprintf(stderr, "Unknown architecture string: %s\n", optarg);
- parse_error = 1;
- }
- break;
-
- case OPT_OLDBLOB:
- oldfile = optarg;
- break;
-
- case OPT_KLOADADDR:
- address_str = optarg;
- kernel_body_load_address = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr, "Invalid --kloadaddr\n");
- parse_error = 1;
- }
- break;
-
- case OPT_KEYBLOCK:
- keyblock_file = optarg;
- break;
-
- case OPT_SIGNPUBKEY:
- signpubkey_file = optarg;
- break;
-
- case OPT_SIGNPRIVATE:
- signprivkey_file = optarg;
- break;
-
- case OPT_VMLINUZ:
- vmlinuz_file = optarg;
- break;
-
- case OPT_BOOTLOADER:
- bootloader_file = optarg;
- break;
-
- case OPT_CONFIG:
- config_file = optarg;
- break;
-
- case OPT_VBLOCKONLY:
- opt_vblockonly = 1;
- break;
-
- case OPT_VERSION:
- version_str = optarg;
- version = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr, "Invalid --version\n");
- parse_error = 1;
- }
- break;
-
- case OPT_MINVERSION:
- min_version = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr, "Invalid --minversion\n");
- parse_error = 1;
- }
- break;
-
- case OPT_PAD:
- opt_pad = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr, "Invalid --pad\n");
- parse_error = 1;
- }
- break;
- }
- }
-
- if (parse_error)
- return PrintHelp(progname);
-
- switch(mode) {
- case OPT_MODE_PACK:
-
- /* Required */
-
- if (!keyblock_file)
- Fatal("Missing required keyblock file.\n");
-
- g_keyblock = (VbKeyBlockHeader*)ReadFile(keyblock_file, 0);
- if (!g_keyblock)
- Fatal("Error reading key block.\n");
-
- if (!signprivkey_file)
- Fatal("Missing required signprivate file.\n");
-
- signpriv_key = PrivateKeyRead(signprivkey_file);
- if (!signpriv_key)
- Fatal("Error reading signing key.\n");
-
- /* Optional */
-
- if (config_file) {
- Debug("Reading %s\n", config_file);
- g_config_data = ReadConfigFile(config_file, &g_config_size);
- if (!g_config_data)
- Fatal("Error reading config file.\n");
- }
-
- if (vmlinuz_file)
- if (!ImportVmlinuzFile(vmlinuz_file, arch, kernel_body_load_address))
- Fatal("Error reading kernel file.\n");
-
- if (bootloader_file) {
- Debug("Reading %s\n", bootloader_file);
- g_bootloader_data = ReadFile(bootloader_file, &g_bootloader_size);
- if (!g_bootloader_data)
- Fatal("Error reading bootloader file.\n");
- Debug(" bootloader file size=0x%" PRIx64 "\n", g_bootloader_size);
- }
-
- /* Do it */
-
- kernel_blob = CreateKernelBlob(kernel_body_load_address, arch,
- &kernel_size);
-
- return Pack(filename, kernel_blob, kernel_size,
- version, kernel_body_load_address,
- signpriv_key);
+static int do_vbutil_kernel(int argc, char *argv[])
+{
+ char *filename = NULL;
+ char *oldfile = NULL;
+ char *keyblock_file = NULL;
+ char *signpubkey_file = NULL;
+ char *signprivkey_file = NULL;
+ char *version_str = NULL;
+ int version = -1;
+ char *vmlinuz_file = NULL;
+ char *bootloader_file = NULL;
+ char *config_file = NULL;
+ arch_t arch = ARCH_X86;
+ char *address_str = NULL;
+ uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_ADDR;
+ int mode = 0;
+ int parse_error = 0;
+ uint64_t min_version = 0;
+ char *e;
+ int i;
+ VbPrivateKey *signpriv_key = NULL;
+ VbPublicKey *signpub_key = NULL;
+ uint8_t *kernel_blob = NULL;
+ uint64_t kernel_size = 0;
+
+ char *progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
+ !parse_error) {
+ switch (i) {
+ default:
+ case '?':
+ /* Unhandled option */
+ parse_error = 1;
+ break;
+
+ case 0:
+ /* silently handled option */
+ break;
+
+ case OPT_MODE_PACK:
+ case OPT_MODE_REPACK:
+ case OPT_MODE_VERIFY:
+ if (mode && (mode != i)) {
+ fprintf(stderr,
+ "Only one mode can be specified\n");
+ parse_error = 1;
+ break;
+ }
+ mode = i;
+ filename = optarg;
+ break;
+
+ case OPT_ARCH:
+ /* check the first 3 characters to also detect x86_64 */
+ if ((!strncasecmp(optarg, "x86", 3)) ||
+ (!strcasecmp(optarg, "amd64")))
+ arch = ARCH_X86;
+ else if ((!strcasecmp(optarg, "arm")) ||
+ (!strcasecmp(optarg, "aarch64")))
+ arch = ARCH_ARM;
+ else if (!strcasecmp(optarg, "mips"))
+ arch = ARCH_MIPS;
+ else {
+ fprintf(stderr,
+ "Unknown architecture string: %s\n",
+ optarg);
+ parse_error = 1;
+ }
+ break;
+
+ case OPT_OLDBLOB:
+ oldfile = optarg;
+ break;
+
+ case OPT_KLOADADDR:
+ address_str = optarg;
+ kernel_body_load_address = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ fprintf(stderr, "Invalid --kloadaddr\n");
+ parse_error = 1;
+ }
+ break;
+
+ case OPT_KEYBLOCK:
+ keyblock_file = optarg;
+ break;
+
+ case OPT_SIGNPUBKEY:
+ signpubkey_file = optarg;
+ break;
+
+ case OPT_SIGNPRIVATE:
+ signprivkey_file = optarg;
+ break;
+
+ case OPT_VMLINUZ:
+ vmlinuz_file = optarg;
+ break;
+
+ case OPT_BOOTLOADER:
+ bootloader_file = optarg;
+ break;
+
+ case OPT_CONFIG:
+ config_file = optarg;
+ break;
+
+ case OPT_VBLOCKONLY:
+ opt_vblockonly = 1;
+ break;
+
+ case OPT_VERSION:
+ version_str = optarg;
+ version = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ fprintf(stderr, "Invalid --version\n");
+ parse_error = 1;
+ }
+ break;
+
+ case OPT_MINVERSION:
+ min_version = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ fprintf(stderr, "Invalid --minversion\n");
+ parse_error = 1;
+ }
+ break;
+
+ case OPT_PAD:
+ opt_pad = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ fprintf(stderr, "Invalid --pad\n");
+ parse_error = 1;
+ }
+ break;
+ }
+ }
+
+ if (parse_error)
+ return PrintHelp(progname);
+
+ switch (mode) {
+ case OPT_MODE_PACK:
+
+ /* Required */
+
+ if (!keyblock_file)
+ Fatal("Missing required keyblock file.\n");
+
+ g_keyblock = (VbKeyBlockHeader *) ReadFile(keyblock_file, 0);
+ if (!g_keyblock)
+ Fatal("Error reading key block.\n");
+
+ if (!signprivkey_file)
+ Fatal("Missing required signprivate file.\n");
+
+ signpriv_key = PrivateKeyRead(signprivkey_file);
+ if (!signpriv_key)
+ Fatal("Error reading signing key.\n");
+
+ /* Optional */
+
+ if (config_file) {
+ Debug("Reading %s\n", config_file);
+ g_config_data =
+ ReadConfigFile(config_file, &g_config_size);
+ if (!g_config_data)
+ Fatal("Error reading config file.\n");
+ }
+
+ if (vmlinuz_file)
+ if (!ImportVmlinuzFile
+ (vmlinuz_file, arch, kernel_body_load_address))
+ Fatal("Error reading kernel file.\n");
+
+ if (bootloader_file) {
+ Debug("Reading %s\n", bootloader_file);
+ g_bootloader_data =
+ ReadFile(bootloader_file, &g_bootloader_size);
+ if (!g_bootloader_data)
+ Fatal("Error reading bootloader file.\n");
+ Debug(" bootloader file size=0x%" PRIx64 "\n",
+ g_bootloader_size);
+ }
- case OPT_MODE_REPACK:
+ /* Do it */
- /* Required */
+ kernel_blob = CreateKernelBlob(kernel_body_load_address, arch,
+ &kernel_size);
- if (!signprivkey_file)
- Fatal("Missing required signprivate file.\n");
+ return Pack(filename, kernel_blob, kernel_size,
+ version, kernel_body_load_address, signpriv_key);
- signpriv_key = PrivateKeyRead(signprivkey_file);
- if (!signpriv_key)
- Fatal("Error reading signing key.\n");
+ case OPT_MODE_REPACK:
- if (!oldfile)
- Fatal("Missing previously packed blob.\n");
+ /* Required */
- /* Load the old blob */
+ if (!signprivkey_file)
+ Fatal("Missing required signprivate file.\n");
+
+ signpriv_key = PrivateKeyRead(signprivkey_file);
+ if (!signpriv_key)
+ Fatal("Error reading signing key.\n");
+
+ if (!oldfile)
+ Fatal("Missing previously packed blob.\n");
- kernel_blob = ReadOldBlobFromFileOrDie(oldfile, &kernel_size);
- if (0 != Verify(kernel_blob, kernel_size, 0, 0, 0))
- Fatal("The oldblob doesn't verify\n");
+ /* Load the old blob */
- /* Take it apart */
+ kernel_blob = ReadOldBlobFromFileOrDie(oldfile, &kernel_size);
+ if (0 != Verify(kernel_blob, kernel_size, 0, 0, 0))
+ Fatal("The oldblob doesn't verify\n");
- UnpackKernelBlob(kernel_blob, kernel_size);
- free(kernel_blob);
+ /* Take it apart */
- /* Load optional params */
+ UnpackKernelBlob(kernel_blob, kernel_size);
+ free(kernel_blob);
- if (!version_str)
- version = g_preamble->kernel_version;
+ /* Load optional params */
- if (!address_str)
- kernel_body_load_address = g_preamble->body_load_address;
+ if (!version_str)
+ version = g_preamble->kernel_version;
- if (config_file) {
- if (g_config_data)
- free(g_config_data);
- Debug("Reading %s\n", config_file);
- g_config_data = ReadConfigFile(config_file, &g_config_size);
- if (!g_config_data)
- Fatal("Error reading config file.\n");
- }
+ if (!address_str)
+ kernel_body_load_address =
+ g_preamble->body_load_address;
- if (keyblock_file) {
- if (g_keyblock)
- free(g_keyblock);
- g_keyblock = (VbKeyBlockHeader*)ReadFile(keyblock_file, 0);
- if (!g_keyblock)
- Fatal("Error reading key block.\n");
- }
+ if (config_file) {
+ if (g_config_data)
+ free(g_config_data);
+ Debug("Reading %s\n", config_file);
+ g_config_data =
+ ReadConfigFile(config_file, &g_config_size);
+ if (!g_config_data)
+ Fatal("Error reading config file.\n");
+ }
- /* Put it back together */
+ if (keyblock_file) {
+ if (g_keyblock)
+ free(g_keyblock);
+ g_keyblock =
+ (VbKeyBlockHeader *) ReadFile(keyblock_file, 0);
+ if (!g_keyblock)
+ Fatal("Error reading key block.\n");
+ }
- kernel_blob = CreateKernelBlob(kernel_body_load_address, arch,
- &kernel_size);
+ /* Put it back together */
- return Pack(filename, kernel_blob, kernel_size,
- version, kernel_body_load_address,
- signpriv_key);
+ kernel_blob = CreateKernelBlob(kernel_body_load_address, arch,
+ &kernel_size);
+ return Pack(filename, kernel_blob, kernel_size,
+ version, kernel_body_load_address, signpriv_key);
- case OPT_MODE_VERIFY:
+ case OPT_MODE_VERIFY:
- /* Optional */
+ /* Optional */
- if (signpubkey_file) {
- signpub_key = PublicKeyRead(signpubkey_file);
- if (!signpub_key)
- Fatal("Error reading public key.\n");
- }
+ if (signpubkey_file) {
+ signpub_key = PublicKeyRead(signpubkey_file);
+ if (!signpub_key)
+ Fatal("Error reading public key.\n");
+ }
- /* Do it */
+ /* Do it */
- kernel_blob = ReadOldBlobFromFileOrDie(filename, &kernel_size);
+ kernel_blob = ReadOldBlobFromFileOrDie(filename, &kernel_size);
- return Verify(kernel_blob, kernel_size, signpub_key,
- keyblock_file, min_version);
- }
+ return Verify(kernel_blob, kernel_size, signpub_key,
+ keyblock_file, min_version);
+ }
- fprintf(stderr, "You must specify a mode: --pack, --repack or --verify\n");
- return PrintHelp(progname);
+ fprintf(stderr,
+ "You must specify a mode: --pack, --repack or --verify\n");
+ return PrintHelp(progname);
}
DECLARE_FUTIL_COMMAND(vbutil_kernel, do_vbutil_kernel,
diff --git a/futility/cmd_vbutil_key.c b/futility/cmd_vbutil_key.c
index 88d8e83b..c8c1c61b 100644
--- a/futility/cmd_vbutil_key.c
+++ b/futility/cmd_vbutil_key.c
@@ -6,7 +6,7 @@
*/
#include <getopt.h>
-#include <inttypes.h> /* For PRIu64 */
+#include <inttypes.h> /* For PRIu64 */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -18,224 +18,227 @@
#include "util_misc.h"
#include "vboot_common.h"
-
/* Command line options */
enum {
- OPT_INKEY = 1000,
- OPT_KEY_VERSION,
- OPT_ALGORITHM,
- OPT_MODE_PACK,
- OPT_MODE_UNPACK,
- OPT_COPYTO,
+ OPT_INKEY = 1000,
+ OPT_KEY_VERSION,
+ OPT_ALGORITHM,
+ OPT_MODE_PACK,
+ OPT_MODE_UNPACK,
+ OPT_COPYTO,
};
static const struct option long_opts[] = {
- {"key", 1, 0, OPT_INKEY },
- {"version", 1, 0, OPT_KEY_VERSION },
- {"algorithm", 1, 0, OPT_ALGORITHM },
- {"pack", 1, 0, OPT_MODE_PACK },
- {"unpack", 1, 0, OPT_MODE_UNPACK },
- {"copyto", 1, 0, OPT_COPYTO },
- {NULL, 0, 0, 0}
+ {"key", 1, 0, OPT_INKEY},
+ {"version", 1, 0, OPT_KEY_VERSION},
+ {"algorithm", 1, 0, OPT_ALGORITHM},
+ {"pack", 1, 0, OPT_MODE_PACK},
+ {"unpack", 1, 0, OPT_MODE_UNPACK},
+ {"copyto", 1, 0, OPT_COPYTO},
+ {NULL, 0, 0, 0}
};
-
/* Print help and return error */
-static int PrintHelp(char *progname) {
- int i;
-
- fprintf(stderr,
- "This program wraps RSA keys with verified boot headers\n");
- fprintf(stderr,
- "\n"
- "Usage: %s --pack <outfile> [PARAMETERS]\n"
- "\n"
- " Required parameters:\n"
- " --key <infile> RSA key file (.keyb or .pem)\n"
- " --version <number> Key version number "
- "(required for .keyb,\n"
- " ignored for .pem)\n"
- " --algorithm <number> "
- "Signing algorithm to use with key:\n",
- progname);
-
- for (i = 0; i < kNumAlgorithms; i++) {
- fprintf(stderr,
- " %d = (%s)\n",
- i, algo_strings[i]);
- }
-
- fprintf(stderr,
- "\nOR\n\n"
- "Usage: %s --unpack <infile>\n"
- "\n"
- " Optional parameters:\n"
- " --copyto <file> "
- "Write a copy of the key to this file.\n"
- "\n",
- progname);
-
- return 1;
+static int PrintHelp(char *progname)
+{
+ int i;
+
+ fprintf(stderr,
+ "This program wraps RSA keys with verified boot headers\n");
+ fprintf(stderr,
+ "\n"
+ "Usage: %s --pack <outfile> [PARAMETERS]\n"
+ "\n"
+ " Required parameters:\n"
+ " --key <infile> RSA key file (.keyb or .pem)\n"
+ " --version <number> Key version number "
+ "(required for .keyb,\n"
+ " ignored for .pem)\n"
+ " --algorithm <number> "
+ "Signing algorithm to use with key:\n", progname);
+
+ for (i = 0; i < kNumAlgorithms; i++) {
+ fprintf(stderr,
+ " %d = (%s)\n",
+ i, algo_strings[i]);
+ }
+
+ fprintf(stderr,
+ "\nOR\n\n"
+ "Usage: %s --unpack <infile>\n"
+ "\n"
+ " Optional parameters:\n"
+ " --copyto <file> "
+ "Write a copy of the key to this file.\n" "\n", progname);
+
+ return 1;
}
/* Pack a .keyb file into a .vbpubk, or a .pem into a .vbprivk */
static int Pack(const char *infile, const char *outfile, uint64_t algorithm,
- uint64_t version) {
- VbPublicKey* pubkey;
- VbPrivateKey* privkey;
-
- if (!infile || !outfile) {
- fprintf(stderr, "vbutil_key: Must specify --in and --out\n");
- return 1;
- }
-
- if ((pubkey = PublicKeyReadKeyb(infile, algorithm, version))) {
- if (0 != PublicKeyWrite(outfile, pubkey)) {
- fprintf(stderr, "vbutil_key: Error writing key.\n");
- return 1;
- }
- free(pubkey);
- return 0;
- }
-
- if ((privkey = PrivateKeyReadPem(infile, algorithm))) {
- if (0 != PrivateKeyWrite(outfile, privkey)) {
- fprintf(stderr, "vbutil_key: Error writing key.\n");
- return 1;
- }
- free(privkey);
- return 0;
- }
-
- VbExError("Unable to parse either .keyb or .pem from %s\n", infile);
- return 1;
+ uint64_t version)
+{
+ VbPublicKey *pubkey;
+ VbPrivateKey *privkey;
+
+ if (!infile || !outfile) {
+ fprintf(stderr, "vbutil_key: Must specify --in and --out\n");
+ return 1;
+ }
+
+ if ((pubkey = PublicKeyReadKeyb(infile, algorithm, version))) {
+ if (0 != PublicKeyWrite(outfile, pubkey)) {
+ fprintf(stderr, "vbutil_key: Error writing key.\n");
+ return 1;
+ }
+ free(pubkey);
+ return 0;
+ }
+
+ if ((privkey = PrivateKeyReadPem(infile, algorithm))) {
+ if (0 != PrivateKeyWrite(outfile, privkey)) {
+ fprintf(stderr, "vbutil_key: Error writing key.\n");
+ return 1;
+ }
+ free(privkey);
+ return 0;
+ }
+
+ VbExError("Unable to parse either .keyb or .pem from %s\n", infile);
+ return 1;
}
-
/* Unpack a .vbpubk or .vbprivk */
-static int Unpack(const char *infile, const char *outfile) {
- VbPublicKey* pubkey;
- VbPrivateKey* privkey;
-
- if (!infile) {
- fprintf(stderr, "Need file to unpack\n");
- return 1;
- }
-
- if ((pubkey = PublicKeyRead(infile))) {
- printf("Public Key file: %s\n", infile);
- printf("Algorithm: %" PRIu64 " %s\n", pubkey->algorithm,
- (pubkey->algorithm < kNumAlgorithms ?
- algo_strings[pubkey->algorithm] : "(invalid)"));
- printf("Key Version: %" PRIu64 "\n", pubkey->key_version);
- printf("Key sha1sum: ");
- PrintPubKeySha1Sum(pubkey);
- printf("\n");
- if (outfile) {
- if (0 != PublicKeyWrite(outfile, pubkey)) {
- fprintf(stderr, "vbutil_key: Error writing key copy.\n");
- free(pubkey);
- return 1;
- }
- }
- free(pubkey);
- return 0;
- }
-
- if ((privkey = PrivateKeyRead(infile))) {
- printf("Private Key file: %s\n", infile);
- printf("Algorithm: %" PRIu64 " %s\n", privkey->algorithm,
- (privkey->algorithm < kNumAlgorithms ?
- algo_strings[privkey->algorithm] : "(invalid)"));
- if (outfile) {
- if (0 != PrivateKeyWrite(outfile, privkey)) {
- fprintf(stderr, "vbutil_key: Error writing key copy.\n");
- free(privkey);
- return 1;
- }
- }
- free(privkey);
- return 0;
- }
-
- VbExError("Unable to parse either .vbpubk or vbprivk from %s\n", infile);
- return 1;
+static int Unpack(const char *infile, const char *outfile)
+{
+ VbPublicKey *pubkey;
+ VbPrivateKey *privkey;
+
+ if (!infile) {
+ fprintf(stderr, "Need file to unpack\n");
+ return 1;
+ }
+
+ if ((pubkey = PublicKeyRead(infile))) {
+ printf("Public Key file: %s\n", infile);
+ printf("Algorithm: %" PRIu64 " %s\n", pubkey->algorithm,
+ (pubkey->algorithm < kNumAlgorithms ?
+ algo_strings[pubkey->algorithm] : "(invalid)"));
+ printf("Key Version: %" PRIu64 "\n", pubkey->key_version);
+ printf("Key sha1sum: ");
+ PrintPubKeySha1Sum(pubkey);
+ printf("\n");
+ if (outfile) {
+ if (0 != PublicKeyWrite(outfile, pubkey)) {
+ fprintf(stderr,
+ "vbutil_key: Error writing key copy\n");
+ free(pubkey);
+ return 1;
+ }
+ }
+ free(pubkey);
+ return 0;
+ }
+
+ if ((privkey = PrivateKeyRead(infile))) {
+ printf("Private Key file: %s\n", infile);
+ printf("Algorithm: %" PRIu64 " %s\n",
+ privkey->algorithm,
+ (privkey->algorithm <
+ kNumAlgorithms ? algo_strings[privkey->
+ algorithm] :
+ "(invalid)"));
+ if (outfile) {
+ if (0 != PrivateKeyWrite(outfile, privkey)) {
+ fprintf(stderr,
+ "vbutil_key: Error writing key copy\n");
+ free(privkey);
+ return 1;
+ }
+ }
+ free(privkey);
+ return 0;
+ }
+
+ VbExError("Unable to parse either .vbpubk or vbprivk from %s\n",
+ infile);
+ return 1;
}
-
-static int do_vbutil_key(int argc, char* argv[]) {
-
- char *infile = NULL;
- char *outfile = NULL;
- int mode = 0;
- int parse_error = 0;
- uint64_t version = 1;
- uint64_t algorithm = kNumAlgorithms;
- char* e;
- int i;
-
- char *progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
- switch (i) {
- case '?':
- /* Unhandled option */
- VbExError("Unknown option\n");
- parse_error = 1;
- break;
-
- case OPT_INKEY:
- infile = optarg;
- break;
-
- case OPT_KEY_VERSION:
- version = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- VbExError("Invalid --version\n");
- parse_error = 1;
- }
- break;
-
- case OPT_ALGORITHM:
- algorithm = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- VbExError("Invalid --algorithm\n");
- parse_error = 1;
- }
- break;
-
- case OPT_MODE_PACK:
- mode = i;
- outfile = optarg;
- break;
-
- case OPT_MODE_UNPACK:
- mode = i;
- infile = optarg;
- break;
-
- case OPT_COPYTO:
- outfile = optarg;
- break;
- }
- }
-
- if (parse_error)
- return PrintHelp(progname);
-
- switch(mode) {
- case OPT_MODE_PACK:
- return Pack(infile, outfile, algorithm, version);
- case OPT_MODE_UNPACK:
- return Unpack(infile, outfile);
- default:
- printf("Must specify a mode.\n");
- return PrintHelp(progname);
- }
+static int do_vbutil_key(int argc, char *argv[])
+{
+
+ char *infile = NULL;
+ char *outfile = NULL;
+ int mode = 0;
+ int parse_error = 0;
+ uint64_t version = 1;
+ uint64_t algorithm = kNumAlgorithms;
+ char *e;
+ int i;
+
+ char *progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
+ switch (i) {
+ case '?':
+ /* Unhandled option */
+ VbExError("Unknown option\n");
+ parse_error = 1;
+ break;
+
+ case OPT_INKEY:
+ infile = optarg;
+ break;
+
+ case OPT_KEY_VERSION:
+ version = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ VbExError("Invalid --version\n");
+ parse_error = 1;
+ }
+ break;
+
+ case OPT_ALGORITHM:
+ algorithm = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ VbExError("Invalid --algorithm\n");
+ parse_error = 1;
+ }
+ break;
+
+ case OPT_MODE_PACK:
+ mode = i;
+ outfile = optarg;
+ break;
+
+ case OPT_MODE_UNPACK:
+ mode = i;
+ infile = optarg;
+ break;
+
+ case OPT_COPYTO:
+ outfile = optarg;
+ break;
+ }
+ }
+
+ if (parse_error)
+ return PrintHelp(progname);
+
+ switch (mode) {
+ case OPT_MODE_PACK:
+ return Pack(infile, outfile, algorithm, version);
+ case OPT_MODE_UNPACK:
+ return Unpack(infile, outfile);
+ default:
+ printf("Must specify a mode.\n");
+ return PrintHelp(progname);
+ }
}
DECLARE_FUTIL_COMMAND(vbutil_key, do_vbutil_key,
diff --git a/futility/cmd_vbutil_keyblock.c b/futility/cmd_vbutil_keyblock.c
index 687537d8..58d89c1a 100644
--- a/futility/cmd_vbutil_keyblock.c
+++ b/futility/cmd_vbutil_keyblock.c
@@ -17,312 +17,324 @@
#include "util_misc.h"
#include "vboot_common.h"
-
/* Command line options */
enum {
- OPT_MODE_PACK = 1000,
- OPT_MODE_UNPACK,
- OPT_DATAPUBKEY,
- OPT_SIGNPUBKEY,
- OPT_SIGNPRIVATE,
- OPT_SIGNPRIVATE_PEM,
- OPT_PEM_ALGORITHM,
- OPT_EXTERNAL_SIGNER,
- OPT_FLAGS,
+ OPT_MODE_PACK = 1000,
+ OPT_MODE_UNPACK,
+ OPT_DATAPUBKEY,
+ OPT_SIGNPUBKEY,
+ OPT_SIGNPRIVATE,
+ OPT_SIGNPRIVATE_PEM,
+ OPT_PEM_ALGORITHM,
+ OPT_EXTERNAL_SIGNER,
+ OPT_FLAGS,
};
static const struct option long_opts[] = {
- {"pack", 1, 0, OPT_MODE_PACK },
- {"unpack", 1, 0, OPT_MODE_UNPACK },
- {"datapubkey", 1, 0, OPT_DATAPUBKEY },
- {"signpubkey", 1, 0, OPT_SIGNPUBKEY },
- {"signprivate", 1, 0, OPT_SIGNPRIVATE },
- {"signprivate_pem", 1, 0, OPT_SIGNPRIVATE_PEM },
- {"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM },
- {"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER },
- {"flags", 1, 0, OPT_FLAGS },
- {NULL, 0, 0, 0}
+ {"pack", 1, 0, OPT_MODE_PACK},
+ {"unpack", 1, 0, OPT_MODE_UNPACK},
+ {"datapubkey", 1, 0, OPT_DATAPUBKEY},
+ {"signpubkey", 1, 0, OPT_SIGNPUBKEY},
+ {"signprivate", 1, 0, OPT_SIGNPRIVATE},
+ {"signprivate_pem", 1, 0, OPT_SIGNPRIVATE_PEM},
+ {"pem_algorithm", 1, 0, OPT_PEM_ALGORITHM},
+ {"externalsigner", 1, 0, OPT_EXTERNAL_SIGNER},
+ {"flags", 1, 0, OPT_FLAGS},
+ {NULL, 0, 0, 0}
};
+static const char usage[] =
+ "Verified boot key block utility\n"
+ "\n"
+ "Usage: %s <--pack|--unpack> <file> [OPTIONS]\n"
+ "\n"
+ "For '--pack <file>', required OPTIONS are:\n"
+ " --datapubkey <file> Data public key in .vbpubk format\n"
+ "\n"
+ "Optional OPTIONS are:\n"
+ " --signprivate <file>"
+ " Signing private key in .vbprivk format.\n"
+ "OR\n"
+ " --signprivate_pem <file>\n"
+ " --pem_algorithm <algo>\n"
+ " Signing private key in .pem format and algorithm id.\n"
+ "(If one of the above arguments is not specified, the keyblock will\n"
+ "not be signed.)\n"
+ "\n"
+ " --flags <number> Specifies allowed use conditions.\n"
+ " --externalsigner \"cmd\""
+ " Use an external program cmd to calculate the signatures.\n"
+ "\n"
+ "For '--unpack <file>', optional OPTIONS are:\n"
+ " --signpubkey <file>"
+ " Signing public key in .vbpubk format. This is required to\n"
+ " verify a signed keyblock.\n"
+ " --datapubkey <file>"
+ " Write the data public key to this file.\n";
/* Print help and return error */
-static int PrintHelp(char *progname) {
- fprintf(stderr,
- "Verified boot key block utility\n"
- "\n"
- "Usage: %s <--pack|--unpack> <file> [OPTIONS]\n"
- "\n"
- "For '--pack <file>', required OPTIONS are:\n"
- " --datapubkey <file> Data public key in .vbpubk format\n"
- "\n"
- "Optional OPTIONS are:\n"
- " --signprivate <file>"
- " Signing private key in .vbprivk format.\n"
- "OR\n"
- " --signprivate_pem <file>\n"
- " --pem_algorithm <algo>\n"
- " Signing private key in .pem format and algorithm id.\n"
- "(If one of the above arguments is not specified, the keyblock will\n"
- "not be signed.)\n"
- "\n"
- " --flags <number> Specifies allowed use conditions.\n"
- " --externalsigner \"cmd\""
- " Use an external program cmd to calculate the signatures.\n"
- "\n"
- "For '--unpack <file>', optional OPTIONS are:\n"
- " --signpubkey <file>"
- " Signing public key in .vbpubk format. This is required to\n"
- " verify a signed keyblock.\n"
- " --datapubkey <file>"
- " Write the data public key to this file.\n",
- progname);
- return 1;
+static int PrintHelp(char *progname)
+{
+ fprintf(stderr, usage, progname);
+ return 1;
}
/* Pack a .keyblock */
-static int Pack(const char* outfile, const char* datapubkey,
- const char* signprivate,
- const char* signprivate_pem, uint64_t pem_algorithm,
- uint64_t flags,
- const char* external_signer) {
- VbPublicKey* data_key;
- VbPrivateKey* signing_key = NULL;
- VbKeyBlockHeader* block;
-
- if (!outfile) {
- fprintf(stderr, "vbutil_keyblock: Must specify output filename.\n");
- return 1;
- }
- if (!datapubkey) {
- fprintf(stderr, "vbutil_keyblock: Must specify data public key.\n");
- return 1;
- }
-
- data_key = PublicKeyRead(datapubkey);
- if (!data_key) {
- fprintf(stderr, "vbutil_keyblock: Error reading data key.\n");
- return 1;
- }
-
- if (signprivate_pem) {
- if (pem_algorithm >= kNumAlgorithms) {
- fprintf(stderr, "vbutil_keyblock: Invalid --pem_algorithm %" PRIu64 "\n",
- pem_algorithm);
- return 1;
- }
- if (external_signer) {
- /* External signing uses the PEM file directly. */
- block = KeyBlockCreate_external(data_key,
- signprivate_pem, pem_algorithm,
- flags,
- external_signer);
- } else {
- signing_key = PrivateKeyReadPem(signprivate_pem, pem_algorithm);
- if (!signing_key) {
- fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n");
- return 1;
- }
- block = KeyBlockCreate(data_key, signing_key, flags);
- }
- } else {
- if (signprivate) {
- signing_key = PrivateKeyRead(signprivate);
- if (!signing_key) {
- fprintf(stderr, "vbutil_keyblock: Error reading signing key.\n");
- return 1;
- }
- }
- block = KeyBlockCreate(data_key, signing_key, flags);
- }
-
- free(data_key);
- if (signing_key)
- free(signing_key);
-
- if (0 != KeyBlockWrite(outfile, block)) {
- fprintf(stderr, "vbutil_keyblock: Error writing key block.\n");
- return 1;
- }
- free(block);
- return 0;
+static int Pack(const char *outfile, const char *datapubkey,
+ const char *signprivate,
+ const char *signprivate_pem, uint64_t pem_algorithm,
+ uint64_t flags, const char *external_signer)
+{
+ VbPublicKey *data_key;
+ VbPrivateKey *signing_key = NULL;
+ VbKeyBlockHeader *block;
+
+ if (!outfile) {
+ fprintf(stderr,
+ "vbutil_keyblock: Must specify output filename.\n");
+ return 1;
+ }
+ if (!datapubkey) {
+ fprintf(stderr,
+ "vbutil_keyblock: Must specify data public key.\n");
+ return 1;
+ }
+
+ data_key = PublicKeyRead(datapubkey);
+ if (!data_key) {
+ fprintf(stderr, "vbutil_keyblock: Error reading data key.\n");
+ return 1;
+ }
+
+ if (signprivate_pem) {
+ if (pem_algorithm >= kNumAlgorithms) {
+ fprintf(stderr,
+ "vbutil_keyblock: Invalid --pem_algorithm %"
+ PRIu64 "\n", pem_algorithm);
+ return 1;
+ }
+ if (external_signer) {
+ /* External signing uses the PEM file directly. */
+ block = KeyBlockCreate_external(data_key,
+ signprivate_pem,
+ pem_algorithm, flags,
+ external_signer);
+ } else {
+ signing_key =
+ PrivateKeyReadPem(signprivate_pem, pem_algorithm);
+ if (!signing_key) {
+ fprintf(stderr, "vbutil_keyblock:"
+ " Error reading signing key.\n");
+ return 1;
+ }
+ block = KeyBlockCreate(data_key, signing_key, flags);
+ }
+ } else {
+ if (signprivate) {
+ signing_key = PrivateKeyRead(signprivate);
+ if (!signing_key) {
+ fprintf(stderr, "vbutil_keyblock:"
+ " Error reading signing key.\n");
+ return 1;
+ }
+ }
+ block = KeyBlockCreate(data_key, signing_key, flags);
+ }
+
+ free(data_key);
+ if (signing_key)
+ free(signing_key);
+
+ if (0 != KeyBlockWrite(outfile, block)) {
+ fprintf(stderr, "vbutil_keyblock: Error writing key block.\n");
+ return 1;
+ }
+ free(block);
+ return 0;
}
-static int Unpack(const char* infile, const char* datapubkey,
- const char* signpubkey) {
- VbPublicKey* data_key;
- VbPublicKey* sign_key = NULL;
- VbKeyBlockHeader* block;
-
- if (!infile) {
- fprintf(stderr, "vbutil_keyblock: Must specify filename\n");
- return 1;
- }
-
- block = KeyBlockRead(infile);
- if (!block) {
- fprintf(stderr, "vbutil_keyblock: Error reading key block.\n");
- return 1;
- }
-
- /* If the block is signed, then verify it with the signing public key, since
- KeyBlockRead() only verified the hash. */
- if (block->key_block_signature.sig_size && signpubkey) {
- sign_key = PublicKeyRead(signpubkey);
- if (!sign_key) {
- fprintf(stderr, "vbutil_keyblock: Error reading signpubkey.\n");
- return 1;
- }
- if (0 != KeyBlockVerify(block, block->key_block_size, sign_key, 0)) {
- fprintf(stderr, "vbutil_keyblock: Error verifying key block.\n");
- return 1;
- }
- free(sign_key);
- }
-
- printf("Key block file: %s\n", infile);
- printf("Signature %s\n", sign_key ? "valid" : "ignored");
- printf("Flags: %" PRIu64 " ", block->key_block_flags);
- if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
- printf(" !DEV");
- if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
- printf(" DEV");
- if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
- printf(" !REC");
- if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
- printf(" REC");
- printf("\n");
-
- data_key = &block->data_key;
- printf("Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
- (data_key->algorithm < kNumAlgorithms ?
- algo_strings[data_key->algorithm] : "(invalid)"));
- printf("Data key version: %" PRIu64 "\n", data_key->key_version);
- printf("Data key sha1sum: ");
- PrintPubKeySha1Sum(data_key);
- printf("\n");
-
- if (datapubkey) {
- if (0 != PublicKeyWrite(datapubkey, data_key)) {
- fprintf(stderr,
- "vbutil_keyblock: unable to write public key\n");
- return 1;
- }
- }
-
- free(block);
- return 0;
+static int Unpack(const char *infile, const char *datapubkey,
+ const char *signpubkey)
+{
+ VbPublicKey *data_key;
+ VbPublicKey *sign_key = NULL;
+ VbKeyBlockHeader *block;
+
+ if (!infile) {
+ fprintf(stderr, "vbutil_keyblock: Must specify filename\n");
+ return 1;
+ }
+
+ block = KeyBlockRead(infile);
+ if (!block) {
+ fprintf(stderr, "vbutil_keyblock: Error reading key block.\n");
+ return 1;
+ }
+
+ /* If the block is signed, then verify it with the signing public key,
+ * since KeyBlockRead() only verified the hash. */
+ if (block->key_block_signature.sig_size && signpubkey) {
+ sign_key = PublicKeyRead(signpubkey);
+ if (!sign_key) {
+ fprintf(stderr,
+ "vbutil_keyblock: Error reading signpubkey.\n");
+ return 1;
+ }
+ if (0 !=
+ KeyBlockVerify(block, block->key_block_size, sign_key, 0)) {
+ fprintf(stderr, "vbutil_keyblock:"
+ " Error verifying key block.\n");
+ return 1;
+ }
+ free(sign_key);
+ }
+
+ printf("Key block file: %s\n", infile);
+ printf("Signature %s\n", sign_key ? "valid" : "ignored");
+ printf("Flags: %" PRIu64 " ", block->key_block_flags);
+ if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_0)
+ printf(" !DEV");
+ if (block->key_block_flags & KEY_BLOCK_FLAG_DEVELOPER_1)
+ printf(" DEV");
+ if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)
+ printf(" !REC");
+ if (block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_1)
+ printf(" REC");
+ printf("\n");
+
+ data_key = &block->data_key;
+ printf("Data key algorithm: %" PRIu64 " %s\n", data_key->algorithm,
+ (data_key->algorithm < kNumAlgorithms ?
+ algo_strings[data_key->algorithm] : "(invalid)"));
+ printf("Data key version: %" PRIu64 "\n", data_key->key_version);
+ printf("Data key sha1sum: ");
+ PrintPubKeySha1Sum(data_key);
+ printf("\n");
+
+ if (datapubkey) {
+ if (0 != PublicKeyWrite(datapubkey, data_key)) {
+ fprintf(stderr, "vbutil_keyblock:"
+ " unable to write public key\n");
+ return 1;
+ }
+ }
+
+ free(block);
+ return 0;
}
-
-static int do_vbutil_keyblock(int argc, char* argv[]) {
-
- char* filename = NULL;
- char* datapubkey = NULL;
- char* signpubkey = NULL;
- char* signprivate = NULL;
- char* signprivate_pem = NULL;
- char* external_signer = NULL;
- uint64_t flags = 0;
- uint64_t pem_algorithm = 0;
- int is_pem_algorithm = 0;
- int mode = 0;
- int parse_error = 0;
- char* e;
- int i;
-
- char *progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
- switch (i) {
- case '?':
- /* Unhandled option */
- printf("Unknown option\n");
- parse_error = 1;
- break;
-
- case OPT_MODE_PACK:
- case OPT_MODE_UNPACK:
- mode = i;
- filename = optarg;
- break;
-
- case OPT_DATAPUBKEY:
- datapubkey = optarg;
- break;
-
- case OPT_SIGNPUBKEY:
- signpubkey = optarg;
- break;
-
- case OPT_SIGNPRIVATE:
- signprivate = optarg;
- break;
-
- case OPT_SIGNPRIVATE_PEM:
- signprivate_pem = optarg;
- break;
-
- case OPT_PEM_ALGORITHM:
- pem_algorithm = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr, "Invalid --pem_algorithm\n");
- parse_error = 1;
- } else {
- is_pem_algorithm = 1;
- }
- break;
-
- case OPT_EXTERNAL_SIGNER:
- external_signer = optarg;
- break;
-
- case OPT_FLAGS:
- flags = strtoul(optarg, &e, 0);
- if (!*optarg || (e && *e)) {
- fprintf(stderr, "Invalid --flags\n");
- parse_error = 1;
- }
- break;
- }
- }
-
- /* Check if the right combination of options was provided. */
- if (signprivate && signprivate_pem) {
- fprintf(stderr, "Only one of --signprivate or --signprivate_pem must"
- " be specified\n");
- parse_error = 1;
- }
-
- if (signprivate_pem && !is_pem_algorithm) {
- fprintf(stderr, "--pem_algorithm must be used with --signprivate_pem\n");
- parse_error = 1;
- }
-
- if (external_signer && !signprivate_pem) {
- fprintf(stderr, "--externalsigner must be used with --signprivate_pem"
- "\n");
- parse_error = 1;
- }
-
- if (parse_error)
- return PrintHelp(progname);
-
- switch(mode) {
- case OPT_MODE_PACK:
- return Pack(filename, datapubkey, signprivate,
- signprivate_pem, pem_algorithm,
- flags,
- external_signer);
- case OPT_MODE_UNPACK:
- return Unpack(filename, datapubkey, signpubkey);
- default:
- printf("Must specify a mode.\n");
- return PrintHelp(progname);
- }
+static int do_vbutil_keyblock(int argc, char *argv[])
+{
+
+ char *filename = NULL;
+ char *datapubkey = NULL;
+ char *signpubkey = NULL;
+ char *signprivate = NULL;
+ char *signprivate_pem = NULL;
+ char *external_signer = NULL;
+ uint64_t flags = 0;
+ uint64_t pem_algorithm = 0;
+ int is_pem_algorithm = 0;
+ int mode = 0;
+ int parse_error = 0;
+ char *e;
+ int i;
+
+ char *progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
+ switch (i) {
+ case '?':
+ /* Unhandled option */
+ printf("Unknown option\n");
+ parse_error = 1;
+ break;
+
+ case OPT_MODE_PACK:
+ case OPT_MODE_UNPACK:
+ mode = i;
+ filename = optarg;
+ break;
+
+ case OPT_DATAPUBKEY:
+ datapubkey = optarg;
+ break;
+
+ case OPT_SIGNPUBKEY:
+ signpubkey = optarg;
+ break;
+
+ case OPT_SIGNPRIVATE:
+ signprivate = optarg;
+ break;
+
+ case OPT_SIGNPRIVATE_PEM:
+ signprivate_pem = optarg;
+ break;
+
+ case OPT_PEM_ALGORITHM:
+ pem_algorithm = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ fprintf(stderr, "Invalid --pem_algorithm\n");
+ parse_error = 1;
+ } else {
+ is_pem_algorithm = 1;
+ }
+ break;
+
+ case OPT_EXTERNAL_SIGNER:
+ external_signer = optarg;
+ break;
+
+ case OPT_FLAGS:
+ flags = strtoul(optarg, &e, 0);
+ if (!*optarg || (e && *e)) {
+ fprintf(stderr, "Invalid --flags\n");
+ parse_error = 1;
+ }
+ break;
+ }
+ }
+
+ /* Check if the right combination of options was provided. */
+ if (signprivate && signprivate_pem) {
+ fprintf(stderr,
+ "Only one of --signprivate or --signprivate_pem must"
+ " be specified\n");
+ parse_error = 1;
+ }
+
+ if (signprivate_pem && !is_pem_algorithm) {
+ fprintf(stderr, "--pem_algorithm must be used with"
+ " --signprivate_pem\n");
+ parse_error = 1;
+ }
+
+ if (external_signer && !signprivate_pem) {
+ fprintf(stderr,
+ "--externalsigner must be used with --signprivate_pem"
+ "\n");
+ parse_error = 1;
+ }
+
+ if (parse_error)
+ return PrintHelp(progname);
+
+ switch (mode) {
+ case OPT_MODE_PACK:
+ return Pack(filename, datapubkey, signprivate,
+ signprivate_pem, pem_algorithm,
+ flags, external_signer);
+ case OPT_MODE_UNPACK:
+ return Unpack(filename, datapubkey, signpubkey);
+ default:
+ printf("Must specify a mode.\n");
+ return PrintHelp(progname);
+ }
}
DECLARE_FUTIL_COMMAND(vbutil_keyblock, do_vbutil_keyblock,
diff --git a/futility/dump_kernel_config_lib.c b/futility/dump_kernel_config_lib.c
index 63c2899f..d3e88a96 100644
--- a/futility/dump_kernel_config_lib.c
+++ b/futility/dump_kernel_config_lib.c
@@ -14,106 +14,109 @@
#include "vboot_api.h"
#include "vboot_host.h"
-static uint8_t* GetKernelConfig(uint8_t* blob, size_t blob_size,
- uint64_t kernel_body_load_address) {
-
- VbKeyBlockHeader* key_block;
- VbKernelPreambleHeader* preamble;
- uint32_t now = 0;
- uint32_t offset = 0;
-
- /* Skip the key block */
- key_block = (VbKeyBlockHeader*)blob;
- now += key_block->key_block_size;
- if (now + blob > blob + blob_size) {
- VbExError("key_block_size advances past the end of the blob\n");
- return NULL;
- }
-
- /* Open up the preamble */
- preamble = (VbKernelPreambleHeader*)(blob + now);
- now += preamble->preamble_size;
- if (now + blob > blob + blob_size) {
- VbExError("preamble_size advances past the end of the blob\n");
- return NULL;
- }
-
- /* Read body_load_address from preamble if no kernel_body_load_address */
- if (kernel_body_load_address == USE_PREAMBLE_LOAD_ADDR)
- kernel_body_load_address = preamble->body_load_address;
-
- /* The x86 kernels have a pointer to the kernel commandline in the zeropage
- * table, but that's irrelevant for ARM. Both types keep the config blob in
- * the same place, so just go find it. */
- offset = preamble->bootloader_address -
- (kernel_body_load_address + CROS_PARAMS_SIZE +
- CROS_CONFIG_SIZE) + now;
- if (offset > blob_size) {
- VbExError("params are outside of the memory blob: %x\n", offset);
- return NULL;
- }
- return blob + offset;
-}
+static uint8_t *GetKernelConfig(uint8_t * blob, size_t blob_size,
+ uint64_t kernel_body_load_address)
+{
-static void* MMapFile(const char* filename, size_t *size) {
- FILE* f;
- uint8_t* buf;
- long file_size = 0;
-
- f = fopen(filename, "rb");
- if (!f) {
- VBDEBUG(("Unable to open file %s\n", filename));
- return NULL;
- }
-
- fseek(f, 0, SEEK_END);
- file_size = ftell(f);
- rewind(f);
-
- if (file_size <= 0) {
- fclose(f);
- return NULL;
- }
- *size = (size_t) file_size;
-
- /* Uses a host primitive as this is not meant for firmware use. */
- buf = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fileno(f), 0);
- if (buf == MAP_FAILED) {
- VbExError("Failed to mmap the file %s\n", filename);
- fclose(f);
- return NULL;
- }
-
- fclose(f);
- return buf;
+ VbKeyBlockHeader *key_block;
+ VbKernelPreambleHeader *preamble;
+ uint32_t now = 0;
+ uint32_t offset = 0;
+
+ /* Skip the key block */
+ key_block = (VbKeyBlockHeader *) blob;
+ now += key_block->key_block_size;
+ if (now + blob > blob + blob_size) {
+ VbExError("key_block_size advances past the end of the blob\n");
+ return NULL;
+ }
+
+ /* Open up the preamble */
+ preamble = (VbKernelPreambleHeader *) (blob + now);
+ now += preamble->preamble_size;
+ if (now + blob > blob + blob_size) {
+ VbExError("preamble_size advances past the end of the blob\n");
+ return NULL;
+ }
+
+ /* Read body_load_address from preamble if no
+ * kernel_body_load_address */
+ if (kernel_body_load_address == USE_PREAMBLE_LOAD_ADDR)
+ kernel_body_load_address = preamble->body_load_address;
+
+ /* The x86 kernels have a pointer to the kernel commandline in the
+ * zeropage table, but that's irrelevant for ARM. Both types keep the
+ * config blob in the same place, so just go find it. */
+ offset = preamble->bootloader_address -
+ (kernel_body_load_address + CROS_PARAMS_SIZE +
+ CROS_CONFIG_SIZE) + now;
+ if (offset > blob_size) {
+ VbExError("params are outside of the memory blob: %x\n",
+ offset);
+ return NULL;
+ }
+ return blob + offset;
}
+static void *MMapFile(const char *filename, size_t * size)
+{
+ FILE *f;
+ uint8_t *buf;
+ long file_size = 0;
+
+ f = fopen(filename, "rb");
+ if (!f) {
+ VBDEBUG(("Unable to open file %s\n", filename));
+ return NULL;
+ }
+
+ fseek(f, 0, SEEK_END);
+ file_size = ftell(f);
+ rewind(f);
+
+ if (file_size <= 0) {
+ fclose(f);
+ return NULL;
+ }
+ *size = (size_t) file_size;
+
+ /* Uses a host primitive as this is not meant for firmware use. */
+ buf = mmap(NULL, *size, PROT_READ, MAP_PRIVATE, fileno(f), 0);
+ if (buf == MAP_FAILED) {
+ VbExError("Failed to mmap the file %s\n", filename);
+ fclose(f);
+ return NULL;
+ }
+
+ fclose(f);
+ return buf;
+}
char *FindKernelConfig(const char *infile, uint64_t kernel_body_load_address)
{
- uint8_t* blob;
- size_t blob_size;
- uint8_t *config = NULL;
- char *newstr = NULL;
-
- blob = MMapFile(infile, &blob_size);
- if (!blob) {
- VbExError("Error reading input file\n");
- return 0;
- }
-
- config = GetKernelConfig(blob, blob_size, kernel_body_load_address);
- if (!config) {
- VbExError("Error parsing input file\n");
- munmap(blob, blob_size);
- return 0;
- }
-
- newstr = strndup((char *)config, CROS_CONFIG_SIZE);
- if (!newstr)
- VbExError("Can't allocate new string\n");
-
- munmap(blob, blob_size);
-
- return newstr;
+ uint8_t *blob;
+ size_t blob_size;
+ uint8_t *config = NULL;
+ char *newstr = NULL;
+
+ blob = MMapFile(infile, &blob_size);
+ if (!blob) {
+ VbExError("Error reading input file\n");
+ return 0;
+ }
+
+ config = GetKernelConfig(blob, blob_size, kernel_body_load_address);
+ if (!config) {
+ VbExError("Error parsing input file\n");
+ munmap(blob, blob_size);
+ return 0;
+ }
+
+ newstr = strndup((char *)config, CROS_CONFIG_SIZE);
+ if (!newstr)
+ VbExError("Can't allocate new string\n");
+
+ munmap(blob, blob_size);
+
+ return newstr;
}
diff --git a/futility/futility.c b/futility/futility.c
index a16beeb1..3496cdc2 100644
--- a/futility/futility.c
+++ b/futility/futility.c
@@ -28,7 +28,7 @@
/******************************************************************************/
-static const char * const usage= "\n\
+static const char *const usage = "\n\
Usage: " MYNAME " PROGRAM|COMMAND [args...]\n\
\n\
This is the unified firmware utility, which will eventually replace\n\
@@ -45,25 +45,26 @@ In either case it will append some usage information to " LOGFILE "\n\
static int do_help(int argc, char *argv[])
{
- const struct futil_cmd_t * const *cmd;
- int i;
+ const struct futil_cmd_t *const *cmd;
+ int i;
- fputs(usage, stdout);
+ fputs(usage, stdout);
- printf("The following commands are built-in:\n\n");
+ printf("The following commands are built-in:\n\n");
- for (cmd = futil_cmds; *cmd; cmd++)
- printf(" %-20s %s\n", (*cmd)->name, (*cmd)->shorthelp);
- printf("\n");
+ for (cmd = futil_cmds; *cmd; cmd++)
+ printf(" %-20s %s\n", (*cmd)->name, (*cmd)->shorthelp);
+ printf("\n");
- if (argc) {
- printf("FYI, you added these args that I'm ignoring:\n");
- for (i = 0; i < argc; i++)
- printf("argv[%d] = %s\n", i, argv[i]);
- }
+ if (argc) {
+ printf("FYI, you added these args that I'm ignoring:\n");
+ for (i = 0; i < argc; i++)
+ printf("argv[%d] = %s\n", i, argv[i]);
+ }
- return 0;
+ return 0;
}
+
DECLARE_FUTIL_COMMAND(help, do_help,
"Show a bit of help (you're looking at it)");
@@ -71,11 +72,11 @@ DECLARE_FUTIL_COMMAND(help, do_help,
* These are built-in functions that we'd like to abandon completely someday.
* TODO: If no one complains, get rid of them.
*/
-static const char * const dep_cmds[] = {
- "dev_sign_file",
+static const char *const dep_cmds[] = {
+ "dev_sign_file",
};
-static const char * const dep_usage= "\n\
+static const char *const dep_usage = "\n\
The program \"%s\" is deprecated and may go away soon.\n\
\n\
If you feel this is in error, please open a bug at\n\
@@ -89,8 +90,8 @@ In the meantime, you may continue to use the program by invoking it as\n\
static void deprecated(const char *depname)
{
- fprintf(stderr, dep_usage, depname, depname);
- exit(1);
+ fprintf(stderr, dep_usage, depname, depname);
+ exit(1);
}
/******************************************************************************/
@@ -101,188 +102,187 @@ static int log_fd = -1;
/* Write the string and a newline. Silently give up on errors */
static void log_str(char *str)
{
- int len, done, n;
+ int len, done, n;
- if (log_fd < 0)
- return;
+ if (log_fd < 0)
+ return;
- if (!str)
- str = "(NULL)";
+ if (!str)
+ str = "(NULL)";
- len = strlen(str);
- if (len == 0) {
- str = "(EMPTY)";
- len = strlen(str);
- }
+ len = strlen(str);
+ if (len == 0) {
+ str = "(EMPTY)";
+ len = strlen(str);
+ }
- for (done = 0; done < len; done += n) {
- n = write(log_fd, str + done, len - done);
- if (n < 0)
- return;
- }
+ for (done = 0; done < len; done += n) {
+ n = write(log_fd, str + done, len - done);
+ if (n < 0)
+ return;
+ }
- if (write(log_fd, "\n", 1) < 0)
- return;
+ if (write(log_fd, "\n", 1) < 0)
+ return;
}
static void log_close(void)
{
- struct flock lock;
-
- if (log_fd >= 0) {
- memset(&lock, 0, sizeof(lock));
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- if (fcntl(log_fd, F_SETLKW, &lock))
- perror("Unable to unlock log file");
-
- close(log_fd);
- log_fd = -1;
- }
+ struct flock lock;
+
+ if (log_fd >= 0) {
+ memset(&lock, 0, sizeof(lock));
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+ if (fcntl(log_fd, F_SETLKW, &lock))
+ perror("Unable to unlock log file");
+
+ close(log_fd);
+ log_fd = -1;
+ }
}
static void log_open(void)
{
- struct flock lock;
- int ret;
+ struct flock lock;
+ int ret;
#ifdef FORCE_LOGGING_ON
- log_fd = open(LOGFILE, O_WRONLY|O_APPEND|O_CREAT, 0666);
+ log_fd = open(LOGFILE, O_WRONLY | O_APPEND | O_CREAT, 0666);
#else
- log_fd = open(LOGFILE, O_WRONLY|O_APPEND);
+ log_fd = open(LOGFILE, O_WRONLY | O_APPEND);
#endif
- if (log_fd < 0) {
+ if (log_fd < 0) {
- if (errno != EACCES)
- return;
+ if (errno != EACCES)
+ return;
- /* Permission problems should improve shortly ... */
- sleep(1);
- log_fd = open(LOGFILE, O_WRONLY|O_APPEND|O_CREAT, 0666);
- if (log_fd < 0) /* Nope, they didn't */
- return;
- }
+ /* Permission problems should improve shortly ... */
+ sleep(1);
+ log_fd = open(LOGFILE, O_WRONLY | O_APPEND | O_CREAT, 0666);
+ if (log_fd < 0) /* Nope, they didn't */
+ return;
+ }
- /* Let anyone have a turn */
- fchmod(log_fd, 0666);
+ /* Let anyone have a turn */
+ fchmod(log_fd, 0666);
- /* But only one at a time */
- memset(&lock, 0, sizeof(lock));
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_END;
+ /* But only one at a time */
+ memset(&lock, 0, sizeof(lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_END;
- ret = fcntl(log_fd, F_SETLKW, &lock); /* this blocks */
- if (ret < 0)
- log_close();
+ ret = fcntl(log_fd, F_SETLKW, &lock); /* this blocks */
+ if (ret < 0)
+ log_close();
}
#define CALLER_PREFIX "CALLER:"
static void log_args(int argc, char *argv[])
{
- int i;
- ssize_t r;
- pid_t parent;
- char buf[80];
- char str_caller[PATH_MAX + sizeof(CALLER_PREFIX)] = CALLER_PREFIX;
- char *truename = str_caller + sizeof(CALLER_PREFIX) - 1;
- /* Note: truename starts on the \0 from CALLER_PREFIX, so we can write
- * PATH_MAX chars into truename and still append a \0 at the end. */
-
- log_open();
-
- /* delimiter */
- log_str("##### HEY #####");
-
- /* Can we tell who called us? */
- parent = getppid();
- snprintf(buf, sizeof(buf), "/proc/%d/exe", parent);
- r = readlink(buf, truename, PATH_MAX);
- if (r >= 0) {
- truename[r] = '\0';
- log_str(str_caller);
- }
-
- /* Now log the stuff about ourselves */
- for (i = 0; i < argc; i++)
- log_str(argv[i]);
-
- log_close();
+ int i;
+ ssize_t r;
+ pid_t parent;
+ char buf[80];
+ char str_caller[PATH_MAX + sizeof(CALLER_PREFIX)] = CALLER_PREFIX;
+ char *truename = str_caller + sizeof(CALLER_PREFIX) - 1;
+ /* Note: truename starts on the \0 from CALLER_PREFIX, so we can write
+ * PATH_MAX chars into truename and still append a \0 at the end. */
+
+ log_open();
+
+ /* delimiter */
+ log_str("##### HEY #####");
+
+ /* Can we tell who called us? */
+ parent = getppid();
+ snprintf(buf, sizeof(buf), "/proc/%d/exe", parent);
+ r = readlink(buf, truename, PATH_MAX);
+ if (r >= 0) {
+ truename[r] = '\0';
+ log_str(str_caller);
+ }
+
+ /* Now log the stuff about ourselves */
+ for (i = 0; i < argc; i++)
+ log_str(argv[i]);
+
+ log_close();
}
-
/******************************************************************************/
/* Here we go */
int main(int argc, char *argv[], char *envp[])
{
- char *fullname, *progname;
- char truename[PATH_MAX];
- char buf[80];
- pid_t myproc;
- ssize_t r;
- const struct futil_cmd_t * const *cmd;
- int i;
- int via_symlink = 0;
-
- log_args(argc, argv);
-
- /* How were we invoked? */
- fullname = strdup(argv[0]);
- progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- /* Invoked directly by name */
- if (0 == strcmp(progname, MYNAME) || 0 == strcmp(progname, MYNAME_S)) {
- if (argc < 2) { /* must have an argument */
- do_help(0, 0);
- exit(1);
- }
-
- /* We can just pass the rest along, then */
- argc--;
- argv++;
-
- /* So now what function do we want to invoke? */
- progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
- } else { /* Invoked by symlink */
- via_symlink = 1;
- /* Block any deprecated functions. */
- for (i = 0; i < ARRAY_SIZE(dep_cmds); i++)
- if (0 == strcmp(dep_cmds[i], progname))
- deprecated(progname);
- }
-
- /* See if it's asking for something we know how to do ourselves */
- for (cmd = futil_cmds; *cmd; cmd++)
- if (0 == strcmp((*cmd)->name, progname))
- return (*cmd)->handler(argc, argv);
-
- /* Nope */
- if (!via_symlink) {
- do_help(0, 0);
- exit(1);
- }
-
- /* Complain about bogus symlink */
-
- myproc = getpid();
- snprintf(buf, sizeof(buf), "/proc/%d/exe", myproc);
- r = readlink(buf, truename, PATH_MAX - 1);
- if (r < 0) {
- fprintf(stderr, "%s is lost: %s => %s: %s\n", MYNAME, argv[0],
- buf, strerror(errno));
- exit(1);
- }
- truename[r] = '\0';
-
- fprintf(stderr, "\n\
+ char *fullname, *progname;
+ char truename[PATH_MAX];
+ char buf[80];
+ pid_t myproc;
+ ssize_t r;
+ const struct futil_cmd_t *const *cmd;
+ int i;
+ int via_symlink = 0;
+
+ log_args(argc, argv);
+
+ /* How were we invoked? */
+ fullname = strdup(argv[0]);
+ progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ /* Invoked directly by name */
+ if (0 == strcmp(progname, MYNAME) || 0 == strcmp(progname, MYNAME_S)) {
+ if (argc < 2) { /* must have an argument */
+ do_help(0, 0);
+ exit(1);
+ }
+
+ /* We can just pass the rest along, then */
+ argc--;
+ argv++;
+
+ /* So now what function do we want to invoke? */
+ progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+ } else { /* Invoked by symlink */
+ via_symlink = 1;
+ /* Block any deprecated functions. */
+ for (i = 0; i < ARRAY_SIZE(dep_cmds); i++)
+ if (0 == strcmp(dep_cmds[i], progname))
+ deprecated(progname);
+ }
+
+ /* See if it's asking for something we know how to do ourselves */
+ for (cmd = futil_cmds; *cmd; cmd++)
+ if (0 == strcmp((*cmd)->name, progname))
+ return (*cmd)->handler(argc, argv);
+
+ /* Nope */
+ if (!via_symlink) {
+ do_help(0, 0);
+ exit(1);
+ }
+
+ /* Complain about bogus symlink */
+
+ myproc = getpid();
+ snprintf(buf, sizeof(buf), "/proc/%d/exe", myproc);
+ r = readlink(buf, truename, PATH_MAX - 1);
+ if (r < 0) {
+ fprintf(stderr, "%s is lost: %s => %s: %s\n", MYNAME, argv[0],
+ buf, strerror(errno));
+ exit(1);
+ }
+ truename[r] = '\0';
+
+ fprintf(stderr, "\n\
The program\n\n %s\n\nis a symlink to\n\n %s\n\
\n\
However, " MYNAME " doesn't know how to implement that function.\n\
@@ -292,5 +292,5 @@ after a fresh checkout/build/install, please open a bug at\n\
\n\
http://dev.chromium.org/for-testers/bug-reporting-guidelines\n\
\n", fullname, truename);
- return 1;
+ return 1;
}
diff --git a/futility/futility.h b/futility/futility.h
index 387c7156..32c553db 100644
--- a/futility/futility.h
+++ b/futility/futility.h
@@ -10,9 +10,9 @@
/* 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);
- const char * const shorthelp;
+ const char *const name;
+ int (*const handler) (int argc, char **argv);
+ const char *const shorthelp;
};
/*
@@ -33,7 +33,7 @@ struct futil_cmd_t {
= &__cmd_##NAME
/* This is the list of pointers to all commands. */
-extern const struct futil_cmd_t * const futil_cmds[];
+extern const struct futil_cmd_t *const futil_cmds[];
/* Size of an array */
#ifndef ARRAY_SIZE
diff --git a/futility/kernel_blob.h b/futility/kernel_blob.h
index 173d48d2..6ecc02d7 100644
--- a/futility/kernel_blob.h
+++ b/futility/kernel_blob.h
@@ -1,65 +1,62 @@
-// Copyright 2010 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.
-//
-// Constants describing the kernel blob content.
-
+/* Copyright 2010 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.
+ *
+ * Constants describing the kernel blob content.
+ */
#ifndef VBOOT_REFERENCE_KERNEL_BLOB_H_
#define VBOOT_REFERENCE_KERNEL_BLOB_H_
-
-// Maximum kernel command-line size
+/* Maximum kernel command-line size */
#define CROS_CONFIG_SIZE 4096
-// Size of the x86 zeropage table
+/* Size of the x86 zeropage table */
#define CROS_PARAMS_SIZE 4096
-// Alignment of various chunks within the kernel blob
+/* Alignment of various chunks within the kernel blob */
#define CROS_ALIGN 4096
-// Sentinel RAM address indicating that no entry address is specified
+/* Sentinel RAM address indicating that no entry address is specified */
#define CROS_NO_ENTRY_ADDR (~0)
-// RAM address where the 32-bit kernel expects to be started
+/* RAM address where the 32-bit kernel expects to be started */
#define CROS_32BIT_ENTRY_ADDR 0x100000
-// Simplified version of x86 kernel e820 memory map entries
+/* Simplified version of x86 kernel e820 memory map entries */
#define E820_ENTRY_MAX 128
#define E820_TYPE_RAM 1
#define E820_TYPE_RESERVED 2
struct linux_kernel_e820entry {
- uint64_t start_addr;
- uint64_t segment_size;
- uint32_t segment_type;
-} __attribute__((packed));
-
-// Simplified version of the x86 kernel zeropage table
-struct linux_kernel_params
-{
- uint8_t pad0[0x1e8 - 0x0];
- uint8_t n_e820_entry; // 1e8
- uint8_t pad1[0x1f1 - 0x1e9];
- uint8_t setup_sects; // 1f1
- uint8_t pad2[0x1fe - 0x1f2];
- uint16_t boot_flag; // 1fe
- uint16_t jump; // 200
- uint32_t header; // 202
- uint16_t version; // 206
- uint8_t pad3[0x210 - 0x208];
- uint8_t type_of_loader; // 210
- uint8_t pad4[0x218 - 0x211];
- uint32_t ramdisk_image; // 218
- uint32_t ramdisk_size; // 21c
- uint8_t pad5[0x228 - 0x220];
- uint32_t cmd_line_ptr; // 228
- uint32_t ramdisk_max; // 22c
- uint32_t kernel_alignment; // 230
- uint8_t relocatable_kernel; // 234
- uint8_t min_alignment; // 235
- uint8_t pad6[0x2d0 - 0x236];
- struct linux_kernel_e820entry e820_entries[E820_ENTRY_MAX]; // 2d0 - cd0
+ uint64_t start_addr;
+ uint64_t segment_size;
+ uint32_t segment_type;
} __attribute__ ((packed));
+/* Simplified version of the x86 kernel zeropage table */
+struct linux_kernel_params {
+ uint8_t pad0[0x1e8 - 0x0];
+ uint8_t n_e820_entry; /* 1e8 */
+ uint8_t pad1[0x1f1 - 0x1e9];
+ uint8_t setup_sects; /* 1f1 */
+ uint8_t pad2[0x1fe - 0x1f2];
+ uint16_t boot_flag; /* 1fe */
+ uint16_t jump; /* 200 */
+ uint32_t header; /* 202 */
+ uint16_t version; /* 206 */
+ uint8_t pad3[0x210 - 0x208];
+ uint8_t type_of_loader; /* 210 */
+ uint8_t pad4[0x218 - 0x211];
+ uint32_t ramdisk_image; /* 218 */
+ uint32_t ramdisk_size; /* 21c */
+ uint8_t pad5[0x228 - 0x220];
+ uint32_t cmd_line_ptr; /* 228 */
+ uint32_t ramdisk_max; /* 22c */
+ uint32_t kernel_alignment; /* 230 */
+ uint8_t relocatable_kernel; /* 234 */
+ uint8_t min_alignment; /* 235 */
+ uint8_t pad6[0x2d0 - 0x236];
+ struct linux_kernel_e820entry e820_entries[E820_ENTRY_MAX]; /* 2d0-cd0 */
+} __attribute__ ((packed));
-#endif // VBOOT_REFERENCE_KERNEL_BLOB_H_
+#endif /* VBOOT_REFERENCE_KERNEL_BLOB_H_ */