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

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

Issue 6597018: Add LoadFirmware() support for NvStorage API (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/vboot_reference.git@master
Patch Set: Created 9 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « firmware/include/load_firmware_fw.h ('k') | firmware/stub/load_firmware_stub.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 * High-level firmware API for loading and verifying rewritable firmware. 5 * High-level firmware API for loading and verifying rewritable firmware.
6 * (Firmware portion) 6 * (Firmware portion)
7 */ 7 */
8 8
9 #include "load_firmware_fw.h" 9 #include "load_firmware_fw.h"
10 #include "rollback_index.h" 10 #include "rollback_index.h"
11 #include "utility.h" 11 #include "utility.h"
12 #include "vboot_common.h" 12 #include "vboot_common.h"
13 #include "vboot_nvstorage.h"
13 14
14 /* Static variables for UpdateFirmwareBodyHash(). It's less than 15 /* Static variables for UpdateFirmwareBodyHash(). It's less than
15 * optimal to have static variables in a library, but in UEFI the 16 * optimal to have static variables in a library, but in UEFI the
16 * caller is deep inside a different firmware stack and doesn't have a 17 * caller is deep inside a different firmware stack and doesn't have a
17 * good way to pass the params struct back to us. */ 18 * good way to pass the params struct back to us. */
18 typedef struct VbLoadFirmwareInternal { 19 typedef struct VbLoadFirmwareInternal {
19 DigestContext body_digest_context; 20 DigestContext body_digest_context;
20 uint64_t body_size_accum; 21 uint64_t body_size_accum;
21 } VbLoadFirmwareInternal; 22 } VbLoadFirmwareInternal;
22 23
23 24
24 void UpdateFirmwareBodyHash(LoadFirmwareParams* params, 25 void UpdateFirmwareBodyHash(LoadFirmwareParams* params,
25 uint8_t* data, uint64_t size) { 26 uint8_t* data, uint64_t size) {
26 VbLoadFirmwareInternal* lfi = 27 VbLoadFirmwareInternal* lfi =
27 (VbLoadFirmwareInternal*)params->load_firmware_internal; 28 (VbLoadFirmwareInternal*)params->load_firmware_internal;
28 29
29 DigestUpdate(&lfi->body_digest_context, data, size); 30 DigestUpdate(&lfi->body_digest_context, data, size);
30 lfi->body_size_accum += size; 31 lfi->body_size_accum += size;
31 } 32 }
32 33
33 34
35 int LoadFirmwareSetup(void) {
36 /* TODO: start initializing the TPM */
37 return LOAD_FIRMWARE_SUCCESS;
38 }
39
40
34 int LoadFirmware(LoadFirmwareParams* params) { 41 int LoadFirmware(LoadFirmwareParams* params) {
35 42
36 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob; 43 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob;
37 VbLoadFirmwareInternal* lfi; 44 VbLoadFirmwareInternal* lfi;
45 VbNvContext* vnc = params->nv_context;
38 46
47 uint32_t try_b_count;
39 uint32_t tpm_version = 0; 48 uint32_t tpm_version = 0;
40 uint64_t lowest_version = 0xFFFFFFFF; 49 uint64_t lowest_version = 0xFFFFFFFF;
41 uint32_t status; 50 uint32_t status;
42 int good_index = -1; 51 int good_index = -1;
43 int is_dev; 52 int is_dev;
44 int index; 53 int index;
54 int i;
55
56 int retval = LOAD_FIRMWARE_RECOVERY;
57 int recovery = VBNV_RECOVERY_RO_UNSPECIFIED;
45 58
46 /* Clear output params in case we fail */ 59 /* Clear output params in case we fail */
47 params->firmware_index = 0; 60 params->firmware_index = 0;
48 61
49 VBDEBUG(("LoadFirmware started...\n")); 62 VBDEBUG(("LoadFirmware started...\n"));
50 63
64 /* Setup NV storage */
65 VbNvSetup(vnc);
66
51 if (params->kernel_sign_key_size < sizeof(VbPublicKey)) { 67 if (params->kernel_sign_key_size < sizeof(VbPublicKey)) {
52 VBDEBUG(("Kernel sign key buffer too small\n")); 68 VBDEBUG(("Kernel sign key buffer too small\n"));
53 return LOAD_FIRMWARE_RECOVERY; 69 goto LoadFirmwareExit;
54 } 70 }
55 71
56 /* Must have a root key */ 72 /* Must have a root key */
57 if (!root_key) { 73 if (!root_key) {
58 VBDEBUG(("No root key\n")); 74 VBDEBUG(("No root key\n"));
59 return LOAD_FIRMWARE_RECOVERY; 75 goto LoadFirmwareExit;
60 } 76 }
61 77
62 /* Parse flags */ 78 /* Parse flags */
63 is_dev = (params->boot_flags & BOOT_FLAG_DEVELOPER ? 1 : 0); 79 is_dev = (params->boot_flags & BOOT_FLAG_DEVELOPER ? 1 : 0);
64 80
65 /* Initialize the TPM and read rollback indices. */ 81 /* Initialize the TPM and read rollback indices. */
66 VBPERFSTART("VB_TPMI"); 82 VBPERFSTART("VB_TPMI");
67 status = RollbackFirmwareSetup(is_dev, &tpm_version); 83 status = RollbackFirmwareSetup(is_dev, &tpm_version);
68 if (0 != status) { 84 if (0 != status) {
69 VBDEBUG(("Unable to setup TPM and read stored versions.\n")); 85 VBDEBUG(("Unable to setup TPM and read stored versions.\n"));
70 VBPERFEND("VB_TPMI"); 86 VBPERFEND("VB_TPMI");
71 return (status == TPM_E_MUST_REBOOT ? 87 if (status == TPM_E_MUST_REBOOT)
72 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY_TPM); 88 retval = LOAD_FIRMWARE_REBOOT;
89 else
90 recovery = VBNV_RECOVERY_RO_TPM_ERROR;
91 goto LoadFirmwareExit;
73 } 92 }
74 VBPERFEND("VB_TPMI"); 93 VBPERFEND("VB_TPMI");
75 94
95 /* Read try-b count and decrement if necessary */
96 VbNvGet(vnc, VBNV_TRY_B_COUNT, &try_b_count);
97 if (0 != try_b_count)
98 VbNvSet(vnc, VBNV_TRY_B_COUNT, try_b_count - 1);
99 VbNvSet(vnc, VBNV_TRIED_FIRMWARE_B, try_b_count ? 1 : 0);
100
76 /* Allocate our internal data */ 101 /* Allocate our internal data */
77 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal)); 102 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal));
78 if (!lfi) 103 if (!lfi)
79 return LOAD_FIRMWARE_RECOVERY; 104 return LOAD_FIRMWARE_RECOVERY;
80 105
81 params->load_firmware_internal = (uint8_t*)lfi; 106 params->load_firmware_internal = (uint8_t*)lfi;
82 107
83 /* Loop over indices */ 108 /* Loop over indices */
84 for (index = 0; index < 2; index++) { 109 for (i = 0; i < 2; i++) {
85 VbKeyBlockHeader* key_block; 110 VbKeyBlockHeader* key_block;
86 uint64_t vblock_size; 111 uint64_t vblock_size;
87 VbFirmwarePreambleHeader* preamble; 112 VbFirmwarePreambleHeader* preamble;
88 RSAPublicKey* data_key; 113 RSAPublicKey* data_key;
89 uint64_t key_version; 114 uint64_t key_version;
90 uint64_t combined_version; 115 uint64_t combined_version;
91 uint8_t* body_digest; 116 uint8_t* body_digest;
92 117
118 /* If try B count is non-zero try firmware B first */
119 index = (try_b_count ? i : 1 - i);
120
93 /* Verify the key block */ 121 /* Verify the key block */
94 VBPERFSTART("VB_VKB"); 122 VBPERFSTART("VB_VKB");
95 if (0 == index) { 123 if (0 == index) {
96 key_block = (VbKeyBlockHeader*)params->verification_block_0; 124 key_block = (VbKeyBlockHeader*)params->verification_block_0;
97 vblock_size = params->verification_size_0; 125 vblock_size = params->verification_size_0;
98 } else { 126 } else {
99 key_block = (VbKeyBlockHeader*)params->verification_block_1; 127 key_block = (VbKeyBlockHeader*)params->verification_block_1;
100 vblock_size = params->verification_size_1; 128 vblock_size = params->verification_size_1;
101 } 129 }
102 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key, 0))) { 130 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key, 0))) {
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 /* Handle finding good firmware */ 269 /* Handle finding good firmware */
242 if (good_index >= 0) { 270 if (good_index >= 0) {
243 271
244 /* Update TPM if necessary */ 272 /* Update TPM if necessary */
245 if (lowest_version > tpm_version) { 273 if (lowest_version > tpm_version) {
246 VBPERFSTART("VB_TPMU"); 274 VBPERFSTART("VB_TPMU");
247 status = RollbackFirmwareWrite((uint32_t)lowest_version); 275 status = RollbackFirmwareWrite((uint32_t)lowest_version);
248 VBPERFEND("VB_TPMU"); 276 VBPERFEND("VB_TPMU");
249 if (0 != status) { 277 if (0 != status) {
250 VBDEBUG(("Unable to write stored versions.\n")); 278 VBDEBUG(("Unable to write stored versions.\n"));
251 return (status == TPM_E_MUST_REBOOT ? 279 if (status == TPM_E_MUST_REBOOT)
252 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY_TPM); 280 retval = LOAD_FIRMWARE_REBOOT;
281 else
282 recovery = VBNV_RECOVERY_RO_TPM_ERROR;
283 goto LoadFirmwareExit;
253 } 284 }
254 } 285 }
255 286
256 /* Lock firmware versions in TPM */ 287 /* Lock firmware versions in TPM */
257 VBPERFSTART("VB_TPML"); 288 VBPERFSTART("VB_TPML");
258 status = RollbackFirmwareLock(); 289 status = RollbackFirmwareLock();
259 VBPERFEND("VB_TPML"); 290 VBPERFEND("VB_TPML");
260 if (0 != status) { 291 if (0 != status) {
261 VBDEBUG(("Unable to lock firmware versions.\n")); 292 VBDEBUG(("Unable to lock firmware versions.\n"));
262 return (status == TPM_E_MUST_REBOOT ? 293 if (status == TPM_E_MUST_REBOOT)
263 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY_TPM); 294 retval = LOAD_FIRMWARE_REBOOT;
295 else
296 recovery = VBNV_RECOVERY_RO_TPM_ERROR;
297 goto LoadFirmwareExit;
264 } 298 }
265 299
266 /* Success */ 300 /* Success */
267 VBDEBUG(("Will boot firmware index %d\n", (int)params->firmware_index)); 301 VBDEBUG(("Will boot firmware index %d\n", (int)params->firmware_index));
268 return LOAD_FIRMWARE_SUCCESS; 302 retval = LOAD_FIRMWARE_SUCCESS;
303 } else {
304 /* No good firmware, so go to recovery mode. */
305 VBDEBUG(("Alas, no good firmware.\n"));
306 recovery = VBNV_RECOVERY_RO_INVALID_RW;
269 } 307 }
270 308
271 /* If we're still here, no good firmware, so go to recovery mode. */ 309 LoadFirmwareExit:
272 VBDEBUG(("Alas, no good firmware.\n")); 310 /* Store recovery request, if any, then tear down non-volatile storage */
273 return LOAD_FIRMWARE_RECOVERY; 311 VbNvSet(vnc, VBNV_RECOVERY_REQUEST, LOAD_FIRMWARE_RECOVERY == retval ?
312 recovery : VBNV_RECOVERY_NOT_REQUESTED);
313 VbNvTeardown(vnc);
314
315 return retval;
274 } 316 }
275 317
276 318
277 int S3Resume(void) { 319 int S3Resume(void) {
278 /* Resume the TPM */ 320 /* Resume the TPM */
279 uint32_t status = RollbackS3Resume(); 321 uint32_t status = RollbackS3Resume();
280 322
323 /* If we can't resume, just do a full reboot. No need to go to recovery
324 * mode here, since if the TPM is really broken we'll catch it on the
325 * next boot. */
281 if (status == TPM_SUCCESS) 326 if (status == TPM_SUCCESS)
282 return LOAD_FIRMWARE_SUCCESS; 327 return LOAD_FIRMWARE_SUCCESS;
283 else if (status == TPM_E_MUST_REBOOT) 328 else
284 return LOAD_FIRMWARE_REBOOT; 329 return LOAD_FIRMWARE_REBOOT;
285 else
286 return LOAD_FIRMWARE_RECOVERY_TPM;
287 } 330 }
OLDNEW
« no previous file with comments | « firmware/include/load_firmware_fw.h ('k') | firmware/stub/load_firmware_stub.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698