diff options
author | Zach Reizner <zachr@chromium.org> | 2015-02-20 14:55:02 -0800 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-02-23 18:41:01 +0000 |
commit | 317bb498a697ae49f070e3ca46100b879f25aa1b (patch) | |
tree | aa3a68bc9e3f06d58ca311c996a53520a323dcd0 /host/lib/extract_vmlinuz.c | |
parent | f44ebbe36b2c1603437edc57b534244e89bfcd9c (diff) | |
download | vboot-317bb498a697ae49f070e3ca46100b879f25aa1b.tar.gz |
vboot2: add library function for extracting vmlinuz from kernel part
postinst needs access to a kernel that is bootable from legacy BIOS.
futility provides extraction of a bootable vmlinuz from the kernel
partition via the command line. This patch provides a function which
does the same thing and is suitable for static linking into postinst
with minimal additonal code linked in. This way we can avoid issues with
running dynamic executables during postinst.
BRANCH=none
TEST=None
BUG=chromium:455343
Change-Id: Iaec2f48e4d8f78a4bbfcc1636b6ce478e95e9a8e
Reviewed-on: https://chromium-review.googlesource.com/251760
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Commit-Queue: Zach Reizner <zachr@chromium.org>
Tested-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'host/lib/extract_vmlinuz.c')
-rw-r--r-- | host/lib/extract_vmlinuz.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/host/lib/extract_vmlinuz.c b/host/lib/extract_vmlinuz.c new file mode 100644 index 00000000..81d3918e --- /dev/null +++ b/host/lib/extract_vmlinuz.c @@ -0,0 +1,74 @@ +/* Copyright 2015 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Exports a vmlinuz from a kernel partition in memory. + */ + +#include <stdlib.h> +#include <string.h> + +#include "vboot_struct.h" + + +int ExtractVmlinuz(void *kpart_data, size_t kpart_size, + void **vmlinuz_out, size_t *vmlinuz_size) { + uint64_t now = 0; + VbKeyBlockHeader *keyblock = NULL; + VbKernelPreambleHeader *preamble = NULL; + uint8_t *kblob_data = NULL; + uint64_t kblob_size = 0; + uint64_t vmlinuz_header_size = 0; + uint64_t vmlinuz_header_address = 0; + uint64_t vmlinuz_header_offset = 0; + void *vmlinuz = NULL; + + keyblock = (VbKeyBlockHeader *)kpart_data; + now += keyblock->key_block_size; + if (now > kpart_size) + return 1; + + preamble = (VbKernelPreambleHeader *)(kpart_data + now); + now += preamble->preamble_size; + if (now > kpart_size) + return 1; + + kblob_data = kpart_data + now; + kblob_size = preamble->body_signature.data_size; + + if (!kblob_data || (now + kblob_size) > kpart_size) + return 1; + + if (preamble->header_version_minor > 0) { + vmlinuz_header_address = preamble->vmlinuz_header_address; + vmlinuz_header_size = preamble->vmlinuz_header_size; + } + + if (!vmlinuz_header_size || + kpart_data + vmlinuz_header_offset + vmlinuz_header_size > kpart_data) { + return 1; + } + + // calculate the vmlinuz_header offset from + // the beginning of the kpart_data. The kblob doesn't + // include the body_load_offset, but does include + // the keyblock and preamble sections. + vmlinuz_header_offset = vmlinuz_header_address - + preamble->body_load_address + + keyblock->key_block_size + + preamble->preamble_size; + + vmlinuz = malloc(vmlinuz_header_size + kblob_size); + if (vmlinuz == NULL) + return 1; + + memcpy(vmlinuz, kpart_data + vmlinuz_header_offset, + vmlinuz_header_size); + + memcpy(vmlinuz + vmlinuz_header_size, kblob_data, kblob_size); + + *vmlinuz_out = vmlinuz; + *vmlinuz_size = vmlinuz_header_size + kblob_size; + + return 0; +} |