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

Side by Side Diff: vboot_firmware/lib/load_kernel_fw.c

Issue 2745007: Major refactoring of structures, with unit tests. (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Implemented LoadFirmware2() 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
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
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698