summaryrefslogtreecommitdiff
path: root/host/lib/extract_vmlinuz.c
diff options
context:
space:
mode:
authorZach Reizner <zachr@chromium.org>2015-02-20 14:55:02 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-02-23 18:41:01 +0000
commit317bb498a697ae49f070e3ca46100b879f25aa1b (patch)
treeaa3a68bc9e3f06d58ca311c996a53520a323dcd0 /host/lib/extract_vmlinuz.c
parentf44ebbe36b2c1603437edc57b534244e89bfcd9c (diff)
downloadvboot-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.c74
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;
+}