Reformat to kernel style

No code changes, just reformatting.

BUG=none
BRANCH=none
TEST=make runtests

Change-Id: Id690c8334147970784db5ac54933ad1f5a58dcc1
Reviewed-on: https://gerrit.chromium.org/gerrit/42263
Tested-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Commit-Queue: Randall Spangler <rspangler@chromium.org>
This commit is contained in:
Randall Spangler
2013-01-29 15:01:12 -08:00
committed by ChromeBot
parent 49cb0d3471
commit 7993f257af
13 changed files with 1863 additions and 1625 deletions

6
PRESUBMIT.cfg Normal file
View File

@@ -0,0 +1,6 @@
[Hook Overrides]
# We are using Linux style indentation with tabs
# The indentation is checked by checkpatch not the python script
tab_check: false

View File

@@ -1,14 +1,16 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "crc8.h" #include "crc8.h"
/* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A /**
* table-based algorithm would be faster, but for only a few bytes it isn't * Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. A table-based
* worth the code size. */ * algorithm would be faster, but for only a few bytes it isn't worth the code
uint8_t Crc8(const void* vptr, int len) { * size. */
uint8_t Crc8(const void *vptr, int len)
{
const uint8_t *data = vptr; const uint8_t *data = vptr;
unsigned crc = 0; unsigned crc = 0;
int i, j; int i, j;
@@ -24,5 +26,3 @@ uint8_t Crc8(const void* vptr, int len) {
return (uint8_t)(crc >> 8); return (uint8_t)(crc >> 8);
} }

View File

@@ -18,9 +18,11 @@
#endif #endif
#ifdef FOR_TEST #ifdef FOR_TEST
/* Compiling for unit test, so we need the real implementations of /*
* Compiling for unit test, so we need the real implementations of
* rollback functions. The unit test mocks the underlying tlcl * rollback functions. The unit test mocks the underlying tlcl
* functions, so this is ok to run on the host. */ * functions, so this is ok to run on the host.
*/
#undef CHROMEOS_ENVIRONMENT #undef CHROMEOS_ENVIRONMENT
#undef DISABLE_ROLLBACK_TPM #undef DISABLE_ROLLBACK_TPM
#endif #endif
@@ -33,7 +35,8 @@ __pragma(warning (disable: 4127))
#define RETURN_ON_FAILURE(tpm_command) do { \ #define RETURN_ON_FAILURE(tpm_command) do { \
uint32_t result; \ uint32_t result; \
if ((result = (tpm_command)) != TPM_SUCCESS) { \ if ((result = (tpm_command)) != TPM_SUCCESS) { \
VBDEBUG(("Rollback: %08x returned by " #tpm_command "\n", (int)result)); \ VBDEBUG(("Rollback: %08x returned by " #tpm_command \
"\n", (int)result)); \
return result; \ return result; \
} \ } \
} while (0) } while (0)

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -6,16 +6,17 @@
*/ */
#include "stateful_util.h" #include "stateful_util.h"
#include "utility.h" #include "utility.h"
void StatefulInit(MemcpyState* state, void* buf, uint64_t len) { void StatefulInit(MemcpyState *state, void *buf, uint64_t len)
{
state->remaining_buf = buf; state->remaining_buf = buf;
state->remaining_len = len; state->remaining_len = len;
state->overrun = 0; state->overrun = 0;
} }
void* StatefulSkip(MemcpyState* state, uint64_t len) { void *StatefulSkip(MemcpyState *state, uint64_t len)
{
if (state->overrun) if (state->overrun)
return NULL; return NULL;
if (len > state->remaining_len) { if (len > state->remaining_len) {
@@ -24,11 +25,11 @@ void* StatefulSkip(MemcpyState* state, uint64_t len) {
} }
state->remaining_buf += len; state->remaining_buf += len;
state->remaining_len -= len; state->remaining_len -= len;
return state; // have to return something non-NULL return state; /* Must return something non-NULL. */
} }
void* StatefulMemcpy(MemcpyState* state, void* dst, void *StatefulMemcpy(MemcpyState *state, void *dst, uint64_t len)
uint64_t len) { {
if (state->overrun) if (state->overrun)
return NULL; return NULL;
if (len > state->remaining_len) { if (len > state->remaining_len) {
@@ -41,8 +42,8 @@ void* StatefulMemcpy(MemcpyState* state, void* dst,
return dst; return dst;
} }
const void* StatefulMemcpy_r(MemcpyState* state, const void* src, const void *StatefulMemcpy_r(MemcpyState *state, const void *src, uint64_t len)
uint64_t len) { {
if (state->overrun) if (state->overrun)
return NULL; return NULL;
if (len > state->remaining_len) { if (len > state->remaining_len) {
@@ -56,7 +57,8 @@ const void* StatefulMemcpy_r(MemcpyState* state, const void* src,
} }
const void *StatefulMemset_r(MemcpyState *state, const uint8_t val, const void *StatefulMemset_r(MemcpyState *state, const uint8_t val,
uint64_t len) { uint64_t len)
{
if (state->overrun) if (state->overrun)
return NULL; return NULL;
if (len > state->remaining_len) { if (len > state->remaining_len) {
@@ -66,5 +68,5 @@ const void* StatefulMemset_r(MemcpyState* state, const uint8_t val,
Memset(state->remaining_buf, val, len); Memset(state->remaining_buf, val, len);
state->remaining_buf += len; state->remaining_buf += len;
state->remaining_len -= len; state->remaining_len -= len;
return state; // have to return something non-NULL return state; /* Must return something non-NULL. */
} }

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -14,7 +14,8 @@
/* TPM PCR to use for storing boot mode measurements. */ /* TPM PCR to use for storing boot mode measurements. */
#define BOOT_MODE_PCR 0 #define BOOT_MODE_PCR 0
/* Input digests for PCR extend. /*
* Input digests for PCR extend.
* These are calculated as: * These are calculated as:
* SHA1("|Developer_Mode||Recovery_Mode||Keyblock_Mode|"). * SHA1("|Developer_Mode||Recovery_Mode||Keyblock_Mode|").
* Developer_Mode can be 0 or 1. * Developer_Mode can be 0 or 1.
@@ -82,31 +83,45 @@ const char* kBootStateSHA1Digests[] = {
#define MAX_BOOT_STATE_INDEX (sizeof(kBootStateSHA1Digests)/sizeof(char *)) #define MAX_BOOT_STATE_INDEX (sizeof(kBootStateSHA1Digests)/sizeof(char *))
/* Used for PCR extend when the passed-in boot state is invalid or /*
* if there is an internal error. */ * Used for PCR extend when the passed-in boot state is invalid or if there is
* an internal error.
*/
const uint8_t kBootInvalidSHA1Digest[] = { const uint8_t kBootInvalidSHA1Digest[] = {
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xff\xff\xff\xff" "\xff\xff\xff\xff"
}; };
/* Given the boot state, return the correct SHA1 digest index for TPMExtend /**
* in kBootStateSHA1Digests[]. */ * Given the boot state, return the correct SHA1 digest index for TPMExtend
int GetBootStateIndex(int dev_mode, int rec_mode, uint64_t keyblock_flags) { * in kBootStateSHA1Digests[].
*/
int GetBootStateIndex(int dev_mode, int rec_mode, uint64_t keyblock_flags)
{
int index = 0; int index = 0;
/* Convert keyblock flags into keyblock mode which we use to index into /*
* kBootStateSHA1Digest[]. */ * Convert keyblock flags into keyblock mode which we use to index into
* kBootStateSHA1Digest[].
*/
switch(keyblock_flags) { switch(keyblock_flags) {
case 6: /* KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1 */ case 6:
/* Developer firmware. */ /*
* KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1
*
* Developer firmware. */
index = 2; index = 2;
break; break;
case 7: /* KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_0 case 7:
* | KEY_BLOCK_FLAGS_DEVELOPER_1 */ /*
* KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_0
* | KEY_BLOCK_FLAGS_DEVELOPER_1
*/
index = 1; index = 1;
break; break;
default: default:
index = 0; /* Any other keyblock flags. */ /* Any other keyblock flags. */
index = 0;
}; };
if (rec_mode) if (rec_mode)
@@ -117,19 +132,25 @@ int GetBootStateIndex(int dev_mode, int rec_mode, uint64_t keyblock_flags) {
} }
uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode, uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode,
uint64_t fw_keyblock_flags) { uint64_t fw_keyblock_flags)
{
uint32_t result; uint32_t result;
const uint8_t *in_digest = NULL; const uint8_t *in_digest = NULL;
uint8_t out_digest[20]; /* For PCR extend output. */ uint8_t out_digest[20]; /* For PCR extend output. */
int digest_index = GetBootStateIndex(developer_mode, recovery_mode, int digest_index = GetBootStateIndex(developer_mode, recovery_mode,
fw_keyblock_flags); fw_keyblock_flags);
if (digest_index >= 0 && digest_index < MAX_BOOT_STATE_INDEX) if (digest_index >= 0 && digest_index < MAX_BOOT_STATE_INDEX) {
in_digest = (const uint8_t*)kBootStateSHA1Digests[digest_index]; in_digest = (const uint8_t*)
else kBootStateSHA1Digests[digest_index];
in_digest = kBootInvalidSHA1Digest; /* Internal out of bounds error. */ } else {
/* Internal out of bounds error. */
in_digest = kBootInvalidSHA1Digest;
}
result = TlclExtend(BOOT_MODE_PCR, in_digest, out_digest); result = TlclExtend(BOOT_MODE_PCR, in_digest, out_digest);
VBDEBUG(("TPM: SetTPMBootModeState boot mode PCR out_digest %02x %02x %02x " VBDEBUG(("TPM: SetTPMBootModeState boot mode PCR out_digest "
"%02x\n", out_digest, out_digest+1, out_digest+2, out_digest+3)); "%02x %02x %02x %02x\n",
out_digest, out_digest+1, out_digest+2, out_digest+3));
return result; return result;
} }

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -16,8 +16,10 @@ int SafeMemcmp(const void* s1, const void* s2, size_t n) {
if (0 == n) if (0 == n)
return 0; return 0;
/* Code snippet without data-dependent branch due to /*
* Nate Lawson (nate@root.org) of Root Labs. */ * Code snippet without data-dependent branch due to Nate Lawson
* (nate@root.org) of Root Labs.
*/
while (n--) while (n--)
result |= *us1++ ^ *us2++; result |= *us1++ ^ *us2++;

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -10,7 +10,8 @@
uint32_t Uint64ToString(char *buf, uint32_t bufsize, uint64_t value, uint32_t Uint64ToString(char *buf, uint32_t bufsize, uint64_t value,
uint32_t radix, uint32_t zero_pad_width) { uint32_t radix, uint32_t zero_pad_width)
{
char ibuf[UINT64_TO_STRING_MAX]; char ibuf[UINT64_TO_STRING_MAX];
char *s; char *s;
uint32_t usedsize = 1; uint32_t usedsize = 1;
@@ -51,8 +52,8 @@ uint32_t Uint64ToString(char *buf, uint32_t bufsize, uint64_t value,
return usedsize - 1; return usedsize - 1;
} }
uint32_t Strncat(char *dest, const char *src, uint32_t destlen)
uint32_t Strncat(char *dest, const char *src, uint32_t destlen) { {
uint32_t used = 0; uint32_t used = 0;
if (!dest || !src) if (!dest || !src)
@@ -61,6 +62,7 @@ uint32_t Strncat(char *dest, const char *src, uint32_t destlen) {
/* Skip past existing string in destination.*/ /* Skip past existing string in destination.*/
while (dest[used] && used < destlen - 1) while (dest[used] && used < destlen - 1)
used++; used++;
/* Now copy source */ /* Now copy source */
while (*src && used < destlen - 1) while (*src && used < destlen - 1)
dest[used++] = *src++; dest[used++] = *src++;

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -15,10 +15,12 @@
#include "vboot_nvstorage.h" #include "vboot_nvstorage.h"
VbError_t VbSelectFirmware(VbCommonParams *cparams, VbError_t VbSelectFirmware(VbCommonParams *cparams,
VbSelectFirmwareParams* fparams) { VbSelectFirmwareParams *fparams)
VbSharedDataHeader* shared = (VbSharedDataHeader*)cparams->shared_data_blob; {
VbSharedDataHeader *shared =
(VbSharedDataHeader *)cparams->shared_data_blob;
VbNvContext vnc; VbNvContext vnc;
VbError_t retval = VBERROR_UNKNOWN; /* Assume error until proven successful */ VbError_t retval = VBERROR_UNKNOWN; /* Default to error */
int is_rec = (shared->recovery_reason ? 1 : 0); int is_rec = (shared->recovery_reason ? 1 : 0);
int is_dev = (shared->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0); int is_dev = (shared->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0);
uint32_t tpm_status = 0; uint32_t tpm_status = 0;
@@ -31,13 +33,14 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
VbNvSetup(&vnc); VbNvSetup(&vnc);
if (is_rec) { if (is_rec) {
/* Recovery is requested; go straight to recovery without checking the /*
* RW firmware. */ * Recovery is requested; go straight to recovery without
* checking the RW firmware.
*/
VBDEBUG(("VbSelectFirmware() detected recovery request\n")); VBDEBUG(("VbSelectFirmware() detected recovery request\n"));
/* Go directly to recovery mode */ /* Go directly to recovery mode */
fparams->selected_firmware = VB_SELECT_FIRMWARE_RECOVERY; fparams->selected_firmware = VB_SELECT_FIRMWARE_RECOVERY;
} else { } else {
/* Chain to LoadFirmware() */ /* Chain to LoadFirmware() */
retval = LoadFirmware(cparams, fparams, &vnc); retval = LoadFirmware(cparams, fparams, &vnc);
@@ -49,20 +52,24 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
/* Translate the selected firmware path */ /* Translate the selected firmware path */
if (shared->flags & VBSD_LF_USE_RO_NORMAL) { if (shared->flags & VBSD_LF_USE_RO_NORMAL) {
/* Request the read-only normal/dev code path */ /* Request the read-only normal/dev code path */
fparams->selected_firmware = VB_SELECT_FIRMWARE_READONLY; fparams->selected_firmware =
VB_SELECT_FIRMWARE_READONLY;
} else if (0 == shared->firmware_index) } else if (0 == shared->firmware_index)
fparams->selected_firmware = VB_SELECT_FIRMWARE_A; fparams->selected_firmware = VB_SELECT_FIRMWARE_A;
else else {
fparams->selected_firmware = VB_SELECT_FIRMWARE_B; fparams->selected_firmware = VB_SELECT_FIRMWARE_B;
}
/* Update TPM if necessary */ /* Update TPM if necessary */
if (shared->fw_version_tpm_start < shared->fw_version_tpm) { if (shared->fw_version_tpm_start < shared->fw_version_tpm) {
VBPERFSTART("VB_TPMU"); VBPERFSTART("VB_TPMU");
tpm_status = RollbackFirmwareWrite(shared->fw_version_tpm); tpm_status =
RollbackFirmwareWrite(shared->fw_version_tpm);
VBPERFEND("VB_TPMU"); VBPERFEND("VB_TPMU");
if (0 != tpm_status) { if (0 != tpm_status) {
VBDEBUG(("Unable to write firmware version to TPM.\n")); VBDEBUG(("Can't write FW version to TPM.\n"));
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_W_ERROR); VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
VBNV_RECOVERY_RO_TPM_W_ERROR);
retval = VBERROR_TPM_WRITE_FIRMWARE; retval = VBERROR_TPM_WRITE_FIRMWARE;
goto VbSelectFirmware_exit; goto VbSelectFirmware_exit;
} }
@@ -74,19 +81,24 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
VBPERFEND("VB_TPML"); VBPERFEND("VB_TPML");
if (0 != tpm_status) { if (0 != tpm_status) {
VBDEBUG(("Unable to lock firmware version in TPM.\n")); VBDEBUG(("Unable to lock firmware version in TPM.\n"));
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_L_ERROR); VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
VBNV_RECOVERY_RO_TPM_L_ERROR);
retval = VBERROR_TPM_LOCK_FIRMWARE; retval = VBERROR_TPM_LOCK_FIRMWARE;
goto VbSelectFirmware_exit; goto VbSelectFirmware_exit;
} }
} }
/* At this point, we have a good idea of how we are going to /*
* boot. Update the TPM with this state information. */ * At this point, we have a good idea of how we are going to
tpm_status = SetTPMBootModeState(is_dev, is_rec, shared->fw_keyblock_flags); * boot. Update the TPM with this state information.
*/
tpm_status = SetTPMBootModeState(is_dev, is_rec,
shared->fw_keyblock_flags);
if (0 != tpm_status) { if (0 != tpm_status) {
VBDEBUG(("Unable to update the TPM with boot mode information.\n")); VBDEBUG(("Can't update the TPM with boot mode information.\n"));
if (!is_rec) { if (!is_rec) {
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_U_ERROR); VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
VBNV_RECOVERY_RO_TPM_U_ERROR);
retval = VBERROR_TPM_SET_BOOT_MODE_STATE; retval = VBERROR_TPM_SET_BOOT_MODE_STATE;
goto VbSelectFirmware_exit; goto VbSelectFirmware_exit;
} }

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -13,10 +13,12 @@
#include "vboot_common.h" #include "vboot_common.h"
#include "vboot_nvstorage.h" #include "vboot_nvstorage.h"
VbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams)
VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) { {
VbSharedDataHeader* shared = (VbSharedDataHeader*)cparams->shared_data_blob; VbSharedDataHeader *shared =
GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)cparams->gbb_data; (VbSharedDataHeader *)cparams->shared_data_blob;
GoogleBinaryBlockHeader *gbb =
(GoogleBinaryBlockHeader *)cparams->gbb_data;
VbNvContext vnc; VbNvContext vnc;
VbError_t retval = VBERROR_SUCCESS; VbError_t retval = VBERROR_SUCCESS;
uint32_t recovery = VBNV_RECOVERY_NOT_REQUESTED; uint32_t recovery = VBNV_RECOVERY_NOT_REQUESTED;
@@ -75,50 +77,67 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
if (is_s3_resume) { if (is_s3_resume) {
VBDEBUG(("VbInit() requesting S3 debug boot\n")); VBDEBUG(("VbInit() requesting S3 debug boot\n"));
iparams->out_flags |= VB_INIT_OUT_S3_DEBUG_BOOT; iparams->out_flags |= VB_INIT_OUT_S3_DEBUG_BOOT;
is_s3_resume = 0; /* Proceed as if this is a normal boot */ is_s3_resume = 0; /* Proceed as if normal boot */
} }
/* Clear the request even if this is a normal boot, since we don't /*
* want the NEXT S3 resume to be a debug reset unless the OS * Clear the request even if this is a normal boot, since we
* asserts the request again. */ * don't want the NEXT S3 resume to be a debug reset unless the
* OS asserts the request again.
*/
VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 0); VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 0);
} }
/* If this isn't a S3 resume, read the current recovery request, then clear /*
* it so we don't get stuck in recovery mode. */ * If this isn't a S3 resume, read the current recovery request, then
* clear it so we don't get stuck in recovery mode.
*/
if (!is_s3_resume) { if (!is_s3_resume) {
VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery); VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery);
VBDEBUG(("VbInit sees recovery request = %d\n", recovery)); VBDEBUG(("VbInit sees recovery request = %d\n", recovery));
if (VBNV_RECOVERY_NOT_REQUESTED != recovery) if (VBNV_RECOVERY_NOT_REQUESTED != recovery)
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_NOT_REQUESTED); VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
VBNV_RECOVERY_NOT_REQUESTED);
} }
/* If the previous boot failed in the firmware somewhere outside of verified /*
* boot, and recovery is not requested for our own reasons, request recovery * If the previous boot failed in the firmware somewhere outside of
* mode. This gives the calling firmware a way to request recovery if it * verified boot, and recovery is not requested for our own reasons,
* finds something terribly wrong. */ * request recovery mode. This gives the calling firmware a way to
* request recovery if it finds something terribly wrong.
*/
if (VBNV_RECOVERY_NOT_REQUESTED == recovery && if (VBNV_RECOVERY_NOT_REQUESTED == recovery &&
iparams->flags & VB_INIT_FLAG_PREVIOUS_BOOT_FAIL) { iparams->flags & VB_INIT_FLAG_PREVIOUS_BOOT_FAIL) {
recovery = VBNV_RECOVERY_RO_FIRMWARE; recovery = VBNV_RECOVERY_RO_FIRMWARE;
} }
/* If recovery button is pressed, override recovery reason. Note that we /*
* do this in the S3 resume path also. */ * If recovery button is pressed, override recovery reason. Note that
* we do this in the S3 resume path also.
*/
if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED) if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED)
recovery = VBNV_RECOVERY_RO_MANUAL; recovery = VBNV_RECOVERY_RO_MANUAL;
/* Copy current recovery reason to shared data. If we fail later on, it /*
* won't matter, since we'll just reboot. */ * Copy current recovery reason to shared data. If we fail later on, it
* won't matter, since we'll just reboot.
*/
shared->recovery_reason = (uint8_t)recovery; shared->recovery_reason = (uint8_t)recovery;
VBDEBUG(("VbInit now sets shared->recovery_reason = %d\n", recovery)); VBDEBUG(("VbInit now sets shared->recovery_reason = %d\n", recovery));
/* If this is a S3 resume, resume the TPM. */ /*
/* FIXME: I think U-Boot won't ever ask us to do this. Can we remove it? */ * If this is a S3 resume, resume the TPM.
*
* FIXME: I think U-Boot won't ever ask us to do this. Can we remove
* it?
*/
if (is_s3_resume) { if (is_s3_resume) {
if (TPM_SUCCESS != RollbackS3Resume()) { if (TPM_SUCCESS != RollbackS3Resume()) {
/* If we can't resume, just do a full reboot. No need to go to recovery /*
* mode here, since if the TPM is really broken we'll catch it on the * If we can't resume, just do a full reboot. No need
* next boot. */ * to go to recovery mode here, since if the TPM is
* really broken we'll catch it on the next boot.
*/
retval = VBERROR_TPM_S3_RESUME; retval = VBERROR_TPM_S3_RESUME;
} }
} else { } else {
@@ -127,11 +146,16 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
shared->flags |= VBSD_HONOR_VIRT_DEV_SWITCH; shared->flags |= VBSD_HONOR_VIRT_DEV_SWITCH;
has_virt_dev_switch = 1; has_virt_dev_switch = 1;
} }
/* We always believe the HW dev-switch, since there's one attached to servo
* which may be active even on systems without a physical switch. The EC /*
* may also implement a fake dev-switch for testing. */ * We always believe the HW dev-switch, since there's one
* attached to servo which may be active even on systems
* without a physical switch. The EC may also implement a fake
* dev-switch for testing.
*/
if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON) if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON)
is_hw_dev = 1; is_hw_dev = 1;
/* We may be asked to clear the virtual dev-switch at boot. */ /* We may be asked to clear the virtual dev-switch at boot. */
VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request); VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request);
@@ -139,42 +163,60 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON)
is_hw_dev = 1; is_hw_dev = 1;
/* Check if we've been explicitly asked to clear the TPM owner */ /* Have we been explicitly asked to clear the TPM owner? */
VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, &clear_tpm_owner_request); VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST,
&clear_tpm_owner_request);
VBPERFSTART("VB_TPMI"); VBPERFSTART("VB_TPMI");
/* Initialize the TPM. If the developer mode state has changed since the /*
* last boot, we need to clear TPM ownership. If the TPM space is * Initialize the TPM. If the developer mode state has changed
* initialized by this call, the virtual dev-switch will be disabled by * since the last boot, we need to clear TPM ownership. If the
* default) */ * TPM space is initialized by this call, the virtual
tpm_status = RollbackFirmwareSetup(recovery, is_hw_dev, disable_dev_request, * dev-switch will be disabled by default)
*/
tpm_status = RollbackFirmwareSetup(recovery, is_hw_dev,
disable_dev_request,
clear_tpm_owner_request, clear_tpm_owner_request,
/* two outputs on success */ /* two outputs on success */
&is_virt_dev, &tpm_version); &is_virt_dev, &tpm_version);
VBPERFEND("VB_TPMI"); VBPERFEND("VB_TPMI");
if (0 != tpm_status) { if (0 != tpm_status) {
VBDEBUG(("Unable to setup TPM and read firmware version (0x%x)\n", VBDEBUG(("Unable to setup TPM and read "
tpm_status)); "firmware version (0x%x)\n", tpm_status));
if (TPM_E_MUST_REBOOT == tpm_status) { if (TPM_E_MUST_REBOOT == tpm_status) {
/* TPM wants to reboot into the same mode we're in now */ /*
* TPM wants to reboot into the same mode we're
* in now
*/
VBDEBUG(("TPM requires a reboot.\n")); VBDEBUG(("TPM requires a reboot.\n"));
if (!recovery) { if (!recovery) {
/* Not recovery mode. Just reboot (not into recovery). */ /*
* Not recovery mode. Just reboot (not
* into recovery).
*/
retval = VBERROR_TPM_REBOOT_REQUIRED; retval = VBERROR_TPM_REBOOT_REQUIRED;
goto VbInit_exit; goto VbInit_exit;
} else if (VBNV_RECOVERY_RO_TPM_REBOOT != shared->recovery_reason) { } else if (VBNV_RECOVERY_RO_TPM_REBOOT !=
/* In recovery mode now, and we haven't requested a TPM reboot yet, shared->recovery_reason) {
* so request one. */ /*
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_REBOOT); * In recovery mode now, and we haven't
* requested a TPM reboot yet, so
* request one.
*/
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
VBNV_RECOVERY_RO_TPM_REBOOT);
retval = VBERROR_TPM_REBOOT_REQUIRED; retval = VBERROR_TPM_REBOOT_REQUIRED;
goto VbInit_exit; goto VbInit_exit;
} }
} }
if (!recovery) { if (!recovery) {
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_S_ERROR); VbNvSet(&vnc, VBNV_RECOVERY_REQUEST,
VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE, tpm_status); VBNV_RECOVERY_RO_TPM_S_ERROR);
VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE,
tpm_status);
retval = VBERROR_TPM_FIRMWARE_SETUP; retval = VBERROR_TPM_FIRMWARE_SETUP;
goto VbInit_exit; goto VbInit_exit;
} }
@@ -199,7 +241,7 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
if (gbb->flags & GBB_FLAG_LOAD_OPTION_ROMS) if (gbb->flags & GBB_FLAG_LOAD_OPTION_ROMS)
iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM; iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM;
/* The factory may need to boot custom OSes whenever the dev-switch is on */ /* Factory may need to boot custom OSes when the dev-switch is on */
if (is_dev && (gbb->flags & GBB_FLAG_ENABLE_ALTERNATE_OS)) if (is_dev && (gbb->flags & GBB_FLAG_ENABLE_ALTERNATE_OS))
iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS; iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS;
@@ -210,8 +252,7 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
VB_INIT_OUT_CLEAR_RAM | VB_INIT_OUT_CLEAR_RAM |
VB_INIT_OUT_ENABLE_DISPLAY | VB_INIT_OUT_ENABLE_DISPLAY |
VB_INIT_OUT_ENABLE_USB_STORAGE); VB_INIT_OUT_ENABLE_USB_STORAGE);
} } else if (is_dev) {
else if (is_dev) {
/* Developer switch is on, so need to support dev mode */ /* Developer switch is on, so need to support dev mode */
iparams->out_flags |= (VB_INIT_OUT_ENABLE_DEVELOPER | iparams->out_flags |= (VB_INIT_OUT_ENABLE_DEVELOPER |
VB_INIT_OUT_CLEAR_RAM | VB_INIT_OUT_CLEAR_RAM |
@@ -222,9 +263,11 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
if (!require_official_os) if (!require_official_os)
iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS; iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS;
/* Dev-mode needs the VGA option ROM to be loaded so it can display the /*
* scary boot screen. If we don't have it, we need to request it and * Dev-mode needs the VGA option ROM to be loaded so it can
* reboot so it can be loaded. */ * display the scary boot screen. If we don't have it, we need
* to request it and reboot so it can be loaded.
*/
if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) && if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) &&
!(iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) { !(iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) {
VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1); VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
@@ -233,15 +276,20 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
} }
} else { } else {
/* Normal mode, so disable dev_boot_* flags. This ensures they will be /*
* initially disabled if the user later transitions back into developer * Normal mode, so disable dev_boot_* flags. This ensures they
* mode. */ * will be initially disabled if the user later transitions
* back into developer mode.
*/
VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0); VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0);
VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 0); VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 0);
VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 0); VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 0);
/* If we don't need the VGA option ROM but got it anyway, stop asking for /*
* it and reboot in case there's some vulnerability in using it. */ * If we don't need the VGA option ROM but got it anyway, stop
* asking for it and reboot in case there's some vulnerability
* in using it.
*/
if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) && if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) &&
(iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) { (iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) {
VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0); VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0);
@@ -262,5 +310,6 @@ VbInit_exit:
shared->timer_vb_init_exit = VbExGetTimer(); shared->timer_vb_init_exit = VbExGetTimer();
VBDEBUG(("VbInit() returning 0x%x\n", retval)); VBDEBUG(("VbInit() returning 0x%x\n", retval));
return retval; return retval;
} }

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -18,8 +18,10 @@
#define UINT_MAX 4294967295U /* 0xffffffff */ #define UINT_MAX 4294967295U /* 0xffffffff */
#endif #endif
/* Need one second of noise in the first 22 seconds. /*
* Total delay >= 30 seconds, <= 60 seconds. */ * Need one second of noise in the first 22 seconds.
* Total delay >= 30 seconds, <= 60 seconds.
*/
#define REQUIRED_NOISE_TIME 1000 #define REQUIRED_NOISE_TIME 1000
#define REQUIRED_NOISE_WITHIN 22000 #define REQUIRED_NOISE_WITHIN 22000
#define REQUIRED_TOTAL_DELAY 30000 #define REQUIRED_TOTAL_DELAY 30000
@@ -39,21 +41,24 @@ uint32_t short_count_ = sizeof(short_notes_) / sizeof(VbDevMusicNote);
/* No need to dynamically allocate this, is there? */ /* No need to dynamically allocate this, is there? */
static VbAudioContext au; static VbAudioContext au;
/* Convert from msecs to VbExGetTimer() units. */ /* Convert from msecs to VbExGetTimer() units. */
static uint64_t ticks_per_msec = 0; /* Initialized by VbAudioOpen() */ static uint64_t ticks_per_msec = 0; /* Initialized by VbAudioOpen() */
static uint64_t VbMsecToTicks(uint16_t msec) { static uint64_t VbMsecToTicks(uint16_t msec) {
return ticks_per_msec * msec; return ticks_per_msec * msec;
} }
/* Find and return a valid set of note events. We'll use the user's struct /**
* if possible, but we will still enforce the 30-second timeout and require at * Find and return a valid set of note events.
* least a second of audible noise within that period. We allocate storage for *
* two reasons: the user's struct will be in flash, which is slow to read, and * We'll use the user's struct if possible, but we will still enforce the
* we may need one extra note at the end to pad out the user's notes to a full * 30-second timeout and require at least a second of audible noise within that
* 30 seconds. The caller should free it when finished. * period. We allocate storage for two reasons: the user's struct will be in
* flash, which is slow to read, and we may need one extra note at the end to
* pad out the user's notes to a full 30 seconds. The caller should free it
* when finished.
*/ */
static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) { static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short)
{
VbDevMusicNote *notebuf = 0; VbDevMusicNote *notebuf = 0;
VbDevMusicNote *builtin = 0; VbDevMusicNote *builtin = 0;
VbDevMusic *hdr = CUSTOM_MUSIC_NOTES; VbDevMusic *hdr = CUSTOM_MUSIC_NOTES;
@@ -62,8 +67,8 @@ static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) {
uint32_t this_msecs, on_msecs, total_msecs; uint32_t this_msecs, on_msecs, total_msecs;
uint32_t count; uint32_t count;
VBDEBUG(("VbGetDevMusicNotes: use_short is %d, hdr is %lx, maxsize is %d\n", VBDEBUG(("VbGetDevMusicNotes: use_short is %d, hdr is %lx, "
use_short, hdr, maxsize)); "maxsize is %d\n", use_short, hdr, maxsize));
if (use_short) { if (use_short) {
builtin = short_notes_; builtin = short_notes_;
@@ -86,8 +91,9 @@ static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) {
goto nope; goto nope;
} }
/* How many notes will fit in the flash region? One more than you'd think, /*
* because there's one note in the header itself. * How many notes will fit in the flash region? One more than you'd
* think, because there's one note in the header itself.
*/ */
maxnotes = 1 + (maxsize - sizeof(VbDevMusic)) / sizeof(VbDevMusicNote); maxnotes = 1 + (maxsize - sizeof(VbDevMusic)) / sizeof(VbDevMusicNote);
if (hdr->count == 0 || hdr->count > maxnotes) { if (hdr->count == 0 || hdr->count > maxnotes) {
@@ -96,17 +102,21 @@ static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) {
goto nope; goto nope;
} }
/* CUSTOM_MUSIC_MAXSIZE can't be larger than the size of the flash (around 8M /*
* or so) so this isn't really necessary, but let's be safe anyway. * CUSTOM_MUSIC_MAXSIZE can't be larger than the size of the flash
* (around 8M or so) so this isn't really necessary, but let's be safe
* anyway.
*/ */
if ((sizeof(VbDevMusicNote) > UINT_MAX / hdr->count) || if ((sizeof(VbDevMusicNote) > UINT_MAX / hdr->count) ||
(sizeof(hdr->count) > UINT_MAX - hdr->count * sizeof(VbDevMusicNote))) { (sizeof(hdr->count) >
UINT_MAX - hdr->count * sizeof(VbDevMusicNote))) {
VBDEBUG(("VbGetDevMusicNotes: count=%d, just isn't right\n")); VBDEBUG(("VbGetDevMusicNotes: count=%d, just isn't right\n"));
goto nope; goto nope;
} }
/* Now we know this won't overflow */ /* Now we know this won't overflow */
mylen = (uint32_t)(sizeof(hdr->count) + hdr->count * sizeof(VbDevMusicNote)); mylen = (uint32_t)(sizeof(hdr->count) +
hdr->count * sizeof(VbDevMusicNote));
mysum = Crc32(&(hdr->count), mylen); mysum = Crc32(&(hdr->count), mylen);
if (mysum != hdr->checksum) { if (mysum != hdr->checksum) {
@@ -115,11 +125,12 @@ static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) {
goto nope; goto nope;
} }
VBDEBUG(("VbGetDevMusicNotes: custom notes struct found at %lx\n", hdr)); VBDEBUG(("VbGetDevMusicNotes: custom notes struct at %lx\n", hdr));
/* Measure the audible sound up to the first 22 seconds, being careful to /*
* avoid rollover. The note time is 16 bits, and the note count is 32 bits. * Measure the audible sound up to the first 22 seconds, being careful
* The product should fit in 64 bits. * to avoid rollover. The note time is 16 bits, and the note count is
* 32 bits. The product should fit in 64 bits.
*/ */
total_msecs = 0; total_msecs = 0;
on_msecs = 0; on_msecs = 0;
@@ -128,7 +139,8 @@ static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) {
if (this_msecs) { if (this_msecs) {
total_msecs += this_msecs; total_msecs += this_msecs;
if (total_msecs <= REQUIRED_NOISE_WITHIN && if (total_msecs <= REQUIRED_NOISE_WITHIN &&
hdr->notes[i].frequency >= 100 && hdr->notes[i].frequency <= 2000) hdr->notes[i].frequency >= 100 &&
hdr->notes[i].frequency <= 2000)
on_msecs += this_msecs; on_msecs += this_msecs;
} }
} }
@@ -136,12 +148,12 @@ static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) {
/* We require at least one second of noise in the first 22 seconds */ /* We require at least one second of noise in the first 22 seconds */
VBDEBUG(("VbGetDevMusicNotes: with %ld msecs of sound to begin\n", VBDEBUG(("VbGetDevMusicNotes: with %ld msecs of sound to begin\n",
on_msecs)); on_msecs));
if (on_msecs < REQUIRED_NOISE_TIME) { if (on_msecs < REQUIRED_NOISE_TIME)
goto nope; goto nope;
}
/* We'll also require that the total time be less than a minute. No real /*
* reason, it just gives us less to worry about. * We'll also require that the total time be less than a minute. No
* real reason, it just gives us less to worry about.
*/ */
VBDEBUG(("VbGetDevMusicNotes: lasting %ld msecs\n", total_msecs)); VBDEBUG(("VbGetDevMusicNotes: lasting %ld msecs\n", total_msecs));
if (total_msecs > MAX_CUSTOM_DELAY) { if (total_msecs > MAX_CUSTOM_DELAY) {
@@ -154,15 +166,16 @@ static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) {
goto nope; goto nope;
} }
/* Okay, it looks good. Allocate the space (plus one) and copy it over. */ /* Looks good. Allocate the space (plus one) and copy it over. */
notebuf = VbExMalloc((hdr->count + 1) * sizeof(VbDevMusicNote)); notebuf = VbExMalloc((hdr->count + 1) * sizeof(VbDevMusicNote));
Memcpy(notebuf, hdr->notes, hdr->count * sizeof(VbDevMusicNote)); Memcpy(notebuf, hdr->notes, hdr->count * sizeof(VbDevMusicNote));
count = hdr->count; count = hdr->count;
/* We also require at least 30 seconds of delay. */ /* We also require at least 30 seconds of delay. */
if (total_msecs < REQUIRED_TOTAL_DELAY) { if (total_msecs < REQUIRED_TOTAL_DELAY) {
/* If the total time is less than 30 seconds, the needed difference will /*
* fit in 16 bits. * If the total time is less than 30 seconds, the needed
* difference will fit in 16 bits.
*/ */
this_msecs = (REQUIRED_TOTAL_DELAY - total_msecs) & 0xffff; this_msecs = (REQUIRED_TOTAL_DELAY - total_msecs) & 0xffff;
notebuf[hdr->count].msec = this_msecs; notebuf[hdr->count].msec = this_msecs;
@@ -172,7 +185,7 @@ static void VbGetDevMusicNotes(VbAudioContext *audio, int use_short) {
this_msecs)); this_msecs));
} }
/* done */ /* Done */
audio->music_notes = notebuf; audio->music_notes = notebuf;
audio->note_count = count; audio->note_count = count;
audio->free_notes_when_done = 1; audio->free_notes_when_done = 1;
@@ -187,9 +200,13 @@ nope:
} }
/* Initialization function. Returns context for processing dev-mode delay */ /**
VbAudioContext* VbAudioOpen(VbCommonParams* cparams) { * Initialization function. Returns context for processing dev-mode delay.
GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)cparams->gbb_data; */
VbAudioContext *VbAudioOpen(VbCommonParams *cparams)
{
GoogleBinaryBlockHeader* gbb =
(GoogleBinaryBlockHeader *)cparams->gbb_data;
VbAudioContext *audio = &au; VbAudioContext *audio = &au;
int use_short = 0; int use_short = 0;
uint64_t a, b; uint64_t a, b;
@@ -214,12 +231,13 @@ VbAudioContext* VbAudioOpen(VbCommonParams* cparams) {
audio->background_beep = 0; audio->background_beep = 0;
} }
/* Prepare to generate audio/delay event. Use a short developer screen delay /*
* if indicated by GBB flags. * Prepare to generate audio/delay event. Use a short developer screen
* delay if indicated by GBB flags.
*/ */
if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1
&& (gbb->flags & GBB_FLAG_DEV_SCREEN_SHORT_DELAY)) { && (gbb->flags & GBB_FLAG_DEV_SCREEN_SHORT_DELAY)) {
VBDEBUG(("VbAudioOpen() - using short developer screen delay\n")); VBDEBUG(("VbAudioOpen() - using short dev screen delay\n"));
use_short = 1; use_short = 1;
} }
@@ -229,8 +247,11 @@ VbAudioContext* VbAudioOpen(VbCommonParams* cparams) {
return audio; return audio;
} }
/* Caller should loop without extra delay until this returns false */ /**
int VbAudioLooping(VbAudioContext* audio) { * Caller should loop without extra delay until this returns false.
*/
int VbAudioLooping(VbAudioContext *audio)
{
uint64_t now; uint64_t now;
uint16_t freq = audio->current_frequency; uint16_t freq = audio->current_frequency;
uint16_t msec = 0; uint16_t msec = 0;
@@ -241,7 +262,8 @@ int VbAudioLooping(VbAudioContext* audio) {
#endif #endif
now = VbExGetTimer(); now = VbExGetTimer();
while (audio->next_note < audio->note_count && now >= audio->play_until) { while (audio->next_note < audio->note_count &&
now >= audio->play_until) {
freq = audio->music_notes[audio->next_note].frequency; freq = audio->music_notes[audio->next_note].frequency;
msec = audio->music_notes[audio->next_note].msec; msec = audio->music_notes[audio->next_note].msec;
audio->play_until += VbMsecToTicks(msec); audio->play_until += VbMsecToTicks(msec);
@@ -253,7 +275,7 @@ int VbAudioLooping(VbAudioContext* audio) {
freq = 0; freq = 0;
} }
// Do action here. /* Do action here. */
if (audio->background_beep) { if (audio->background_beep) {
if (audio->current_frequency != freq) { if (audio->current_frequency != freq) {
VbExBeep(0, freq); VbExBeep(0, freq);
@@ -268,8 +290,11 @@ int VbAudioLooping(VbAudioContext* audio) {
return looping; return looping;
} }
/* Caller should call this prior to booting */ /**
void VbAudioClose(VbAudioContext* audio) { * Caller should call this prior to booting.
*/
void VbAudioClose(VbAudioContext *audio)
{
VbExBeep(0,0); VbExBeep(0,0);
if (audio->free_notes_when_done) if (audio->free_notes_when_done)
VbExFree(audio->music_notes); VbExFree(audio->music_notes);

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -13,18 +13,20 @@
#include "vboot_common.h" #include "vboot_common.h"
#include "vboot_nvstorage.h" #include "vboot_nvstorage.h"
/* Static variables for UpdateFirmwareBodyHash(). It's less than /*
* optimal to have static variables in a library, but in UEFI the * Static variables for UpdateFirmwareBodyHash(). It's less than optimal to
* caller is deep inside a different firmware stack and doesn't have a * have static variables in a library, but in UEFI the caller is deep inside a
* good way to pass the params struct back to us. */ * different firmware stack and doesn't have a good way to pass the params
* struct back to us.
*/
typedef struct VbLoadFirmwareInternal { typedef struct VbLoadFirmwareInternal {
DigestContext body_digest_context; DigestContext body_digest_context;
uint32_t body_size_accum; uint32_t body_size_accum;
} VbLoadFirmwareInternal; } VbLoadFirmwareInternal;
void VbUpdateFirmwareBodyHash(VbCommonParams *cparams, uint8_t *data,
void VbUpdateFirmwareBodyHash(VbCommonParams* cparams, uint32_t size)
uint8_t* data, uint32_t size) { {
VbLoadFirmwareInternal *lfi = VbLoadFirmwareInternal *lfi =
(VbLoadFirmwareInternal*)cparams->vboot_context; (VbLoadFirmwareInternal*)cparams->vboot_context;
@@ -32,11 +34,13 @@ void VbUpdateFirmwareBodyHash(VbCommonParams* cparams,
lfi->body_size_accum += size; lfi->body_size_accum += size;
} }
int LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams, int LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams,
VbNvContext* vnc) { VbNvContext *vnc)
VbSharedDataHeader* shared = (VbSharedDataHeader*)cparams->shared_data_blob; {
GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)cparams->gbb_data; VbSharedDataHeader *shared =
(VbSharedDataHeader *)cparams->shared_data_blob;
GoogleBinaryBlockHeader *gbb =
(GoogleBinaryBlockHeader *)cparams->gbb_data;
VbPublicKey *root_key; VbPublicKey *root_key;
VbLoadFirmwareInternal *lfi; VbLoadFirmwareInternal *lfi;
@@ -76,8 +80,9 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
} }
/* Allocate our internal data */ /* Allocate our internal data */
lfi = (VbLoadFirmwareInternal*)VbExMalloc(sizeof(VbLoadFirmwareInternal)); lfi = (VbLoadFirmwareInternal *)
cparams->vboot_context = (void*)lfi; VbExMalloc(sizeof(VbLoadFirmwareInternal));
cparams->vboot_context = lfi;
/* Loop over indices */ /* Loop over indices */
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
@@ -93,18 +98,22 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
/* If try B count is non-zero try firmware B first */ /* If try B count is non-zero try firmware B first */
index = (try_b_count ? 1 - i : i); index = (try_b_count ? 1 - i : i);
if (0 == index) { if (0 == index) {
key_block = (VbKeyBlockHeader*)fparams->verification_block_A; key_block = (VbKeyBlockHeader *)
fparams->verification_block_A;
vblock_size = fparams->verification_size_A; vblock_size = fparams->verification_size_A;
check_result = &shared->check_fw_a_result; check_result = &shared->check_fw_a_result;
} else { } else {
key_block = (VbKeyBlockHeader*)fparams->verification_block_B; key_block = (VbKeyBlockHeader *)
fparams->verification_block_B;
vblock_size = fparams->verification_size_B; vblock_size = fparams->verification_size_B;
check_result = &shared->check_fw_b_result; check_result = &shared->check_fw_b_result;
} }
/* Check the key block flags against the current boot mode. Do this /*
* before verifying the key block, since flags are faster to check than * Check the key block flags against the current boot mode. Do
* the RSA signature. */ * this before verifying the key block, since flags are faster
* to check than the RSA signature.
*/
if (!(key_block->key_block_flags & if (!(key_block->key_block_flags &
(is_dev ? KEY_BLOCK_FLAG_DEVELOPER_1 : (is_dev ? KEY_BLOCK_FLAG_DEVELOPER_1 :
KEY_BLOCK_FLAG_DEVELOPER_0))) { KEY_BLOCK_FLAG_DEVELOPER_0))) {
@@ -112,6 +121,7 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
*check_result = VBSD_LF_CHECK_DEV_MISMATCH; *check_result = VBSD_LF_CHECK_DEV_MISMATCH;
continue; continue;
} }
/* RW firmware never runs in recovery mode. */ /* RW firmware never runs in recovery mode. */
if (!(key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)) { if (!(key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)) {
VBDEBUG(("Recovery flag mismatch.\n")); VBDEBUG(("Recovery flag mismatch.\n"));
@@ -121,7 +131,8 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
/* Verify the key block */ /* Verify the key block */
VBPERFSTART("VB_VKB"); VBPERFSTART("VB_VKB");
if ((0 != KeyBlockVerify(key_block, vblock_size, root_key, 0))) { if ((0 != KeyBlockVerify(key_block, vblock_size,
root_key, 0))) {
VBDEBUG(("Key block verification failed.\n")); VBDEBUG(("Key block verification failed.\n"));
*check_result = VBSD_LF_CHECK_VERIFY_KEYBLOCK; *check_result = VBSD_LF_CHECK_VERIFY_KEYBLOCK;
VBPERFEND("VB_VKB"); VBPERFEND("VB_VKB");
@@ -138,15 +149,18 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
continue; continue;
} }
if (key_version > 0xFFFF) { if (key_version > 0xFFFF) {
/* Key version is stored in 16 bits in the TPM, so key versions greater /*
* than 0xFFFF can't be stored properly. */ * Key version is stored in 16 bits in the TPM,
* so key versions greater than 0xFFFF can't be
* stored properly.
*/
VBDEBUG(("Key version > 0xFFFF.\n")); VBDEBUG(("Key version > 0xFFFF.\n"));
*check_result = VBSD_LF_CHECK_KEY_ROLLBACK; *check_result = VBSD_LF_CHECK_KEY_ROLLBACK;
continue; continue;
} }
} }
/* Get the key for preamble/data verification from the key block. */ /* Get key for preamble/data verification from the key block. */
data_key = PublicKeyToRSA(&key_block->data_key); data_key = PublicKeyToRSA(&key_block->data_key);
if (!data_key) { if (!data_key) {
VBDEBUG(("Unable to parse data key.\n")); VBDEBUG(("Unable to parse data key.\n"));
@@ -156,9 +170,10 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
/* Verify the preamble, which follows the key block. */ /* Verify the preamble, which follows the key block. */
VBPERFSTART("VB_VPB"); VBPERFSTART("VB_VPB");
preamble = (VbFirmwarePreambleHeader*)((uint8_t*)key_block + preamble = (VbFirmwarePreambleHeader *)
key_block->key_block_size); ((uint8_t *)key_block + key_block->key_block_size);
if ((0 != VerifyFirmwarePreamble(preamble, if ((0 != VerifyFirmwarePreamble(
preamble,
vblock_size - key_block->key_block_size, vblock_size - key_block->key_block_size,
data_key))) { data_key))) {
VBDEBUG(("Preamble verfication failed.\n")); VBDEBUG(("Preamble verfication failed.\n"));
@@ -187,9 +202,11 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
if (lowest_version > combined_version) if (lowest_version > combined_version)
lowest_version = combined_version; lowest_version = combined_version;
/* If we already have good firmware, no need to read another one; /*
* we only needed to look at the versions to check for * If we already have good firmware, no need to read another
* rollback. */ * one; we only needed to look at the versions to check for
* rollback.
*/
if (-1 != good_index) { if (-1 != good_index) {
RSAPublicKeyFree(data_key); RSAPublicKeyFree(data_key);
continue; continue;
@@ -206,7 +223,7 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
continue; continue;
} }
/* Indicate that we should use the RO normal code path */ /* Use the RO normal code path */
shared->flags |= VBSD_LF_USE_RO_NORMAL; shared->flags |= VBSD_LF_USE_RO_NORMAL;
} else { } else {
@@ -214,19 +231,24 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
/* Read the firmware data */ /* Read the firmware data */
VBPERFSTART("VB_RFD"); VBPERFSTART("VB_RFD");
DigestInit(&lfi->body_digest_context, data_key->algorithm); DigestInit(&lfi->body_digest_context,
data_key->algorithm);
lfi->body_size_accum = 0; lfi->body_size_accum = 0;
rv = VbExHashFirmwareBody(cparams, (index ? VB_SELECT_FIRMWARE_B : rv = VbExHashFirmwareBody(
cparams,
(index ? VB_SELECT_FIRMWARE_B :
VB_SELECT_FIRMWARE_A)); VB_SELECT_FIRMWARE_A));
if (VBERROR_SUCCESS != rv) { if (VBERROR_SUCCESS != rv) {
VBDEBUG(("VbExHashFirmwareBody() failed for index %d\n", index)); VBDEBUG(("VbExHashFirmwareBody() failed for "
"index %d\n", index));
*check_result = VBSD_LF_CHECK_GET_FW_BODY; *check_result = VBSD_LF_CHECK_GET_FW_BODY;
RSAPublicKeyFree(data_key); RSAPublicKeyFree(data_key);
VBPERFEND("VB_RFD"); VBPERFEND("VB_RFD");
continue; continue;
} }
if (lfi->body_size_accum != preamble->body_signature.data_size) { if (lfi->body_size_accum !=
VBDEBUG(("Hash updated %d bytes but expected %d\n", preamble->body_signature.data_size) {
VBDEBUG(("Hashed %d bytes but expected %d\n",
(int)lfi->body_size_accum, (int)lfi->body_size_accum,
(int)preamble->body_signature.data_size)); (int)preamble->body_signature.data_size));
*check_result = VBSD_LF_CHECK_HASH_WRONG_SIZE; *check_result = VBSD_LF_CHECK_HASH_WRONG_SIZE;
@@ -239,9 +261,10 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
/* Verify firmware data */ /* Verify firmware data */
VBPERFSTART("VB_VFD"); VBPERFSTART("VB_VFD");
body_digest = DigestFinal(&lfi->body_digest_context); body_digest = DigestFinal(&lfi->body_digest_context);
if (0 != VerifyDigest(body_digest, &preamble->body_signature, if (0 != VerifyDigest(body_digest,
&preamble->body_signature,
data_key)) { data_key)) {
VBDEBUG(("Firmware body verification failed.\n")); VBDEBUG(("FW body verification failed.\n"));
*check_result = VBSD_LF_CHECK_VERIFY_BODY; *check_result = VBSD_LF_CHECK_VERIFY_BODY;
RSAPublicKeyFree(data_key); RSAPublicKeyFree(data_key);
VbExFree(body_digest); VbExFree(body_digest);
@@ -260,22 +283,32 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
*check_result = VBSD_LF_CHECK_VALID; *check_result = VBSD_LF_CHECK_VALID;
if (-1 == good_index) { if (-1 == good_index) {
/* Save the key we actually used */ /* Save the key we actually used */
if (0 != VbSharedDataSetKernelKey(shared, &preamble->kernel_subkey)) { if (0 != VbSharedDataSetKernelKey(
VBDEBUG(("Unable to save kernel subkey to shared data.\n")); shared, &preamble->kernel_subkey)) {
continue; /* The firmware signature was good, but the public /*
* key was bigger that the caller can handle. */ * The firmware signature was good, but the
* public key was bigger that the caller can
* handle.
*/
VBDEBUG(("Unable to save kernel subkey.\n"));
continue;
} }
/* Save the good index, now that we're sure we can actually use /*
* this firmware. That's the one we'll boot. */ * Save the good index, now that we're sure we can
* actually use this firmware. That's the one we'll
* boot.
*/
good_index = index; good_index = index;
shared->firmware_index = (uint8_t)index; shared->firmware_index = (uint8_t)index;
shared->fw_keyblock_flags = key_block->key_block_flags; shared->fw_keyblock_flags = key_block->key_block_flags;
/* If the good firmware's key version is the same as the tpm, /*
* then the TPM doesn't need updating; we can stop now. * If the good firmware's key version is the same as
* Otherwise, we'll check all the other headers to see if they * the tpm, then the TPM doesn't need updating; we can
* contain a newer key. */ * stop now. Otherwise, we'll check all the other
* headers to see if they contain a newer key.
*/
if (combined_version == shared->fw_version_tpm) if (combined_version == shared->fw_version_tpm)
break; break;
} }
@@ -294,8 +327,10 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
shared->fw_version_tpm = lowest_version; shared->fw_version_tpm = lowest_version;
/* Success */ /* Success */
VBDEBUG(("Will boot firmware index %d\n", (int)shared->firmware_index)); VBDEBUG(("Will boot firmware index %d\n",
(int)shared->firmware_index));
retval = VBERROR_SUCCESS; retval = VBERROR_SUCCESS;
} else { } else {
uint8_t a = shared->check_fw_a_result; uint8_t a = shared->check_fw_a_result;
uint8_t b = shared->check_fw_b_result; uint8_t b = shared->check_fw_b_result;
@@ -306,9 +341,13 @@ int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
recovery = VBNV_RECOVERY_RO_INVALID_RW; recovery = VBNV_RECOVERY_RO_INVALID_RW;
retval = VBERROR_LOAD_FIRMWARE; retval = VBERROR_LOAD_FIRMWARE;
/* If the best check result fits in the range of recovery reasons, provide /*
* more detail on how far we got in validation. */ * If the best check result fits in the range of recovery
best_check = (a > b ? a : b) + VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN; * reasons, provide more detail on how far we got in
* validation.
*/
best_check = (a > b ? a : b) +
VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN;
if (best_check >= VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN && if (best_check >= VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN &&
best_check <= VBNV_RECOVERY_RO_INVALID_RW_CHECK_MAX) best_check <= VBNV_RECOVERY_RO_INVALID_RW_CHECK_MAX)
recovery = best_check; recovery = best_check;

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
* *
@@ -20,19 +20,21 @@
#define LOWEST_TPM_VERSION 0xffffffff #define LOWEST_TPM_VERSION 0xffffffff
typedef enum BootMode { typedef enum BootMode {
kBootRecovery = 0, /* Recovery firmware, regardless of dev switch position */ kBootRecovery = 0, /* Recovery firmware, any dev switch position */
kBootNormal = 1, /* Normal boot - kernel must be verified */ kBootNormal = 1, /* Normal boot - kernel must be verified */
kBootDev = 2 /* Developer boot - self-signed kernel ok */ kBootDev = 2 /* Developer boot - self-signed kernel ok */
} BootMode; } BootMode;
/**
/* Allocates and reads GPT data from the drive. The sector_bytes and * Allocate and read GPT data from the drive.
* drive_sectors fields should be filled on input. The primary and
* secondary header and entries are filled on output.
* *
* Returns 0 if successful, 1 if error. */ * The sector_bytes and drive_sectors fields should be filled on input. The
int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) { * primary and secondary header and entries are filled on output.
*
* Returns 0 if successful, 1 if error.
*/
int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{
uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes; uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes;
/* No data to be written yet */ /* No data to be written yet */
@@ -40,12 +42,15 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
/* Allocate all buffers */ /* Allocate all buffers */
gptdata->primary_header = (uint8_t *)VbExMalloc(gptdata->sector_bytes); gptdata->primary_header = (uint8_t *)VbExMalloc(gptdata->sector_bytes);
gptdata->secondary_header = (uint8_t*)VbExMalloc(gptdata->sector_bytes); gptdata->secondary_header =
(uint8_t *)VbExMalloc(gptdata->sector_bytes);
gptdata->primary_entries = (uint8_t *)VbExMalloc(TOTAL_ENTRIES_SIZE); gptdata->primary_entries = (uint8_t *)VbExMalloc(TOTAL_ENTRIES_SIZE);
gptdata->secondary_entries = (uint8_t *)VbExMalloc(TOTAL_ENTRIES_SIZE); gptdata->secondary_entries = (uint8_t *)VbExMalloc(TOTAL_ENTRIES_SIZE);
if (gptdata->primary_header == NULL || gptdata->secondary_header == NULL || if (gptdata->primary_header == NULL ||
gptdata->primary_entries == NULL || gptdata->secondary_entries == NULL) gptdata->secondary_header == NULL ||
gptdata->primary_entries == NULL ||
gptdata->secondary_entries == NULL)
return 1; return 1;
/* Read data from the drive, skipping the protective MBR */ /* Read data from the drive, skipping the protective MBR */
@@ -65,13 +70,13 @@ int AllocAndReadGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
return 0; return 0;
} }
/**
/* Writes any changes for the GPT data back to the drive, then frees * Write any changes for the GPT data back to the drive, then free the buffers.
* the buffers.
* *
* Returns 0 if successful, 1 if error. */ * Returns 0 if successful, 1 if error.
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) { */
int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData *gptdata)
{
int legacy = 0; int legacy = 0;
uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes; uint64_t entries_sectors = TOTAL_ENTRIES_SIZE / gptdata->sector_bytes;
@@ -81,10 +86,12 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
GPT_HEADER_SIGNATURE_SIZE); GPT_HEADER_SIGNATURE_SIZE);
if (gptdata->modified & GPT_MODIFIED_HEADER1) { if (gptdata->modified & GPT_MODIFIED_HEADER1) {
if (legacy) { if (legacy) {
VBDEBUG(("Not updating GPT header 1: legacy mode is enabled.\n")); VBDEBUG(("Not updating GPT header 1: "
"legacy mode is enabled.\n"));
} else { } else {
VBDEBUG(("Updating GPT header 1\n")); VBDEBUG(("Updating GPT header 1\n"));
if (0 != VbExDiskWrite(disk_handle, 1, 1, gptdata->primary_header)) if (0 != VbExDiskWrite(disk_handle, 1, 1,
gptdata->primary_header))
return 1; return 1;
} }
} }
@@ -94,10 +101,12 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
if (gptdata->primary_entries) { if (gptdata->primary_entries) {
if (gptdata->modified & GPT_MODIFIED_ENTRIES1) { if (gptdata->modified & GPT_MODIFIED_ENTRIES1) {
if (legacy) { if (legacy) {
VBDEBUG(("Not updating GPT entries 1: legacy mode is enabled.\n")); VBDEBUG(("Not updating GPT entries 1: "
"legacy mode is enabled.\n"));
} else { } else {
VBDEBUG(("Updating GPT entries 1\n")); VBDEBUG(("Updating GPT entries 1\n"));
if (0 != VbExDiskWrite(disk_handle, 2, entries_sectors, if (0 != VbExDiskWrite(disk_handle, 2,
entries_sectors,
gptdata->primary_entries)) gptdata->primary_entries))
return 1; return 1;
} }
@@ -119,7 +128,8 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
if (gptdata->secondary_header) { if (gptdata->secondary_header) {
if (gptdata->modified & GPT_MODIFIED_HEADER2) { if (gptdata->modified & GPT_MODIFIED_HEADER2) {
VBDEBUG(("Updating GPT entries 2\n")); VBDEBUG(("Updating GPT entries 2\n"));
if (0 != VbExDiskWrite(disk_handle, gptdata->drive_sectors - 1, 1, if (0 != VbExDiskWrite(disk_handle,
gptdata->drive_sectors - 1, 1,
gptdata->secondary_header)) gptdata->secondary_header))
return 1; return 1;
} }
@@ -133,12 +143,14 @@ int WriteAndFreeGptData(VbExDiskHandle_t disk_handle, GptData* gptdata) {
/* disable MSVC warning on const logical expression (as in } while(0);) */ /* disable MSVC warning on const logical expression (as in } while(0);) */
__pragma(warning(disable: 4127)) __pragma(warning(disable: 4127))
VbError_t LoadKernel(LoadKernelParams *params)
VbError_t LoadKernel(LoadKernelParams* params) { {
VbSharedDataHeader* shared = (VbSharedDataHeader*)params->shared_data_blob; VbSharedDataHeader *shared =
(VbSharedDataHeader *)params->shared_data_blob;
VbSharedDataKernelCall *shcall = NULL; VbSharedDataKernelCall *shcall = NULL;
VbNvContext* vnc = params->nv_context; VbNvContext* vnc = params->nv_context;
GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)params->gbb_data; GoogleBinaryBlockHeader* gbb =
(GoogleBinaryBlockHeader *)params->gbb_data;
VbPublicKey* kernel_subkey; VbPublicKey* kernel_subkey;
GptData gpt; GptData gpt;
uint64_t part_start, part_size; uint64_t part_start, part_size;
@@ -181,8 +193,10 @@ VbError_t LoadKernel(LoadKernelParams* params) {
boot_mode = kBootNormal; boot_mode = kBootNormal;
} }
/* Set up tracking for this call. This wraps around if called many times, /*
* so we need to initialize the call entry each time. */ * Set up tracking for this call. This wraps around if called many
* times, so we need to initialize the call entry each time.
*/
shcall = shared->lk_calls + (shared->lk_call_count shcall = shared->lk_calls + (shared->lk_call_count
& (VBSD_MAX_KERNEL_CALLS - 1)); & (VBSD_MAX_KERNEL_CALLS - 1));
Memset(shcall, 0, sizeof(VbSharedDataKernelCall)); Memset(shcall, 0, sizeof(VbSharedDataKernelCall));
@@ -203,7 +217,8 @@ VbError_t LoadKernel(LoadKernelParams* params) {
if (kBootRecovery == boot_mode) { if (kBootRecovery == boot_mode) {
/* Use the recovery key to verify the kernel */ /* Use the recovery key to verify the kernel */
kernel_subkey = (VbPublicKey*)((uint8_t*)gbb + gbb->recovery_key_offset); kernel_subkey = (VbPublicKey*)
((uint8_t*)gbb + gbb->recovery_key_offset);
} else { } else {
/* Use the kernel subkey passed from LoadFirmware(). */ /* Use the kernel subkey passed from LoadFirmware(). */
kernel_subkey = &shared->kernel_subkey; kernel_subkey = &shared->kernel_subkey;
@@ -231,7 +246,8 @@ VbError_t LoadKernel(LoadKernelParams* params) {
goto bad_gpt; goto bad_gpt;
/* Loop over candidate kernel partitions */ /* Loop over candidate kernel partitions */
while (GPT_SUCCESS == GptNextKernelEntry(&gpt, &part_start, &part_size)) { while (GPT_SUCCESS ==
GptNextKernelEntry(&gpt, &part_start, &part_size)) {
VbSharedDataKernelPart *shpart = NULL; VbSharedDataKernelPart *shpart = NULL;
VbKeyBlockHeader *key_block; VbKeyBlockHeader *key_block;
VbKernelPreambleHeader *preamble; VbKernelPreambleHeader *preamble;
@@ -246,15 +262,20 @@ VbError_t LoadKernel(LoadKernelParams* params) {
VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n", VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n",
part_start, part_size)); part_start, part_size));
/* Set up tracking for this partition. This wraps around if called /*
* many times, so initialize the partition entry each time. */ * Set up tracking for this partition. This wraps around if
* called many times, so initialize the partition entry each
* time.
*/
shpart = shcall->parts + (shcall->kernel_parts_found shpart = shcall->parts + (shcall->kernel_parts_found
& (VBSD_MAX_KERNEL_PARTS - 1)); & (VBSD_MAX_KERNEL_PARTS - 1));
Memset(shpart, 0, sizeof(VbSharedDataKernelPart)); Memset(shpart, 0, sizeof(VbSharedDataKernelPart));
shpart->sector_start = part_start; shpart->sector_start = part_start;
shpart->sector_count = part_size; shpart->sector_count = part_size;
/* TODO: GPT partitions start at 1, but cgptlib starts them at 0. /*
* Adjust here, until cgptlib is fixed. */ * TODO: GPT partitions start at 1, but cgptlib starts them at
* 0. Adjust here, until cgptlib is fixed.
*/
shpart->gpt_index = (uint8_t)(gpt.current_kernel + 1); shpart->gpt_index = (uint8_t)(gpt.current_kernel + 1);
shcall->kernel_parts_found++; shcall->kernel_parts_found++;
@@ -268,8 +289,8 @@ VbError_t LoadKernel(LoadKernelParams* params) {
goto bad_kernel; goto bad_kernel;
} }
if (0 != VbExDiskRead(params->disk_handle, part_start, kbuf_sectors, if (0 != VbExDiskRead(params->disk_handle, part_start,
kbuf)) { kbuf_sectors, kbuf)) {
VBDEBUG(("Unable to read start of partition.\n")); VBDEBUG(("Unable to read start of partition.\n"));
shpart->check_result = VBSD_LKP_CHECK_READ_START; shpart->check_result = VBSD_LKP_CHECK_READ_START;
goto bad_kernel; goto bad_kernel;
@@ -288,27 +309,36 @@ VbError_t LoadKernel(LoadKernelParams* params) {
#else #else
/* Verify the key block. */ /* Verify the key block. */
key_block = (VbKeyBlockHeader*)kbuf; key_block = (VbKeyBlockHeader*)kbuf;
if (0 != KeyBlockVerify(key_block, KBUF_SIZE, kernel_subkey, 0)) { if (0 != KeyBlockVerify(key_block, KBUF_SIZE,
kernel_subkey, 0)) {
VBDEBUG(("Verifying key block signature failed.\n")); VBDEBUG(("Verifying key block signature failed.\n"));
shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_SIG; shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_SIG;
key_block_valid = 0; key_block_valid = 0;
/* If we're not in developer mode, this kernel is bad. */ /* If not in developer mode, this kernel is bad. */
if (kBootDev != boot_mode) if (kBootDev != boot_mode)
goto bad_kernel; goto bad_kernel;
/* In developer mode, we can explictly disallow self-signed kernels */ /*
* In developer mode, we can explictly disallow
* self-signed kernels
*/
if (require_official_os) { if (require_official_os) {
VBDEBUG(("Self-signed custom kernels are not enabled.\n")); VBDEBUG(("Self-signed kernels not enabled.\n"));
shpart->check_result = VBSD_LKP_CHECK_SELF_SIGNED; shpart->check_result =
VBSD_LKP_CHECK_SELF_SIGNED;
goto bad_kernel; goto bad_kernel;
} }
/* Allow the kernel if the SHA-512 hash of the key block is valid. */ /*
if (0 != KeyBlockVerify(key_block, KBUF_SIZE, kernel_subkey, 1)) { * Allow the kernel if the SHA-512 hash of the key
* block is valid.
*/
if (0 != KeyBlockVerify(key_block, KBUF_SIZE,
kernel_subkey, 1)) {
VBDEBUG(("Verifying key block hash failed.\n")); VBDEBUG(("Verifying key block hash failed.\n"));
shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_HASH; shpart->check_result =
VBSD_LKP_CHECK_KEY_BLOCK_HASH;
goto bad_kernel; goto bad_kernel;
} }
} }
@@ -334,25 +364,30 @@ VbError_t LoadKernel(LoadKernelParams* params) {
if (kBootRecovery != boot_mode) { if (kBootRecovery != boot_mode) {
if (key_version < (shared->kernel_version_tpm >> 16)) { if (key_version < (shared->kernel_version_tpm >> 16)) {
VBDEBUG(("Key version too old.\n")); VBDEBUG(("Key version too old.\n"));
shpart->check_result = VBSD_LKP_CHECK_KEY_ROLLBACK; shpart->check_result =
VBSD_LKP_CHECK_KEY_ROLLBACK;
key_block_valid = 0; key_block_valid = 0;
} }
if (key_version > 0xFFFF) { if (key_version > 0xFFFF) {
/* Key version is stored in 16 bits in the TPM, so key versions /*
* greater than 0xFFFF can't be stored properly. */ * Key version is stored in 16 bits in the TPM,
* so key versions greater than 0xFFFF can't be
* stored properly.
*/
VBDEBUG(("Key version > 0xFFFF.\n")); VBDEBUG(("Key version > 0xFFFF.\n"));
shpart->check_result = VBSD_LKP_CHECK_KEY_ROLLBACK; shpart->check_result =
VBSD_LKP_CHECK_KEY_ROLLBACK;
key_block_valid = 0; key_block_valid = 0;
} }
} }
/* If we're not in developer mode, require the key block to be valid. */ /* If not in developer mode, key block required to be valid. */
if (kBootDev != boot_mode && !key_block_valid) { if (kBootDev != boot_mode && !key_block_valid) {
VBDEBUG(("Key block is invalid.\n")); VBDEBUG(("Key block is invalid.\n"));
goto bad_kernel; goto bad_kernel;
} }
/* Get the key for preamble/data verification from the key block. */ /* Get key for preamble/data verification from the key block. */
data_key = PublicKeyToRSA(&key_block->data_key); data_key = PublicKeyToRSA(&key_block->data_key);
if (!data_key) { if (!data_key) {
VBDEBUG(("Data key bad.\n")); VBDEBUG(("Data key bad.\n"));
@@ -361,8 +396,10 @@ VbError_t LoadKernel(LoadKernelParams* params) {
} }
/* Verify the preamble, which follows the key block */ /* Verify the preamble, which follows the key block */
preamble = (VbKernelPreambleHeader*)(kbuf + key_block->key_block_size); preamble = (VbKernelPreambleHeader *)
if ((0 != VerifyKernelPreamble(preamble, (kbuf + key_block->key_block_size);
if ((0 != VerifyKernelPreamble(
preamble,
KBUF_SIZE - key_block->key_block_size, KBUF_SIZE - key_block->key_block_size,
data_key))) { data_key))) {
VBDEBUG(("Preamble verification failed.\n")); VBDEBUG(("Preamble verification failed.\n"));
@@ -370,16 +407,23 @@ VbError_t LoadKernel(LoadKernelParams* params) {
goto bad_kernel; goto bad_kernel;
} }
/* If the key block is valid and we're not in recovery mode, check for /*
* rollback of the kernel version. */ * If the key block is valid and we're not in recovery mode,
combined_version = (uint32_t)((key_version << 16) | * check for rollback of the kernel version.
*/
combined_version = (uint32_t)(
(key_version << 16) |
(preamble->kernel_version & 0xFFFF)); (preamble->kernel_version & 0xFFFF));
shpart->combined_version = combined_version; shpart->combined_version = combined_version;
if (key_block_valid && kBootRecovery != boot_mode) { if (key_block_valid && kBootRecovery != boot_mode) {
if (combined_version < shared->kernel_version_tpm) { if (combined_version < shared->kernel_version_tpm) {
VBDEBUG(("Kernel version too low.\n")); VBDEBUG(("Kernel version too low.\n"));
shpart->check_result = VBSD_LKP_CHECK_KERNEL_ROLLBACK; shpart->check_result =
/* If we're not in developer mode, kernel version must be valid. */ VBSD_LKP_CHECK_KERNEL_ROLLBACK;
/*
* If not in developer mode, kernel version
* must be valid.
*/
if (kBootDev != boot_mode) if (kBootDev != boot_mode)
goto bad_kernel; goto bad_kernel;
} }
@@ -393,34 +437,43 @@ VbError_t LoadKernel(LoadKernelParams* params) {
lowest_version = combined_version; lowest_version = combined_version;
else { else {
VBDEBUG(("Key block valid: %d\n", key_block_valid)); VBDEBUG(("Key block valid: %d\n", key_block_valid));
VBDEBUG(("Combined version: %u\n", (unsigned) combined_version)); VBDEBUG(("Combined version: %u\n",
(unsigned) combined_version));
} }
/* If we already have a good kernel, no need to read another /*
* If we already have a good kernel, no need to read another
* one; we only needed to look at the versions to check for * one; we only needed to look at the versions to check for
* rollback. So skip to the next kernel preamble. */ * rollback. So skip to the next kernel preamble.
*/
if (-1 != good_partition) if (-1 != good_partition)
continue; continue;
/* Verify kernel body starts at a multiple of the sector size. */ /* Verify kernel body starts at multiple of sector size. */
body_offset = key_block->key_block_size + preamble->preamble_size; body_offset = key_block->key_block_size +
preamble->preamble_size;
if (0 != body_offset % blba) { if (0 != body_offset % blba) {
VBDEBUG(("Kernel body not at multiple of sector size.\n")); VBDEBUG(("Kernel body not at multiple of "
"sector size.\n"));
shpart->check_result = VBSD_LKP_CHECK_BODY_OFFSET; shpart->check_result = VBSD_LKP_CHECK_BODY_OFFSET;
goto bad_kernel; goto bad_kernel;
} }
body_offset_sectors = body_offset / blba; body_offset_sectors = body_offset / blba;
body_sectors = (preamble->body_signature.data_size + blba - 1) / blba; body_sectors =
(preamble->body_signature.data_size + blba - 1) / blba;
if (!params->kernel_buffer) { if (!params->kernel_buffer) {
/* Get kernel load address and size from the header. */ /* Get kernel load address and size from the header. */
params->kernel_buffer = (void*) ((long)preamble->body_load_address); params->kernel_buffer =
(void *)((long)preamble->body_load_address);
params->kernel_buffer_size = body_sectors * blba; params->kernel_buffer_size = body_sectors * blba;
} else { } else {
/* Verify kernel body fits in the buffer */ /* Verify kernel body fits in the buffer */
if (body_sectors * blba > params->kernel_buffer_size) { if (body_sectors * blba > params->kernel_buffer_size) {
VBDEBUG(("Kernel body doesn't fit in memory.\n")); VBDEBUG(("Kernel body doesn't "
shpart->check_result = VBSD_LKP_CHECK_BODY_EXCEEDS_MEM; "fit in memory.\n"));
shpart->check_result =
VBSD_LKP_CHECK_BODY_EXCEEDS_MEM;
goto bad_kernel; goto bad_kernel;
} }
} }
@@ -458,21 +511,28 @@ VbError_t LoadKernel(LoadKernelParams* params) {
data_key = NULL; data_key = NULL;
#endif #endif
/* If we're still here, the kernel is valid. */ /*
/* Save the first good partition we find; that's the one we'll boot */ * If we're still here, the kernel is valid. Save the first
* good partition we find; that's the one we'll boot.
*/
VBDEBUG(("Partition is good.\n")); VBDEBUG(("Partition is good.\n"));
shpart->check_result = VBSD_LKP_CHECK_KERNEL_GOOD; shpart->check_result = VBSD_LKP_CHECK_KERNEL_GOOD;
if (key_block_valid) if (key_block_valid)
shpart->flags |= VBSD_LKP_FLAG_KEY_BLOCK_VALID; shpart->flags |= VBSD_LKP_FLAG_KEY_BLOCK_VALID;
good_partition_key_block_valid = key_block_valid; good_partition_key_block_valid = key_block_valid;
/* TODO: GPT partitions start at 1, but cgptlib starts them at 0. /*
* Adjust here, until cgptlib is fixed. */ * TODO: GPT partitions start at 1, but cgptlib starts them at
* 0. Adjust here, until cgptlib is fixed.
*/
good_partition = gpt.current_kernel + 1; good_partition = gpt.current_kernel + 1;
params->partition_number = gpt.current_kernel + 1; params->partition_number = gpt.current_kernel + 1;
GetCurrentKernelUniqueGuid(&gpt, &params->partition_guid); GetCurrentKernelUniqueGuid(&gpt, &params->partition_guid);
/* TODO: GetCurrentKernelUniqueGuid() should take a destination size, or /*
* the dest should be a struct, so we know it's big enough. */ * TODO: GetCurrentKernelUniqueGuid() should take a destination
* size, or the dest should be a struct, so we know it's big
* enough.
*/
#if defined(CONFIG_SANDBOX) #if defined(CONFIG_SANDBOX)
params->bootloader_address = 0; params->bootloader_address = 0;
params->bootloader_size = 0; params->bootloader_size = 0;
@@ -484,18 +544,23 @@ VbError_t LoadKernel(LoadKernelParams* params) {
/* Update GPT to note this is the kernel we're trying */ /* Update GPT to note this is the kernel we're trying */
GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_TRY); GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_TRY);
/* If we're in recovery mode or we're about to boot a dev-signed kernel, /*
* there's no rollback protection, so we can stop at the first valid * If we're in recovery mode or we're about to boot a
* kernel. */ * dev-signed kernel, there's no rollback protection, so we can
* stop at the first valid kernel.
*/
if (kBootRecovery == boot_mode || !key_block_valid) { if (kBootRecovery == boot_mode || !key_block_valid) {
VBDEBUG(("In recovery mode or dev-signed kernel\n")); VBDEBUG(("In recovery mode or dev-signed kernel\n"));
break; break;
} }
/* Otherwise, we do care about the key index in the TPM. If the good /*
* partition's key version is the same as the tpm, then the TPM doesn't * Otherwise, we do care about the key index in the TPM. If
* need updating; we can stop now. Otherwise, we'll check all the other * the good partition's key version is the same as the tpm,
* headers to see if they contain a newer key. */ * then the TPM doesn't need updating; we can stop now.
* Otherwise, we'll check all the other headers to see if they
* contain a newer key.
*/
if (combined_version == shared->kernel_version_tpm) { if (combined_version == shared->kernel_version_tpm) {
VBDEBUG(("Same kernel version\n")); VBDEBUG(("Same kernel version\n"));
break; break;
@@ -529,9 +594,12 @@ VbError_t LoadKernel(LoadKernelParams* params) {
VBDEBUG(("Good_partition >= 0\n")); VBDEBUG(("Good_partition >= 0\n"));
shcall->check_result = VBSD_LKC_CHECK_GOOD_PARTITION; shcall->check_result = VBSD_LKC_CHECK_GOOD_PARTITION;
shared->kernel_version_lowest = lowest_version; shared->kernel_version_lowest = lowest_version;
/* Sanity check - only store a new TPM version if we found one. /*
* If lowest_version is still at its initial value, we didn't find * Sanity check - only store a new TPM version if we found one.
* one; for example, we're in developer mode and just didn't look. */ * If lowest_version is still at its initial value, we didn't
* find one; for example, we're in developer mode and just
* didn't look.
*/
if (lowest_version != LOWEST_TPM_VERSION && if (lowest_version != LOWEST_TPM_VERSION &&
lowest_version > shared->kernel_version_tpm) lowest_version > shared->kernel_version_tpm)
shared->kernel_version_tpm = lowest_version; shared->kernel_version_tpm = lowest_version;
@@ -554,8 +622,10 @@ LoadKernelExit:
VbNvSet(vnc, VBNV_RECOVERY_REQUEST, VBERROR_SUCCESS != retval ? VbNvSet(vnc, VBNV_RECOVERY_REQUEST, VBERROR_SUCCESS != retval ?
recovery : VBNV_RECOVERY_NOT_REQUESTED); recovery : VBNV_RECOVERY_NOT_REQUESTED);
/* If LoadKernel was called with bad parameters, /*
* shcall may not be initialized. */ * If LoadKernel() was called with bad parameters, shcall may not be
* initialized.
*/
if (shcall) if (shcall)
shcall->return_code = (uint8_t)retval; shcall->return_code = (uint8_t)retval;

View File

@@ -1,4 +1,4 @@
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. /* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be * Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. * found in the LICENSE file.
*/ */
@@ -11,9 +11,10 @@
#include "vboot_common.h" #include "vboot_common.h"
#include "vboot_nvstorage.h" #include "vboot_nvstorage.h"
/* Constants for NV storage. We use this rather than structs and /*
* bitfields so the data format is consistent across platforms and * Constants for NV storage. We use this rather than structs and bitfields so
* compilers. */ * the data format is consistent across platforms and compilers.
*/
#define HEADER_OFFSET 0 #define HEADER_OFFSET 0
#define HEADER_MASK 0xC0 #define HEADER_MASK 0xC0
#define HEADER_SIGNATURE 0x40 #define HEADER_SIGNATURE 0x40
@@ -43,8 +44,8 @@
#define KERNEL_FIELD_OFFSET 11 #define KERNEL_FIELD_OFFSET 11
#define CRC_OFFSET 15 #define CRC_OFFSET 15
int VbNvSetup(VbNvContext *context)
int VbNvSetup(VbNvContext* context) { {
uint8_t *raw = context->raw; uint8_t *raw = context->raw;
/* Nothing has changed yet. */ /* Nothing has changed yet. */
@@ -54,10 +55,10 @@ int VbNvSetup(VbNvContext* context) {
/* Check data for consistency */ /* Check data for consistency */
if ((HEADER_SIGNATURE != (raw[HEADER_OFFSET] & HEADER_MASK)) if ((HEADER_SIGNATURE != (raw[HEADER_OFFSET] & HEADER_MASK))
|| (Crc8(raw, CRC_OFFSET) != raw[CRC_OFFSET])) { || (Crc8(raw, CRC_OFFSET) != raw[CRC_OFFSET])) {
/* Data is inconsistent (bad CRC or header); reset defaults */
/* Data is inconsistent (bad CRC or header), so reset defaults */
Memset(raw, 0, VBNV_BLOCK_SIZE); Memset(raw, 0, VBNV_BLOCK_SIZE);
raw[HEADER_OFFSET] = (HEADER_SIGNATURE | HEADER_FIRMWARE_SETTINGS_RESET | raw[HEADER_OFFSET] = (HEADER_SIGNATURE |
HEADER_FIRMWARE_SETTINGS_RESET |
HEADER_KERNEL_SETTINGS_RESET); HEADER_KERNEL_SETTINGS_RESET);
/* Regenerate CRC on exit */ /* Regenerate CRC on exit */
@@ -67,9 +68,8 @@ int VbNvSetup(VbNvContext* context) {
return 0; return 0;
} }
int VbNvTeardown(VbNvContext *context)
int VbNvTeardown(VbNvContext* context) { {
if (context->regenerate_crc) { if (context->regenerate_crc) {
context->raw[CRC_OFFSET] = Crc8(context->raw, CRC_OFFSET); context->raw[CRC_OFFSET] = Crc8(context->raw, CRC_OFFSET);
context->regenerate_crc = 0; context->regenerate_crc = 0;
@@ -79,17 +79,19 @@ int VbNvTeardown(VbNvContext* context) {
return 0; return 0;
} }
int VbNvGet(VbNvContext *context, VbNvParam param, uint32_t *dest)
int VbNvGet(VbNvContext* context, VbNvParam param, uint32_t* dest) { {
const uint8_t *raw = context->raw; const uint8_t *raw = context->raw;
switch (param) { switch (param) {
case VBNV_FIRMWARE_SETTINGS_RESET: case VBNV_FIRMWARE_SETTINGS_RESET:
*dest = (raw[HEADER_OFFSET] & HEADER_FIRMWARE_SETTINGS_RESET ? 1 : 0); *dest = (raw[HEADER_OFFSET] & HEADER_FIRMWARE_SETTINGS_RESET ?
1 : 0);
return 0; return 0;
case VBNV_KERNEL_SETTINGS_RESET: case VBNV_KERNEL_SETTINGS_RESET:
*dest = (raw[HEADER_OFFSET] & HEADER_KERNEL_SETTINGS_RESET ? 1 : 0); *dest = (raw[HEADER_OFFSET] & HEADER_KERNEL_SETTINGS_RESET ?
1 : 0);
return 0; return 0;
case VBNV_DEBUG_RESET_MODE: case VBNV_DEBUG_RESET_MODE:
@@ -128,7 +130,8 @@ int VbNvGet(VbNvContext* context, VbNvParam param, uint32_t* dest) {
return 0; return 0;
case VBNV_DEV_BOOT_SIGNED_ONLY: case VBNV_DEV_BOOT_SIGNED_ONLY:
*dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_SIGNED_ONLY_MASK ? 1 : 0); *dest = (raw[DEV_FLAGS_OFFSET] & DEV_BOOT_SIGNED_ONLY_MASK ?
1 : 0);
return 0; return 0;
case VBNV_DISABLE_DEV_REQUEST: case VBNV_DISABLE_DEV_REQUEST:
@@ -140,7 +143,8 @@ int VbNvGet(VbNvContext* context, VbNvParam param, uint32_t* dest) {
return 0; return 0;
case VBNV_CLEAR_TPM_OWNER_REQUEST: case VBNV_CLEAR_TPM_OWNER_REQUEST:
*dest = (raw[TPM_FLAGS_OFFSET] & TPM_CLEAR_OWNER_REQUEST ? 1 : 0); *dest = (raw[TPM_FLAGS_OFFSET] & TPM_CLEAR_OWNER_REQUEST ?
1 : 0);
return 0; return 0;
case VBNV_CLEAR_TPM_OWNER_DONE: case VBNV_CLEAR_TPM_OWNER_DONE:
@@ -152,12 +156,12 @@ int VbNvGet(VbNvContext* context, VbNvParam param, uint32_t* dest) {
} }
} }
int VbNvSet(VbNvContext *context, VbNvParam param, uint32_t value)
int VbNvSet(VbNvContext* context, VbNvParam param, uint32_t value) { {
uint8_t *raw = context->raw; uint8_t *raw = context->raw;
uint32_t current; uint32_t current;
/* If we're not changing the value, we don't need to regenerate the CRC. */ /* If not changing the value, don't regenerate the CRC. */
if (0 == VbNvGet(context, param, &current) && current == value) if (0 == VbNvGet(context, param, &current) && current == value)
return 0; return 0;
@@ -193,8 +197,11 @@ int VbNvSet(VbNvContext* context, VbNvParam param, uint32_t value) {
break; break;
case VBNV_RECOVERY_REQUEST: case VBNV_RECOVERY_REQUEST:
/* Map values outside the valid range to the legacy reason, since we /*
* can't determine if we're called from kernel or user mode. */ * Map values outside the valid range to the legacy reason,
* since we can't determine if we're called from kernel or user
* mode.
*/
if (value > 0xFF) if (value > 0xFF)
value = VBNV_RECOVERY_LEGACY; value = VBNV_RECOVERY_LEGACY;
raw[RECOVERY_OFFSET] = (uint8_t)value; raw[RECOVERY_OFFSET] = (uint8_t)value;