| 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 "load_kernel_fw.h" | 9 #include "load_kernel_fw.h" |
| 10 | 10 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 uint64_t part_start, part_size; | 157 uint64_t part_start, part_size; |
| 158 uint64_t blba = params->bytes_per_lba; | 158 uint64_t blba = params->bytes_per_lba; |
| 159 uint8_t* kbuf = NULL; | 159 uint8_t* kbuf = NULL; |
| 160 uint64_t kbuf_sectors; | 160 uint64_t kbuf_sectors; |
| 161 int found_partition = 0; | 161 int found_partition = 0; |
| 162 int good_partition = -1; | 162 int good_partition = -1; |
| 163 uint16_t tpm_kernel_key_version, tpm_kernel_version; | 163 uint16_t tpm_kernel_key_version, tpm_kernel_version; |
| 164 uint16_t lowest_kernel_key_version = 0xFFFF; | 164 uint16_t lowest_kernel_key_version = 0xFFFF; |
| 165 uint16_t lowest_kernel_version = 0xFFFF; | 165 uint16_t lowest_kernel_version = 0xFFFF; |
| 166 KernelImage *kim = NULL; | 166 KernelImage *kim = NULL; |
| 167 int is_dev = ((BOOT_FLAG_DEVELOPER & params->boot_flags) && |
| 168 !(BOOT_FLAG_RECOVERY & params->boot_flags)); |
| 169 int is_normal = (!(BOOT_FLAG_DEVELOPER & params->boot_flags) && |
| 170 !(BOOT_FLAG_RECOVERY & params->boot_flags)); |
| 167 | 171 |
| 168 /* Clear output params in case we fail */ | 172 /* Clear output params in case we fail */ |
| 169 params->partition_number = 0; | 173 params->partition_number = 0; |
| 170 params->bootloader_address = 0; | 174 params->bootloader_address = 0; |
| 171 params->bootloader_size = 0; | 175 params->bootloader_size = 0; |
| 172 | 176 |
| 173 if (BOOT_MODE_NORMAL == params->boot_mode) { | 177 if (is_normal) { |
| 174 /* Read current kernel key index from TPM. Assumes TPM is already | 178 /* Read current kernel key index from TPM. Assumes TPM is already |
| 175 * initialized. */ | 179 * initialized. */ |
| 176 if (0 != GetStoredVersions(KERNEL_VERSIONS, | 180 if (0 != GetStoredVersions(KERNEL_VERSIONS, |
| 177 &tpm_kernel_key_version, | 181 &tpm_kernel_key_version, |
| 178 &tpm_kernel_version)) | 182 &tpm_kernel_version)) |
| 179 return LOAD_KERNEL_RECOVERY; | 183 return LOAD_KERNEL_RECOVERY; |
| 180 } | 184 } |
| 181 | 185 |
| 182 do { | 186 do { |
| 183 /* Read GPT data */ | 187 /* Read GPT data */ |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 if (part_size < kbuf_sectors) | 219 if (part_size < kbuf_sectors) |
| 216 continue; | 220 continue; |
| 217 if (0 != BootDeviceReadLBA(part_start, kbuf_sectors, kbuf)) | 221 if (0 != BootDeviceReadLBA(part_start, kbuf_sectors, kbuf)) |
| 218 continue; | 222 continue; |
| 219 | 223 |
| 220 /* Verify the kernel header and preamble */ | 224 /* Verify the kernel header and preamble */ |
| 221 if (VERIFY_KERNEL_SUCCESS != VerifyKernelHeader( | 225 if (VERIFY_KERNEL_SUCCESS != VerifyKernelHeader( |
| 222 params->header_sign_key_blob, | 226 params->header_sign_key_blob, |
| 223 kbuf, | 227 kbuf, |
| 224 KBUF_SIZE, | 228 KBUF_SIZE, |
| 225 (BOOT_MODE_DEVELOPER == params->boot_mode ? 1 : 0), | 229 (is_dev ? 1 : 0), |
| 226 kim, | 230 kim, |
| 227 &kernel_sign_key)) { | 231 &kernel_sign_key)) { |
| 228 continue; | 232 continue; |
| 229 } | 233 } |
| 230 | 234 |
| 231 #ifdef PRINT_DEBUG_INFO | 235 #ifdef PRINT_DEBUG_INFO |
| 232 printf("Kernel header:\n"); | 236 printf("Kernel header:\n"); |
| 233 printf("header version: %d\n", kim->header_version); | 237 printf("header version: %d\n", kim->header_version); |
| 234 printf("header len: %d\n", kim->header_len); | 238 printf("header len: %d\n", kim->header_len); |
| 235 printf("firmware sign alg: %d\n", kim->firmware_sign_algorithm); | 239 printf("firmware sign alg: %d\n", kim->firmware_sign_algorithm); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 258 /* Check for lowest key version from a valid header. */ | 262 /* Check for lowest key version from a valid header. */ |
| 259 if (lowest_kernel_key_version > kim->kernel_key_version) { | 263 if (lowest_kernel_key_version > kim->kernel_key_version) { |
| 260 lowest_kernel_key_version = kim->kernel_key_version; | 264 lowest_kernel_key_version = kim->kernel_key_version; |
| 261 lowest_kernel_version = kim->kernel_version; | 265 lowest_kernel_version = kim->kernel_version; |
| 262 } | 266 } |
| 263 else if (lowest_kernel_key_version == kim->kernel_key_version && | 267 else if (lowest_kernel_key_version == kim->kernel_key_version && |
| 264 lowest_kernel_version > kim->kernel_version) { | 268 lowest_kernel_version > kim->kernel_version) { |
| 265 lowest_kernel_version = kim->kernel_version; | 269 lowest_kernel_version = kim->kernel_version; |
| 266 } | 270 } |
| 267 | 271 |
| 272 /* If we already have a good kernel, no need to read another |
| 273 * one; we only needed to look at the versions to check for |
| 274 * rollback. */ |
| 275 if (-1 != good_partition) |
| 276 continue; |
| 277 |
| 268 /* Verify kernel padding is a multiple of sector size. */ | 278 /* Verify kernel padding is a multiple of sector size. */ |
| 269 if (0 != kim->padded_header_size % blba) { | 279 if (0 != kim->padded_header_size % blba) { |
| 270 RSAPublicKeyFree(kernel_sign_key); | 280 RSAPublicKeyFree(kernel_sign_key); |
| 271 continue; | 281 continue; |
| 272 } | 282 } |
| 273 | 283 |
| 274 kernel_start = part_start + (kim->padded_header_size / blba); | 284 kernel_start = part_start + (kim->padded_header_size / blba); |
| 275 kernel_sectors = (kim->kernel_len + blba - 1) / blba; | 285 kernel_sectors = (kim->kernel_len + blba - 1) / blba; |
| 276 | 286 |
| 277 /* Read the kernel data */ | 287 /* Read the kernel data */ |
| (...skipping 19 matching lines...) Expand all Loading... |
| 297 /* If we're still here, the kernel is valid. */ | 307 /* If we're still here, the kernel is valid. */ |
| 298 /* Save the first good partition we find; that's the one we'll boot */ | 308 /* Save the first good partition we find; that's the one we'll boot */ |
| 299 if (-1 == good_partition) { | 309 if (-1 == good_partition) { |
| 300 good_partition = gpt.current_kernel; | 310 good_partition = gpt.current_kernel; |
| 301 params->partition_number = gpt.current_kernel; | 311 params->partition_number = gpt.current_kernel; |
| 302 params->bootloader_address = kim->bootloader_offset; | 312 params->bootloader_address = kim->bootloader_offset; |
| 303 params->bootloader_size = kim->bootloader_size; | 313 params->bootloader_size = kim->bootloader_size; |
| 304 | 314 |
| 305 /* If we're in developer or recovery mode, there's no rollback | 315 /* If we're in developer or recovery mode, there's no rollback |
| 306 * protection, so we can stop at the first valid kernel. */ | 316 * protection, so we can stop at the first valid kernel. */ |
| 307 if (BOOT_MODE_NORMAL != params->boot_mode) | 317 if (!is_normal) |
| 308 break; | 318 break; |
| 309 | 319 |
| 310 /* Otherwise, we're in normal boot mode, so we do care about | 320 /* Otherwise, we're in normal boot mode, so we do care about |
| 311 * the key index in the TPM. If the good partition's key | 321 * the key index in the TPM. If the good partition's key |
| 312 * version is the same as the tpm, then the TPM doesn't need | 322 * version is the same as the tpm, then the TPM doesn't need |
| 313 * updating; we can stop now. Otherwise, we'll check all the | 323 * updating; we can stop now. Otherwise, we'll check all the |
| 314 * other headers to see if they contain a newer key. */ | 324 * other headers to see if they contain a newer key. */ |
| 315 if (kim->kernel_key_version == tpm_kernel_key_version && | 325 if (kim->kernel_key_version == tpm_kernel_key_version && |
| 316 kim->kernel_version == tpm_kernel_version) | 326 kim->kernel_version == tpm_kernel_version) |
| 317 break; | 327 break; |
| 318 } | 328 } |
| 319 } /* while(GptNextKernelEntry) */ | 329 } /* while(GptNextKernelEntry) */ |
| 320 } while(0); | 330 } while(0); |
| 321 | 331 |
| 322 /* Free kernel work and image buffers */ | 332 /* Free kernel work and image buffers */ |
| 323 if (kbuf) | 333 if (kbuf) |
| 324 Free(kbuf); | 334 Free(kbuf); |
| 325 if (kim) | 335 if (kim) |
| 326 Free(kim); | 336 Free(kim); |
| 327 | 337 |
| 328 /* Write and free GPT data */ | 338 /* Write and free GPT data */ |
| 329 WriteAndFreeGptData(&gpt); | 339 WriteAndFreeGptData(&gpt); |
| 330 | 340 |
| 331 /* Handle finding a good partition */ | 341 /* Handle finding a good partition */ |
| 332 if (good_partition >= 0) { | 342 if (good_partition >= 0) { |
| 333 | 343 |
| 334 if (BOOT_MODE_NORMAL == params->boot_mode) { | 344 if (is_normal) { |
| 335 /* See if we need to update the TPM, for normal boot mode only. */ | 345 /* See if we need to update the TPM, for normal boot mode only. */ |
| 336 if ((lowest_kernel_key_version > tpm_kernel_key_version) || | 346 if ((lowest_kernel_key_version > tpm_kernel_key_version) || |
| 337 (lowest_kernel_key_version == tpm_kernel_key_version && | 347 (lowest_kernel_key_version == tpm_kernel_key_version && |
| 338 lowest_kernel_version > tpm_kernel_version)) { | 348 lowest_kernel_version > tpm_kernel_version)) { |
| 339 if (0 != WriteStoredVersions(KERNEL_VERSIONS, | 349 if (0 != WriteStoredVersions(KERNEL_VERSIONS, |
| 340 lowest_kernel_key_version, | 350 lowest_kernel_key_version, |
| 341 lowest_kernel_version)) | 351 lowest_kernel_version)) |
| 342 return LOAD_KERNEL_RECOVERY; | 352 return LOAD_KERNEL_RECOVERY; |
| 343 } | 353 } |
| 344 } | 354 } |
| 345 | 355 |
| 346 if (BOOT_MODE_RECOVERY != params->boot_mode) { | 356 if (!(BOOT_FLAG_RECOVERY & params->boot_flags)) { |
| 347 /* We can lock the TPM now, since we've decided which kernel we | 357 /* We can lock the TPM now, since we've decided which kernel we |
| 348 * like. If we don't find a good kernel, we leave the TPM | 358 * like. If we don't find a good kernel, we leave the TPM |
| 349 * unlocked so we can try again on the next boot device. If no | 359 * unlocked so we can try again on the next boot device. If no |
| 350 * kernels are good, we'll reboot to recovery mode, so it's ok to | 360 * kernels are good, we'll reboot to recovery mode, so it's ok to |
| 351 * leave the TPM unlocked in that case too. | 361 * leave the TPM unlocked in that case too. |
| 352 * | 362 * |
| 353 * If we're already in recovery mode, we need to leave PP unlocked, | 363 * If we're already in recovery mode, we need to leave PP unlocked, |
| 354 * so don't lock the kernel versions. */ | 364 * so don't lock the kernel versions. */ |
| 355 if (0 != LockKernelVersionsByLockingPP()) | 365 if (0 != LockKernelVersionsByLockingPP()) |
| 356 return LOAD_KERNEL_RECOVERY; | 366 return LOAD_KERNEL_RECOVERY; |
| 357 } | 367 } |
| 358 | 368 |
| 359 /* Success! */ | 369 /* Success! */ |
| 360 return LOAD_KERNEL_SUCCESS; | 370 return LOAD_KERNEL_SUCCESS; |
| 361 } | 371 } |
| 362 | 372 |
| 363 /* Handle error cases */ | 373 /* Handle error cases */ |
| 364 if (found_partition) | 374 if (found_partition) |
| 365 return LOAD_KERNEL_INVALID; | 375 return LOAD_KERNEL_INVALID; |
| 366 else | 376 else |
| 367 return LOAD_KERNEL_NOT_FOUND; | 377 return LOAD_KERNEL_NOT_FOUND; |
| 368 } | 378 } |
| OLD | NEW |