1 /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2  * Use of this source code is governed by a BSD-style license that can be
3  * found in the LICENSE file.
4  *
5  * Routines for verifying a kernel or disk image
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "host_common.h"
13 #include "util_misc.h"
14 #include "vboot_common.h"
15 #include "vboot_api.h"
16 #include "vboot_kernel.h"
17 
18 static uint8_t *diskbuf;
19 
20 static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
21 static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
22 static VbNvContext nvc;
23 
24 static LoadKernelParams params;
25 static VbCommonParams cparams;
26 
VbExDiskRead(VbExDiskHandle_t handle,uint64_t lba_start,uint64_t lba_count,void * buffer)27 VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
28 		       uint64_t lba_count, void *buffer)
29 {
30 	if (handle != (VbExDiskHandle_t)1)
31 		return VBERROR_UNKNOWN;
32 	if (lba_start >= params.streaming_lba_count)
33 		return VBERROR_UNKNOWN;
34 	if (lba_start + lba_count > params.streaming_lba_count)
35 		return VBERROR_UNKNOWN;
36 
37 	memcpy(buffer, diskbuf + lba_start * 512, lba_count * 512);
38 	return VBERROR_SUCCESS;
39 }
40 
VbExDiskWrite(VbExDiskHandle_t handle,uint64_t lba_start,uint64_t lba_count,const void * buffer)41 VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
42 			uint64_t lba_count, const void *buffer)
43 {
44 	if (handle != (VbExDiskHandle_t)1)
45 		return VBERROR_UNKNOWN;
46 	if (lba_start >= params.streaming_lba_count)
47 		return VBERROR_UNKNOWN;
48 	if (lba_start + lba_count > params.streaming_lba_count)
49 		return VBERROR_UNKNOWN;
50 
51 	memcpy(diskbuf + lba_start * 512, buffer, lba_count * 512);
52 	return VBERROR_SUCCESS;
53 }
54 
print_help(const char * progname)55 static void print_help(const char *progname)
56 {
57 	printf("\nUsage: %s <disk_image> <kernel.vbpubk>\n\n",
58 	       progname);
59 }
60 
main(int argc,char * argv[])61 int main(int argc, char *argv[])
62 {
63 	VbPublicKey *kernkey;
64 	uint64_t disk_bytes = 0;
65 	int rv;
66 
67 	if (argc < 3) {
68 		print_help(argv[0]);
69 		return 1;
70 	}
71 
72 	/* Load disk file */
73 	/* TODO: is it better to mmap() in the long run? */
74 	diskbuf = ReadFile(argv[1], &disk_bytes);
75 	if (!diskbuf) {
76 		fprintf(stderr, "Can't read disk file %s\n", argv[1]);
77 		return 1;
78 	}
79 
80 	/* Read public key */
81 	kernkey = PublicKeyRead(argv[2]);
82 	if (!kernkey) {
83 		fprintf(stderr, "Can't read key file %s\n", argv[2]);
84 		return 1;
85 	}
86 
87 	/* Set up shared data blob */
88 	VbSharedDataInit(shared, sizeof(shared_data));
89 	VbSharedDataSetKernelKey(shared, kernkey);
90 	/* TODO: optional TPM current kernel version */
91 
92 	/* Set up params */
93 	params.shared_data_blob = shared_data;
94 	params.shared_data_size = sizeof(shared_data);
95 	params.disk_handle = (VbExDiskHandle_t)1;
96 	params.bytes_per_lba = 512;
97 	params.streaming_lba_count = disk_bytes / 512;
98 	params.gpt_lba_count = params.streaming_lba_count;
99 
100 	params.kernel_buffer_size = 16 * 1024 * 1024;
101 	params.kernel_buffer = malloc(params.kernel_buffer_size);
102 	if (!params.kernel_buffer) {
103 		fprintf(stderr, "Can't allocate kernel buffer\n");
104 		return 1;
105 	}
106 
107 	/* GBB and cparams only needed by LoadKernel() in recovery mode */
108 	params.gbb_data = NULL;
109 	params.gbb_size = 0;
110 
111 	/* TODO(chromium:441893): support dev-mode flag and external gpt flag */
112 	params.boot_flags = 0;
113 
114 	/*
115 	 * LoadKernel() cares only about VBNV_DEV_BOOT_SIGNED_ONLY, and only in
116 	 * dev mode.  So just use defaults.
117 	 */
118 	VbNvSetup(&nvc);
119 	params.nv_context = &nvc;
120 
121 	/* Try loading kernel */
122 	rv = LoadKernel(&params, &cparams);
123 	if (rv != VBERROR_SUCCESS) {
124 		fprintf(stderr, "LoadKernel() failed with code %d\n", rv);
125 		return 1;
126 	}
127 
128 	printf("Found a good kernel.\n");
129 	printf("Partition number:   %d\n", (int)params.partition_number);
130 	printf("Bootloader address: 0x%" PRIx64 "\n",
131 	       params.bootloader_address);
132 
133 	/* TODO: print other things (partition GUID, nv_context, shared_data) */
134 
135 	printf("Yaay!\n");
136 	return 0;
137 }
138