Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: src/platform/vboot_reference/vboot_firmware/lib/load_kernel_fw.c

Issue 2561001: Fix LoadKernel() (Closed) Base URL: ssh://gitrw.chromium.org/chromiumos
Patch Set: Make requested changes. Rename bootloader start to bootloader address. Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/platform/vboot_reference/vboot_firmware/lib/kernel_image_fw.c ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 * 4 *
5 * Functions for loading a kernel from disk. 5 * Functions for loading a kernel from disk.
6 * (Firmware portion) 6 * (Firmware portion)
7 */ 7 */
8 8
9 #include "load_kernel_fw.h" 9 #include "load_kernel_fw.h"
10 10
11 #include "boot_device.h" 11 #include "boot_device.h"
12 #include "cgptlib.h" 12 #include "cgptlib.h"
13 #include "kernel_image_fw.h" 13 #include "kernel_image_fw.h"
14 #include "rollback_index.h" 14 #include "rollback_index.h"
15 #include "utility.h" 15 #include "utility.h"
16 16
17 #define GPT_ENTRIES_SIZE 16384 /* Bytes to read for GPT entries */ 17 #define GPT_ENTRIES_SIZE 16384 /* Bytes to read for GPT entries */
18 18
19 // TODO: for testing 19 // TODO: for testing
20 #include <stdio.h> 20 #include <stdio.h>
21 #include <inttypes.h> /* For PRIu64 macro */
21 #include "cgptlib_internal.h" 22 #include "cgptlib_internal.h"
22 23
23 /* TODO: Remove this terrible hack which fakes partition attributes 24 /* TODO: Remove this terrible hack which fakes partition attributes
24 * for the kernel partitions so that GptNextKernelEntry() won't 25 * for the kernel partitions so that GptNextKernelEntry() won't
25 * choke. */ 26 * choke. */
26 void FakePartitionAttributes(GptData* gpt) { 27 void FakePartitionAttributes(GptData* gpt) {
27 GptEntry* entries = (GptEntry*)gpt->primary_entries; 28 GptEntry* entries = (GptEntry*)gpt->primary_entries;
28 GptEntry* e; 29 GptEntry* e;
29 int i; 30 int i;
30 printf("Hacking partition attributes...\n"); 31 printf("Hacking partition attributes...\n");
31 printf("Note that GUIDs below have first 3 fields endian-swapped\n");
32 32
33 for (i = 0, e = entries; i < 12; i++, e++) { 33 for (i = 0, e = entries; i < 12; i++, e++) {
34 34
35 printf("%2d %08x %04x %04x %02x %02x %02x %02x %02x %02x %02x %02x\n", 35 printf("%2d %08x %04x %04x %02x %02x %02x %02x %02x %02x %02x %02x",
36 i, 36 i,
37 e->type.u.Uuid.time_low, 37 e->type.u.Uuid.time_low,
38 e->type.u.Uuid.time_mid, 38 e->type.u.Uuid.time_mid,
39 e->type.u.Uuid.time_high_and_version, 39 e->type.u.Uuid.time_high_and_version,
40 e->type.u.Uuid.clock_seq_high_and_reserved, 40 e->type.u.Uuid.clock_seq_high_and_reserved,
41 e->type.u.Uuid.clock_seq_low, 41 e->type.u.Uuid.clock_seq_low,
42 e->type.u.Uuid.node[0], 42 e->type.u.Uuid.node[0],
43 e->type.u.Uuid.node[1], 43 e->type.u.Uuid.node[1],
44 e->type.u.Uuid.node[2], 44 e->type.u.Uuid.node[2],
45 e->type.u.Uuid.node[3], 45 e->type.u.Uuid.node[3],
46 e->type.u.Uuid.node[4], 46 e->type.u.Uuid.node[4],
47 e->type.u.Uuid.node[5] 47 e->type.u.Uuid.node[5]
48 ); 48 );
49 printf(" %8" PRIu64 " %8" PRIu64"\n", e->starting_lba,
50 e->ending_lba - e->starting_lba + 1);
49 if (!IsKernelEntry(e)) 51 if (!IsKernelEntry(e))
50 continue; 52 continue;
51 printf("Hacking attributes for kernel partition %d\n", i); 53 printf("Hacking attributes for kernel partition %d\n", i);
52 SetEntryPriority(e, 2); 54 SetEntryPriority(e, 2);
53 SetEntrySuccessful(e, 1); 55 SetEntrySuccessful(e, 1);
54 } 56 }
55 } 57 }
56 58
57 59
58 int AllocAndReadGptData(GptData *gptdata) { 60 int AllocAndReadGptData(GptData *gptdata) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 uint64_t blba = params->bytes_per_lba; 139 uint64_t blba = params->bytes_per_lba;
138 uint8_t* kbuf = NULL; 140 uint8_t* kbuf = NULL;
139 uint64_t kbuf_sectors; 141 uint64_t kbuf_sectors;
140 int found_partition = 0; 142 int found_partition = 0;
141 int good_partition = -1; 143 int good_partition = -1;
142 uint16_t tpm_kernel_key_version, tpm_kernel_version; 144 uint16_t tpm_kernel_key_version, tpm_kernel_version;
143 uint16_t lowest_kernel_key_version = 0xFFFF; 145 uint16_t lowest_kernel_key_version = 0xFFFF;
144 uint16_t lowest_kernel_version = 0xFFFF; 146 uint16_t lowest_kernel_version = 0xFFFF;
145 KernelImage *kim = NULL; 147 KernelImage *kim = NULL;
146 148
149 /* Clear output params in case we fail */
150 params->partition_number = 0;
151 params->bootloader_address = 0;
152 params->bootloader_size = 0;
153
147 /* Read current kernel key index from TPM. Assumes TPM is already 154 /* Read current kernel key index from TPM. Assumes TPM is already
148 * initialized. */ 155 * initialized. */
149 /* TODO: Is that a safe assumption? Normally, SetupTPM() would be called 156 /* TODO: Is that a safe assumption? Normally, SetupTPM() would be called
150 * when the RW firmware is verified. Is it harmful to call SetupTPM() 157 * when the RW firmware is verified. Is it harmful to call SetupTPM()
151 * again if it's already initialized? It'd be easier if we could just do 158 * again if it's already initialized? It'd be easier if we could just do
152 * that. */ 159 * that. */
153 GetStoredVersions(KERNEL_VERSIONS, 160 GetStoredVersions(KERNEL_VERSIONS,
154 &tpm_kernel_key_version, 161 &tpm_kernel_key_version,
155 &tpm_kernel_version); 162 &tpm_kernel_version);
156 163
157 do { 164 do {
158 /* Read GPT data */ 165 /* Read GPT data */
159 gpt.sector_bytes = blba; 166 gpt.sector_bytes = blba;
160 gpt.drive_sectors = params->ending_lba + 1; 167 gpt.drive_sectors = params->ending_lba + 1;
161 if (0 != AllocAndReadGptData(&gpt)) 168 if (0 != AllocAndReadGptData(&gpt))
162 break; 169 break;
163 170
164 fprintf(stderr, "RRS1\n");
165
166 /* Initialize GPT library */ 171 /* Initialize GPT library */
167 if (GPT_SUCCESS != GptInit(&gpt)) 172 if (GPT_SUCCESS != GptInit(&gpt))
168 break; 173 break;
169 174
170 /* TODO: TERRIBLE KLUDGE - fake partition attributes */ 175 /* TODO: TERRIBLE KLUDGE - fake partition attributes */
171 FakePartitionAttributes(&gpt); 176 FakePartitionAttributes(&gpt);
172 177
173 /* Allocate kernel header and image work buffers */ 178 /* Allocate kernel header and image work buffers */
174 kbuf = (uint8_t*)Malloc(KBUF_SIZE); 179 kbuf = (uint8_t*)Malloc(KBUF_SIZE);
175 if (!kbuf) 180 if (!kbuf)
176 break; 181 break;
177 182
178 kbuf_sectors = KBUF_SIZE / blba; 183 kbuf_sectors = KBUF_SIZE / blba;
179 kim = (KernelImage*)Malloc(sizeof(KernelImage)); 184 kim = (KernelImage*)Malloc(sizeof(KernelImage));
180 if (!kim) 185 if (!kim)
181 break; 186 break;
182 187
183 fprintf(stderr, "RRS2\n");
184
185 /* Loop over candidate kernel partitions */ 188 /* Loop over candidate kernel partitions */
186 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) { 189 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) {
187 RSAPublicKey *kernel_sign_key = NULL; 190 RSAPublicKey *kernel_sign_key = NULL;
188 int kernel_start, kernel_sectors; 191 int kernel_start, kernel_sectors;
189 192
190 fprintf(stderr, "RRS3\n");
191
192 /* Found at least one kernel partition. */ 193 /* Found at least one kernel partition. */
193 found_partition = 1; 194 found_partition = 1;
194 195
195 /* Read the first part of the kernel partition */ 196 /* Read the first part of the kernel partition */
196 if (part_size < kbuf_sectors) 197 if (part_size < kbuf_sectors)
197 continue; 198 continue;
198 if (0 != BootDeviceReadLBA(part_start, kbuf_sectors, kbuf)) 199 if (0 != BootDeviceReadLBA(part_start, kbuf_sectors, kbuf))
199 continue; 200 continue;
200 201
201 fprintf(stderr, "RRS4\n");
202
203 /* Verify the kernel header and preamble */ 202 /* Verify the kernel header and preamble */
204 if (VERIFY_KERNEL_SUCCESS != VerifyKernelHeader( 203 if (VERIFY_KERNEL_SUCCESS != VerifyKernelHeader(
205 params->header_sign_key_blob, 204 params->header_sign_key_blob,
206 kbuf, 205 kbuf,
207 KBUF_SIZE, 206 KBUF_SIZE,
208 (BOOT_MODE_DEVELOPER == params->boot_mode ? 1 : 0), 207 (BOOT_MODE_DEVELOPER == params->boot_mode ? 1 : 0),
209 kim, 208 kim,
210 &kernel_sign_key)) { 209 &kernel_sign_key)) {
211 continue; 210 continue;
212 } 211 }
213 212
214 fprintf(stderr, "RRS5\n"); 213 printf("Kernel header:\n");
214 printf("header version: %d\n", kim->header_version);
215 printf("header len: %d\n", kim->header_len);
216 printf("firmware sign alg: %d\n", kim->firmware_sign_algorithm);
217 printf("kernel sign alg: %d\n", kim->kernel_sign_algorithm);
218 printf("kernel key version: %d\n", kim->kernel_key_version);
219 printf("kernel version: %d\n", kim->kernel_version);
220 printf("kernel len: %" PRIu64 "\n", kim->kernel_len);
221 printf("bootloader addr: %" PRIu64 "\n", kim->bootloader_offset);
222 printf("bootloader size: %" PRIu64 "\n", kim->bootloader_size);
223 printf("padded header size: %" PRIu64 "\n", kim->padded_header_size);
215 224
216 /* Check for rollback of key version */ 225 /* Check for rollback of key version */
217 if (kim->kernel_key_version < tpm_kernel_key_version) { 226 if (kim->kernel_key_version < tpm_kernel_key_version) {
218 RSAPublicKeyFree(kernel_sign_key); 227 RSAPublicKeyFree(kernel_sign_key);
219 continue; 228 continue;
220 } 229 }
221 230
222 /* Check for rollback of kernel version */ 231 /* Check for rollback of kernel version */
223 if (kim->kernel_key_version == tpm_kernel_key_version && 232 if (kim->kernel_key_version == tpm_kernel_key_version &&
224 kim->kernel_version < tpm_kernel_version) { 233 kim->kernel_version < tpm_kernel_version) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 } 272 }
264 273
265 /* Done with the kernel signing key, so can free it now */ 274 /* Done with the kernel signing key, so can free it now */
266 RSAPublicKeyFree(kernel_sign_key); 275 RSAPublicKeyFree(kernel_sign_key);
267 276
268 /* If we're still here, the kernel is valid. */ 277 /* If we're still here, the kernel is valid. */
269 /* Save the first good partition we find; that's the one we'll boot */ 278 /* Save the first good partition we find; that's the one we'll boot */
270 if (-1 == good_partition) { 279 if (-1 == good_partition) {
271 good_partition = gpt.current_kernel; 280 good_partition = gpt.current_kernel;
272 params->partition_number = gpt.current_kernel; 281 params->partition_number = gpt.current_kernel;
273 params->bootloader_start = (uint8_t*)params->kernel_buffer + 282 params->bootloader_address = kim->bootloader_offset;
274 kim->bootloader_offset;
275 params->bootloader_size = kim->bootloader_size; 283 params->bootloader_size = kim->bootloader_size;
276 284
277 /* If the good partition's key version is the same as the tpm, then 285 /* If the good partition's key version is the same as the tpm, then
278 * the TPM doesn't need updating; we can stop now. Otherwise, we'll 286 * the TPM doesn't need updating; we can stop now. Otherwise, we'll
279 * check all the other headers to see if they contain a newer key. */ 287 * check all the other headers to see if they contain a newer key. */
280 if (kim->kernel_key_version == tpm_kernel_key_version && 288 if (kim->kernel_key_version == tpm_kernel_key_version &&
281 kim->kernel_version == tpm_kernel_version) 289 kim->kernel_version == tpm_kernel_version)
282 break; 290 break;
283 } 291 }
284 } /* while(GptNextKernelEntry) */ 292 } /* while(GptNextKernelEntry) */
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 331
324 // Handle error cases 332 // Handle error cases
325 if (found_partition) 333 if (found_partition)
326 return LOAD_KERNEL_INVALID; 334 return LOAD_KERNEL_INVALID;
327 else 335 else
328 return LOAD_KERNEL_NOT_FOUND; 336 return LOAD_KERNEL_NOT_FOUND;
329 /* TODO: no error code for "internal error", but what would the firmware do 337 /* TODO: no error code for "internal error", but what would the firmware do
330 * with that anyway? So in the do-while(0) code above, the firmware just 338 * with that anyway? So in the do-while(0) code above, the firmware just
331 * does 'break' to indicate an internal error... */ 339 * does 'break' to indicate an internal error... */
332 } 340 }
OLDNEW
« no previous file with comments | « src/platform/vboot_reference/vboot_firmware/lib/kernel_image_fw.c ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698