xref: /aosp_15_r20/external/vboot_reference/futility/cmd_vbutil_kernel.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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