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