summaryrefslogtreecommitdiff
path: root/src/vendorcode
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode')
-rw-r--r--src/vendorcode/google/chromeos/Makefile.inc1
-rw-r--r--src/vendorcode/google/chromeos/antirollback.c602
-rw-r--r--src/vendorcode/google/chromeos/vboot_main.c81
3 files changed, 188 insertions, 496 deletions
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index cb3d9a68b8..4438a92545 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -101,6 +101,7 @@ VERSTAGE_LIB = $(obj)/vendorcode/google/chromeos/verstage.a
INCLUDES += -I$(VB_SOURCE)/firmware/2lib/include
INCLUDES += -I$(VB_SOURCE)/firmware/include
verstage-y += vboot_main.c fmap.c chromeos.c
+verstage-y += antirollback.c vbnv_ec.c
VB_FIRMWARE_ARCH := $(ARCHDIR-$(ARCH-VERSTAGE-y))
VB2_LIB = $(obj)/external/vboot_reference/vboot_fw2.a
diff --git a/src/vendorcode/google/chromeos/antirollback.c b/src/vendorcode/google/chromeos/antirollback.c
index 306e90329b..020a06abb2 100644
--- a/src/vendorcode/google/chromeos/antirollback.c
+++ b/src/vendorcode/google/chromeos/antirollback.c
@@ -6,261 +6,118 @@
* stored in the TPM NVRAM.
*/
-#include "sysincludes.h"
-
-#include "crc8.h"
-#include "rollback_index.h"
-#include "tlcl.h"
-#include "tss_constants.h"
-#include "utility.h"
-#include "vboot_api.h"
+#include <2api.h>
+#include <2sysincludes.h>
+#include <antirollback.h>
+#include <tpm_lite/tlcl.h>
+#include <tpm_lite/tss_constants.h>
#ifndef offsetof
#define offsetof(A,B) __builtin_offsetof(A,B)
#endif
-/*
- * Provide protoypes for functions not in the header file. These prototypes
- * fix -Wmissing-prototypes warnings.
- */
-uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf);
-uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf);
-uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk);
-uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk);
-
#ifdef FOR_TEST
-/*
- * Compiling for unit test, so we need the real implementations of
- * rollback functions. The unit test mocks the underlying tlcl
- * functions, so this is ok to run on the host.
- */
-#undef CHROMEOS_ENVIRONMENT
-#undef DISABLE_ROLLBACK_TPM
+#include <stdio.h>
+#define VBDEBUG(format, args...) printf(format, ## args)
+#else
+#include <console/console.h>
+#define VBDEBUG(format, args...) \
+ printk(BIOS_INFO, "%s():%d: " format, __func__, __LINE__, ## args)
#endif
-#define RETURN_ON_FAILURE(tpm_command) do { \
+#define RETURN_ON_FAILURE(tpm_cmd) do { \
uint32_t result_; \
- if ((result_ = (tpm_command)) != TPM_SUCCESS) { \
- VBDEBUG(("Rollback: %08x returned by " #tpm_command \
- "\n", (int)result_)); \
+ if ((result_ = (tpm_cmd)) != TPM_SUCCESS) { \
+ VBDEBUG("Antirollback: %08x returned by " #tpm_cmd \
+ "\n", (int)result_); \
return result_; \
} \
} while (0)
-uint32_t TPMClearAndReenable(void)
+uint32_t tpm_clear_and_reenable(void)
{
- VBDEBUG(("TPM: Clear and re-enable\n"));
- RETURN_ON_FAILURE(TlclForceClear());
- RETURN_ON_FAILURE(TlclSetEnable());
- RETURN_ON_FAILURE(TlclSetDeactivated(0));
+ VBDEBUG("TPM: Clear and re-enable\n");
+ RETURN_ON_FAILURE(tlcl_force_clear());
+ RETURN_ON_FAILURE(tlcl_set_enable());
+ RETURN_ON_FAILURE(tlcl_set_deactivated(0));
return TPM_SUCCESS;
}
-uint32_t SafeWrite(uint32_t index, const void *data, uint32_t length)
+uint32_t safe_write(uint32_t index, const void *data, uint32_t length)
{
- uint32_t result = TlclWrite(index, data, length);
+ uint32_t result = tlcl_write(index, data, length);
if (result == TPM_E_MAXNVWRITES) {
- RETURN_ON_FAILURE(TPMClearAndReenable());
- return TlclWrite(index, data, length);
+ RETURN_ON_FAILURE(tpm_clear_and_reenable());
+ return tlcl_write(index, data, length);
} else {
return result;
}
}
-uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size)
+uint32_t safe_define_space(uint32_t index, uint32_t perm, uint32_t size)
{
- uint32_t result = TlclDefineSpace(index, perm, size);
+ uint32_t result = tlcl_define_space(index, perm, size);
if (result == TPM_E_MAXNVWRITES) {
- RETURN_ON_FAILURE(TPMClearAndReenable());
- return TlclDefineSpace(index, perm, size);
+ RETURN_ON_FAILURE(tpm_clear_and_reenable());
+ return tlcl_define_space(index, perm, size);
} else {
return result;
}
}
-/* Functions to read and write firmware and kernel spaces. */
-uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf)
+static uint32_t read_space_firmware(struct vb2_context *ctx)
{
- uint32_t r;
int attempts = 3;
while (attempts--) {
- r = TlclRead(FIRMWARE_NV_INDEX, rsf,
- sizeof(RollbackSpaceFirmware));
- if (r != TPM_SUCCESS)
- return r;
-
- /*
- * No CRC in this version, so we'll create one when we write
- * it. Note that we're marking this as version 2, not
- * ROLLBACK_SPACE_FIRMWARE_VERSION, because version 2 just
- * added the CRC. Later versions will need to set default
- * values for any extra fields explicitly (probably here).
- */
- if (rsf->struct_version < 2) {
- /* Danger Will Robinson! Danger! */
- rsf->struct_version = 2;
- return TPM_SUCCESS;
- }
+ RETURN_ON_FAILURE(tlcl_read(FIRMWARE_NV_INDEX, ctx->secdata,
+ VB2_SECDATA_SIZE));
- /*
- * If the CRC is good, we're done. If it's bad, try a couple
- * more times to see if it gets better before we give up. It
- * could just be noise.
- */
- if (rsf->crc8 == Crc8(rsf,
- offsetof(RollbackSpaceFirmware, crc8)))
+ if (vb2api_secdata_check(ctx) == VB2_SUCCESS)
return TPM_SUCCESS;
- VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
+ VBDEBUG("TPM: %s() - bad CRC\n", __func__);
}
- VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
+ VBDEBUG("TPM: %s() - too many bad CRCs, giving up\n", __func__);
return TPM_E_CORRUPTED_STATE;
}
-uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf)
+static uint32_t write_space_firmware(struct vb2_context *ctx)
{
- RollbackSpaceFirmware rsf2;
+ uint8_t secdata[VB2_SECDATA_SIZE];
uint32_t r;
int attempts = 3;
- /* All writes should use struct_version 2 or greater. */
- if (rsf->struct_version < 2)
- rsf->struct_version = 2;
- rsf->crc8 = Crc8(rsf, offsetof(RollbackSpaceFirmware, crc8));
-
+ memcpy(secdata, ctx->secdata, VB2_SECDATA_SIZE);
while (attempts--) {
- r = SafeWrite(FIRMWARE_NV_INDEX, rsf,
- sizeof(RollbackSpaceFirmware));
+ r = safe_write(FIRMWARE_NV_INDEX, secdata, VB2_SECDATA_SIZE);
/* Can't write, not gonna try again */
if (r != TPM_SUCCESS)
return r;
/* Read it back to be sure it got the right values. */
- r = ReadSpaceFirmware(&rsf2); /* This checks the CRC */
- if (r == TPM_SUCCESS)
+ r = read_space_firmware(ctx);
+ if (r == TPM_SUCCESS && memcmp(secdata, ctx->secdata,
+ VB2_SECDATA_SIZE) == 0)
return r;
- VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
+ VBDEBUG("TPM: %s() failed\n", __func__);
/* Try writing it again. Maybe it was garbled on the way out. */
}
- VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
+ VBDEBUG("TPM: %s() - too many failures, giving up\n", __func__);
return TPM_E_CORRUPTED_STATE;
}
-uint32_t SetVirtualDevMode(int val)
+uint32_t factory_initialize_tpm(struct vb2_context *ctx)
{
- RollbackSpaceFirmware rsf;
-
- VBDEBUG(("TPM: Entering %s()\n", __func__));
- if (TPM_SUCCESS != ReadSpaceFirmware(&rsf))
- return VBERROR_TPM_FIRMWARE_SETUP;
-
- VBDEBUG(("TPM: flags were 0x%02x\n", rsf.flags));
- if (val)
- rsf.flags |= FLAG_VIRTUAL_DEV_MODE_ON;
- else
- rsf.flags &= ~FLAG_VIRTUAL_DEV_MODE_ON;
- /*
- * NOTE: This doesn't update the FLAG_LAST_BOOT_DEVELOPER bit. That
- * will be done by SetupTPM() on the next boot.
- */
- VBDEBUG(("TPM: flags are now 0x%02x\n", rsf.flags));
-
- if (TPM_SUCCESS != WriteSpaceFirmware(&rsf))
- return VBERROR_TPM_SET_BOOT_MODE_STATE;
-
- VBDEBUG(("TPM: Leaving %s()\n", __func__));
- return VBERROR_SUCCESS;
-}
-
-uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk)
-{
- uint32_t r;
- int attempts = 3;
-
- while (attempts--) {
- r = TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
- if (r != TPM_SUCCESS)
- return r;
-
- /*
- * No CRC in this version, so we'll create one when we write
- * it. Note that we're marking this as version 2, not
- * ROLLBACK_SPACE_KERNEL_VERSION, because version 2 just added
- * the CRC. Later versions will need to set default values for
- * any extra fields explicitly (probably here).
- */
- if (rsk->struct_version < 2) {
- /* Danger Will Robinson! Danger! */
- rsk->struct_version = 2;
- return TPM_SUCCESS;
- }
-
- /*
- * If the CRC is good, we're done. If it's bad, try a couple
- * more times to see if it gets better before we give up. It
- * could just be noise.
- */
- if (rsk->crc8 == Crc8(rsk, offsetof(RollbackSpaceKernel, crc8)))
- return TPM_SUCCESS;
-
- VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
- }
-
- VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
- return TPM_E_CORRUPTED_STATE;
-}
-
-uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk)
-{
- RollbackSpaceKernel rsk2;
- uint32_t r;
- int attempts = 3;
-
- /* All writes should use struct_version 2 or greater. */
- if (rsk->struct_version < 2)
- rsk->struct_version = 2;
- rsk->crc8 = Crc8(rsk, offsetof(RollbackSpaceKernel, crc8));
-
- while (attempts--) {
- r = SafeWrite(KERNEL_NV_INDEX, rsk,
- sizeof(RollbackSpaceKernel));
- /* Can't write, not gonna try again */
- if (r != TPM_SUCCESS)
- return r;
-
- /* Read it back to be sure it got the right values. */
- r = ReadSpaceKernel(&rsk2); /* This checks the CRC */
- if (r == TPM_SUCCESS)
- return r;
-
- VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
- /* Try writing it again. Maybe it was garbled on the way out. */
- }
-
- VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
- return TPM_E_CORRUPTED_STATE;
-}
-
-uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf,
- RollbackSpaceKernel *rsk)
-{
- static const RollbackSpaceFirmware rsf_init = {
- .struct_version = ROLLBACK_SPACE_FIRMWARE_VERSION,
- };
- static const RollbackSpaceKernel rsk_init = {
- .struct_version = ROLLBACK_SPACE_KERNEL_VERSION,
- .uid = ROLLBACK_SPACE_KERNEL_UID,
- };
TPM_PERMANENT_FLAGS pflags;
uint32_t result;
- VBDEBUG(("TPM: One-time initialization\n"));
+ VBDEBUG("TPM: factory initialization\n");
/*
* Do a full test. This only happens the first time the device is
@@ -270,11 +127,11 @@ uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf,
* test---specifically the ones that set lifetime flags, and are only
* executed once per physical TPM.
*/
- result = TlclSelfTestFull();
+ result = tlcl_self_test_full();
if (result != TPM_SUCCESS)
return result;
- result = TlclGetPermanentFlags(&pflags);
+ result = tlcl_get_permanent_flags(&pflags);
if (result != TPM_SUCCESS)
return result;
@@ -282,11 +139,11 @@ uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf,
* TPM may come from the factory without physical presence finalized.
* Fix if necessary.
*/
- VBDEBUG(("TPM: physicalPresenceLifetimeLock=%d\n",
- pflags.physicalPresenceLifetimeLock));
+ VBDEBUG("TPM: physicalPresenceLifetimeLock=%d\n",
+ pflags.physicalPresenceLifetimeLock);
if (!pflags.physicalPresenceLifetimeLock) {
- VBDEBUG(("TPM: Finalizing physical presence\n"));
- RETURN_ON_FAILURE(TlclFinalizePhysicalPresence());
+ VBDEBUG("TPM: Finalizing physical presence\n");
+ RETURN_ON_FAILURE(tlcl_finalize_physical_presence());
}
/*
@@ -294,40 +151,27 @@ uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf,
* execution of a TPM_NV_DefineSpace with the handle of
* TPM_NV_INDEX_LOCK. Here we create that space if it doesn't already
* exist. */
- VBDEBUG(("TPM: nvLocked=%d\n", pflags.nvLocked));
+ VBDEBUG("TPM: nvLocked=%d\n", pflags.nvLocked);
if (!pflags.nvLocked) {
- VBDEBUG(("TPM: Enabling NV locking\n"));
- RETURN_ON_FAILURE(TlclSetNvLocked());
+ VBDEBUG("TPM: Enabling NV locking\n");
+ RETURN_ON_FAILURE(tlcl_set_nv_locked());
}
/* Clear TPM owner, in case the TPM is already owned for some reason. */
- VBDEBUG(("TPM: Clearing owner\n"));
- RETURN_ON_FAILURE(TPMClearAndReenable());
-
- /* Initializes the firmware and kernel spaces */
- Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware));
- Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel));
+ VBDEBUG("TPM: Clearing owner\n");
+ RETURN_ON_FAILURE(tpm_clear_and_reenable());
- /* Define the backup space. No need to initialize it, though. */
- RETURN_ON_FAILURE(SafeDefineSpace(
- BACKUP_NV_INDEX, TPM_NV_PER_PPWRITE, BACKUP_NV_SIZE));
-
- /* Define and initialize the kernel space */
- RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE,
- sizeof(RollbackSpaceKernel)));
- RETURN_ON_FAILURE(WriteSpaceKernel(rsk));
-
- /* Do the firmware space last, so we retry if we don't get this far. */
- RETURN_ON_FAILURE(SafeDefineSpace(
- FIRMWARE_NV_INDEX,
- TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE,
- sizeof(RollbackSpaceFirmware)));
- RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
+ /* Defines and sets vb2 secdata space */
+ vb2api_secdata_create(ctx);
+ RETURN_ON_FAILURE(safe_define_space(FIRMWARE_NV_INDEX,
+ TPM_NV_PER_GLOBALLOCK |
+ TPM_NV_PER_PPWRITE,
+ VB2_SECDATA_SIZE));
+ RETURN_ON_FAILURE(write_space_firmware(ctx));
return TPM_SUCCESS;
}
-
/*
* SetupTPM starts the TPM and establishes the root of trust for the
* anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a
@@ -348,329 +192,107 @@ uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf,
* to the TPM flashram at every reboot or wake-up, because of concerns about
* the durability of the NVRAM.
*/
-uint32_t SetupTPM(int developer_mode, int disable_dev_request,
- int clear_tpm_owner_request, RollbackSpaceFirmware* rsf)
+uint32_t setup_tpm(struct vb2_context *ctx)
{
- uint8_t in_flags;
uint8_t disable;
uint8_t deactivated;
uint32_t result;
- uint32_t versions;
- RETURN_ON_FAILURE(TlclLibInit());
+ RETURN_ON_FAILURE(tlcl_lib_init());
#ifdef TEGRA_SOFT_REBOOT_WORKAROUND
- result = TlclStartup();
+ result = tlcl_startup();
if (result == TPM_E_INVALID_POSTINIT) {
/*
* Some prototype hardware doesn't reset the TPM on a CPU
* reset. We do a hard reset to get around this.
*/
- VBDEBUG(("TPM: soft reset detected\n", result));
+ VBDEBUG("TPM: soft reset detected\n", result);
return TPM_E_MUST_REBOOT;
} else if (result != TPM_SUCCESS) {
- VBDEBUG(("TPM: TlclStartup returned %08x\n", result));
+ VBDEBUG("TPM: tlcl_startup returned %08x\n", result);
return result;
}
#else
- RETURN_ON_FAILURE(TlclStartup());
+ RETURN_ON_FAILURE(tlcl_startup());
#endif
- /*
- * Some TPMs start the self test automatically at power on. In that case we
- * don't need to call ContinueSelfTest. On some (other) TPMs,
- * ContinueSelfTest may block. In that case, we definitely don't want to
- * call it here. For TPMs in the intersection of these two sets, we're
- * screwed. (In other words: TPMs that require manually starting the
- * self-test AND block will have poor performance until we split
- * TlclSendReceive() into Send() and Receive(), and have a state machine to
- * control setup.)
- *
- * This comment is likely to become obsolete in the near future, so don't
- * trust it. It may have not been updated.
- */
+ /*
+ * Some TPMs start the self test automatically at power on. In that case
+ * we don't need to call ContinueSelfTest. On some (other) TPMs,
+ * continue_self_test may block. In that case, we definitely don't want
+ * to call it here. For TPMs in the intersection of these two sets, we
+ * are screwed. (In other words: TPMs that require manually starting the
+ * self-test AND block will have poor performance until we split
+ * tlcl_send_receive() into send() and receive(), and have a state
+ * machine to control setup.)
+ *
+ * This comment is likely to become obsolete in the near future, so
+ * don't trust it. It may have not been updated.
+ */
#ifdef TPM_MANUAL_SELFTEST
#ifdef TPM_BLOCKING_CONTINUESELFTEST
#warning "lousy TPM!"
#endif
- RETURN_ON_FAILURE(TlclContinueSelfTest());
+ RETURN_ON_FAILURE(tlcl_continue_self_test());
#endif
- result = TlclAssertPhysicalPresence();
+ result = tlcl_assert_physical_presence();
if (result != TPM_SUCCESS) {
/*
* It is possible that the TPM was delivered with the physical
* presence command disabled. This tries enabling it, then
* tries asserting PP again.
*/
- RETURN_ON_FAILURE(TlclPhysicalPresenceCMDEnable());
- RETURN_ON_FAILURE(TlclAssertPhysicalPresence());
+ RETURN_ON_FAILURE(tlcl_physical_presence_cmd_enable());
+ RETURN_ON_FAILURE(tlcl_assert_physical_presence());
}
/* Check that the TPM is enabled and activated. */
- RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated, NULL));
+ RETURN_ON_FAILURE(tlcl_get_flags(&disable, &deactivated, NULL));
if (disable || deactivated) {
- VBDEBUG(("TPM: disabled (%d) or deactivated (%d). Fixing...\n",
- disable, deactivated));
- RETURN_ON_FAILURE(TlclSetEnable());
- RETURN_ON_FAILURE(TlclSetDeactivated(0));
- VBDEBUG(("TPM: Must reboot to re-enable\n"));
+ VBDEBUG("TPM: disabled (%d) or deactivated (%d). Fixing...\n",
+ disable, deactivated);
+ RETURN_ON_FAILURE(tlcl_set_enable());
+ RETURN_ON_FAILURE(tlcl_set_deactivated(0));
+ VBDEBUG("TPM: Must reboot to re-enable\n");
return TPM_E_MUST_REBOOT;
}
- /* Read the firmware space. */
- result = ReadSpaceFirmware(rsf);
- if (TPM_E_BADINDEX == result) {
- RollbackSpaceKernel rsk;
-
- /*
- * This is the first time we've run, and the TPM has not been
- * initialized. Initialize it.
- */
- VBDEBUG(("TPM: Not initialized yet.\n"));
- RETURN_ON_FAILURE(OneTimeInitializeTPM(rsf, &rsk));
- } else if (TPM_SUCCESS != result) {
- VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n"));
- return TPM_E_CORRUPTED_STATE;
- }
- Memcpy(&versions, &rsf->fw_versions, sizeof(versions));
- VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n",
- rsf->struct_version, rsf->flags, versions));
- in_flags = rsf->flags;
-
- /* If we've been asked to clear the virtual dev-mode flag, do so now */
- if (disable_dev_request) {
- rsf->flags &= ~FLAG_VIRTUAL_DEV_MODE_ON;
- VBDEBUG(("TPM: Clearing virt dev-switch: f%x\n", rsf->flags));
- }
-
- /*
- * The developer_mode value that's passed in is only set by a hardware
- * dev-switch. We should OR it with the virtual switch, whether or not
- * the virtual switch is used. If it's not used, it shouldn't change,
- * so it doesn't matter.
- */
- if (rsf->flags & FLAG_VIRTUAL_DEV_MODE_ON)
- developer_mode = 1;
-
- /*
- * Clear ownership if developer flag has toggled, or if an owner-clear
- * has been requested.
- */
- if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) !=
- (in_flags & FLAG_LAST_BOOT_DEVELOPER)) {
- VBDEBUG(("TPM: Developer flag changed; clearing owner.\n"));
- RETURN_ON_FAILURE(TPMClearAndReenable());
- } else if (clear_tpm_owner_request) {
- VBDEBUG(("TPM: Clearing owner as specifically requested.\n"));
- RETURN_ON_FAILURE(TPMClearAndReenable());
- }
-
- if (developer_mode)
- rsf->flags |= FLAG_LAST_BOOT_DEVELOPER;
- else
- rsf->flags &= ~FLAG_LAST_BOOT_DEVELOPER;
-
-
- /* If firmware space is dirty, flush it back to the TPM */
- if (rsf->flags != in_flags) {
- VBDEBUG(("TPM: Updating firmware space.\n"));
- RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
- }
-
- VBDEBUG(("TPM: SetupTPM() succeeded\n"));
- return TPM_SUCCESS;
-}
-
-
-#ifdef DISABLE_ROLLBACK_TPM
-/* Dummy implementations which don't support TPM rollback protection */
-
-uint32_t RollbackS3Resume(void)
-{
-#ifndef CHROMEOS_ENVIRONMENT
- /*
- * Initialize the TPM, but ignore return codes. In ChromeOS
- * environment, don't even talk to the TPM.
- */
- TlclLibInit();
- TlclResume();
-#endif
- return TPM_SUCCESS;
-}
-
-uint32_t RollbackFirmwareSetup(int is_hw_dev,
- int disable_dev_request,
- int clear_tpm_owner_request,
- int *is_virt_dev, uint32_t *version)
-{
-#ifndef CHROMEOS_ENVIRONMENT
- /*
- * Initialize the TPM, but ignores return codes. In ChromeOS
- * environment, don't even talk to the TPM.
- */
- TlclLibInit();
- TlclStartup();
- TlclContinueSelfTest();
-#endif
- *is_virt_dev = 0;
- *version = 0;
- return TPM_SUCCESS;
-}
-
-uint32_t RollbackFirmwareWrite(uint32_t version)
-{
- return TPM_SUCCESS;
-}
-
-uint32_t RollbackFirmwareLock(void)
-{
- return TPM_SUCCESS;
-}
-
-uint32_t RollbackKernelRead(uint32_t* version)
-{
- *version = 0;
- return TPM_SUCCESS;
-}
-
-uint32_t RollbackKernelWrite(uint32_t version)
-{
- return TPM_SUCCESS;
-}
-
-uint32_t RollbackBackupRead(uint8_t *raw)
-{
+ VBDEBUG("TPM: SetupTPM() succeeded\n");
return TPM_SUCCESS;
}
-uint32_t RollbackBackupWrite(uint8_t *raw)
+uint32_t antirollback_read_space_firmware(struct vb2_context *ctx)
{
- return TPM_SUCCESS;
-}
+ uint32_t rv;
-uint32_t RollbackKernelLock(int recovery_mode)
-{
- return TPM_SUCCESS;
-}
+ rv = setup_tpm(ctx);
+ if (rv)
+ return rv;
-#else
-
-uint32_t RollbackS3Resume(void)
-{
- uint32_t result;
- RETURN_ON_FAILURE(TlclLibInit());
- result = TlclResume();
- if (result == TPM_E_INVALID_POSTINIT) {
+ /* Read the firmware space. */
+ rv = read_space_firmware(ctx);
+ if (rv == TPM_E_BADINDEX) {
/*
- * We're on a platform where the TPM maintains power in S3, so
- * it's already initialized.
+ * This seems the first time we've run. Initialize the TPM.
*/
- return TPM_SUCCESS;
- }
- return result;
-}
-
-uint32_t RollbackFirmwareSetup(int is_hw_dev,
- int disable_dev_request,
- int clear_tpm_owner_request,
- int *is_virt_dev, uint32_t *version)
-{
- RollbackSpaceFirmware rsf;
-
- /* Set version to 0 in case we fail */
- *version = 0;
-
- RETURN_ON_FAILURE(SetupTPM(is_hw_dev, disable_dev_request,
- clear_tpm_owner_request, &rsf));
- Memcpy(version, &rsf.fw_versions, sizeof(*version));
- *is_virt_dev = (rsf.flags & FLAG_VIRTUAL_DEV_MODE_ON) ? 1 : 0;
- VBDEBUG(("TPM: RollbackFirmwareSetup %x\n", (int)*version));
- return TPM_SUCCESS;
-}
-
-uint32_t RollbackFirmwareWrite(uint32_t version)
-{
- RollbackSpaceFirmware rsf;
- uint32_t old_version;
-
- RETURN_ON_FAILURE(ReadSpaceFirmware(&rsf));
- Memcpy(&old_version, &rsf.fw_versions, sizeof(old_version));
- VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)old_version,
- (int)version));
- Memcpy(&rsf.fw_versions, &version, sizeof(version));
- return WriteSpaceFirmware(&rsf);
-}
-
-uint32_t RollbackFirmwareLock(void)
-{
- return TlclSetGlobalLock();
-}
-
-uint32_t RollbackKernelRead(uint32_t* version)
-{
- RollbackSpaceKernel rsk;
- uint32_t perms, uid;
-
- /*
- * Read the kernel space and verify its permissions. If the kernel
- * space has the wrong permission, or it doesn't contain the right
- * identifier, we give up. This will need to be fixed by the
- * recovery kernel. We have to worry about this because at any time
- * (even with PP turned off) the TPM owner can remove and redefine a
- * PP-protected space (but not write to it).
- */
- RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
- RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms));
- Memcpy(&uid, &rsk.uid, sizeof(uid));
- if (TPM_NV_PER_PPWRITE != perms || ROLLBACK_SPACE_KERNEL_UID != uid)
+ VBDEBUG("TPM: Not initialized yet.\n");
+ RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
+ } else if (rv != TPM_SUCCESS) {
+ VBDEBUG("TPM: Firmware space in a bad state; giving up.\n");
+ //RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
return TPM_E_CORRUPTED_STATE;
+ }
- Memcpy(version, &rsk.kernel_versions, sizeof(*version));
- VBDEBUG(("TPM: RollbackKernelRead %x\n", (int)*version));
return TPM_SUCCESS;
}
-uint32_t RollbackKernelWrite(uint32_t version)
+uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
{
- RollbackSpaceKernel rsk;
- uint32_t old_version;
- RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
- Memcpy(&old_version, &rsk.kernel_versions, sizeof(old_version));
- VBDEBUG(("TPM: RollbackKernelWrite %x --> %x\n",
- (int)old_version, (int)version));
- Memcpy(&rsk.kernel_versions, &version, sizeof(version));
- return WriteSpaceKernel(&rsk);
+ return write_space_firmware(ctx);
}
-/*
- * We don't really care whether the TPM owner has been messing with this or
- * not. We lock it along with the Kernel space just to avoid problems, but it's
- * only useful in dev-mode and only when the battery has been drained
- * completely. There aren't any security issues. It's just in the TPM because
- * we don't have any other place to keep it.
- */
-uint32_t RollbackBackupRead(uint8_t *raw)
-{
- uint32_t r;
- r = TlclRead(BACKUP_NV_INDEX, raw, BACKUP_NV_SIZE);
- VBDEBUG(("TPM: %s returning 0x%x\n", __func__, r));
- return r;
-}
-
-uint32_t RollbackBackupWrite(uint8_t *raw)
+uint32_t antirollback_lock_space_firmware()
{
- uint32_t r;
- r = TlclWrite(BACKUP_NV_INDEX, raw, BACKUP_NV_SIZE);
- VBDEBUG(("TPM: %s returning 0x%x\n", __func__, r));
- return r;
+ return tlcl_set_global_lock();
}
-
-uint32_t RollbackKernelLock(int recovery_mode)
-{
- if (recovery_mode)
- return TPM_SUCCESS;
- else
- return TlclLockPhysicalPresence();
-}
-
-#endif /* DISABLE_ROLLBACK_TPM */
diff --git a/src/vendorcode/google/chromeos/vboot_main.c b/src/vendorcode/google/chromeos/vboot_main.c
index 8251cfd9b4..252dfb1bf8 100644
--- a/src/vendorcode/google/chromeos/vboot_main.c
+++ b/src/vendorcode/google/chromeos/vboot_main.c
@@ -1,10 +1,14 @@
#include <2api.h>
#include <2struct.h>
+#include <antirollback.h>
+#include <arch/exception.h>
#include <arch/stages.h>
#include <cbfs.h>
#include <console/console.h>
#include <console/vtxprintf.h>
#include <reset.h>
+#include <soc/addressmap.h>
+#include <soc/clock.h>
#include <string.h>
#include "chromeos.h"
@@ -64,8 +68,12 @@ void vb2ex_printf(const char *func, const char *fmt, ...)
int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
{
- VBDEBUG("Clearing owner\n");
- return VB2_ERROR_UNKNOWN;
+ uint32_t rv;
+ VBDEBUG("Clearing TPM owner\n");
+ rv = tpm_clear_and_reenable();
+ if (rv)
+ return VB2_ERROR_EX_TPM_CLEAR_OWNER;
+ return VB2_SUCCESS;
}
int vb2ex_read_resource(struct vb2_context *ctx,
@@ -222,6 +230,54 @@ static void enter_stage(struct cbfs_stage *stage)
stage_exit((void *)(uintptr_t)stage->entry);
}
+enum {
+ L2CTLR_ECC_PARITY = 0x1 << 21,
+ L2CTLR_TAG_RAM_LATENCY_MASK = 0x7 << 6,
+ L2CTLR_TAG_RAM_LATENCY_CYCLES_3 = 2 << 6,
+ L2CTLR_DATA_RAM_LATENCY_MASK = 0x7 << 0,
+ L2CTLR_DATA_RAM_LATENCY_CYCLES_3 = 2 << 0
+};
+
+enum {
+ L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE = 0x1 << 27,
+ L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT = 0x1 << 7,
+ L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL = 0x1 << 3
+};
+
+/* Configures L2 Control Register to use 3 cycles for DATA/TAG RAM latency. */
+static void configure_l2ctlr(void)
+{
+ uint32_t val;
+
+ val = read_l2ctlr();
+ val &= ~(L2CTLR_DATA_RAM_LATENCY_MASK | L2CTLR_TAG_RAM_LATENCY_MASK);
+ val |= (L2CTLR_DATA_RAM_LATENCY_CYCLES_3 | L2CTLR_TAG_RAM_LATENCY_CYCLES_3 |
+ L2CTLR_ECC_PARITY);
+ write_l2ctlr(val);
+}
+
+/* Configures L2 Auxiliary Control Register for Cortex A15. */
+static void configure_l2actlr(void)
+{
+ uint32_t val;
+
+ val = read_l2actlr();
+ val |= (L2ACTLR_DISABLE_CLEAN_EVICT_PUSH_EXTERNAL |
+ L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT |
+ L2ACTLR_FORCE_L2_LOGIC_CLOCK_ENABLE_ACTIVE);
+ write_l2actlr(val);
+}
+
+static void enable_cache(void)
+{
+ mmu_init();
+ mmu_config_range(0, CONFIG_SYS_SDRAM_BASE >> 20, DCACHE_OFF);
+ mmu_config_range(0x40000000 >> 20, 2, DCACHE_WRITEBACK);
+ mmu_disable_range(0, 1);
+ VBDEBUG("Enabling cache\n");
+ dcache_mmu_enable();
+}
+
/**
* Save non-volatile and/or secure data if needed.
*/
@@ -229,16 +285,24 @@ static void save_if_needed(struct vb2_context *ctx)
{
if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) {
VBDEBUG("Saving nvdata\n");
- //save_vbnv(ctx->nvdata);
+ save_vbnv(ctx->nvdata);
ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED;
}
if (ctx->flags & VB2_CONTEXT_SECDATA_CHANGED) {
VBDEBUG("Saving secdata\n");
- //antirollback_write_space_firmware(ctx);
+ antirollback_write_space_firmware(ctx);
ctx->flags &= ~VB2_CONTEXT_SECDATA_CHANGED;
}
}
+/**
+ * Load and verify the next stage from RW image and jump to it
+ *
+ * If validation fails, it exits to romstage for recovery or reboots.
+ *
+ * TODO: Avoid loading a stage twice (once in hash_body & again in load_stage).
+ * when per-stage verification is ready.
+ */
void __attribute__((noinline)) select_firmware(void)
{
struct vb2_context ctx;
@@ -248,7 +312,12 @@ void __attribute__((noinline)) select_firmware(void)
struct cbfs_stage *stage;
int rv;
+ /* Do minimum to enable cache and run vboot at full speed */
+ configure_l2ctlr();
+ configure_l2actlr();
console_init();
+ exception_init();
+ enable_cache();
/* Set up context */
memset(&ctx, 0, sizeof(ctx));
@@ -257,12 +326,12 @@ void __attribute__((noinline)) select_firmware(void)
memset(ctx.workbuf, 0, ctx.workbuf_size);
/* Read nvdata from a non-volatile storage */
- //read_vbnv(ctx.nvdata);
+ read_vbnv(ctx.nvdata);
/* Read secdata from TPM. Initialize TPM if secdata not found. We don't
* check the return value here because vb2api_fw_phase1 will catch
* invalid secdata and tell us what to do (=reboot). */
- //antirollback_read_space_firmware(&ctx);
+ antirollback_read_space_firmware(&ctx);
if (get_developer_mode_switch())
ctx.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE;