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>
This commit is contained in:
Zach Reizner
2015-02-20 14:55:02 -08:00
committed by ChromeOS Commit Bot
parent f44ebbe36b
commit 317bb498a6
3 changed files with 86 additions and 1 deletions

View File

@@ -454,6 +454,7 @@ HOSTLIB_SRCS = \
futility/dump_kernel_config_lib.c \
host/arch/${ARCH}/lib/crossystem_arch.c \
host/lib/crossystem.c \
host/lib/extract_vmlinuz.c \
host/lib/fmap.c \
host/lib/host_misc.c
@@ -478,7 +479,8 @@ TINYHOSTLIB_SRCS = \
firmware/stub/vboot_api_stub_disk.c \
firmware/stub/vboot_api_stub_sf.c \
firmware/stub/utility_stub.c \
futility/dump_kernel_config_lib.c
futility/dump_kernel_config_lib.c \
host/lib/extract_vmlinuz.c
TINYHOSTLIB_OBJS = ${TINYHOSTLIB_SRCS:%.c=${BUILD}/%.o}

View File

@@ -58,5 +58,14 @@ char *FindKernelConfig(const char *filename,
uint64_t kernel_body_load_address);
/****************************************************************************/
/* Kernel partition */
/* Used to get a bootable vmlinuz from the kernel partition. vmlinuz_out must
* be free'd after this function returns success. Success is indicated by a
* zero return value.
*/
int ExtractVmlinuz(void *kpart_data, size_t kpart_size,
void **vmlinuz_out, size_t *vmlinuz_size);
#endif /* VBOOT_HOST_H_ */

View File

@@ -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;
}