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 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