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 |