diff options
Diffstat (limited to 'src/vendorcode/google')
-rw-r--r-- | src/vendorcode/google/chromeos/Makefile.inc | 1 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/antirollback.c | 602 | ||||
-rw-r--r-- | src/vendorcode/google/chromeos/vboot_main.c | 81 |
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; |