1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2015 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker *
5*8617a60dSAndroid Build Coastguard Worker * Exports a vmlinuz from a kernel partition in memory.
6*8617a60dSAndroid Build Coastguard Worker */
7*8617a60dSAndroid Build Coastguard Worker
8*8617a60dSAndroid Build Coastguard Worker #include <stdlib.h>
9*8617a60dSAndroid Build Coastguard Worker #include <string.h>
10*8617a60dSAndroid Build Coastguard Worker
11*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
12*8617a60dSAndroid Build Coastguard Worker #include "2struct.h"
13*8617a60dSAndroid Build Coastguard Worker #include "vboot_host.h"
14*8617a60dSAndroid Build Coastguard Worker #include "vboot_struct.h"
15*8617a60dSAndroid Build Coastguard Worker
ExtractVmlinuz(void * kpart_data,size_t kpart_size,void ** vmlinuz_out,size_t * vmlinuz_size)16*8617a60dSAndroid Build Coastguard Worker int ExtractVmlinuz(void *kpart_data, size_t kpart_size,
17*8617a60dSAndroid Build Coastguard Worker void **vmlinuz_out, size_t *vmlinuz_size) {
18*8617a60dSAndroid Build Coastguard Worker size_t now = 0;
19*8617a60dSAndroid Build Coastguard Worker struct vb2_kernel_preamble *preamble = NULL;
20*8617a60dSAndroid Build Coastguard Worker uint8_t *kblob_data = NULL;
21*8617a60dSAndroid Build Coastguard Worker uint32_t kblob_size = 0;
22*8617a60dSAndroid Build Coastguard Worker uint32_t vmlinuz_header_size = 0;
23*8617a60dSAndroid Build Coastguard Worker uint64_t vmlinuz_header_address = 0;
24*8617a60dSAndroid Build Coastguard Worker uint64_t vmlinuz_header_offset = 0;
25*8617a60dSAndroid Build Coastguard Worker void *vmlinuz = NULL;
26*8617a60dSAndroid Build Coastguard Worker
27*8617a60dSAndroid Build Coastguard Worker struct vb2_keyblock *keyblock = (struct vb2_keyblock *)kpart_data;
28*8617a60dSAndroid Build Coastguard Worker now += keyblock->keyblock_size;
29*8617a60dSAndroid Build Coastguard Worker if (now > kpart_size)
30*8617a60dSAndroid Build Coastguard Worker return 1;
31*8617a60dSAndroid Build Coastguard Worker
32*8617a60dSAndroid Build Coastguard Worker preamble = (struct vb2_kernel_preamble *)(kpart_data + now);
33*8617a60dSAndroid Build Coastguard Worker now += preamble->preamble_size;
34*8617a60dSAndroid Build Coastguard Worker if (now > kpart_size)
35*8617a60dSAndroid Build Coastguard Worker return 1;
36*8617a60dSAndroid Build Coastguard Worker
37*8617a60dSAndroid Build Coastguard Worker kblob_data = kpart_data + now;
38*8617a60dSAndroid Build Coastguard Worker kblob_size = preamble->body_signature.data_size;
39*8617a60dSAndroid Build Coastguard Worker
40*8617a60dSAndroid Build Coastguard Worker if (!kblob_data || (now + kblob_size) > kpart_size)
41*8617a60dSAndroid Build Coastguard Worker return 1;
42*8617a60dSAndroid Build Coastguard Worker
43*8617a60dSAndroid Build Coastguard Worker if (preamble->header_version_minor > 0) {
44*8617a60dSAndroid Build Coastguard Worker vmlinuz_header_address = preamble->vmlinuz_header_address;
45*8617a60dSAndroid Build Coastguard Worker vmlinuz_header_size = preamble->vmlinuz_header_size;
46*8617a60dSAndroid Build Coastguard Worker }
47*8617a60dSAndroid Build Coastguard Worker
48*8617a60dSAndroid Build Coastguard Worker if (!vmlinuz_header_size ||
49*8617a60dSAndroid Build Coastguard Worker kpart_data + vmlinuz_header_offset + vmlinuz_header_size >
50*8617a60dSAndroid Build Coastguard Worker kpart_data) {
51*8617a60dSAndroid Build Coastguard Worker return 1;
52*8617a60dSAndroid Build Coastguard Worker }
53*8617a60dSAndroid Build Coastguard Worker
54*8617a60dSAndroid Build Coastguard Worker // calculate the vmlinuz_header offset from
55*8617a60dSAndroid Build Coastguard Worker // the beginning of the kpart_data. The kblob doesn't
56*8617a60dSAndroid Build Coastguard Worker // include the body_load_offset, but does include
57*8617a60dSAndroid Build Coastguard Worker // the keyblock and preamble sections.
58*8617a60dSAndroid Build Coastguard Worker vmlinuz_header_offset = vmlinuz_header_address -
59*8617a60dSAndroid Build Coastguard Worker preamble->body_load_address +
60*8617a60dSAndroid Build Coastguard Worker keyblock->keyblock_size +
61*8617a60dSAndroid Build Coastguard Worker preamble->preamble_size;
62*8617a60dSAndroid Build Coastguard Worker
63*8617a60dSAndroid Build Coastguard Worker vmlinuz = malloc(vmlinuz_header_size + kblob_size);
64*8617a60dSAndroid Build Coastguard Worker if (vmlinuz == NULL)
65*8617a60dSAndroid Build Coastguard Worker return 1;
66*8617a60dSAndroid Build Coastguard Worker
67*8617a60dSAndroid Build Coastguard Worker memcpy(vmlinuz, kpart_data + vmlinuz_header_offset,
68*8617a60dSAndroid Build Coastguard Worker vmlinuz_header_size);
69*8617a60dSAndroid Build Coastguard Worker
70*8617a60dSAndroid Build Coastguard Worker memcpy(vmlinuz + vmlinuz_header_size, kblob_data, kblob_size);
71*8617a60dSAndroid Build Coastguard Worker
72*8617a60dSAndroid Build Coastguard Worker *vmlinuz_out = vmlinuz;
73*8617a60dSAndroid Build Coastguard Worker *vmlinuz_size = vmlinuz_header_size + kblob_size;
74*8617a60dSAndroid Build Coastguard Worker
75*8617a60dSAndroid Build Coastguard Worker return 0;
76*8617a60dSAndroid Build Coastguard Worker }
77