mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 18:25:10 +00:00
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>
75 lines
2.0 KiB
C
75 lines
2.0 KiB
C
/* 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;
|
|
}
|