blob: 2d8a43d15faae875a3db99894e5d02e4b7763f6b [file] [log] [blame]
Zach Reizner317bb492015-02-20 14:55:02 -08001/* 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
Randall Spangler939cc3a2016-06-21 15:23:32 -070011#include "vb2_struct.h"
Zach Reizner317bb492015-02-20 14:55:02 -080012#include "vboot_struct.h"
13
14
15int ExtractVmlinuz(void *kpart_data, size_t kpart_size,
16 void **vmlinuz_out, size_t *vmlinuz_size) {
Randall Spangler939cc3a2016-06-21 15:23:32 -070017 size_t now = 0;
Randall Spangler5c537e32016-06-30 14:52:30 -070018 struct vb2_kernel_preamble *preamble = NULL;
Zach Reizner317bb492015-02-20 14:55:02 -080019 uint8_t *kblob_data = NULL;
Randall Spangler5c537e32016-06-30 14:52:30 -070020 uint32_t kblob_size = 0;
21 uint32_t vmlinuz_header_size = 0;
Zach Reizner317bb492015-02-20 14:55:02 -080022 uint64_t vmlinuz_header_address = 0;
23 uint64_t vmlinuz_header_offset = 0;
24 void *vmlinuz = NULL;
25
Randall Spangler939cc3a2016-06-21 15:23:32 -070026 struct vb2_keyblock *keyblock = (struct vb2_keyblock *)kpart_data;
27 now += keyblock->keyblock_size;
Zach Reizner317bb492015-02-20 14:55:02 -080028 if (now > kpart_size)
29 return 1;
30
Randall Spangler5c537e32016-06-30 14:52:30 -070031 preamble = (struct vb2_kernel_preamble *)(kpart_data + now);
Zach Reizner317bb492015-02-20 14:55:02 -080032 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 ||
Randall Spangler5c537e32016-06-30 14:52:30 -070048 kpart_data + vmlinuz_header_offset + vmlinuz_header_size >
49 kpart_data) {
Zach Reizner317bb492015-02-20 14:55:02 -080050 return 1;
51 }
52
53 // calculate the vmlinuz_header offset from
54 // the beginning of the kpart_data. The kblob doesn't
55 // include the body_load_offset, but does include
56 // the keyblock and preamble sections.
57 vmlinuz_header_offset = vmlinuz_header_address -
58 preamble->body_load_address +
Randall Spangler939cc3a2016-06-21 15:23:32 -070059 keyblock->keyblock_size +
Zach Reizner317bb492015-02-20 14:55:02 -080060 preamble->preamble_size;
61
62 vmlinuz = malloc(vmlinuz_header_size + kblob_size);
63 if (vmlinuz == NULL)
64 return 1;
65
66 memcpy(vmlinuz, kpart_data + vmlinuz_header_offset,
67 vmlinuz_header_size);
68
69 memcpy(vmlinuz + vmlinuz_header_size, kblob_data, kblob_size);
70
71 *vmlinuz_out = vmlinuz;
72 *vmlinuz_size = vmlinuz_header_size + kblob_size;
73
74 return 0;
75}