1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2014 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker *
5*8617a60dSAndroid Build Coastguard Worker * Verified boot kernel utility
6*8617a60dSAndroid Build Coastguard Worker */
7*8617a60dSAndroid Build Coastguard Worker
8*8617a60dSAndroid Build Coastguard Worker #include <errno.h>
9*8617a60dSAndroid Build Coastguard Worker #include <fcntl.h>
10*8617a60dSAndroid Build Coastguard Worker #include <getopt.h>
11*8617a60dSAndroid Build Coastguard Worker #include <inttypes.h> /* For PRIu64 */
12*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
13*8617a60dSAndroid Build Coastguard Worker #include <linux/fs.h> /* For BLKGETSIZE64 */
14*8617a60dSAndroid Build Coastguard Worker #endif
15*8617a60dSAndroid Build Coastguard Worker #include <stdarg.h>
16*8617a60dSAndroid Build Coastguard Worker #include <stdio.h>
17*8617a60dSAndroid Build Coastguard Worker #include <string.h>
18*8617a60dSAndroid Build Coastguard Worker #include <sys/ioctl.h>
19*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
20*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
21*8617a60dSAndroid Build Coastguard Worker
22*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
23*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
24*8617a60dSAndroid Build Coastguard Worker #include "file_type.h"
25*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
26*8617a60dSAndroid Build Coastguard Worker #include "host_common.h"
27*8617a60dSAndroid Build Coastguard Worker #include "kernel_blob.h"
28*8617a60dSAndroid Build Coastguard Worker #include "vb1_helper.h"
29*8617a60dSAndroid Build Coastguard Worker
30*8617a60dSAndroid Build Coastguard Worker /* Global opts */
31*8617a60dSAndroid Build Coastguard Worker static int opt_verbose;
32*8617a60dSAndroid Build Coastguard Worker static int opt_vblockonly;
33*8617a60dSAndroid Build Coastguard Worker static uint64_t opt_pad = 65536;
34*8617a60dSAndroid Build Coastguard Worker
35*8617a60dSAndroid Build Coastguard Worker /* Command line options */
36*8617a60dSAndroid Build Coastguard Worker enum {
37*8617a60dSAndroid Build Coastguard Worker OPT_MODE_PACK = 1000,
38*8617a60dSAndroid Build Coastguard Worker OPT_MODE_REPACK,
39*8617a60dSAndroid Build Coastguard Worker OPT_MODE_VERIFY,
40*8617a60dSAndroid Build Coastguard Worker OPT_MODE_GET_VMLINUZ,
41*8617a60dSAndroid Build Coastguard Worker OPT_ARCH,
42*8617a60dSAndroid Build Coastguard Worker OPT_OLDBLOB,
43*8617a60dSAndroid Build Coastguard Worker OPT_KLOADADDR,
44*8617a60dSAndroid Build Coastguard Worker OPT_KEYBLOCK,
45*8617a60dSAndroid Build Coastguard Worker OPT_SIGNPUBKEY,
46*8617a60dSAndroid Build Coastguard Worker OPT_SIGNPRIVATE,
47*8617a60dSAndroid Build Coastguard Worker OPT_VERSION,
48*8617a60dSAndroid Build Coastguard Worker OPT_VMLINUZ,
49*8617a60dSAndroid Build Coastguard Worker OPT_BOOTLOADER,
50*8617a60dSAndroid Build Coastguard Worker OPT_CONFIG,
51*8617a60dSAndroid Build Coastguard Worker OPT_VBLOCKONLY,
52*8617a60dSAndroid Build Coastguard Worker OPT_PAD,
53*8617a60dSAndroid Build Coastguard Worker OPT_VERBOSE,
54*8617a60dSAndroid Build Coastguard Worker OPT_MINVERSION,
55*8617a60dSAndroid Build Coastguard Worker OPT_VMLINUZ_OUT,
56*8617a60dSAndroid Build Coastguard Worker OPT_FLAGS,
57*8617a60dSAndroid Build Coastguard Worker OPT_HELP,
58*8617a60dSAndroid Build Coastguard Worker };
59*8617a60dSAndroid Build Coastguard Worker
60*8617a60dSAndroid Build Coastguard Worker static const struct option long_opts[] = {
61*8617a60dSAndroid Build Coastguard Worker {"pack", 1, 0, OPT_MODE_PACK},
62*8617a60dSAndroid Build Coastguard Worker {"repack", 1, 0, OPT_MODE_REPACK},
63*8617a60dSAndroid Build Coastguard Worker {"verify", 1, 0, OPT_MODE_VERIFY},
64*8617a60dSAndroid Build Coastguard Worker {"get-vmlinuz", 1, 0, OPT_MODE_GET_VMLINUZ},
65*8617a60dSAndroid Build Coastguard Worker {"arch", 1, 0, OPT_ARCH},
66*8617a60dSAndroid Build Coastguard Worker {"oldblob", 1, 0, OPT_OLDBLOB},
67*8617a60dSAndroid Build Coastguard Worker {"kloadaddr", 1, 0, OPT_KLOADADDR},
68*8617a60dSAndroid Build Coastguard Worker {"keyblock", 1, 0, OPT_KEYBLOCK},
69*8617a60dSAndroid Build Coastguard Worker {"signpubkey", 1, 0, OPT_SIGNPUBKEY},
70*8617a60dSAndroid Build Coastguard Worker {"signprivate", 1, 0, OPT_SIGNPRIVATE},
71*8617a60dSAndroid Build Coastguard Worker {"version", 1, 0, OPT_VERSION},
72*8617a60dSAndroid Build Coastguard Worker {"minversion", 1, 0, OPT_MINVERSION},
73*8617a60dSAndroid Build Coastguard Worker {"vmlinuz", 1, 0, OPT_VMLINUZ},
74*8617a60dSAndroid Build Coastguard Worker {"bootloader", 1, 0, OPT_BOOTLOADER},
75*8617a60dSAndroid Build Coastguard Worker {"config", 1, 0, OPT_CONFIG},
76*8617a60dSAndroid Build Coastguard Worker {"vblockonly", 0, 0, OPT_VBLOCKONLY},
77*8617a60dSAndroid Build Coastguard Worker {"pad", 1, 0, OPT_PAD},
78*8617a60dSAndroid Build Coastguard Worker {"verbose", 0, &opt_verbose, 1},
79*8617a60dSAndroid Build Coastguard Worker {"vmlinuz-out", 1, 0, OPT_VMLINUZ_OUT},
80*8617a60dSAndroid Build Coastguard Worker {"flags", 1, 0, OPT_FLAGS},
81*8617a60dSAndroid Build Coastguard Worker {"help", 0, 0, OPT_HELP},
82*8617a60dSAndroid Build Coastguard Worker {NULL, 0, 0, 0}
83*8617a60dSAndroid Build Coastguard Worker };
84*8617a60dSAndroid Build Coastguard Worker
85*8617a60dSAndroid Build Coastguard Worker
86*8617a60dSAndroid Build Coastguard Worker
87*8617a60dSAndroid Build Coastguard Worker static const char usage[] =
88*8617a60dSAndroid Build Coastguard Worker "\n"
89*8617a60dSAndroid Build Coastguard Worker "Usage: " MYNAME " %s --pack <file> [PARAMETERS]\n"
90*8617a60dSAndroid Build Coastguard Worker "\n"
91*8617a60dSAndroid Build Coastguard Worker " Required parameters:\n"
92*8617a60dSAndroid Build Coastguard Worker " --keyblock <file> Keyblock in .keyblock format\n"
93*8617a60dSAndroid Build Coastguard Worker " --signprivate <file> Private key to sign kernel data,\n"
94*8617a60dSAndroid Build Coastguard Worker " in .vbprivk format\n"
95*8617a60dSAndroid Build Coastguard Worker " --version <number> Kernel version\n"
96*8617a60dSAndroid Build Coastguard Worker " --vmlinuz <file> Linux kernel bzImage file\n"
97*8617a60dSAndroid Build Coastguard Worker " --config <file> Command line file\n"
98*8617a60dSAndroid Build Coastguard Worker " --arch <arch> Cpu architecture (default x86)\n"
99*8617a60dSAndroid Build Coastguard Worker "\n"
100*8617a60dSAndroid Build Coastguard Worker " Optional:\n"
101*8617a60dSAndroid Build Coastguard Worker " --kloadaddr <address> Assign kernel body load address\n"
102*8617a60dSAndroid Build Coastguard Worker " --bootloader <file> Bootloader stub\n"
103*8617a60dSAndroid Build Coastguard Worker " --pad <number> Verification padding size in bytes\n"
104*8617a60dSAndroid Build Coastguard Worker " --vblockonly Emit just the verification blob\n"
105*8617a60dSAndroid Build Coastguard Worker " --flags NUM Flags to be passed in the header\n"
106*8617a60dSAndroid Build Coastguard Worker "\nOR\n\n"
107*8617a60dSAndroid Build Coastguard Worker "Usage: " MYNAME " %s --repack <file> [PARAMETERS]\n"
108*8617a60dSAndroid Build Coastguard Worker "\n"
109*8617a60dSAndroid Build Coastguard Worker " Required parameters:\n"
110*8617a60dSAndroid Build Coastguard Worker " --signprivate <file> Private key to sign kernel data,\n"
111*8617a60dSAndroid Build Coastguard Worker " in .vbprivk format\n"
112*8617a60dSAndroid Build Coastguard Worker " --oldblob <file> Previously packed kernel blob\n"
113*8617a60dSAndroid Build Coastguard Worker " (including verfication blob)\n"
114*8617a60dSAndroid Build Coastguard Worker "\n"
115*8617a60dSAndroid Build Coastguard Worker " Optional:\n"
116*8617a60dSAndroid Build Coastguard Worker " --keyblock <file> Keyblock in .keyblock format\n"
117*8617a60dSAndroid Build Coastguard Worker " --config <file> New command line file\n"
118*8617a60dSAndroid Build Coastguard Worker " --version <number> Kernel version\n"
119*8617a60dSAndroid Build Coastguard Worker " --kloadaddr <address> Assign kernel body load address\n"
120*8617a60dSAndroid Build Coastguard Worker " --pad <number> Verification blob size in bytes\n"
121*8617a60dSAndroid Build Coastguard Worker " --vblockonly Emit just the verification blob\n"
122*8617a60dSAndroid Build Coastguard Worker "\nOR\n\n"
123*8617a60dSAndroid Build Coastguard Worker "Usage: " MYNAME " %s --verify <file> [PARAMETERS]\n"
124*8617a60dSAndroid Build Coastguard Worker "\n"
125*8617a60dSAndroid Build Coastguard Worker " Optional:\n"
126*8617a60dSAndroid Build Coastguard Worker " --signpubkey <file>"
127*8617a60dSAndroid Build Coastguard Worker " Public key to verify kernel keyblock,\n"
128*8617a60dSAndroid Build Coastguard Worker " in .vbpubk format\n"
129*8617a60dSAndroid Build Coastguard Worker " --verbose Print a more detailed report\n"
130*8617a60dSAndroid Build Coastguard Worker " --keyblock <file> Outputs the verified keyblock,\n"
131*8617a60dSAndroid Build Coastguard Worker " in .keyblock format\n"
132*8617a60dSAndroid Build Coastguard Worker " --pad <number> Verification padding size in bytes\n"
133*8617a60dSAndroid Build Coastguard Worker " --minversion <number> Minimum combined kernel key version\n"
134*8617a60dSAndroid Build Coastguard Worker "\nOR\n\n"
135*8617a60dSAndroid Build Coastguard Worker "Usage: " MYNAME " %s --get-vmlinuz <file> [PARAMETERS]\n"
136*8617a60dSAndroid Build Coastguard Worker "\n"
137*8617a60dSAndroid Build Coastguard Worker " Required parameters:\n"
138*8617a60dSAndroid Build Coastguard Worker " --vmlinuz-out <file> vmlinuz image output file\n"
139*8617a60dSAndroid Build Coastguard Worker "\n";
140*8617a60dSAndroid Build Coastguard Worker
141*8617a60dSAndroid Build Coastguard Worker
142*8617a60dSAndroid Build Coastguard Worker /* Print help and return error */
print_help(int argc,char * argv[])143*8617a60dSAndroid Build Coastguard Worker static void print_help(int argc, char *argv[])
144*8617a60dSAndroid Build Coastguard Worker {
145*8617a60dSAndroid Build Coastguard Worker printf(usage, argv[0], argv[0], argv[0], argv[0]);
146*8617a60dSAndroid Build Coastguard Worker }
147*8617a60dSAndroid Build Coastguard Worker
148*8617a60dSAndroid Build Coastguard Worker
149*8617a60dSAndroid Build Coastguard Worker /* Return an explanation when fread() fails. */
error_fread(FILE * fp)150*8617a60dSAndroid Build Coastguard Worker static const char *error_fread(FILE *fp)
151*8617a60dSAndroid Build Coastguard Worker {
152*8617a60dSAndroid Build Coastguard Worker const char *retval = "beats me why";
153*8617a60dSAndroid Build Coastguard Worker if (feof(fp))
154*8617a60dSAndroid Build Coastguard Worker retval = "EOF";
155*8617a60dSAndroid Build Coastguard Worker else if (ferror(fp))
156*8617a60dSAndroid Build Coastguard Worker retval = strerror(errno);
157*8617a60dSAndroid Build Coastguard Worker clearerr(fp);
158*8617a60dSAndroid Build Coastguard Worker return retval;
159*8617a60dSAndroid Build Coastguard Worker }
160*8617a60dSAndroid Build Coastguard Worker
161*8617a60dSAndroid Build Coastguard Worker
162*8617a60dSAndroid Build Coastguard Worker /* This reads a complete kernel partition into a buffer */
ReadOldKPartFromFileOrDie(const char * filename,uint32_t * size_ptr)163*8617a60dSAndroid Build Coastguard Worker static uint8_t *ReadOldKPartFromFileOrDie(const char *filename,
164*8617a60dSAndroid Build Coastguard Worker uint32_t *size_ptr)
165*8617a60dSAndroid Build Coastguard Worker {
166*8617a60dSAndroid Build Coastguard Worker FILE *fp = NULL;
167*8617a60dSAndroid Build Coastguard Worker struct stat statbuf;
168*8617a60dSAndroid Build Coastguard Worker uint8_t *buf;
169*8617a60dSAndroid Build Coastguard Worker uint32_t file_size = 0;
170*8617a60dSAndroid Build Coastguard Worker
171*8617a60dSAndroid Build Coastguard Worker if (stat(filename, &statbuf))
172*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to stat %s: %s\n", filename, strerror(errno));
173*8617a60dSAndroid Build Coastguard Worker
174*8617a60dSAndroid Build Coastguard Worker if (S_ISBLK(statbuf.st_mode)) {
175*8617a60dSAndroid Build Coastguard Worker #if !defined(HAVE_MACOS) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
176*8617a60dSAndroid Build Coastguard Worker int fd = open(filename, O_RDONLY);
177*8617a60dSAndroid Build Coastguard Worker if (fd >= 0) {
178*8617a60dSAndroid Build Coastguard Worker ioctl(fd, BLKGETSIZE64, &file_size);
179*8617a60dSAndroid Build Coastguard Worker close(fd);
180*8617a60dSAndroid Build Coastguard Worker }
181*8617a60dSAndroid Build Coastguard Worker #endif
182*8617a60dSAndroid Build Coastguard Worker } else {
183*8617a60dSAndroid Build Coastguard Worker file_size = statbuf.st_size;
184*8617a60dSAndroid Build Coastguard Worker }
185*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("%s size is %#x\n", filename, file_size);
186*8617a60dSAndroid Build Coastguard Worker if (file_size < opt_pad)
187*8617a60dSAndroid Build Coastguard Worker FATAL("%s is too small to be a valid kernel blob\n", filename);
188*8617a60dSAndroid Build Coastguard Worker
189*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Reading %s\n", filename);
190*8617a60dSAndroid Build Coastguard Worker fp = fopen(filename, "rb");
191*8617a60dSAndroid Build Coastguard Worker if (!fp)
192*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to open file %s: %s\n", filename,
193*8617a60dSAndroid Build Coastguard Worker strerror(errno));
194*8617a60dSAndroid Build Coastguard Worker
195*8617a60dSAndroid Build Coastguard Worker buf = malloc(file_size);
196*8617a60dSAndroid Build Coastguard Worker if (1 != fread(buf, file_size, 1, fp))
197*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to read entirety of %s: %s\n", filename,
198*8617a60dSAndroid Build Coastguard Worker error_fread(fp));
199*8617a60dSAndroid Build Coastguard Worker
200*8617a60dSAndroid Build Coastguard Worker if (size_ptr)
201*8617a60dSAndroid Build Coastguard Worker *size_ptr = file_size;
202*8617a60dSAndroid Build Coastguard Worker
203*8617a60dSAndroid Build Coastguard Worker fclose(fp);
204*8617a60dSAndroid Build Coastguard Worker return buf;
205*8617a60dSAndroid Build Coastguard Worker }
206*8617a60dSAndroid Build Coastguard Worker
207*8617a60dSAndroid Build Coastguard Worker /****************************************************************************/
208*8617a60dSAndroid Build Coastguard Worker
do_vbutil_kernel(int argc,char * argv[])209*8617a60dSAndroid Build Coastguard Worker static int do_vbutil_kernel(int argc, char *argv[])
210*8617a60dSAndroid Build Coastguard Worker {
211*8617a60dSAndroid Build Coastguard Worker char *filename = NULL;
212*8617a60dSAndroid Build Coastguard Worker char *oldfile = NULL;
213*8617a60dSAndroid Build Coastguard Worker char *keyblock_file = NULL;
214*8617a60dSAndroid Build Coastguard Worker char *signpubkey_file = NULL;
215*8617a60dSAndroid Build Coastguard Worker char *signprivkey_info = NULL;
216*8617a60dSAndroid Build Coastguard Worker char *version_str = NULL;
217*8617a60dSAndroid Build Coastguard Worker int version = -1;
218*8617a60dSAndroid Build Coastguard Worker char *vmlinuz_file = NULL;
219*8617a60dSAndroid Build Coastguard Worker char *bootloader_file = NULL;
220*8617a60dSAndroid Build Coastguard Worker char *config_file = NULL;
221*8617a60dSAndroid Build Coastguard Worker char *vmlinuz_out_file = NULL;
222*8617a60dSAndroid Build Coastguard Worker enum arch_t arch = ARCH_X86;
223*8617a60dSAndroid Build Coastguard Worker uint64_t kernel_body_load_address = CROS_32BIT_ENTRY_ADDR;
224*8617a60dSAndroid Build Coastguard Worker int mode = 0;
225*8617a60dSAndroid Build Coastguard Worker int parse_error = 0;
226*8617a60dSAndroid Build Coastguard Worker uint32_t min_version = 0;
227*8617a60dSAndroid Build Coastguard Worker char *e;
228*8617a60dSAndroid Build Coastguard Worker int i = 0;
229*8617a60dSAndroid Build Coastguard Worker int errcount = 0;
230*8617a60dSAndroid Build Coastguard Worker int rv;
231*8617a60dSAndroid Build Coastguard Worker struct vb2_keyblock *keyblock = NULL;
232*8617a60dSAndroid Build Coastguard Worker struct vb2_keyblock *t_keyblock = NULL;
233*8617a60dSAndroid Build Coastguard Worker struct vb2_private_key *signpriv_key = NULL;
234*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *signpub_key = NULL;
235*8617a60dSAndroid Build Coastguard Worker uint8_t *kpart_data = NULL;
236*8617a60dSAndroid Build Coastguard Worker uint32_t kpart_size = 0;
237*8617a60dSAndroid Build Coastguard Worker uint8_t *vmlinuz_buf = NULL;
238*8617a60dSAndroid Build Coastguard Worker uint32_t vmlinuz_size = 0;
239*8617a60dSAndroid Build Coastguard Worker uint8_t *t_config_data;
240*8617a60dSAndroid Build Coastguard Worker uint32_t t_config_size;
241*8617a60dSAndroid Build Coastguard Worker uint8_t *t_bootloader_data;
242*8617a60dSAndroid Build Coastguard Worker uint32_t t_bootloader_size;
243*8617a60dSAndroid Build Coastguard Worker uint32_t vmlinuz_header_size = 0;
244*8617a60dSAndroid Build Coastguard Worker uint64_t vmlinuz_header_address = 0;
245*8617a60dSAndroid Build Coastguard Worker uint32_t vmlinuz_header_offset = 0;
246*8617a60dSAndroid Build Coastguard Worker struct vb2_kernel_preamble *preamble = NULL;
247*8617a60dSAndroid Build Coastguard Worker uint8_t *kblob_data = NULL;
248*8617a60dSAndroid Build Coastguard Worker uint32_t kblob_size = 0;
249*8617a60dSAndroid Build Coastguard Worker uint8_t *vblock_data = NULL;
250*8617a60dSAndroid Build Coastguard Worker uint32_t vblock_size = 0;
251*8617a60dSAndroid Build Coastguard Worker uint32_t flags = 0;
252*8617a60dSAndroid Build Coastguard Worker FILE *f;
253*8617a60dSAndroid Build Coastguard Worker
254*8617a60dSAndroid Build Coastguard Worker while (((i = getopt_long(argc, argv, ":", long_opts, NULL)) != -1) &&
255*8617a60dSAndroid Build Coastguard Worker !parse_error) {
256*8617a60dSAndroid Build Coastguard Worker switch (i) {
257*8617a60dSAndroid Build Coastguard Worker default:
258*8617a60dSAndroid Build Coastguard Worker case '?':
259*8617a60dSAndroid Build Coastguard Worker /* Unhandled option */
260*8617a60dSAndroid Build Coastguard Worker parse_error = 1;
261*8617a60dSAndroid Build Coastguard Worker break;
262*8617a60dSAndroid Build Coastguard Worker
263*8617a60dSAndroid Build Coastguard Worker case 0:
264*8617a60dSAndroid Build Coastguard Worker /* silently handled option */
265*8617a60dSAndroid Build Coastguard Worker break;
266*8617a60dSAndroid Build Coastguard Worker case OPT_HELP:
267*8617a60dSAndroid Build Coastguard Worker print_help(argc, argv);
268*8617a60dSAndroid Build Coastguard Worker return !!parse_error;
269*8617a60dSAndroid Build Coastguard Worker
270*8617a60dSAndroid Build Coastguard Worker case OPT_MODE_PACK:
271*8617a60dSAndroid Build Coastguard Worker case OPT_MODE_REPACK:
272*8617a60dSAndroid Build Coastguard Worker case OPT_MODE_VERIFY:
273*8617a60dSAndroid Build Coastguard Worker case OPT_MODE_GET_VMLINUZ:
274*8617a60dSAndroid Build Coastguard Worker if (mode && (mode != i)) {
275*8617a60dSAndroid Build Coastguard Worker ERROR("Only one mode can be specified\n");
276*8617a60dSAndroid Build Coastguard Worker parse_error = 1;
277*8617a60dSAndroid Build Coastguard Worker break;
278*8617a60dSAndroid Build Coastguard Worker }
279*8617a60dSAndroid Build Coastguard Worker mode = i;
280*8617a60dSAndroid Build Coastguard Worker filename = optarg;
281*8617a60dSAndroid Build Coastguard Worker break;
282*8617a60dSAndroid Build Coastguard Worker
283*8617a60dSAndroid Build Coastguard Worker case OPT_ARCH:
284*8617a60dSAndroid Build Coastguard Worker /* check the first 3 characters to also detect x86_64 */
285*8617a60dSAndroid Build Coastguard Worker if ((!strncasecmp(optarg, "x86", 3)) ||
286*8617a60dSAndroid Build Coastguard Worker (!strcasecmp(optarg, "amd64")))
287*8617a60dSAndroid Build Coastguard Worker arch = ARCH_X86;
288*8617a60dSAndroid Build Coastguard Worker /* check the first 3 characters to also detect arm64 */
289*8617a60dSAndroid Build Coastguard Worker else if ((!strncasecmp(optarg, "arm", 3)) ||
290*8617a60dSAndroid Build Coastguard Worker (!strcasecmp(optarg, "aarch64")))
291*8617a60dSAndroid Build Coastguard Worker arch = ARCH_ARM;
292*8617a60dSAndroid Build Coastguard Worker else if (!strcasecmp(optarg, "mips"))
293*8617a60dSAndroid Build Coastguard Worker arch = ARCH_MIPS;
294*8617a60dSAndroid Build Coastguard Worker else {
295*8617a60dSAndroid Build Coastguard Worker ERROR("Unknown architecture string: %s\n", optarg);
296*8617a60dSAndroid Build Coastguard Worker parse_error = 1;
297*8617a60dSAndroid Build Coastguard Worker }
298*8617a60dSAndroid Build Coastguard Worker break;
299*8617a60dSAndroid Build Coastguard Worker
300*8617a60dSAndroid Build Coastguard Worker case OPT_OLDBLOB:
301*8617a60dSAndroid Build Coastguard Worker oldfile = optarg;
302*8617a60dSAndroid Build Coastguard Worker break;
303*8617a60dSAndroid Build Coastguard Worker
304*8617a60dSAndroid Build Coastguard Worker case OPT_KLOADADDR:
305*8617a60dSAndroid Build Coastguard Worker kernel_body_load_address = strtoul(optarg, &e, 0);
306*8617a60dSAndroid Build Coastguard Worker if (!*optarg || (e && *e)) {
307*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid --kloadaddr\n");
308*8617a60dSAndroid Build Coastguard Worker parse_error = 1;
309*8617a60dSAndroid Build Coastguard Worker }
310*8617a60dSAndroid Build Coastguard Worker break;
311*8617a60dSAndroid Build Coastguard Worker
312*8617a60dSAndroid Build Coastguard Worker case OPT_KEYBLOCK:
313*8617a60dSAndroid Build Coastguard Worker keyblock_file = optarg;
314*8617a60dSAndroid Build Coastguard Worker break;
315*8617a60dSAndroid Build Coastguard Worker
316*8617a60dSAndroid Build Coastguard Worker case OPT_SIGNPUBKEY:
317*8617a60dSAndroid Build Coastguard Worker signpubkey_file = optarg;
318*8617a60dSAndroid Build Coastguard Worker break;
319*8617a60dSAndroid Build Coastguard Worker
320*8617a60dSAndroid Build Coastguard Worker case OPT_SIGNPRIVATE:
321*8617a60dSAndroid Build Coastguard Worker signprivkey_info = optarg;
322*8617a60dSAndroid Build Coastguard Worker break;
323*8617a60dSAndroid Build Coastguard Worker
324*8617a60dSAndroid Build Coastguard Worker case OPT_VMLINUZ:
325*8617a60dSAndroid Build Coastguard Worker vmlinuz_file = optarg;
326*8617a60dSAndroid Build Coastguard Worker break;
327*8617a60dSAndroid Build Coastguard Worker
328*8617a60dSAndroid Build Coastguard Worker case OPT_FLAGS:
329*8617a60dSAndroid Build Coastguard Worker flags = (uint32_t)strtoul(optarg, &e, 0);
330*8617a60dSAndroid Build Coastguard Worker if (!*optarg || (e && *e)) {
331*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid --flags\n");
332*8617a60dSAndroid Build Coastguard Worker parse_error = 1;
333*8617a60dSAndroid Build Coastguard Worker }
334*8617a60dSAndroid Build Coastguard Worker break;
335*8617a60dSAndroid Build Coastguard Worker
336*8617a60dSAndroid Build Coastguard Worker case OPT_BOOTLOADER:
337*8617a60dSAndroid Build Coastguard Worker bootloader_file = optarg;
338*8617a60dSAndroid Build Coastguard Worker break;
339*8617a60dSAndroid Build Coastguard Worker
340*8617a60dSAndroid Build Coastguard Worker case OPT_CONFIG:
341*8617a60dSAndroid Build Coastguard Worker config_file = optarg;
342*8617a60dSAndroid Build Coastguard Worker break;
343*8617a60dSAndroid Build Coastguard Worker
344*8617a60dSAndroid Build Coastguard Worker case OPT_VBLOCKONLY:
345*8617a60dSAndroid Build Coastguard Worker opt_vblockonly = 1;
346*8617a60dSAndroid Build Coastguard Worker break;
347*8617a60dSAndroid Build Coastguard Worker
348*8617a60dSAndroid Build Coastguard Worker case OPT_VERSION:
349*8617a60dSAndroid Build Coastguard Worker version_str = optarg;
350*8617a60dSAndroid Build Coastguard Worker version = strtoul(optarg, &e, 0);
351*8617a60dSAndroid Build Coastguard Worker if (!*optarg || (e && *e)) {
352*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid --version\n");
353*8617a60dSAndroid Build Coastguard Worker parse_error = 1;
354*8617a60dSAndroid Build Coastguard Worker }
355*8617a60dSAndroid Build Coastguard Worker break;
356*8617a60dSAndroid Build Coastguard Worker
357*8617a60dSAndroid Build Coastguard Worker case OPT_MINVERSION:
358*8617a60dSAndroid Build Coastguard Worker min_version = strtoul(optarg, &e, 0);
359*8617a60dSAndroid Build Coastguard Worker if (!*optarg || (e && *e)) {
360*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid --minversion\n");
361*8617a60dSAndroid Build Coastguard Worker parse_error = 1;
362*8617a60dSAndroid Build Coastguard Worker }
363*8617a60dSAndroid Build Coastguard Worker break;
364*8617a60dSAndroid Build Coastguard Worker
365*8617a60dSAndroid Build Coastguard Worker case OPT_PAD:
366*8617a60dSAndroid Build Coastguard Worker opt_pad = strtoul(optarg, &e, 0);
367*8617a60dSAndroid Build Coastguard Worker if (!*optarg || (e && *e)) {
368*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid --pad\n");
369*8617a60dSAndroid Build Coastguard Worker parse_error = 1;
370*8617a60dSAndroid Build Coastguard Worker }
371*8617a60dSAndroid Build Coastguard Worker break;
372*8617a60dSAndroid Build Coastguard Worker case OPT_VMLINUZ_OUT:
373*8617a60dSAndroid Build Coastguard Worker vmlinuz_out_file = optarg;
374*8617a60dSAndroid Build Coastguard Worker }
375*8617a60dSAndroid Build Coastguard Worker }
376*8617a60dSAndroid Build Coastguard Worker
377*8617a60dSAndroid Build Coastguard Worker if (parse_error) {
378*8617a60dSAndroid Build Coastguard Worker print_help(argc, argv);
379*8617a60dSAndroid Build Coastguard Worker return 1;
380*8617a60dSAndroid Build Coastguard Worker }
381*8617a60dSAndroid Build Coastguard Worker
382*8617a60dSAndroid Build Coastguard Worker switch (mode) {
383*8617a60dSAndroid Build Coastguard Worker case OPT_MODE_PACK:
384*8617a60dSAndroid Build Coastguard Worker
385*8617a60dSAndroid Build Coastguard Worker if (!keyblock_file)
386*8617a60dSAndroid Build Coastguard Worker FATAL("Missing required keyblock file.\n");
387*8617a60dSAndroid Build Coastguard Worker
388*8617a60dSAndroid Build Coastguard Worker t_keyblock = (struct vb2_keyblock *)ReadFile(keyblock_file, 0);
389*8617a60dSAndroid Build Coastguard Worker if (!t_keyblock)
390*8617a60dSAndroid Build Coastguard Worker FATAL("Error reading keyblock.\n");
391*8617a60dSAndroid Build Coastguard Worker
392*8617a60dSAndroid Build Coastguard Worker if (!signprivkey_info)
393*8617a60dSAndroid Build Coastguard Worker FATAL("Missing required signprivate info.\n");
394*8617a60dSAndroid Build Coastguard Worker
395*8617a60dSAndroid Build Coastguard Worker signpriv_key = vb2_read_private_key(signprivkey_info);
396*8617a60dSAndroid Build Coastguard Worker if (!signpriv_key)
397*8617a60dSAndroid Build Coastguard Worker FATAL("Error reading signing key.\n");
398*8617a60dSAndroid Build Coastguard Worker
399*8617a60dSAndroid Build Coastguard Worker if (!config_file)
400*8617a60dSAndroid Build Coastguard Worker FATAL("Missing required config file.\n");
401*8617a60dSAndroid Build Coastguard Worker
402*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Reading %s\n", config_file);
403*8617a60dSAndroid Build Coastguard Worker t_config_data =
404*8617a60dSAndroid Build Coastguard Worker ReadConfigFile(config_file, &t_config_size);
405*8617a60dSAndroid Build Coastguard Worker if (!t_config_data)
406*8617a60dSAndroid Build Coastguard Worker FATAL("Error reading config file.\n");
407*8617a60dSAndroid Build Coastguard Worker
408*8617a60dSAndroid Build Coastguard Worker if (bootloader_file) {
409*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Reading %s\n", bootloader_file);
410*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_read_file(bootloader_file,
411*8617a60dSAndroid Build Coastguard Worker &t_bootloader_data,
412*8617a60dSAndroid Build Coastguard Worker &t_bootloader_size))
413*8617a60dSAndroid Build Coastguard Worker FATAL("Error reading bootloader file.\n");
414*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG(" bootloader file size=%#x\n", t_bootloader_size);
415*8617a60dSAndroid Build Coastguard Worker } else {
416*8617a60dSAndroid Build Coastguard Worker t_bootloader_data = NULL;
417*8617a60dSAndroid Build Coastguard Worker t_bootloader_size = 0;
418*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("No external bootloader file passed in.\n");
419*8617a60dSAndroid Build Coastguard Worker }
420*8617a60dSAndroid Build Coastguard Worker
421*8617a60dSAndroid Build Coastguard Worker if (!vmlinuz_file)
422*8617a60dSAndroid Build Coastguard Worker FATAL("Missing required vmlinuz file.\n");
423*8617a60dSAndroid Build Coastguard Worker
424*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Reading %s\n", vmlinuz_file);
425*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS !=
426*8617a60dSAndroid Build Coastguard Worker vb2_read_file(vmlinuz_file, &vmlinuz_buf, &vmlinuz_size))
427*8617a60dSAndroid Build Coastguard Worker FATAL("Error reading vmlinuz file.\n");
428*8617a60dSAndroid Build Coastguard Worker
429*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG(" vmlinuz file size=%#x\n", vmlinuz_size);
430*8617a60dSAndroid Build Coastguard Worker if (!vmlinuz_size)
431*8617a60dSAndroid Build Coastguard Worker FATAL("Empty vmlinuz file\n");
432*8617a60dSAndroid Build Coastguard Worker
433*8617a60dSAndroid Build Coastguard Worker kblob_data = CreateKernelBlob(
434*8617a60dSAndroid Build Coastguard Worker vmlinuz_buf, vmlinuz_size,
435*8617a60dSAndroid Build Coastguard Worker arch, kernel_body_load_address,
436*8617a60dSAndroid Build Coastguard Worker t_config_data, t_config_size,
437*8617a60dSAndroid Build Coastguard Worker t_bootloader_data, t_bootloader_size,
438*8617a60dSAndroid Build Coastguard Worker &kblob_size);
439*8617a60dSAndroid Build Coastguard Worker if (!kblob_data)
440*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to create kernel blob\n");
441*8617a60dSAndroid Build Coastguard Worker
442*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("kblob_size = %#x\n", kblob_size);
443*8617a60dSAndroid Build Coastguard Worker
444*8617a60dSAndroid Build Coastguard Worker vblock_data = SignKernelBlob(kblob_data, kblob_size, opt_pad,
445*8617a60dSAndroid Build Coastguard Worker version, kernel_body_load_address,
446*8617a60dSAndroid Build Coastguard Worker t_keyblock, signpriv_key, flags,
447*8617a60dSAndroid Build Coastguard Worker &vblock_size);
448*8617a60dSAndroid Build Coastguard Worker if (!vblock_data)
449*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to sign kernel blob\n");
450*8617a60dSAndroid Build Coastguard Worker
451*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("vblock_size = %#x\n", vblock_size);
452*8617a60dSAndroid Build Coastguard Worker
453*8617a60dSAndroid Build Coastguard Worker if (opt_vblockonly)
454*8617a60dSAndroid Build Coastguard Worker rv = WriteSomeParts(filename,
455*8617a60dSAndroid Build Coastguard Worker vblock_data, vblock_size,
456*8617a60dSAndroid Build Coastguard Worker NULL, 0);
457*8617a60dSAndroid Build Coastguard Worker else
458*8617a60dSAndroid Build Coastguard Worker rv = WriteSomeParts(filename,
459*8617a60dSAndroid Build Coastguard Worker vblock_data, vblock_size,
460*8617a60dSAndroid Build Coastguard Worker kblob_data, kblob_size);
461*8617a60dSAndroid Build Coastguard Worker
462*8617a60dSAndroid Build Coastguard Worker free(vmlinuz_buf);
463*8617a60dSAndroid Build Coastguard Worker free(t_config_data);
464*8617a60dSAndroid Build Coastguard Worker free(t_bootloader_data);
465*8617a60dSAndroid Build Coastguard Worker free(vblock_data);
466*8617a60dSAndroid Build Coastguard Worker vb2_free_private_key(signpriv_key);
467*8617a60dSAndroid Build Coastguard Worker return rv;
468*8617a60dSAndroid Build Coastguard Worker
469*8617a60dSAndroid Build Coastguard Worker case OPT_MODE_REPACK:
470*8617a60dSAndroid Build Coastguard Worker
471*8617a60dSAndroid Build Coastguard Worker /* Required */
472*8617a60dSAndroid Build Coastguard Worker
473*8617a60dSAndroid Build Coastguard Worker if (!signprivkey_info)
474*8617a60dSAndroid Build Coastguard Worker FATAL("Missing required signprivate info.\n");
475*8617a60dSAndroid Build Coastguard Worker
476*8617a60dSAndroid Build Coastguard Worker if (bootloader_file)
477*8617a60dSAndroid Build Coastguard Worker FATAL("--repack doesn't support --bootloader.\n");
478*8617a60dSAndroid Build Coastguard Worker
479*8617a60dSAndroid Build Coastguard Worker signpriv_key = vb2_read_private_key(signprivkey_info);
480*8617a60dSAndroid Build Coastguard Worker if (!signpriv_key)
481*8617a60dSAndroid Build Coastguard Worker FATAL("Error reading signing key.\n");
482*8617a60dSAndroid Build Coastguard Worker
483*8617a60dSAndroid Build Coastguard Worker if (!oldfile)
484*8617a60dSAndroid Build Coastguard Worker FATAL("Missing previously packed blob.\n");
485*8617a60dSAndroid Build Coastguard Worker
486*8617a60dSAndroid Build Coastguard Worker /* Load the kernel partition */
487*8617a60dSAndroid Build Coastguard Worker kpart_data = ReadOldKPartFromFileOrDie(oldfile, &kpart_size);
488*8617a60dSAndroid Build Coastguard Worker
489*8617a60dSAndroid Build Coastguard Worker /* Make sure we have a kernel partition */
490*8617a60dSAndroid Build Coastguard Worker if (FILE_TYPE_KERN_PREAMBLE !=
491*8617a60dSAndroid Build Coastguard Worker futil_file_type_buf(kpart_data, kpart_size))
492*8617a60dSAndroid Build Coastguard Worker FATAL("%s is not a kernel blob\n", oldfile);
493*8617a60dSAndroid Build Coastguard Worker
494*8617a60dSAndroid Build Coastguard Worker kblob_data = unpack_kernel_partition(kpart_data, kpart_size,
495*8617a60dSAndroid Build Coastguard Worker &keyblock, &preamble,
496*8617a60dSAndroid Build Coastguard Worker &kblob_size);
497*8617a60dSAndroid Build Coastguard Worker
498*8617a60dSAndroid Build Coastguard Worker if (!kblob_data)
499*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to unpack kernel partition\n");
500*8617a60dSAndroid Build Coastguard Worker
501*8617a60dSAndroid Build Coastguard Worker kernel_body_load_address = preamble->body_load_address;
502*8617a60dSAndroid Build Coastguard Worker
503*8617a60dSAndroid Build Coastguard Worker /* Update the config if asked */
504*8617a60dSAndroid Build Coastguard Worker if (config_file) {
505*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Reading %s\n", config_file);
506*8617a60dSAndroid Build Coastguard Worker t_config_data =
507*8617a60dSAndroid Build Coastguard Worker ReadConfigFile(config_file, &t_config_size);
508*8617a60dSAndroid Build Coastguard Worker if (!t_config_data)
509*8617a60dSAndroid Build Coastguard Worker FATAL("Error reading config file.\n");
510*8617a60dSAndroid Build Coastguard Worker if (UpdateKernelBlobConfig(
511*8617a60dSAndroid Build Coastguard Worker kblob_data, kblob_size,
512*8617a60dSAndroid Build Coastguard Worker t_config_data, t_config_size))
513*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to update config\n");
514*8617a60dSAndroid Build Coastguard Worker }
515*8617a60dSAndroid Build Coastguard Worker
516*8617a60dSAndroid Build Coastguard Worker if (!version_str)
517*8617a60dSAndroid Build Coastguard Worker version = preamble->kernel_version;
518*8617a60dSAndroid Build Coastguard Worker
519*8617a60dSAndroid Build Coastguard Worker if (vb2_kernel_get_flags(preamble))
520*8617a60dSAndroid Build Coastguard Worker flags = vb2_kernel_get_flags(preamble);
521*8617a60dSAndroid Build Coastguard Worker
522*8617a60dSAndroid Build Coastguard Worker if (keyblock_file) {
523*8617a60dSAndroid Build Coastguard Worker t_keyblock = (struct vb2_keyblock *)
524*8617a60dSAndroid Build Coastguard Worker ReadFile(keyblock_file, 0);
525*8617a60dSAndroid Build Coastguard Worker if (!t_keyblock)
526*8617a60dSAndroid Build Coastguard Worker FATAL("Error reading keyblock.\n");
527*8617a60dSAndroid Build Coastguard Worker }
528*8617a60dSAndroid Build Coastguard Worker
529*8617a60dSAndroid Build Coastguard Worker /* Reuse previous body size */
530*8617a60dSAndroid Build Coastguard Worker vblock_data = SignKernelBlob(kblob_data, kblob_size, opt_pad,
531*8617a60dSAndroid Build Coastguard Worker version, kernel_body_load_address,
532*8617a60dSAndroid Build Coastguard Worker t_keyblock ? t_keyblock : keyblock,
533*8617a60dSAndroid Build Coastguard Worker signpriv_key, flags, &vblock_size);
534*8617a60dSAndroid Build Coastguard Worker if (!vblock_data)
535*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to sign kernel blob\n");
536*8617a60dSAndroid Build Coastguard Worker
537*8617a60dSAndroid Build Coastguard Worker if (opt_vblockonly)
538*8617a60dSAndroid Build Coastguard Worker rv = WriteSomeParts(filename,
539*8617a60dSAndroid Build Coastguard Worker vblock_data, vblock_size,
540*8617a60dSAndroid Build Coastguard Worker NULL, 0);
541*8617a60dSAndroid Build Coastguard Worker else
542*8617a60dSAndroid Build Coastguard Worker rv = WriteSomeParts(filename,
543*8617a60dSAndroid Build Coastguard Worker vblock_data, vblock_size,
544*8617a60dSAndroid Build Coastguard Worker kblob_data, kblob_size);
545*8617a60dSAndroid Build Coastguard Worker return rv;
546*8617a60dSAndroid Build Coastguard Worker
547*8617a60dSAndroid Build Coastguard Worker case OPT_MODE_VERIFY:
548*8617a60dSAndroid Build Coastguard Worker
549*8617a60dSAndroid Build Coastguard Worker /* Optional */
550*8617a60dSAndroid Build Coastguard Worker
551*8617a60dSAndroid Build Coastguard Worker if (signpubkey_file) {
552*8617a60dSAndroid Build Coastguard Worker signpub_key = vb2_read_packed_key(signpubkey_file);
553*8617a60dSAndroid Build Coastguard Worker if (!signpub_key)
554*8617a60dSAndroid Build Coastguard Worker FATAL("Error reading public key.\n");
555*8617a60dSAndroid Build Coastguard Worker }
556*8617a60dSAndroid Build Coastguard Worker
557*8617a60dSAndroid Build Coastguard Worker /* Do it */
558*8617a60dSAndroid Build Coastguard Worker
559*8617a60dSAndroid Build Coastguard Worker /* Load the kernel partition */
560*8617a60dSAndroid Build Coastguard Worker kpart_data = ReadOldKPartFromFileOrDie(filename, &kpart_size);
561*8617a60dSAndroid Build Coastguard Worker
562*8617a60dSAndroid Build Coastguard Worker kblob_data = unpack_kernel_partition(kpart_data, kpart_size,
563*8617a60dSAndroid Build Coastguard Worker 0, 0, &kblob_size);
564*8617a60dSAndroid Build Coastguard Worker if (!kblob_data)
565*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to unpack kernel partition\n");
566*8617a60dSAndroid Build Coastguard Worker
567*8617a60dSAndroid Build Coastguard Worker rv = VerifyKernelBlob(kblob_data, kblob_size,
568*8617a60dSAndroid Build Coastguard Worker signpub_key, keyblock_file, min_version);
569*8617a60dSAndroid Build Coastguard Worker
570*8617a60dSAndroid Build Coastguard Worker return rv;
571*8617a60dSAndroid Build Coastguard Worker
572*8617a60dSAndroid Build Coastguard Worker case OPT_MODE_GET_VMLINUZ:
573*8617a60dSAndroid Build Coastguard Worker
574*8617a60dSAndroid Build Coastguard Worker if (!vmlinuz_out_file) {
575*8617a60dSAndroid Build Coastguard Worker ERROR("USE: vbutil_kernel --get-vmlinuz <file> "
576*8617a60dSAndroid Build Coastguard Worker "--vmlinuz-out <file>\n");
577*8617a60dSAndroid Build Coastguard Worker print_help(argc, argv);
578*8617a60dSAndroid Build Coastguard Worker return 1;
579*8617a60dSAndroid Build Coastguard Worker }
580*8617a60dSAndroid Build Coastguard Worker
581*8617a60dSAndroid Build Coastguard Worker kpart_data = ReadOldKPartFromFileOrDie(filename, &kpart_size);
582*8617a60dSAndroid Build Coastguard Worker
583*8617a60dSAndroid Build Coastguard Worker kblob_data = unpack_kernel_partition(kpart_data, kpart_size,
584*8617a60dSAndroid Build Coastguard Worker &keyblock, &preamble,
585*8617a60dSAndroid Build Coastguard Worker &kblob_size);
586*8617a60dSAndroid Build Coastguard Worker
587*8617a60dSAndroid Build Coastguard Worker if (!kblob_data)
588*8617a60dSAndroid Build Coastguard Worker FATAL("Unable to unpack kernel partition\n");
589*8617a60dSAndroid Build Coastguard Worker
590*8617a60dSAndroid Build Coastguard Worker f = fopen(vmlinuz_out_file, "wb");
591*8617a60dSAndroid Build Coastguard Worker if (!f) {
592*8617a60dSAndroid Build Coastguard Worker FATAL("Can't open output file %s\n", vmlinuz_out_file);
593*8617a60dSAndroid Build Coastguard Worker return 1;
594*8617a60dSAndroid Build Coastguard Worker }
595*8617a60dSAndroid Build Coastguard Worker
596*8617a60dSAndroid Build Coastguard Worker /* Now stick 16-bit header followed by kernel block into
597*8617a60dSAndroid Build Coastguard Worker output */
598*8617a60dSAndroid Build Coastguard Worker vb2_kernel_get_vmlinuz_header(preamble,
599*8617a60dSAndroid Build Coastguard Worker &vmlinuz_header_address,
600*8617a60dSAndroid Build Coastguard Worker &vmlinuz_header_size);
601*8617a60dSAndroid Build Coastguard Worker if (vmlinuz_header_size) {
602*8617a60dSAndroid Build Coastguard Worker // verify that the 16-bit header is included in the
603*8617a60dSAndroid Build Coastguard Worker // kblob (to make sure that it's included in the
604*8617a60dSAndroid Build Coastguard Worker // signature)
605*8617a60dSAndroid Build Coastguard Worker if (vb2_verify_member_inside(
606*8617a60dSAndroid Build Coastguard Worker (void *)preamble->body_load_address,
607*8617a60dSAndroid Build Coastguard Worker kblob_size,
608*8617a60dSAndroid Build Coastguard Worker (void *)vmlinuz_header_address,
609*8617a60dSAndroid Build Coastguard Worker vmlinuz_header_size, 0, 0)) {
610*8617a60dSAndroid Build Coastguard Worker fclose(f);
611*8617a60dSAndroid Build Coastguard Worker unlink(vmlinuz_out_file);
612*8617a60dSAndroid Build Coastguard Worker FATAL("Vmlinuz header not signed!\n");
613*8617a60dSAndroid Build Coastguard Worker return 1;
614*8617a60dSAndroid Build Coastguard Worker }
615*8617a60dSAndroid Build Coastguard Worker // calculate the vmlinuz_header offset from
616*8617a60dSAndroid Build Coastguard Worker // the beginning of the kpart_data. The kblob doesn't
617*8617a60dSAndroid Build Coastguard Worker // include the body_load_offset, but does include
618*8617a60dSAndroid Build Coastguard Worker // the keyblock and preamble sections.
619*8617a60dSAndroid Build Coastguard Worker vmlinuz_header_offset = vmlinuz_header_address -
620*8617a60dSAndroid Build Coastguard Worker preamble->body_load_address +
621*8617a60dSAndroid Build Coastguard Worker keyblock->keyblock_size +
622*8617a60dSAndroid Build Coastguard Worker preamble->preamble_size;
623*8617a60dSAndroid Build Coastguard Worker errcount |=
624*8617a60dSAndroid Build Coastguard Worker (1 != fwrite(kpart_data + vmlinuz_header_offset,
625*8617a60dSAndroid Build Coastguard Worker vmlinuz_header_size,
626*8617a60dSAndroid Build Coastguard Worker 1,
627*8617a60dSAndroid Build Coastguard Worker f));
628*8617a60dSAndroid Build Coastguard Worker }
629*8617a60dSAndroid Build Coastguard Worker errcount |= (1 != fwrite(kblob_data,
630*8617a60dSAndroid Build Coastguard Worker kblob_size,
631*8617a60dSAndroid Build Coastguard Worker 1,
632*8617a60dSAndroid Build Coastguard Worker f));
633*8617a60dSAndroid Build Coastguard Worker if (errcount) {
634*8617a60dSAndroid Build Coastguard Worker fclose(f);
635*8617a60dSAndroid Build Coastguard Worker unlink(vmlinuz_out_file);
636*8617a60dSAndroid Build Coastguard Worker FATAL("Can't write output file %s\n", vmlinuz_out_file);
637*8617a60dSAndroid Build Coastguard Worker return 1;
638*8617a60dSAndroid Build Coastguard Worker }
639*8617a60dSAndroid Build Coastguard Worker
640*8617a60dSAndroid Build Coastguard Worker fclose(f);
641*8617a60dSAndroid Build Coastguard Worker return 0;
642*8617a60dSAndroid Build Coastguard Worker }
643*8617a60dSAndroid Build Coastguard Worker
644*8617a60dSAndroid Build Coastguard Worker ERROR("You must specify a mode: "
645*8617a60dSAndroid Build Coastguard Worker "--pack, --repack, --verify, or --get-vmlinuz\n");
646*8617a60dSAndroid Build Coastguard Worker print_help(argc, argv);
647*8617a60dSAndroid Build Coastguard Worker return 1;
648*8617a60dSAndroid Build Coastguard Worker }
649*8617a60dSAndroid Build Coastguard Worker
650*8617a60dSAndroid Build Coastguard Worker DECLARE_FUTIL_COMMAND(vbutil_kernel, do_vbutil_kernel, VBOOT_VERSION_1_0,
651*8617a60dSAndroid Build Coastguard Worker "Creates, signs, and verifies the kernel partition");
652