mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-29 20:54:07 +00:00
Tolerate lack of TPM reset in common cases.
This is a temporary workaround for Tegra boards that don't reset the TPM when the CPU is reset. It makes the firmware more lenient when execution starts with an already locked TPM. BUG=chromeos-partner:3574 TEST=none (yet) Change-Id: If6a060595c1eb41e95e0935f8467de8bb6256b12 Reviewed-on: http://gerrit.chromium.org/gerrit/1429 Reviewed-by: Gaurav Shah <gauravsh@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Tested-by: Nick Sanders <nsanders@chromium.org>
This commit is contained in:
committed by
Nick Sanders
parent
a78123412d
commit
7b90cf3f00
@@ -43,4 +43,9 @@ extern void debug(const char *format, ...);
|
|||||||
#define UINT64_MAX (UINT64_C(0xffffffffffffffffULL))
|
#define UINT64_MAX (UINT64_C(0xffffffffffffffffULL))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* This workaround applies to Kaen prototypes and is not expected to be needed
|
||||||
|
* in the final products. See crosbug.com/15759.
|
||||||
|
*/
|
||||||
|
#define TEGRA_SOFT_REBOOT_WORKAROUND
|
||||||
|
|
||||||
#endif /*__ARCH_ARM_BIOSINCLUDES_H__ */
|
#endif /*__ARCH_ARM_BIOSINCLUDES_H__ */
|
||||||
|
|||||||
@@ -15,6 +15,10 @@
|
|||||||
|
|
||||||
static int g_rollback_recovery_mode = 0;
|
static int g_rollback_recovery_mode = 0;
|
||||||
|
|
||||||
|
#ifdef TEGRA_SOFT_REBOOT_WORKAROUND
|
||||||
|
static int soft_reset = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 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))
|
||||||
|
|
||||||
@@ -47,6 +51,21 @@ static uint32_t SafeWrite(uint32_t index, const void* data, uint32_t length) {
|
|||||||
if (result == TPM_E_MAXNVWRITES) {
|
if (result == TPM_E_MAXNVWRITES) {
|
||||||
RETURN_ON_FAILURE(TPMClearAndReenable());
|
RETURN_ON_FAILURE(TPMClearAndReenable());
|
||||||
return TlclWrite(index, data, length);
|
return TlclWrite(index, data, length);
|
||||||
|
#ifdef TEGRA_SOFT_REBOOT_WORKAROUND
|
||||||
|
} else if ((result == TPM_E_BAD_PRESENCE ||
|
||||||
|
result == TPM_E_AREA_LOCKED) &&
|
||||||
|
soft_reset == 1) {
|
||||||
|
/* Ignore writes that failed because the TPM wasn't unlocked.
|
||||||
|
*
|
||||||
|
* This may have security implications. 1. It may delay updating the
|
||||||
|
* version number, therefore widening the window for a rollback attack.
|
||||||
|
* 2. It may prevent noticing transitions between developer mode and normal
|
||||||
|
* mode, in which case the TPM owner will not be cleared when
|
||||||
|
* transitioning. See crosbug.com/15759. Note that this code path is not
|
||||||
|
* taken on systems where a CPU reset implies a TPM reset.
|
||||||
|
*/
|
||||||
|
return TPM_SUCCESS;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -190,7 +209,22 @@ uint32_t SetupTPM(int recovery_mode, int developer_mode,
|
|||||||
|
|
||||||
RETURN_ON_FAILURE(TlclLibInit());
|
RETURN_ON_FAILURE(TlclLibInit());
|
||||||
|
|
||||||
|
#ifdef TEGRA_SOFT_REBOOT_WORKAROUND
|
||||||
|
result = TlclStartup();
|
||||||
|
if (result == TPM_E_INVALID_POSTINIT) {
|
||||||
|
/* Some prototype hardware doesn't reset the TPM on a CPU reset. We try to
|
||||||
|
* tolerate this failure, which is possible in most cases.
|
||||||
|
*/
|
||||||
|
VBDEBUG(("TPM: soft reset detected\n", result));
|
||||||
|
soft_reset = 1;
|
||||||
|
} else if (result != TPM_SUCCESS) {
|
||||||
|
VBDEBUG(("TPM: TlclStartup returned %08x\n", result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#else
|
||||||
RETURN_ON_FAILURE(TlclStartup());
|
RETURN_ON_FAILURE(TlclStartup());
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Some TPMs start the self test automatically at power on. In that case we
|
/* Some TPMs start the self test automatically at power on. In that case we
|
||||||
* don't need to call ContinueSelfTest. On some (other) TPMs,
|
* don't need to call ContinueSelfTest. On some (other) TPMs,
|
||||||
* ContinueSelfTest may block. In that case, we definitely don't want to
|
* ContinueSelfTest may block. In that case, we definitely don't want to
|
||||||
@@ -210,7 +244,20 @@ uint32_t SetupTPM(int recovery_mode, int developer_mode,
|
|||||||
RETURN_ON_FAILURE(TlclContinueSelfTest());
|
RETURN_ON_FAILURE(TlclContinueSelfTest());
|
||||||
#endif
|
#endif
|
||||||
result = TlclAssertPhysicalPresence();
|
result = TlclAssertPhysicalPresence();
|
||||||
if (result != 0) {
|
#ifdef TEGRA_SOFT_REBOOT_WORKAROUND
|
||||||
|
/*
|
||||||
|
* If soft_reset is true, the failure to assert PP is expected because the
|
||||||
|
* TPM is locked from a previous boot. In this case we will never execute
|
||||||
|
* the PhysicalPresenceCMDEnable below, but that's OK because this is a
|
||||||
|
* warm boot and at some point in the past we must have cold-booted with
|
||||||
|
* this firmware (one would hope), so that situation (TPM delivered with PP
|
||||||
|
* disabled) has already been resolved.
|
||||||
|
*/
|
||||||
|
if (soft_reset) {
|
||||||
|
result = TPM_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (result != TPM_SUCCESS) {
|
||||||
/* It is possible that the TPM was delivered with the physical presence
|
/* It is possible that the TPM was delivered with the physical presence
|
||||||
* command disabled. This tries enabling it, then tries asserting PP
|
* command disabled. This tries enabling it, then tries asserting PP
|
||||||
* again.
|
* again.
|
||||||
@@ -437,7 +484,18 @@ uint32_t RollbackKernelLock(void) {
|
|||||||
if (g_rollback_recovery_mode) {
|
if (g_rollback_recovery_mode) {
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef TEGRA_SOFT_REBOOT_WORKAROUND
|
||||||
|
TPM_STCLEAR_FLAGS flags;
|
||||||
|
uint32_t result = TlclLockPhysicalPresence();
|
||||||
|
if (result == TPM_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
RETURN_ON_FAILURE(TlclGetSTClearFlags(&flags));
|
||||||
|
/* Ignore PP locking failure if PP is already locked. */
|
||||||
|
return flags.physicalPresenceLock == 1 ? TPM_SUCCESS : result;
|
||||||
|
#else
|
||||||
return TlclLockPhysicalPresence();
|
return TlclLockPhysicalPresence();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user