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