futility: Use only vboot 2.0 APIs for keyblocks
[vboot.git] / host / lib / extract_vmlinuz.c
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 "vb2_struct.h"
12 #include "vboot_struct.h"
13
14
15 int ExtractVmlinuz(void *kpart_data, size_t kpart_size,
16                    void **vmlinuz_out, size_t *vmlinuz_size) {
17         size_t now = 0;
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         struct vb2_keyblock *keyblock = (struct vb2_keyblock *)kpart_data;
27         now += keyblock->keyblock_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->keyblock_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 }