OLD | NEW |
1 /* Copyright (c) 2010-2011 The Chromium OS Authors. All rights reserved. | 1 /* Copyright (c) 2011 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 |
11 #include "boot_device.h" | 11 #include "boot_device.h" |
12 #include "cgptlib.h" | 12 #include "cgptlib.h" |
13 #include "cgptlib_internal.h" | 13 #include "cgptlib_internal.h" |
| 14 #include "gbb_header.h" |
14 #include "load_kernel_fw.h" | 15 #include "load_kernel_fw.h" |
15 #include "rollback_index.h" | 16 #include "rollback_index.h" |
16 #include "utility.h" | 17 #include "utility.h" |
17 #include "vboot_common.h" | 18 #include "vboot_common.h" |
18 | 19 |
19 #define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */ | 20 #define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */ |
20 | 21 |
21 typedef enum BootMode { | 22 typedef enum BootMode { |
22 kBootNormal, /* Normal firmware */ | 23 kBootNormal, /* Normal firmware */ |
23 kBootDev, /* Dev firmware AND dev switch is on */ | 24 kBootDev, /* Dev firmware AND dev switch is on */ |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 } | 112 } |
112 | 113 |
113 /* Success */ | 114 /* Success */ |
114 return 0; | 115 return 0; |
115 } | 116 } |
116 | 117 |
117 /* disable MSVC warning on const logical expression (as in } while(0);) */ | 118 /* disable MSVC warning on const logical expression (as in } while(0);) */ |
118 __pragma(warning(disable: 4127)) | 119 __pragma(warning(disable: 4127)) |
119 | 120 |
120 int LoadKernel(LoadKernelParams* params) { | 121 int LoadKernel(LoadKernelParams* params) { |
| 122 VbSharedDataHeader* shared = (VbSharedDataHeader*)params->shared_data_blob; |
121 VbNvContext* vnc = params->nv_context; | 123 VbNvContext* vnc = params->nv_context; |
| 124 GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)params->gbb_data; |
122 VbPublicKey* kernel_subkey; | 125 VbPublicKey* kernel_subkey; |
123 GptData gpt; | 126 GptData gpt; |
124 uint64_t part_start, part_size; | 127 uint64_t part_start, part_size; |
125 uint64_t blba; | 128 uint64_t blba; |
126 uint64_t kbuf_sectors; | 129 uint64_t kbuf_sectors; |
127 uint8_t* kbuf = NULL; | 130 uint8_t* kbuf = NULL; |
128 int found_partitions = 0; | 131 int found_partitions = 0; |
129 int good_partition = -1; | 132 int good_partition = -1; |
130 int good_partition_key_block_valid = 0; | 133 int good_partition_key_block_valid = 0; |
131 uint32_t tpm_version = 0; | 134 uint32_t tpm_version = 0; |
(...skipping 15 matching lines...) Expand all Loading... |
147 if (!params || | 150 if (!params || |
148 !params->bytes_per_lba || | 151 !params->bytes_per_lba || |
149 !params->ending_lba || | 152 !params->ending_lba || |
150 !params->kernel_buffer || | 153 !params->kernel_buffer || |
151 !params->kernel_buffer_size) { | 154 !params->kernel_buffer_size) { |
152 VBDEBUG(("LoadKernel() called with invalid params\n")); | 155 VBDEBUG(("LoadKernel() called with invalid params\n")); |
153 goto LoadKernelExit; | 156 goto LoadKernelExit; |
154 } | 157 } |
155 | 158 |
156 /* Initialization */ | 159 /* Initialization */ |
157 kernel_subkey = (VbPublicKey*)params->header_sign_key_blob; | |
158 blba = params->bytes_per_lba; | 160 blba = params->bytes_per_lba; |
159 kbuf_sectors = KBUF_SIZE / blba; | 161 kbuf_sectors = KBUF_SIZE / blba; |
160 if (0 == kbuf_sectors) { | 162 if (0 == kbuf_sectors) { |
161 VBDEBUG(("LoadKernel() called with sector size > KBUF_SIZE\n")); | 163 VBDEBUG(("LoadKernel() called with sector size > KBUF_SIZE\n")); |
162 goto LoadKernelExit; | 164 goto LoadKernelExit; |
163 } | 165 } |
164 | 166 |
165 rec_switch = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0); | 167 rec_switch = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0); |
166 dev_switch = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0); | 168 dev_switch = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0); |
167 | 169 |
(...skipping 12 matching lines...) Expand all Loading... |
180 /* Normal firmware */ | 182 /* Normal firmware */ |
181 boot_mode = kBootNormal; | 183 boot_mode = kBootNormal; |
182 dev_switch = 0; /* Always do a fully verified boot */ | 184 dev_switch = 0; /* Always do a fully verified boot */ |
183 } | 185 } |
184 | 186 |
185 /* Clear output params in case we fail */ | 187 /* Clear output params in case we fail */ |
186 params->partition_number = 0; | 188 params->partition_number = 0; |
187 params->bootloader_address = 0; | 189 params->bootloader_address = 0; |
188 params->bootloader_size = 0; | 190 params->bootloader_size = 0; |
189 | 191 |
190 /* Let the TPM know if we're in recovery mode */ | |
191 if (kBootRecovery == boot_mode) { | 192 if (kBootRecovery == boot_mode) { |
| 193 /* Initialize the shared data structure, since LoadFirmware() didn't do it |
| 194 * for us. */ |
| 195 if (0 != VbSharedDataInit(shared, params->shared_data_size)) { |
| 196 /* Error initializing the shared data, but we can keep going. We just |
| 197 * can't use the shared data. */ |
| 198 VBDEBUG(("Shared data init error\n")); |
| 199 params->shared_data_size = 0; |
| 200 shared = NULL; |
| 201 } |
| 202 |
| 203 /* Use the recovery key to verify the kernel */ |
| 204 kernel_subkey = (VbPublicKey*)((uint8_t*)gbb + gbb->recovery_key_offset); |
| 205 |
| 206 /* Let the TPM know if we're in recovery mode */ |
192 if (0 != RollbackKernelRecovery(dev_switch)) { | 207 if (0 != RollbackKernelRecovery(dev_switch)) { |
193 VBDEBUG(("Error setting up TPM for recovery kernel\n")); | 208 VBDEBUG(("Error setting up TPM for recovery kernel\n")); |
194 /* Ignore return code, since we need to boot recovery mode to | 209 /* Ignore return code, since we need to boot recovery mode to |
195 * fix the TPM. */ | 210 * fix the TPM. */ |
196 } | 211 } |
197 } else { | 212 } else { |
| 213 /* Use the kernel subkey passed from LoadFirmware(). */ |
| 214 kernel_subkey = &shared->kernel_subkey; |
| 215 |
198 /* Read current kernel key index from TPM. Assumes TPM is already | 216 /* Read current kernel key index from TPM. Assumes TPM is already |
199 * initialized. */ | 217 * initialized. */ |
200 status = RollbackKernelRead(&tpm_version); | 218 status = RollbackKernelRead(&tpm_version); |
201 if (0 != status) { | 219 if (0 != status) { |
202 VBDEBUG(("Unable to get kernel versions from TPM\n")); | 220 VBDEBUG(("Unable to get kernel versions from TPM\n")); |
203 if (status == TPM_E_MUST_REBOOT) | 221 if (status == TPM_E_MUST_REBOOT) |
204 retval = LOAD_KERNEL_REBOOT; | 222 retval = LOAD_KERNEL_REBOOT; |
205 else | 223 else |
206 recovery = VBNV_RECOVERY_RW_TPM_ERROR; | 224 recovery = VBNV_RECOVERY_RW_TPM_ERROR; |
207 goto LoadKernelExit; | 225 goto LoadKernelExit; |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 LoadKernelExit: | 516 LoadKernelExit: |
499 | 517 |
500 /* Save whether the good partition's key block was fully verified */ | 518 /* Save whether the good partition's key block was fully verified */ |
501 VbNvSet(vnc, VBNV_FW_VERIFIED_KERNEL_KEY, good_partition_key_block_valid); | 519 VbNvSet(vnc, VBNV_FW_VERIFIED_KERNEL_KEY, good_partition_key_block_valid); |
502 | 520 |
503 /* Store recovery request, if any, then tear down non-volatile storage */ | 521 /* Store recovery request, if any, then tear down non-volatile storage */ |
504 VbNvSet(vnc, VBNV_RECOVERY_REQUEST, LOAD_KERNEL_RECOVERY == retval ? | 522 VbNvSet(vnc, VBNV_RECOVERY_REQUEST, LOAD_KERNEL_RECOVERY == retval ? |
505 recovery : VBNV_RECOVERY_NOT_REQUESTED); | 523 recovery : VBNV_RECOVERY_NOT_REQUESTED); |
506 VbNvTeardown(vnc); | 524 VbNvTeardown(vnc); |
507 | 525 |
| 526 /* Store how much shared data we used, if any */ |
| 527 if (shared) |
| 528 params->shared_data_size = shared->data_used; |
| 529 |
508 return retval; | 530 return retval; |
509 } | 531 } |
OLD | NEW |