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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 !params->kernel_buffer || | 134 !params->kernel_buffer || |
135 !params->kernel_buffer_size) { | 135 !params->kernel_buffer_size) { |
136 VBDEBUG(("LoadKernel() called with invalid params\n")); | 136 VBDEBUG(("LoadKernel() called with invalid params\n")); |
137 return LOAD_KERNEL_INVALID; | 137 return LOAD_KERNEL_INVALID; |
138 } | 138 } |
139 | 139 |
140 /* Initialization */ | 140 /* Initialization */ |
141 kernel_subkey = (VbPublicKey*)params->header_sign_key_blob; | 141 kernel_subkey = (VbPublicKey*)params->header_sign_key_blob; |
142 blba = params->bytes_per_lba; | 142 blba = params->bytes_per_lba; |
143 kbuf_sectors = KBUF_SIZE / blba; | 143 kbuf_sectors = KBUF_SIZE / blba; |
| 144 if (0 == kbuf_sectors) { |
| 145 VBDEBUG(("LoadKernel() called with sector size > KBUF_SIZE\n")); |
| 146 return LOAD_KERNEL_INVALID; |
| 147 } |
| 148 |
144 is_dev = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0); | 149 is_dev = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0); |
145 is_rec = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0); | 150 is_rec = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0); |
146 is_normal = (!is_dev && !is_rec); | 151 is_normal = (!is_dev && !is_rec); |
147 | 152 |
148 /* Clear output params in case we fail */ | 153 /* Clear output params in case we fail */ |
149 params->partition_number = 0; | 154 params->partition_number = 0; |
150 params->bootloader_address = 0; | 155 params->bootloader_address = 0; |
151 params->bootloader_size = 0; | 156 params->bootloader_size = 0; |
152 | 157 |
153 /* Let the TPM know if we're in recovery mode */ | 158 /* Let the TPM know if we're in recovery mode */ |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 break; | 196 break; |
192 | 197 |
193 /* Loop over candidate kernel partitions */ | 198 /* Loop over candidate kernel partitions */ |
194 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) { | 199 while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) { |
195 VbKeyBlockHeader* key_block; | 200 VbKeyBlockHeader* key_block; |
196 VbKernelPreambleHeader* preamble; | 201 VbKernelPreambleHeader* preamble; |
197 RSAPublicKey* data_key; | 202 RSAPublicKey* data_key; |
198 uint64_t key_version; | 203 uint64_t key_version; |
199 uint64_t combined_version; | 204 uint64_t combined_version; |
200 uint64_t body_offset; | 205 uint64_t body_offset; |
| 206 uint64_t body_offset_sectors; |
| 207 uint64_t body_sectors; |
201 | 208 |
202 VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n", | 209 VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n", |
203 part_start, part_size)); | 210 part_start, part_size)); |
204 | 211 |
205 /* Found at least one kernel partition. */ | 212 /* Found at least one kernel partition. */ |
206 found_partitions++; | 213 found_partitions++; |
207 | 214 |
208 /* Read the first part of the kernel partition */ | 215 /* Read the first part of the kernel partition */ |
209 if (part_size < kbuf_sectors) | 216 if (part_size < kbuf_sectors) |
210 continue; | 217 continue; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 continue; | 299 continue; |
293 } | 300 } |
294 | 301 |
295 /* Verify kernel body starts at a multiple of the sector size. */ | 302 /* Verify kernel body starts at a multiple of the sector size. */ |
296 body_offset = key_block->key_block_size + preamble->preamble_size; | 303 body_offset = key_block->key_block_size + preamble->preamble_size; |
297 if (0 != body_offset % blba) { | 304 if (0 != body_offset % blba) { |
298 VBDEBUG(("Kernel body not at multiple of sector size.\n")); | 305 VBDEBUG(("Kernel body not at multiple of sector size.\n")); |
299 RSAPublicKeyFree(data_key); | 306 RSAPublicKeyFree(data_key); |
300 continue; | 307 continue; |
301 } | 308 } |
| 309 body_offset_sectors = body_offset / blba; |
| 310 |
| 311 /* Verify kernel body fits in the buffer */ |
| 312 body_sectors = (preamble->body_signature.data_size + blba - 1) / blba; |
| 313 if (body_sectors * blba > params->kernel_buffer_size) { |
| 314 VBDEBUG(("Kernel body doesn't fit in memory.\n")); |
| 315 RSAPublicKeyFree(data_key); |
| 316 continue; |
| 317 } |
302 | 318 |
303 /* Verify kernel body fits in the partition */ | 319 /* Verify kernel body fits in the partition */ |
304 if (body_offset + preamble->body_signature.data_size > | 320 if (body_offset_sectors + body_sectors > part_size) { |
305 part_size * blba) { | |
306 VBDEBUG(("Kernel body doesn't fit in partition.\n")); | 321 VBDEBUG(("Kernel body doesn't fit in partition.\n")); |
307 RSAPublicKeyFree(data_key); | 322 RSAPublicKeyFree(data_key); |
308 continue; | 323 continue; |
309 } | 324 } |
310 | 325 |
311 /* Read the kernel data */ | 326 /* Read the kernel data */ |
312 if (0 != BootDeviceReadLBA( | 327 if (0 != BootDeviceReadLBA(part_start + body_offset_sectors, |
313 part_start + (body_offset / blba), | 328 body_sectors, |
314 (preamble->body_signature.data_size + blba - 1) / blba, | 329 params->kernel_buffer)) { |
315 params->kernel_buffer)) { | |
316 VBDEBUG(("Unable to read kernel data.\n")); | 330 VBDEBUG(("Unable to read kernel data.\n")); |
317 RSAPublicKeyFree(data_key); | 331 RSAPublicKeyFree(data_key); |
318 continue; | 332 continue; |
319 } | 333 } |
320 | 334 |
321 /* Verify kernel data */ | 335 /* Verify kernel data */ |
322 if (0 != VerifyData((const uint8_t*)params->kernel_buffer, | 336 if (0 != VerifyData((const uint8_t*)params->kernel_buffer, |
323 params->kernel_buffer_size, | 337 params->kernel_buffer_size, |
324 &preamble->body_signature, data_key)) { | 338 &preamble->body_signature, data_key)) { |
325 VBDEBUG(("Kernel data verification failed.\n")); | 339 VBDEBUG(("Kernel data verification failed.\n")); |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 /* Success! */ | 418 /* Success! */ |
405 return LOAD_KERNEL_SUCCESS; | 419 return LOAD_KERNEL_SUCCESS; |
406 } | 420 } |
407 | 421 |
408 // Handle error cases | 422 // Handle error cases |
409 if (found_partitions) | 423 if (found_partitions) |
410 return LOAD_KERNEL_INVALID; | 424 return LOAD_KERNEL_INVALID; |
411 else | 425 else |
412 return LOAD_KERNEL_NOT_FOUND; | 426 return LOAD_KERNEL_NOT_FOUND; |
413 } | 427 } |
OLD | NEW |