OLD | NEW |
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 "vboot_kernel.h" | 9 #include "vboot_kernel.h" |
10 | 10 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 kbuf_sectors = KBUF_SIZE / blba; | 145 kbuf_sectors = KBUF_SIZE / blba; |
146 is_dev = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0); | 146 is_dev = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0); |
147 is_rec = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0); | 147 is_rec = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0); |
148 is_normal = (!is_dev && !is_rec); | 148 is_normal = (!is_dev && !is_rec); |
149 | 149 |
150 /* Clear output params in case we fail */ | 150 /* Clear output params in case we fail */ |
151 params->partition_number = 0; | 151 params->partition_number = 0; |
152 params->bootloader_address = 0; | 152 params->bootloader_address = 0; |
153 params->bootloader_size = 0; | 153 params->bootloader_size = 0; |
154 | 154 |
155 if (!is_dev) { | 155 /* Let the TPM know if we're in recovery mode */ |
156 /* TODO: should use the TPM all the time; for now, only use when | 156 if (is_rec) { |
157 * not in developer mode. */ | 157 if (0 != RollbackKernelRecovery(is_dev)) { |
158 /* Let the TPM know if we're in recovery mode */ | 158 VBDEBUG(("Error setting up TPM for recovery kernel\n")); |
159 if (is_rec) { | 159 /* Ignore return code, since we need to boot recovery mode to |
160 if (0 != RollbackKernelRecovery(is_dev ? 1 : 0)) { | 160 * fix the TPM. */ |
161 VBDEBUG(("Error setting up TPM for recovery kernel\n")); | |
162 /* Ignore return code, since we need to boot recovery mode to | |
163 * fix the TPM. */ | |
164 } | |
165 } | 161 } |
166 } | 162 } |
167 | 163 |
168 if (is_normal) { | 164 if (is_normal) { |
169 /* Read current kernel key index from TPM. Assumes TPM is already | 165 /* Read current kernel key index from TPM. Assumes TPM is already |
170 * initialized. */ | 166 * initialized. */ |
171 status = RollbackKernelRead(&tpm_key_version, &tpm_kernel_version); | 167 status = RollbackKernelRead(&tpm_key_version, &tpm_kernel_version); |
172 if (0 != status) { | 168 if (0 != status) { |
173 VBDEBUG(("Unable to get kernel versions from TPM\n")); | 169 VBDEBUG(("Unable to get kernel versions from TPM\n")); |
174 return (status == TPM_E_MUST_REBOOT ? | 170 return (status == TPM_E_MUST_REBOOT ? |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 RSAPublicKeyFree(data_key); | 339 RSAPublicKeyFree(data_key); |
344 | 340 |
345 /* If we're still here, the kernel is valid. */ | 341 /* If we're still here, the kernel is valid. */ |
346 /* Save the first good partition we find; that's the one we'll boot */ | 342 /* Save the first good partition we find; that's the one we'll boot */ |
347 VBDEBUG(("Partiton is good.\n")); | 343 VBDEBUG(("Partiton is good.\n")); |
348 /* TODO: GPT partitions start at 1, but cgptlib starts them at 0. | 344 /* TODO: GPT partitions start at 1, but cgptlib starts them at 0. |
349 * Adjust here, until cgptlib is fixed. */ | 345 * Adjust here, until cgptlib is fixed. */ |
350 good_partition = gpt.current_kernel + 1; | 346 good_partition = gpt.current_kernel + 1; |
351 params->partition_number = gpt.current_kernel + 1; | 347 params->partition_number = gpt.current_kernel + 1; |
352 GetCurrentKernelUniqueGuid(&gpt, ¶ms->partition_guid); | 348 GetCurrentKernelUniqueGuid(&gpt, ¶ms->partition_guid); |
| 349 /* TODO: GetCurrentKernelUniqueGuid() should take a destination size, or |
| 350 * the dest should be a struct, so we know it's big enough. */ |
353 params->bootloader_address = preamble->bootloader_address; | 351 params->bootloader_address = preamble->bootloader_address; |
354 params->bootloader_size = preamble->bootloader_size; | 352 params->bootloader_size = preamble->bootloader_size; |
355 /* If we're in developer or recovery mode, there's no rollback | 353 /* If we're in developer or recovery mode, there's no rollback |
356 * protection, so we can stop at the first valid kernel. */ | 354 * protection, so we can stop at the first valid kernel. */ |
357 if (!is_normal) { | 355 if (!is_normal) { |
358 VBDEBUG(("Boot_flags = !is_normal\n")); | 356 VBDEBUG(("Boot_flags = !is_normal\n")); |
359 break; | 357 break; |
360 } | 358 } |
361 | 359 |
362 /* Otherwise, we're in normal boot mode, so we do care about the | 360 /* Otherwise, we're in normal boot mode, so we do care about the |
(...skipping 30 matching lines...) Expand all Loading... |
393 * back to normal mode. */ | 391 * back to normal mode. */ |
394 VBDEBUG(("Boot_flags = is_normal\n")); | 392 VBDEBUG(("Boot_flags = is_normal\n")); |
395 if ((lowest_key_version > tpm_key_version) || | 393 if ((lowest_key_version > tpm_key_version) || |
396 (lowest_key_version == tpm_key_version && | 394 (lowest_key_version == tpm_key_version && |
397 lowest_kernel_version > tpm_kernel_version)) { | 395 lowest_kernel_version > tpm_kernel_version)) { |
398 | 396 |
399 status = RollbackKernelWrite((uint16_t)lowest_key_version, | 397 status = RollbackKernelWrite((uint16_t)lowest_key_version, |
400 (uint16_t)lowest_kernel_version); | 398 (uint16_t)lowest_kernel_version); |
401 if (0 != status) { | 399 if (0 != status) { |
402 VBDEBUG(("Error writing kernel versions to TPM.\n")); | 400 VBDEBUG(("Error writing kernel versions to TPM.\n")); |
403 return (status == TPM_E_MUST_REBOOT ? | 401 return (status == TPM_E_MUST_REBOOT ? |
404 LOAD_KERNEL_REBOOT : LOAD_KERNEL_RECOVERY); | 402 LOAD_KERNEL_REBOOT : LOAD_KERNEL_RECOVERY); |
405 } | 403 } |
406 } | 404 } |
407 } | 405 } |
408 | 406 |
409 if (!is_dev) { | 407 /* Lock the kernel versions */ |
410 /* TODO: should use the TPM all the time; for now, only use when | 408 status = RollbackKernelLock(); |
411 * not in developer mode. */ | 409 if (0 != status) { |
412 /* Lock the kernel versions */ | 410 VBDEBUG(("Error locking kernel versions.\n")); |
413 status = RollbackKernelLock(); | 411 /* Don't reboot to recovery mode if we're already there */ |
414 if (0 != status) { | 412 if (!is_rec) |
415 VBDEBUG(("Error locking kernel versions.\n")); | 413 return (status == TPM_E_MUST_REBOOT ? |
416 /* Don't reboot to recovery mode if we're already there */ | 414 LOAD_KERNEL_REBOOT : LOAD_KERNEL_RECOVERY); |
417 if (!is_rec) | |
418 return (status == TPM_E_MUST_REBOOT ? | |
419 LOAD_KERNEL_REBOOT : LOAD_KERNEL_RECOVERY); | |
420 } | |
421 } | 415 } |
422 | 416 |
423 /* Success! */ | 417 /* Success! */ |
424 return LOAD_KERNEL_SUCCESS; | 418 return LOAD_KERNEL_SUCCESS; |
425 } | 419 } |
426 | 420 |
427 // Handle error cases | 421 // Handle error cases |
428 if (found_partitions) | 422 if (found_partitions) |
429 return LOAD_KERNEL_INVALID; | 423 return LOAD_KERNEL_INVALID; |
430 else | 424 else |
431 return LOAD_KERNEL_NOT_FOUND; | 425 return LOAD_KERNEL_NOT_FOUND; |
432 } | 426 } |
OLD | NEW |