| 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 |