diff options
-rw-r--r-- | utility/dump_kernel_config.c | 60 | ||||
-rw-r--r-- | utility/vbutil_kernel.c | 59 |
2 files changed, 94 insertions, 25 deletions
diff --git a/utility/dump_kernel_config.c b/utility/dump_kernel_config.c index 4decc7de..b44a12e0 100644 --- a/utility/dump_kernel_config.c +++ b/utility/dump_kernel_config.c @@ -5,6 +5,7 @@ * Exports the kernel commandline from a given partition/image. */ +#include <getopt.h> #include <inttypes.h> /* For uint64_t */ #include <stdio.h> #include <stdlib.h> @@ -16,17 +17,28 @@ #include "vboot_common.h" #include "vboot_struct.h" +enum { + OPT_KLOADADDR = 1000, +}; + +static struct option long_opts[] = { + { "kloadaddr", 1, 0, OPT_KLOADADDR }, + { NULL, 0, 0, 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 <image/blockdevice>\n" + "Usage: dump_kernel_config [--kloadaddr <ADDRESS>] " + "<image/blockdevice>\n" "\n" ""); return 1; } -static uint8_t* find_kernel_config(uint8_t* blob, uint64_t blob_size) { +static uint8_t* find_kernel_config(uint8_t* blob, uint64_t blob_size, + uint64_t kernel_body_load_address) { VbKeyBlockHeader* key_block; VbKernelPreambleHeader* preamble; struct linux_kernel_params *params; @@ -52,7 +64,7 @@ static uint8_t* find_kernel_config(uint8_t* blob, uint64_t blob_size) { /* The parameters are packed before the bootloader and there is no specific * pointer to it so we just walk back by its allocated size. */ offset = preamble->bootloader_address - - (CROS_32BIT_ENTRY_ADDR + CROS_PARAMS_SIZE) + now; + (kernel_body_load_address + CROS_PARAMS_SIZE) + now; if (offset > blob_size) { error("params are outside of the memory blob: %x\n", offset); return NULL; @@ -60,7 +72,7 @@ static uint8_t* find_kernel_config(uint8_t* blob, uint64_t blob_size) { params = (struct linux_kernel_params *)(blob + offset); /* Grab the offset to the kernel command line using the supplied pointer. */ - offset = params->cmd_line_ptr - CROS_32BIT_ENTRY_ADDR + now; + offset = params->cmd_line_ptr - kernel_body_load_address + now; if (offset > blob_size) { error("cmdline is outside of the memory blob: %x\n", offset); return NULL; @@ -104,10 +116,43 @@ static void* MapFile(const char *filename, size_t *size) { int main(int argc, char* argv[]) { uint8_t* blob; size_t blob_size; - char* infile = argv[1]; + char* infile = NULL; uint8_t *config = NULL; + uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_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 (argc < 2) + if (parse_error) return PrintHelp(); if (!infile || !*infile) { @@ -122,7 +167,8 @@ int main(int argc, char* argv[]) { return 1; } - config = find_kernel_config(blob, (uint64_t)blob_size); + config = find_kernel_config(blob, (uint64_t)blob_size, + kernel_body_load_address); if (!config) { error("Error parsing input file\n"); munmap(blob, blob_size); diff --git a/utility/vbutil_kernel.c b/utility/vbutil_kernel.c index a8986db5..85f8a514 100644 --- a/utility/vbutil_kernel.c +++ b/utility/vbutil_kernel.c @@ -35,6 +35,7 @@ enum { OPT_MODE_VERIFY, OPT_ARCH, OPT_OLDBLOB, + OPT_KLOADADDR, OPT_KEYBLOCK, OPT_SIGNPUBKEY, OPT_SIGNPRIVATE, @@ -58,6 +59,7 @@ static struct option long_opts[] = { {"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 }, @@ -92,6 +94,7 @@ static int PrintHelp(char *progname) { " --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); @@ -109,6 +112,7 @@ static int PrintHelp(char *progname) { " --version <number> Kernel version\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); @@ -121,7 +125,8 @@ static int PrintHelp(char *progname) { " Public key to verify kernel keyblock, in .vbpubk format\n" " --verbose Print a more detailed report\n" " --keyblock <file>" - " Outputs the verified key block, in .keyblock format\n" + " Outputs the verified key block, in .keyblock format\n" + " --kloadaddr <address> Assign kernel body load address\n" "\n", progname); return 1; @@ -199,9 +204,9 @@ typedef struct blob_s { } blob_t; /* Given a blob return the location of the kernel command line buffer. */ -static char* BpCmdLineLocation(blob_t *bp) +static char* BpCmdLineLocation(blob_t *bp, uint64_t kernel_body_load_address) { - return (char*)(bp->blob + bp->bootloader_address - CROS_32BIT_ENTRY_ADDR - + return (char*)(bp->blob + bp->bootloader_address - kernel_body_load_address - CROS_CONFIG_SIZE - CROS_PARAMS_SIZE); } @@ -249,7 +254,8 @@ static blob_t *NewBlob(uint64_t version, const char* vmlinuz, const char* bootloader_file, const char* config_file, - int arch) { + int arch, + uint64_t kernel_body_load_address) { blob_t* bp; struct linux_kernel_header* lh = 0; struct linux_kernel_params* params = 0; @@ -340,7 +346,7 @@ static blob_t *NewBlob(uint64_t version, Debug("config goes at blob+0x%" PRIx64 "\n", now); /* Find the load address of the commandline. We'll need it later. */ - cmdline_addr = CROS_32BIT_ENTRY_ADDR + now + + cmdline_addr = kernel_body_load_address + now + find_cmdline_start((char *)config_buf, config_size); Debug(" cmdline_addr=0x%" PRIx64 "\n", cmdline_addr); @@ -377,7 +383,7 @@ static blob_t *NewBlob(uint64_t version, /* Finally, append the bootloader. Remember where it will load in * memory, too. */ Debug("bootloader goes at blob+=0x%" PRIx64 "\n", now); - bp->bootloader_address = CROS_32BIT_ENTRY_ADDR + now; + bp->bootloader_address = kernel_body_load_address + now; bp->bootloader_size = roundup(bootloader_size, CROS_ALIGN); Debug(" bootloader_address=0x%" PRIx64 "\n", bp->bootloader_address); Debug(" bootloader_size=0x%" PRIx64 "\n", bp->bootloader_size); @@ -525,7 +531,8 @@ unwind_oldblob: /* Pack a .kernel */ static int Pack(const char* outfile, const char* keyblock_file, const char* signprivate, blob_t *bp, uint64_t pad, - int vblockonly) { + int vblockonly, + uint64_t kernel_body_load_address) { VbPrivateKey* signing_key; VbSignature* body_sig; VbKernelPreambleHeader* preamble; @@ -579,7 +586,7 @@ static int Pack(const char* outfile, const char* keyblock_file, /* Create preamble */ preamble = CreateKernelPreamble(bp->kernel_version, - CROS_32BIT_ENTRY_ADDR, + kernel_body_load_address, bp->bootloader_address, bp->bootloader_size, body_sig, @@ -628,7 +635,8 @@ static int Pack(const char* outfile, const char* keyblock_file, /* * Replace kernel command line in a blob representing a kernel. */ -static int ReplaceConfig(blob_t* bp, const char* config_file) +static int ReplaceConfig(blob_t* bp, const char* config_file, + uint64_t kernel_body_load_address) { uint8_t* new_conf; uint64_t config_size; @@ -643,14 +651,16 @@ static int ReplaceConfig(blob_t* bp, const char* config_file) } /* fill the config buffer with zeros */ - Memset(BpCmdLineLocation(bp), 0, CROS_CONFIG_SIZE); - Memcpy(BpCmdLineLocation(bp), new_conf, config_size); + Memset(BpCmdLineLocation(bp, kernel_body_load_address), 0, CROS_CONFIG_SIZE); + Memcpy(BpCmdLineLocation(bp, kernel_body_load_address), + new_conf, config_size); Free(new_conf); return 0; } static int Verify(const char* infile, const char* signpubkey, int verbose, - const char* key_block_file) { + const char* key_block_file, + uint64_t kernel_body_load_address) { VbKeyBlockHeader* key_block; VbKernelPreambleHeader* preamble; @@ -769,7 +779,7 @@ static int Verify(const char* infile, const char* signpubkey, int verbose, goto verify_exit; } - printf("Config:\n%s\n", BpCmdLineLocation(bp)); + printf("Config:\n%s\n", BpCmdLineLocation(bp, kernel_body_load_address)); verify_exit: FreeBlob(bp); @@ -790,6 +800,7 @@ int main(int argc, char* argv[]) { int arch = ARCH_X86; int vblockonly = 0; int verbose = 0; + uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_ADDR; uint64_t pad = DEFAULT_PADDING; int mode = 0; int parse_error = 0; @@ -844,6 +855,14 @@ int main(int argc, char* argv[]) { oldfile = optarg; 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; + case OPT_KEYBLOCK: key_block_file = optarg; break; @@ -899,10 +918,12 @@ int main(int argc, char* argv[]) { switch(mode) { case OPT_MODE_PACK: - bp = NewBlob(version, vmlinuz, bootloader, config_file, arch); + bp = NewBlob(version, vmlinuz, bootloader, config_file, arch, + kernel_body_load_address); if (!bp) return 1; - r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly); + r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly, + kernel_body_load_address); FreeBlob(bp); return r; @@ -917,18 +938,20 @@ int main(int argc, char* argv[]) { bp = OldBlob(oldfile); if (!bp) return 1; - r = ReplaceConfig(bp, config_file); + r = ReplaceConfig(bp, config_file, kernel_body_load_address); if (!r) { if (version >= 0) { bp->kernel_version = (uint64_t) version; } - r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly); + r = Pack(filename, key_block_file, signprivate, bp, pad, vblockonly, + kernel_body_load_address); } FreeBlob(bp); return r; case OPT_MODE_VERIFY: - return Verify(filename, signpubkey, verbose, key_block_file); + return Verify(filename, signpubkey, verbose, key_block_file, + kernel_body_load_address); default: fprintf(stderr, |