Home | History | Annotate | Download | only in lib
      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