mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-24 18:25:10 +00:00
vboot: Remove vboot1 init and select-firmware APIs
And nuke all the underlying code that is unused once those APIs are gone. These APIs are not used by any project in ToT, having been superseded last year by the vboot2 APIs. No functional changes to live code, just lots of deletes. CQ-DEPEND=CL:347414 BUG=chromium:611535 BRANCH=none TEST=make runtests; build samus Change-Id: I05ac752d74d1343dd03600b1c5e6ed22822e2802 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/347257
This commit is contained in:
committed by
chrome-bot
parent
c61df529d0
commit
2afa87360d
@@ -503,410 +503,6 @@ static void MiscTest(void)
|
||||
"TlclSetDeactivated(0)\n"
|
||||
"TlclWrite(0x123, 8)\n",
|
||||
"tlcl calls");
|
||||
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(SafeDefineSpace(0x123, 6, 8), 0, "SafeDefineSpace()");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclDefineSpace(0x123, 0x6, 8)\n",
|
||||
"tlcl calls");
|
||||
|
||||
ResetMocks(1, TPM_E_BADINDEX);
|
||||
TEST_EQ(SafeDefineSpace(0x123, 6, 8), TPM_E_BADINDEX,
|
||||
"SafeDefineSpace() bad");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclDefineSpace(0x123, 0x6, 8)\n",
|
||||
"tlcl calls");
|
||||
|
||||
ResetMocks(1, TPM_E_MAXNVWRITES);
|
||||
TEST_EQ(SafeDefineSpace(0x123, 6, 8), 0,
|
||||
"SafeDefineSpace() retry max writes");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclDefineSpace(0x123, 0x6, 8)\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n"
|
||||
"TlclDefineSpace(0x123, 0x6, 8)\n",
|
||||
"tlcl calls");
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* Tests for one-time initialization */
|
||||
static void OneTimeInitTest(void)
|
||||
{
|
||||
RollbackSpaceFirmware rsf;
|
||||
RollbackSpaceKernel rsk;
|
||||
|
||||
/* Complete initialization */
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclSelfTestFull()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclFinalizePhysicalPresence()\n"
|
||||
"TlclSetNvLocked()\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n"
|
||||
/* backup space */
|
||||
"TlclDefineSpace(0x1009, 0x1, 16)\n"
|
||||
/* kernel space */
|
||||
"TlclDefineSpace(0x1008, 0x1, 13)\n"
|
||||
"TlclWrite(0x1008, 13)\n"
|
||||
"TlclRead(0x1008, 13)\n"
|
||||
/* firmware space */
|
||||
"TlclDefineSpace(0x1007, 0x8001, 10)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
TEST_EQ(mock_rsf.struct_version, ROLLBACK_SPACE_FIRMWARE_VERSION,
|
||||
"rsf ver");
|
||||
TEST_EQ(mock_rsf.flags, 0, "rsf flags");
|
||||
TEST_EQ(mock_rsf.fw_versions, 0, "rsf fw_versions");
|
||||
TEST_EQ(mock_rsk.struct_version, ROLLBACK_SPACE_KERNEL_VERSION,
|
||||
"rsk ver");
|
||||
TEST_EQ(mock_rsk.uid, ROLLBACK_SPACE_KERNEL_UID, "rsk uid");
|
||||
TEST_EQ(mock_rsk.kernel_versions, 0, "rsk kernel_versions");
|
||||
|
||||
/* Physical presence already initialized */
|
||||
ResetMocks(0, 0);
|
||||
mock_pflags.physicalPresenceLifetimeLock = 1;
|
||||
TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclSelfTestFull()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclSetNvLocked()\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n"
|
||||
/* backup space */
|
||||
"TlclDefineSpace(0x1009, 0x1, 16)\n"
|
||||
/* kernel space */
|
||||
"TlclDefineSpace(0x1008, 0x1, 13)\n"
|
||||
"TlclWrite(0x1008, 13)\n"
|
||||
"TlclRead(0x1008, 13)\n"
|
||||
/* firmware space */
|
||||
"TlclDefineSpace(0x1007, 0x8001, 10)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* NV locking already initialized */
|
||||
ResetMocks(0, 0);
|
||||
mock_pflags.nvLocked = 1;
|
||||
TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), 0, "OneTimeInitializeTPM()");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclSelfTestFull()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclFinalizePhysicalPresence()\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n"
|
||||
/* backup space */
|
||||
"TlclDefineSpace(0x1009, 0x1, 16)\n"
|
||||
/* kernel space */
|
||||
"TlclDefineSpace(0x1008, 0x1, 13)\n"
|
||||
"TlclWrite(0x1008, 13)\n"
|
||||
"TlclRead(0x1008, 13)\n"
|
||||
/* firmware space */
|
||||
"TlclDefineSpace(0x1007, 0x8001, 10)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* Self test error */
|
||||
ResetMocks(1, TPM_E_IOERROR);
|
||||
TEST_EQ(OneTimeInitializeTPM(&rsf, &rsk), TPM_E_IOERROR,
|
||||
"OneTimeInitializeTPM() selftest");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclSelfTestFull()\n",
|
||||
"tlcl calls");
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Tests for TPM setup */
|
||||
|
||||
static void SetupTpmTest(void)
|
||||
{
|
||||
RollbackSpaceFirmware rsf;
|
||||
|
||||
/* Complete setup */
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM()");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* If TPM is disabled or deactivated, must enable it */
|
||||
ResetMocks(0, 0);
|
||||
mock_pflags.disable = 1;
|
||||
TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_MUST_REBOOT,
|
||||
"SetupTPM() disabled");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n",
|
||||
"tlcl calls");
|
||||
|
||||
ResetMocks(0, 0);
|
||||
mock_pflags.deactivated = 1;
|
||||
TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_MUST_REBOOT,
|
||||
"SetupTPM() deactivated");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* If physical presence command isn't enabled, try to enable it */
|
||||
ResetMocks(3, TPM_E_IOERROR);
|
||||
TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() pp cmd");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclPhysicalPresenceCMDEnable()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* If firmware space is missing, do one-time init */
|
||||
ResetMocks(5, TPM_E_BADINDEX);
|
||||
mock_pflags.physicalPresenceLifetimeLock = 1;
|
||||
mock_pflags.nvLocked = 1;
|
||||
TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() no firmware space");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n"
|
||||
/* Calls from one-time init */
|
||||
"TlclSelfTestFull()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n"
|
||||
/* backup space */
|
||||
"TlclDefineSpace(0x1009, 0x1, 16)\n"
|
||||
"TlclDefineSpace(0x1008, 0x1, 13)\n"
|
||||
"TlclWrite(0x1008, 13)\n"
|
||||
"TlclRead(0x1008, 13)\n"
|
||||
"TlclDefineSpace(0x1007, 0x8001, 10)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* Other firmware space error is passed through */
|
||||
ResetMocks(5, TPM_E_IOERROR);
|
||||
TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_CORRUPTED_STATE,
|
||||
"SetupTPM() bad firmware space");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* If developer flag has toggled, clear ownership and write new flag */
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(SetupTPM(1, 0, 0, &rsf), 0, "SetupTPM() to dev");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
TEST_EQ(mock_rsf.flags, FLAG_LAST_BOOT_DEVELOPER,
|
||||
"fw space flags to dev 1");
|
||||
|
||||
ResetMocks(0, 0);
|
||||
mock_rsf.flags = FLAG_LAST_BOOT_DEVELOPER;
|
||||
TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() from dev");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
TEST_EQ(mock_rsf.flags, 0, "fw space flags from dev 1");
|
||||
|
||||
/* If TPM clear request, clear ownership also */
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(SetupTPM(0, 0, 1, &rsf), 0, "SetupTPM() clear owner");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* Handle request to clear virtual dev switch */
|
||||
ResetMocks(0, 0);
|
||||
mock_rsf.flags = FLAG_VIRTUAL_DEV_MODE_ON | FLAG_LAST_BOOT_DEVELOPER;
|
||||
TEST_EQ(SetupTPM(0, 1, 0, &rsf), 0, "SetupTPM() clear virtual dev");
|
||||
TEST_EQ(mock_rsf.flags, 0, "Clear virtual dev");
|
||||
|
||||
/* If virtual dev switch is on, that should set last boot developer */
|
||||
ResetMocks(0, 0);
|
||||
mock_rsf.flags = FLAG_VIRTUAL_DEV_MODE_ON;
|
||||
SetupTPM(0, 0, 0, &rsf);
|
||||
TEST_EQ(mock_rsf.flags,
|
||||
FLAG_VIRTUAL_DEV_MODE_ON | FLAG_LAST_BOOT_DEVELOPER,
|
||||
"virtual dev sets last boot");
|
||||
|
||||
/*
|
||||
* Note: SetupTPM() recovery_mode parameter sets a global flag in
|
||||
* rollback_index.c; this is tested along with RollbackKernelLock()
|
||||
* below.
|
||||
*/
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Tests for RollbackFirmware() calls */
|
||||
|
||||
static void RollbackFirmwareTest(void)
|
||||
{
|
||||
uint32_t version;
|
||||
int dev_mode;
|
||||
|
||||
/* Normal setup */
|
||||
ResetMocks(0, 0);
|
||||
dev_mode = 0;
|
||||
version = 123;
|
||||
mock_rsf.fw_versions = 0x12345678;
|
||||
TEST_EQ(RollbackFirmwareSetup(0, dev_mode, 0, &dev_mode, &version),
|
||||
0, "RollbackFirmwareSetup()");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
TEST_EQ(version, 0x12345678, "RollbackFirmwareSetup() version");
|
||||
|
||||
/* Error during setup should clear version */
|
||||
ResetMocks(1, TPM_E_IOERROR);
|
||||
dev_mode = 0;
|
||||
version = 123;
|
||||
mock_rsf.fw_versions = 0x12345678;
|
||||
TEST_EQ(RollbackFirmwareSetup(0, dev_mode, 0, &dev_mode, &version),
|
||||
TPM_E_IOERROR,
|
||||
"RollbackFirmwareSetup() error");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n",
|
||||
"tlcl calls");
|
||||
TEST_EQ(version, 0, "RollbackFirmwareSetup() version on error");
|
||||
|
||||
/* Developer mode flag gets passed properly */
|
||||
ResetMocks(0, 0);
|
||||
dev_mode = 1;
|
||||
TEST_EQ(RollbackFirmwareSetup(dev_mode, 0, 0, &dev_mode, &version),
|
||||
0, "RollbackFirmwareSetup() to dev");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
TEST_EQ(mock_rsf.flags, FLAG_LAST_BOOT_DEVELOPER,
|
||||
"fw space flags to dev 2");
|
||||
|
||||
/* So does clear-TPM request */
|
||||
ResetMocks(0, 0);
|
||||
dev_mode = 0;
|
||||
TEST_EQ(RollbackFirmwareSetup(dev_mode, 0, 1, &dev_mode, &version),
|
||||
0, "RollbackFirmwareSetup() clear owner");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclStartup()\n"
|
||||
"TlclAssertPhysicalPresence()\n"
|
||||
"TlclGetPermanentFlags()\n"
|
||||
"TlclRead(0x1007, 10)\n"
|
||||
"TlclForceClear()\n"
|
||||
"TlclSetEnable()\n"
|
||||
"TlclSetDeactivated(0)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* Test write */
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(RollbackFirmwareWrite(0xBEAD1234), 0,
|
||||
"RollbackFirmwareWrite()");
|
||||
TEST_EQ(mock_rsf.fw_versions, 0xBEAD1234,
|
||||
"RollbackFirmwareWrite() version");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclRead(0x1007, 10)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
|
||||
ResetMocks(1, TPM_E_IOERROR);
|
||||
TEST_EQ(RollbackFirmwareWrite(123), TPM_E_IOERROR,
|
||||
"RollbackFirmwareWrite() error");
|
||||
|
||||
/* Test setting virtual dev mode */
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(SetVirtualDevMode(1), 0, "SetVirtualDevMode(1)");
|
||||
TEST_EQ(mock_rsf.flags, FLAG_VIRTUAL_DEV_MODE_ON, "Virtual dev on");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclRead(0x1007, 10)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(SetVirtualDevMode(0), 0, "SetVirtualDevMode(0)");
|
||||
TEST_EQ(mock_rsf.flags, 0, "Virtual dev off");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclRead(0x1007, 10)\n"
|
||||
"TlclWrite(0x1007, 10)\n"
|
||||
"TlclRead(0x1007, 10)\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* Test lock */
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(RollbackFirmwareLock(), 0, "RollbackFirmwareLock()");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclSetGlobalLock()\n",
|
||||
"tlcl calls");
|
||||
|
||||
ResetMocks(1, TPM_E_IOERROR);
|
||||
TEST_EQ(RollbackFirmwareLock(), TPM_E_IOERROR,
|
||||
"RollbackFirmwareLock() error");
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -914,16 +510,8 @@ static void RollbackFirmwareTest(void)
|
||||
|
||||
static void RollbackKernelTest(void)
|
||||
{
|
||||
RollbackSpaceFirmware rsf;
|
||||
uint32_t version = 0;
|
||||
|
||||
/*
|
||||
* RollbackKernel*() functions use a global flag inside
|
||||
* rollback_index.c based on recovery mode, which is set by SetupTPM().
|
||||
* Clear the flag for the first set of tests.
|
||||
*/
|
||||
TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM()");
|
||||
|
||||
/* Normal read */
|
||||
ResetMocks(0, 0);
|
||||
mock_rsk.uid = ROLLBACK_SPACE_KERNEL_UID;
|
||||
@@ -978,7 +566,6 @@ static void RollbackKernelTest(void)
|
||||
"RollbackKernelLock() error");
|
||||
|
||||
/* Test lock with recovery on; shouldn't lock PP */
|
||||
SetupTPM(0, 0, 0, &rsf);
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(RollbackKernelLock(1), 0, "RollbackKernelLock() in recovery");
|
||||
TEST_STR_EQ(mock_calls, "", "no tlcl calls");
|
||||
@@ -990,27 +577,6 @@ static void RollbackKernelTest(void)
|
||||
"tlcl calls");
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Tests for RollbackS3Resume() */
|
||||
static void RollbackS3ResumeTest(void)
|
||||
{
|
||||
ResetMocks(0, 0);
|
||||
TEST_EQ(RollbackS3Resume(), 0, "RollbackS3Resume()");
|
||||
TEST_STR_EQ(mock_calls,
|
||||
"TlclLibInit()\n"
|
||||
"TlclResume()\n",
|
||||
"tlcl calls");
|
||||
|
||||
/* Should ignore postinit error */
|
||||
ResetMocks(2, TPM_E_INVALID_POSTINIT);
|
||||
TEST_EQ(RollbackS3Resume(), 0, "RollbackS3Resume() postinit");
|
||||
|
||||
/* Resume with other error */
|
||||
ResetMocks(2, TPM_E_IOERROR);
|
||||
TEST_EQ(RollbackS3Resume(), TPM_E_IOERROR,
|
||||
"RollbackS3Resume() other error");
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Tests for RollbackFwmpRead() calls */
|
||||
|
||||
@@ -1109,11 +675,7 @@ int main(int argc, char* argv[])
|
||||
CrcTestFirmware();
|
||||
CrcTestKernel();
|
||||
MiscTest();
|
||||
OneTimeInitTest();
|
||||
SetupTpmTest();
|
||||
RollbackFirmwareTest();
|
||||
RollbackKernelTest();
|
||||
RollbackS3ResumeTest();
|
||||
RollbackFwmpTest();
|
||||
|
||||
return gTestSuccess ? 0 : 255;
|
||||
|
||||
@@ -17,22 +17,8 @@
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int is_virt_dev;
|
||||
uint32_t version;
|
||||
uint32_t version = 1;
|
||||
|
||||
TEST_EQ(RollbackS3Resume(), 0, "RollbackS3Resume()");
|
||||
|
||||
is_virt_dev = 1;
|
||||
version = 1;
|
||||
TEST_EQ(RollbackFirmwareSetup(0, 0, 0, &is_virt_dev, &version),
|
||||
0, "RollbackFirmwareSetup()");
|
||||
TEST_EQ(is_virt_dev, 0, "rfs is_virt_dev");
|
||||
TEST_EQ(version, 0, "rfs version");
|
||||
|
||||
TEST_EQ(RollbackFirmwareWrite(0), 0, "RollbackFirmwareWrite()");
|
||||
TEST_EQ(RollbackFirmwareLock(), 0, "RollbackFirmwareLock()");
|
||||
|
||||
version = 1;
|
||||
TEST_EQ(RollbackKernelRead(&version), 0, "RollbackKernelRead()");
|
||||
TEST_EQ(version, 0, "rkr version");
|
||||
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* Tests for tpm_bootmode functions
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define _STUB_IMPLEMENTATION_ /* So we can use memset() ourselves */
|
||||
|
||||
#include "test_common.h"
|
||||
#include "utility.h"
|
||||
#include "tpm_bootmode.h"
|
||||
|
||||
extern const char* kBootStateSHA1Digests[];
|
||||
|
||||
/* Last in_digest passed to TlclExtend() for each PCR */
|
||||
static const uint8_t *last_in[20];
|
||||
|
||||
/* Return value to pass for TlclExtend() */
|
||||
static uint32_t extend_returns;
|
||||
|
||||
/* How many calls to TlclExtend() should one SetTPMBootModeState() make? */
|
||||
static int expected_extend_count;
|
||||
/* How many did we get? */
|
||||
static int actual_extend_count;
|
||||
|
||||
static GoogleBinaryBlockHeader gbb_v1 = {
|
||||
.major_version = GBB_MAJOR_VER,
|
||||
.minor_version = 1,
|
||||
};
|
||||
|
||||
static GoogleBinaryBlockHeader gbb_v2 = {
|
||||
.major_version = GBB_MAJOR_VER,
|
||||
.minor_version = 2,
|
||||
.hwid_digest = {1, 2, 3, 4,},
|
||||
};
|
||||
|
||||
/* Mocked TlclExtend() function for testing */
|
||||
uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest,
|
||||
uint8_t *out_digest)
|
||||
{
|
||||
/* Should be using correct pcr */
|
||||
TEST_EQ(pcr_num, actual_extend_count, "TlclExtend pcr_num");
|
||||
|
||||
last_in[actual_extend_count] = in_digest;
|
||||
|
||||
actual_extend_count++;
|
||||
return extend_returns;
|
||||
}
|
||||
|
||||
|
||||
/* Test setting TPM boot mode state */
|
||||
static void BootStateTest(void)
|
||||
{
|
||||
int recdev;
|
||||
int flags;
|
||||
int index;
|
||||
char what[128];
|
||||
|
||||
/* Test all permutations of developer and recovery mode */
|
||||
for (recdev = 0; recdev < 4; recdev++) {
|
||||
/* Exhaustively test all permutations of key block flags
|
||||
* currently defined in vboot_struct.h (KEY_BLOCK_FLAG_*) */
|
||||
for (flags = 0; flags < 16; flags++) {
|
||||
index = recdev * 3;
|
||||
if (6 == flags)
|
||||
index += 2;
|
||||
else if (7 == flags)
|
||||
index += 1;
|
||||
|
||||
/* Passing a null pointer for GBB */
|
||||
memset(last_in, 0, sizeof(last_in));
|
||||
actual_extend_count = 0;
|
||||
expected_extend_count = 1;
|
||||
TEST_EQ(SetTPMBootModeState(recdev & 2, recdev & 1,
|
||||
flags, 0), 0,
|
||||
"SetTPMBootModeState return (gbb0)");
|
||||
snprintf(what, sizeof(what),
|
||||
"SetTPMBootModeState %d, 0x%x (gbb0)",
|
||||
recdev, flags);
|
||||
TEST_PTR_EQ(last_in[0],
|
||||
kBootStateSHA1Digests[index], what);
|
||||
TEST_EQ(expected_extend_count, actual_extend_count,
|
||||
"Expected TlclExtend call count (gbb0)");
|
||||
snprintf(what, sizeof(what),
|
||||
"SetTPMBootModeState %d, 0x%x (gbb0) PCR1",
|
||||
recdev, flags);
|
||||
TEST_PTR_EQ(last_in[1], NULL, what);
|
||||
|
||||
/* GBB v1.1 - should be exactly the same */
|
||||
memset(last_in, 0, sizeof(last_in));
|
||||
actual_extend_count = 0;
|
||||
expected_extend_count = 1;
|
||||
TEST_EQ(SetTPMBootModeState(recdev & 2, recdev & 1,
|
||||
flags, &gbb_v1), 0,
|
||||
"SetTPMBootModeState return (gbb1)");
|
||||
snprintf(what, sizeof(what),
|
||||
"SetTPMBootModeState %d, 0x%x (gbb1)",
|
||||
recdev, flags);
|
||||
TEST_PTR_EQ(last_in[0],
|
||||
kBootStateSHA1Digests[index], what);
|
||||
TEST_EQ(expected_extend_count, actual_extend_count,
|
||||
"Expected TlclExtend call count (gbb1)");
|
||||
snprintf(what, sizeof(what),
|
||||
"SetTPMBootModeState %d, 0x%x (gbb1) PCR1",
|
||||
recdev, flags);
|
||||
TEST_PTR_EQ(last_in[1], NULL, what);
|
||||
|
||||
/* GBB v1.2 - should extend PCR1 with HWID digest */
|
||||
memset(last_in, 0, sizeof(last_in));
|
||||
actual_extend_count = 0;
|
||||
expected_extend_count = 2;
|
||||
TEST_EQ(SetTPMBootModeState(recdev & 2, recdev & 1,
|
||||
flags, &gbb_v2), 0,
|
||||
"SetTPMBootModeState return (gbb2)");
|
||||
snprintf(what, sizeof(what),
|
||||
"SetTPMBootModeState %d, 0x%x (gbb2)",
|
||||
recdev, flags);
|
||||
TEST_PTR_EQ(last_in[0],
|
||||
kBootStateSHA1Digests[index], what);
|
||||
TEST_EQ(expected_extend_count, actual_extend_count,
|
||||
"Expected TlclExtend call count (gbb2)");
|
||||
snprintf(what, sizeof(what),
|
||||
"SetTPMBootModeState %d, 0x%x (gbb2) PCR1",
|
||||
recdev, flags);
|
||||
TEST_PTR_EQ(last_in[1], gbb_v2.hwid_digest, what);
|
||||
}
|
||||
}
|
||||
|
||||
extend_returns = 1;
|
||||
actual_extend_count = 0;
|
||||
expected_extend_count = 1;
|
||||
TEST_EQ(SetTPMBootModeState(0, 0, 0, 0), 1,
|
||||
"SetTPMBootModeState error");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int error_code = 0;
|
||||
|
||||
BootStateTest();
|
||||
|
||||
if (!gTestSuccess)
|
||||
error_code = 255;
|
||||
|
||||
return error_code;
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* Tests for vboot_api_firmware
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "gbb_header.h"
|
||||
#include "host_common.h"
|
||||
#include "rollback_index.h"
|
||||
#include "test_common.h"
|
||||
#include "vboot_common.h"
|
||||
#include "vboot_nvstorage.h"
|
||||
#include "vboot_struct.h"
|
||||
|
||||
/* Flags for mock_*_got_flags variables */
|
||||
#define MOCK_DEV_FLAG 0x01 /* Developer parameter non-zero */
|
||||
#define MOCK_REC_FLAG 0x02 /* Recovery parameter non-zero */
|
||||
|
||||
/* Mock data */
|
||||
static VbCommonParams cparams;
|
||||
static VbSelectFirmwareParams fparams;
|
||||
static GoogleBinaryBlockHeader gbb;
|
||||
static VbNvContext vnc;
|
||||
static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
|
||||
static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data;
|
||||
static uint64_t mock_timer;
|
||||
static int nv_write_called;
|
||||
/* Mock TPM versions */
|
||||
static uint32_t mock_tpm_version;
|
||||
static uint32_t mock_lf_tpm_version; /* TPM version set by LoadFirmware() */
|
||||
/* Variables for tracking params passed to mock functions */
|
||||
static uint32_t mock_stbms_got_flags;
|
||||
static uint64_t mock_stbms_got_fw_flags;
|
||||
static int mock_rfl_called;
|
||||
/* Mock return values, so we can simulate errors */
|
||||
static VbError_t mock_rfw_retval;
|
||||
static VbError_t mock_rfl_retval;
|
||||
static VbError_t mock_lf_retval;
|
||||
static VbError_t mock_stbms_retval;
|
||||
|
||||
/* Reset mock data (for use before each test) */
|
||||
static void ResetMocks(void) {
|
||||
Memset(&cparams, 0, sizeof(cparams));
|
||||
cparams.shared_data_size = sizeof(shared_data);
|
||||
cparams.shared_data_blob = shared_data;
|
||||
|
||||
Memset(&fparams, 0, sizeof(fparams));
|
||||
|
||||
Memset(&gbb, 0, sizeof(gbb));
|
||||
cparams.gbb_data = &gbb;
|
||||
cparams.gbb_size = sizeof(gbb);
|
||||
cparams.gbb = &gbb;
|
||||
|
||||
Memset(&vnc, 0, sizeof(vnc));
|
||||
VbNvSetup(&vnc);
|
||||
VbNvTeardown(&vnc); /* So CRC gets generated */
|
||||
|
||||
Memset(&shared_data, 0, sizeof(shared_data));
|
||||
VbSharedDataInit(shared, sizeof(shared_data));
|
||||
shared->fw_keyblock_flags = 0xABCDE0;
|
||||
|
||||
mock_timer = 10;
|
||||
nv_write_called = mock_rfl_called = 0;
|
||||
|
||||
mock_stbms_got_flags = 0;
|
||||
mock_stbms_got_fw_flags = 0;
|
||||
|
||||
mock_tpm_version = mock_lf_tpm_version = 0x20004;
|
||||
shared->fw_version_tpm_start = mock_tpm_version;
|
||||
mock_rfw_retval = mock_rfl_retval = 0;
|
||||
mock_lf_retval = mock_stbms_retval = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Mocked verification functions */
|
||||
|
||||
VbError_t VbExNvStorageRead(uint8_t* buf) {
|
||||
Memcpy(buf, vnc.raw, sizeof(vnc.raw));
|
||||
return VBERROR_SUCCESS;
|
||||
}
|
||||
|
||||
VbError_t VbExNvStorageWrite(const uint8_t* buf) {
|
||||
nv_write_called = 1;
|
||||
Memcpy(vnc.raw, buf, sizeof(vnc.raw));
|
||||
return VBERROR_SUCCESS;
|
||||
}
|
||||
|
||||
uint64_t VbExGetTimer(void) {
|
||||
/* Exponential-ish rather than linear time, so that subtracting any
|
||||
* two mock values will yield a unique result. */
|
||||
uint64_t new_timer = mock_timer * 2 + 1;
|
||||
VbAssert(new_timer > mock_timer); /* Make sure we don't overflow */
|
||||
mock_timer = new_timer;
|
||||
return mock_timer;
|
||||
}
|
||||
|
||||
uint32_t RollbackFirmwareWrite(uint32_t version) {
|
||||
mock_tpm_version = version;
|
||||
return mock_rfw_retval;
|
||||
}
|
||||
|
||||
uint32_t RollbackFirmwareLock(void) {
|
||||
mock_rfl_called = 1;
|
||||
return mock_rfl_retval;
|
||||
}
|
||||
|
||||
uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode,
|
||||
uint64_t fw_keyblock_flags,
|
||||
GoogleBinaryBlockHeader *gbb) {
|
||||
if (recovery_mode)
|
||||
mock_stbms_got_flags |= MOCK_REC_FLAG;
|
||||
if (developer_mode)
|
||||
mock_stbms_got_flags |= MOCK_DEV_FLAG;
|
||||
|
||||
mock_stbms_got_fw_flags = fw_keyblock_flags;
|
||||
|
||||
return mock_stbms_retval;
|
||||
}
|
||||
|
||||
int LoadFirmware(VbCommonParams* cparams, VbSelectFirmwareParams* fparams,
|
||||
VbNvContext* vnc) {
|
||||
shared->fw_version_tpm = mock_lf_tpm_version;
|
||||
return mock_lf_retval;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Test VbSelectFirmware() and check expected return value and
|
||||
* recovery reason */
|
||||
static void TestVbSf(VbError_t expected_retval,
|
||||
uint8_t expected_recovery, const char* desc) {
|
||||
uint32_t rr = 256;
|
||||
|
||||
TEST_EQ(VbSelectFirmware(&cparams, &fparams), expected_retval, desc);
|
||||
VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &rr);
|
||||
TEST_EQ(rr, expected_recovery, " recovery request");
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void VbSelectFirmwareTest(void) {
|
||||
/* Normal call */
|
||||
ResetMocks();
|
||||
TestVbSf(0, 0, "Normal call");
|
||||
TEST_EQ(shared->timer_vb_select_firmware_enter, 21, " time enter");
|
||||
TEST_EQ(shared->timer_vb_select_firmware_exit, 43, " time exit");
|
||||
TEST_EQ(nv_write_called, 0, " NV write not called since nothing changed");
|
||||
TEST_EQ(mock_stbms_got_flags, 0, " SetTPMBootModeState() flags");
|
||||
TEST_EQ(mock_stbms_got_fw_flags, 0xABCDE0, " fw keyblock flags");
|
||||
TEST_EQ(mock_rfl_called, 1, " RollbackFirmwareLock() called");
|
||||
|
||||
/* Developer mode call */
|
||||
ResetMocks();
|
||||
shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
|
||||
TestVbSf(0, 0, "Developer mode");
|
||||
TEST_EQ(mock_stbms_got_flags, MOCK_DEV_FLAG, " SetTPMBootModeState() flags");
|
||||
TEST_EQ(mock_rfl_called, 1, " RollbackFirmwareLock() called");
|
||||
|
||||
/* Recovery mode doesn't call LoadFirmware(),
|
||||
* RollbackFirmwareWrite(), or RollbackFirmwareLock(). */
|
||||
ResetMocks();
|
||||
shared->recovery_reason = VBNV_RECOVERY_US_TEST;
|
||||
mock_lf_retval = VBERROR_UNKNOWN;
|
||||
mock_rfw_retval = mock_rfl_retval = TPM_E_IOERROR;
|
||||
TestVbSf(0, 0, "Recovery mode");
|
||||
TEST_EQ(fparams.selected_firmware, VB_SELECT_FIRMWARE_RECOVERY,
|
||||
" select recovery");
|
||||
TEST_EQ(mock_stbms_got_flags, MOCK_REC_FLAG, " SetTPMBootModeState() flags");
|
||||
TEST_EQ(mock_rfl_called, 0, " RollbackFirmwareLock() not called");
|
||||
|
||||
/* Dev + recovery */
|
||||
ResetMocks();
|
||||
shared->recovery_reason = VBNV_RECOVERY_US_TEST;
|
||||
shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
|
||||
TestVbSf(0, 0, "Recovery+developer mode");
|
||||
TEST_EQ(fparams.selected_firmware, VB_SELECT_FIRMWARE_RECOVERY,
|
||||
" select recovery");
|
||||
TEST_EQ(mock_stbms_got_flags, MOCK_DEV_FLAG|MOCK_REC_FLAG,
|
||||
" SetTPMBootModeState() flags");
|
||||
TEST_EQ(mock_rfl_called, 0, " RollbackFirmwareLock() not called");
|
||||
|
||||
/* LoadFirmware() error code passed through */
|
||||
ResetMocks();
|
||||
mock_lf_retval = 0x12345;
|
||||
TestVbSf(0x12345, 0, "LoadFirmware() error");
|
||||
|
||||
/* Select different firmware paths based on LoadFirmware() result */
|
||||
ResetMocks();
|
||||
shared->flags |= VBSD_LF_USE_RO_NORMAL;
|
||||
TestVbSf(0, 0, "LoadFirmware() RO-normal");
|
||||
TEST_EQ(fparams.selected_firmware, VB_SELECT_FIRMWARE_READONLY,
|
||||
" select RO normal");
|
||||
ResetMocks();
|
||||
shared->firmware_index = 0;
|
||||
TestVbSf(0, 0, "LoadFirmware() A");
|
||||
TEST_EQ(fparams.selected_firmware, VB_SELECT_FIRMWARE_A, " select A");
|
||||
ResetMocks();
|
||||
shared->firmware_index = 1;
|
||||
TestVbSf(0, 0, "LoadFirmware() B");
|
||||
TEST_EQ(fparams.selected_firmware, VB_SELECT_FIRMWARE_B, " select B");
|
||||
|
||||
/* Handle TPM version updates */
|
||||
ResetMocks();
|
||||
mock_lf_tpm_version = 0x30005;
|
||||
TestVbSf(0, 0, "TPM version update");
|
||||
TEST_EQ(shared->fw_version_tpm_start, 0x20004, " TPM version start");
|
||||
TEST_EQ(shared->fw_version_tpm, 0x30005, " TPM version");
|
||||
TEST_EQ(mock_tpm_version, 0x30005, " TPM version written back");
|
||||
|
||||
/* Check error writing TPM version */
|
||||
ResetMocks();
|
||||
mock_lf_tpm_version = 0x30005;
|
||||
mock_rfw_retval = TPM_E_IOERROR;
|
||||
TestVbSf(VBERROR_TPM_WRITE_FIRMWARE, VBNV_RECOVERY_RO_TPM_W_ERROR,
|
||||
"TPM version update failure");
|
||||
|
||||
/* If no change to TPM version, RollbackFirmwareWrite() not called */
|
||||
ResetMocks();
|
||||
mock_rfw_retval = TPM_E_IOERROR;
|
||||
TestVbSf(0, 0, "LoadFirmware() TPM version not updated");
|
||||
TEST_EQ(shared->fw_version_tpm_start, 0x20004, " TPM version start");
|
||||
TEST_EQ(shared->fw_version_tpm, 0x20004, " TPM version");
|
||||
TEST_EQ(mock_tpm_version, 0x20004, " TPM version (not) written back");
|
||||
|
||||
/* Check errors from SetTPMBootModeState() */
|
||||
ResetMocks();
|
||||
mock_stbms_retval = TPM_E_IOERROR;
|
||||
TestVbSf(VBERROR_TPM_SET_BOOT_MODE_STATE, VBNV_RECOVERY_RO_TPM_U_ERROR,
|
||||
"TPM set boot mode state failure");
|
||||
ResetMocks();
|
||||
mock_stbms_retval = TPM_E_IOERROR;
|
||||
shared->recovery_reason = VBNV_RECOVERY_US_TEST;
|
||||
TestVbSf(0, 0, "TPM set boot mode state failure ignored in recovery");
|
||||
|
||||
/* Handle RollbackFirmwareLock() errors */
|
||||
ResetMocks();
|
||||
mock_rfl_retval = TPM_E_IOERROR;
|
||||
TestVbSf(VBERROR_TPM_LOCK_FIRMWARE, VBNV_RECOVERY_RO_TPM_L_ERROR,
|
||||
"TPM lock firmware failure");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int error_code = 0;
|
||||
|
||||
VbSelectFirmwareTest();
|
||||
|
||||
if (vboot_api_stub_check_memory())
|
||||
error_code = 255;
|
||||
if (!gTestSuccess)
|
||||
error_code = 255;
|
||||
|
||||
return error_code;
|
||||
}
|
||||
@@ -1,803 +0,0 @@
|
||||
/* 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
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* Tests for vboot_api_init
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "gbb_header.h"
|
||||
#include "host_common.h"
|
||||
#include "rollback_index.h"
|
||||
#include "test_common.h"
|
||||
#include "vboot_common.h"
|
||||
#include "vboot_nvstorage.h"
|
||||
#include "vboot_struct.h"
|
||||
|
||||
/* Mock data */
|
||||
static VbCommonParams cparams;
|
||||
static VbInitParams iparams;
|
||||
static VbNvContext vnc;
|
||||
static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
|
||||
static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
|
||||
static uint64_t mock_timer;
|
||||
static int rollback_s3_retval;
|
||||
static int nv_write_called;
|
||||
static GoogleBinaryBlockHeader gbb;
|
||||
static int mock_virt_dev_sw;
|
||||
static uint32_t mock_tpm_version;
|
||||
static uint32_t mock_rfs_retval;
|
||||
static int rfs_clear_tpm_request;
|
||||
static int rfs_disable_dev_request;
|
||||
static uint8_t backup_space[BACKUP_NV_SIZE];
|
||||
static int backup_write_called;
|
||||
static int backup_read_called;
|
||||
|
||||
/* Reset mock data (for use before each test) */
|
||||
static void ResetMocks(void)
|
||||
{
|
||||
Memset(&cparams, 0, sizeof(cparams));
|
||||
cparams.shared_data_size = sizeof(shared_data);
|
||||
cparams.shared_data_blob = shared_data;
|
||||
cparams.gbb_data = &gbb;
|
||||
cparams.gbb_size = sizeof(gbb);
|
||||
|
||||
Memset(&gbb, 0, sizeof(gbb));
|
||||
gbb.major_version = GBB_MAJOR_VER;
|
||||
gbb.minor_version = GBB_MINOR_VER;
|
||||
gbb.flags = 0;
|
||||
|
||||
Memset(&iparams, 0, sizeof(iparams));
|
||||
|
||||
Memset(&vnc, 0, sizeof(vnc));
|
||||
VbNvSetup(&vnc);
|
||||
VbNvTeardown(&vnc); /* So CRC gets generated */
|
||||
|
||||
Memset(backup_space, 0, sizeof(backup_space));
|
||||
backup_write_called = 0;
|
||||
backup_read_called = 0;
|
||||
|
||||
Memset(&shared_data, 0, sizeof(shared_data));
|
||||
VbSharedDataInit(shared, sizeof(shared_data));
|
||||
|
||||
mock_timer = 10;
|
||||
rollback_s3_retval = TPM_SUCCESS;
|
||||
nv_write_called = 0;
|
||||
|
||||
mock_virt_dev_sw = 0;
|
||||
mock_tpm_version = 0x10001;
|
||||
mock_rfs_retval = 0;
|
||||
|
||||
rfs_clear_tpm_request = 0;
|
||||
rfs_disable_dev_request = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Mocked verification functions */
|
||||
|
||||
VbError_t VbExNvStorageRead(uint8_t *buf)
|
||||
{
|
||||
Memcpy(buf, vnc.raw, sizeof(vnc.raw));
|
||||
return VBERROR_SUCCESS;
|
||||
}
|
||||
|
||||
VbError_t VbExNvStorageWrite(const uint8_t *buf)
|
||||
{
|
||||
nv_write_called++;
|
||||
Memcpy(vnc.raw, buf, sizeof(vnc.raw));
|
||||
return VBERROR_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t RollbackBackupRead(uint8_t *raw)
|
||||
{
|
||||
backup_read_called++;
|
||||
Memcpy(raw, backup_space, sizeof(backup_space));
|
||||
return TPM_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t RollbackBackupWrite(uint8_t *raw)
|
||||
{
|
||||
backup_write_called++;
|
||||
Memcpy(backup_space, raw, sizeof(backup_space));
|
||||
return TPM_SUCCESS;
|
||||
}
|
||||
|
||||
uint64_t VbExGetTimer(void)
|
||||
{
|
||||
/*
|
||||
* Exponential-ish rather than linear time, so that subtracting any
|
||||
* two mock values will yield a unique result.
|
||||
*/
|
||||
uint64_t new_timer = mock_timer * 2 + 1;
|
||||
VbAssert(new_timer > mock_timer); /* Make sure we don't overflow */
|
||||
mock_timer = new_timer;
|
||||
return mock_timer;
|
||||
}
|
||||
|
||||
uint32_t RollbackS3Resume(void)
|
||||
{
|
||||
return rollback_s3_retval;
|
||||
}
|
||||
|
||||
uint32_t RollbackFirmwareSetup(int is_hw_dev,
|
||||
int disable_dev_request,
|
||||
int clear_tpm_owner_request,
|
||||
/* two outputs on success */
|
||||
int *is_virt_dev, uint32_t *version)
|
||||
{
|
||||
rfs_clear_tpm_request = clear_tpm_owner_request;
|
||||
rfs_disable_dev_request = disable_dev_request;
|
||||
|
||||
*is_virt_dev = mock_virt_dev_sw;
|
||||
*version = mock_tpm_version;
|
||||
return mock_rfs_retval;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Test VbInit() and check expected return value and recovery reason */
|
||||
|
||||
static void TestVbInit(VbError_t expected_retval,
|
||||
uint8_t expected_recovery, const char *desc)
|
||||
{
|
||||
uint32_t rr = 256;
|
||||
|
||||
TEST_EQ(VbInit(&cparams, &iparams), expected_retval, desc);
|
||||
VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &rr);
|
||||
TEST_EQ(rr, expected_recovery, " (recovery request)");
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void VbInitTest(void)
|
||||
{
|
||||
uint32_t u;
|
||||
|
||||
/* Test passing in too small a shared data area */
|
||||
ResetMocks();
|
||||
cparams.shared_data_size = VB_SHARED_DATA_MIN_SIZE - 1;
|
||||
TestVbInit(VBERROR_INIT_SHARED_DATA, 0, "Shared data too small");
|
||||
|
||||
/* Normal call; dev=0 rec=0 */
|
||||
ResetMocks();
|
||||
TestVbInit(0, 0, "Normal call");
|
||||
TEST_EQ(shared->timer_vb_init_enter, 21, " time enter");
|
||||
TEST_EQ(shared->timer_vb_init_exit, 43, " time exit");
|
||||
TEST_EQ(shared->flags, 0, " shared flags");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
TEST_EQ(nv_write_called, 0,
|
||||
" NV write not called since nothing changed");
|
||||
|
||||
/* If NV data is trashed, we initialize it */
|
||||
ResetMocks();
|
||||
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
|
||||
/*
|
||||
* Note that we're not doing a VbNvTeardown(), so the CRC hasn't been
|
||||
* regenerated yet. So VbInit() should ignore the corrupted recovery
|
||||
* value and boot normally.
|
||||
*/
|
||||
TestVbInit(0, 0, "NV data trashed");
|
||||
TEST_EQ(nv_write_called, 1, " NV write called");
|
||||
|
||||
/*
|
||||
* Test boot switch flags which are just passed through to shared
|
||||
* flags, and don't have an effect on VbInit().
|
||||
*/
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_WP_ENABLED;
|
||||
TestVbInit(0, 0, "Flags test WP");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_FIRMWARE_WP_ENABLED,
|
||||
" shared flags");
|
||||
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_SW_WP_ENABLED;
|
||||
TestVbInit(0, 0, "Flags test SW WP");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_FIRMWARE_SW_WP_ENABLED,
|
||||
" shared flags");
|
||||
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_RO_NORMAL_SUPPORT;
|
||||
TestVbInit(0, 0, " flags test RO normal");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_RO_NORMAL_SUPPORT,
|
||||
" shared flags");
|
||||
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_EC_SOFTWARE_SYNC;
|
||||
TestVbInit(0, 0, " flags test EC software sync");
|
||||
TEST_EQ(shared->flags, VBSD_EC_SOFTWARE_SYNC, " shared flags");
|
||||
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_EC_SLOW_UPDATE;
|
||||
TestVbInit(0, 0, " flags test EC slow update");
|
||||
TEST_EQ(shared->flags, VBSD_EC_SLOW_UPDATE, " shared flags");
|
||||
|
||||
/* S3 resume */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_S3_RESUME;
|
||||
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
|
||||
VbNvTeardown(&vnc);
|
||||
/* S3 resume doesn't clear the recovery request (or act on it) */
|
||||
TestVbInit(0, 123, "S3 resume");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_S3_RESUME, " shared flags S3");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
TEST_EQ(shared->recovery_reason, 0,
|
||||
" S3 doesn't look at recovery request");
|
||||
|
||||
/* S3 resume with TPM resume error */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_S3_RESUME;
|
||||
rollback_s3_retval = 1;
|
||||
/* S3 resume doesn't clear the recovery request (or act on it) */
|
||||
TestVbInit(VBERROR_TPM_S3_RESUME, 0, "S3 resume rollback error");
|
||||
|
||||
/*
|
||||
* Normal boot doesn't care about TPM resume error because it doesn't
|
||||
* call RollbackS3Resume().
|
||||
*/
|
||||
ResetMocks();
|
||||
rollback_s3_retval = 1;
|
||||
TestVbInit(0, 0, "Normal doesn't S3 resume");
|
||||
|
||||
/* S3 resume with debug reset */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_S3_RESUME;
|
||||
VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "S3 debug reset");
|
||||
TEST_EQ(iparams.out_flags, VB_INIT_OUT_S3_DEBUG_BOOT, " out flags");
|
||||
VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &u);
|
||||
TEST_EQ(u, 0, " S3 clears nv debug reset mode");
|
||||
|
||||
/* Normal boot clears S3 debug reset mode; doesn't set output flag */
|
||||
ResetMocks();
|
||||
VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "Normal with debug reset mode");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &u);
|
||||
TEST_EQ(u, 0, " normal clears nv debug reset mode");
|
||||
|
||||
/*
|
||||
* S3 resume with debug reset is a normal boot, so doesn't resume the
|
||||
* TPM.
|
||||
*/
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_S3_RESUME;
|
||||
rollback_s3_retval = 1;
|
||||
VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "S3 debug reset rollback error");
|
||||
|
||||
/* Developer mode */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON;
|
||||
TestVbInit(0, 0, "Dev mode on");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER |
|
||||
VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
|
||||
|
||||
/* Developer mode forced by GBB flag */
|
||||
ResetMocks();
|
||||
iparams.flags = 0;
|
||||
gbb.flags = GBB_FLAG_FORCE_DEV_SWITCH_ON;
|
||||
TestVbInit(0, 0, "Dev mode via GBB");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER |
|
||||
VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
|
||||
|
||||
/* Developer mode when option ROM matters and isn't loaded */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON |
|
||||
VB_INIT_FLAG_OPROM_MATTERS;
|
||||
TestVbInit(VBERROR_VGA_OPROM_MISMATCH, 0, "Dev mode need oprom");
|
||||
VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u);
|
||||
TEST_EQ(u, 1, " oprom requested");
|
||||
|
||||
/* Developer mode when option ROM matters and is already loaded */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON |
|
||||
VB_INIT_FLAG_OPROM_MATTERS | VB_INIT_FLAG_OPROM_LOADED;
|
||||
TestVbInit(0, 0, "Dev mode has oprom");
|
||||
|
||||
/* Normal mode when option ROM matters and is loaded */
|
||||
ResetMocks();
|
||||
VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
iparams.flags = VB_INIT_FLAG_OPROM_MATTERS | VB_INIT_FLAG_OPROM_LOADED;
|
||||
TestVbInit(VBERROR_VGA_OPROM_MISMATCH, 0, "Normal mode with oprom");
|
||||
VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u);
|
||||
TEST_EQ(u, 0, " oprom not requested");
|
||||
|
||||
/* Option ROMs can be forced by GBB flag */
|
||||
ResetMocks();
|
||||
gbb.flags = GBB_FLAG_LOAD_OPTION_ROMS;
|
||||
TestVbInit(0, 0, "GBB load option ROMs");
|
||||
TEST_EQ(iparams.out_flags, VB_INIT_OUT_ENABLE_OPROM, " out flags");
|
||||
|
||||
/* If requiring signed only, don't enable alternate OS by default */
|
||||
ResetMocks();
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON;
|
||||
TestVbInit(0, 0, "Dev signed only");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER, " out flags");
|
||||
|
||||
/* But that can be overridden by the GBB */
|
||||
ResetMocks();
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON;
|
||||
gbb.flags = GBB_FLAG_ENABLE_ALTERNATE_OS;
|
||||
TestVbInit(0, 0, "Force option ROMs via GBB");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER |
|
||||
VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
|
||||
|
||||
/* The GBB override is ignored in normal mode */
|
||||
ResetMocks();
|
||||
gbb.flags = GBB_FLAG_ENABLE_ALTERNATE_OS;
|
||||
TestVbInit(0, 0, "Normal mode ignores forcing option ROMs via GBB");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
|
||||
/* Recovery mode from NV storage */
|
||||
ResetMocks();
|
||||
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "Recovery mode - from nv");
|
||||
TEST_EQ(shared->recovery_reason, 123, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_ENABLE_RECOVERY |
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags");
|
||||
TEST_EQ(shared->flags, 0, " shared flags");
|
||||
|
||||
/* Recovery mode from recovery button */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED;
|
||||
TestVbInit(0, 0, "Recovery mode - button");
|
||||
TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_MANUAL,
|
||||
" recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_ENABLE_RECOVERY |
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_REC_SWITCH_ON, " shared flags");
|
||||
|
||||
/* Recovery button reason supersedes NV reason */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED;
|
||||
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "Recovery mode - button AND nv");
|
||||
TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_MANUAL,
|
||||
" recovery reason");
|
||||
|
||||
/* Recovery mode from previous boot fail */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_PREVIOUS_BOOT_FAIL;
|
||||
TestVbInit(0, 0, "Recovery mode - previous boot fail");
|
||||
TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_FIRMWARE,
|
||||
" recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_ENABLE_RECOVERY |
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags");
|
||||
TEST_EQ(shared->flags, 0, " shared flags");
|
||||
|
||||
/* Recovery mode from NV supersedes previous boot fail */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_PREVIOUS_BOOT_FAIL;
|
||||
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, 123);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "Recovery mode - previous boot fail AND nv");
|
||||
TEST_EQ(shared->recovery_reason, 123, " recovery reason");
|
||||
|
||||
/* Dev + recovery = recovery */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED |
|
||||
VB_INIT_FLAG_DEV_SWITCH_ON;
|
||||
TestVbInit(0, 0, "Recovery mode - button");
|
||||
TEST_EQ(shared->recovery_reason, VBNV_RECOVERY_RO_MANUAL,
|
||||
" recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_ENABLE_RECOVERY |
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE, " out flags");
|
||||
TEST_EQ(shared->flags,
|
||||
VBSD_BOOT_REC_SWITCH_ON | VBSD_BOOT_DEV_SWITCH_ON,
|
||||
" shared flags");
|
||||
}
|
||||
|
||||
static void VbInitTestTPM(void)
|
||||
{
|
||||
uint32_t u;
|
||||
|
||||
/* Rollback setup needs to reboot */
|
||||
ResetMocks();
|
||||
mock_rfs_retval = TPM_E_MUST_REBOOT;
|
||||
TestVbInit(VBERROR_TPM_REBOOT_REQUIRED, 0,
|
||||
"Rollback TPM reboot (rec=0)");
|
||||
ResetMocks();
|
||||
mock_rfs_retval = TPM_E_MUST_REBOOT;
|
||||
iparams.flags = VB_INIT_FLAG_REC_BUTTON_PRESSED;
|
||||
TestVbInit(VBERROR_TPM_REBOOT_REQUIRED, VBNV_RECOVERY_RO_TPM_REBOOT,
|
||||
"Rollback TPM reboot, in recovery, first time");
|
||||
/* Ignore if we already tried rebooting */
|
||||
ResetMocks();
|
||||
mock_rfs_retval = TPM_E_MUST_REBOOT;
|
||||
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_REBOOT);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "Rollback TPM reboot, in recovery, already retried");
|
||||
TEST_EQ(shared->fw_version_tpm, 0x10001, " shared fw_version_tpm");
|
||||
|
||||
/* Other rollback setup errors */
|
||||
ResetMocks();
|
||||
mock_rfs_retval = TPM_E_IOERROR;
|
||||
mock_tpm_version = 0x20002;
|
||||
TestVbInit(VBERROR_TPM_FIRMWARE_SETUP, VBNV_RECOVERY_RO_TPM_S_ERROR,
|
||||
"Rollback TPM setup error - not in recovery");
|
||||
TEST_EQ(shared->fw_version_tpm, 0, " shared fw_version_tpm not set");
|
||||
ResetMocks();
|
||||
mock_rfs_retval = TPM_E_IOERROR;
|
||||
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_US_TEST);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "Rollback TPM setup error ignored in recovery");
|
||||
TEST_EQ(shared->fw_version_tpm, 0x10001, " shared fw_version_tpm");
|
||||
|
||||
/* Virtual developer switch, but not enabled. */
|
||||
ResetMocks();
|
||||
VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
iparams.flags = VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
|
||||
TestVbInit(0, 0, "TPM Dev mode off");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
TEST_EQ(shared->flags, VBSD_HONOR_VIRT_DEV_SWITCH, " shared flags");
|
||||
VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &u);
|
||||
TEST_EQ(u, 0, " disable dev request");
|
||||
|
||||
/* Virtual developer switch, enabled. */
|
||||
ResetMocks();
|
||||
VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
iparams.flags = VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
|
||||
mock_virt_dev_sw = 1;
|
||||
TestVbInit(0, 0, "TPM Dev mode on");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER |
|
||||
VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
|
||||
TEST_EQ(shared->flags,
|
||||
VBSD_BOOT_DEV_SWITCH_ON | VBSD_HONOR_VIRT_DEV_SWITCH,
|
||||
" shared flags");
|
||||
/* Disable-request doesn't get cleared because dev mode is still on */
|
||||
VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &u);
|
||||
TEST_EQ(u, 1, " disable dev request");
|
||||
/* Disable request was passed on to RollbackFirmwareSetup() */
|
||||
TEST_EQ(rfs_disable_dev_request, 1, " rfs disable dev");
|
||||
|
||||
/* Ignore virtual developer switch, even though enabled. */
|
||||
ResetMocks();
|
||||
mock_virt_dev_sw = 1;
|
||||
TestVbInit(0, 0, "TPM Dev mode on but ignored");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
TEST_EQ(shared->flags, 0, " shared flags");
|
||||
|
||||
/* HW dev switch on, no virtual developer switch */
|
||||
ResetMocks();
|
||||
iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON;
|
||||
TestVbInit(0, 0, "HW Dev mode on");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER |
|
||||
VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
|
||||
|
||||
/* Check TPM owner clear request */
|
||||
ResetMocks();
|
||||
VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "TPM clear owner");
|
||||
VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, &u);
|
||||
TEST_EQ(u, 0, " tpm clear request");
|
||||
VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_DONE, &u);
|
||||
TEST_EQ(u, 1, " tpm clear request");
|
||||
TEST_EQ(rfs_clear_tpm_request, 1, "rfs tpm clear request");
|
||||
}
|
||||
|
||||
static void VbInitTestBackup(void)
|
||||
{
|
||||
VbNvContext tmp_vnc;
|
||||
uint32_t u, nv_w, bu_r;
|
||||
|
||||
ResetMocks();
|
||||
/* Normal mode call */
|
||||
TestVbInit(0, 0, "normal mode, no backup");
|
||||
TEST_EQ(shared->flags, 0, " shared flags");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
TEST_EQ(nv_write_called, 0,
|
||||
" NV write not called since nothing changed");
|
||||
|
||||
ResetMocks();
|
||||
/* Now set some params that should be backed up. */
|
||||
VbNvSet(&vnc, VBNV_KERNEL_FIELD, 0xaabbccdd);
|
||||
VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 0xa5);
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 1);
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 1);
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, 1);
|
||||
VbNvSet(&vnc, VBNV_DEV_DEFAULT_BOOT, 1);
|
||||
VbNvSet(&vnc, VBNV_FASTBOOT_UNLOCK_IN_FW, 1);
|
||||
/* and some that don't */
|
||||
VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
|
||||
VbNvSet(&vnc, VBNV_TRY_B_COUNT, 3);
|
||||
/* Make sure they're clean */
|
||||
VbNvTeardown(&vnc);
|
||||
/* Normal mode call */
|
||||
TestVbInit(0, 0, "normal mode, some backup");
|
||||
TEST_EQ(shared->flags, 0, " shared flags");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
TEST_EQ(nv_write_called, 1,
|
||||
" Write NV because things have changed");
|
||||
/* Some fields should be unchanged */
|
||||
VbNvGet(&vnc, VBNV_KERNEL_FIELD, &u);
|
||||
TEST_EQ(u, 0xaabbccdd, " NV kernel field");
|
||||
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
|
||||
TEST_EQ(u, 0xa5, " NV localization index");
|
||||
VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u);
|
||||
TEST_EQ(u, 1, " NV oprom_needed");
|
||||
VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u);
|
||||
TEST_EQ(u, 3, " NV try_b_count");
|
||||
/* But normal mode should have cleared the DEV_BOOT flags */
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &u);
|
||||
TEST_EQ(u, 0, " NV dev_boot_usb");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_LEGACY, &u);
|
||||
TEST_EQ(u, 0, " NV dev_boot_legacy");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u);
|
||||
TEST_EQ(u, 0, " NV dev_boot_signed_only");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, &u);
|
||||
TEST_EQ(u, 0, " NV dev_boot_fastboot_full_cap");
|
||||
VbNvGet(&vnc, VBNV_DEV_DEFAULT_BOOT, &u);
|
||||
TEST_EQ(u, 0, " NV dev_default_boot");
|
||||
VbNvGet(&vnc, VBNV_FASTBOOT_UNLOCK_IN_FW, &u);
|
||||
TEST_EQ(u, 0, " NV_fastboot_unlock_in_fw ");
|
||||
/* So we should have written the backup */
|
||||
TEST_EQ(backup_write_called, 1, " Backup written once");
|
||||
/* And the backup should reflect the persisent flags. */
|
||||
Memset(&tmp_vnc, 0, sizeof(tmp_vnc));
|
||||
TEST_EQ(0, RestoreNvFromBackup(&tmp_vnc), "read from backup");
|
||||
VbNvGet(&tmp_vnc, VBNV_KERNEL_FIELD, &u);
|
||||
TEST_EQ(u, 0xaabbccdd, " BU kernel field");
|
||||
VbNvGet(&tmp_vnc, VBNV_LOCALIZATION_INDEX, &u);
|
||||
TEST_EQ(u, 0xa5, " BU localization index");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_USB, &u);
|
||||
TEST_EQ(u, 0, " BU dev_boot_usb");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_LEGACY, &u);
|
||||
TEST_EQ(u, 0, " BU dev_boot_legacy");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u);
|
||||
TEST_EQ(u, 0, " BU dev_boot_signed_only");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, &u);
|
||||
TEST_EQ(u, 0, " BU dev_boot_fastboot_full_cap");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_DEFAULT_BOOT, &u);
|
||||
TEST_EQ(u, 0, " BU dev_default_boot");
|
||||
VbNvGet(&tmp_vnc, VBNV_FASTBOOT_UNLOCK_IN_FW, &u);
|
||||
TEST_EQ(u, 0, " BU fastboot_unlock_in_fw");
|
||||
/* but not the others */
|
||||
VbNvGet(&tmp_vnc, VBNV_OPROM_NEEDED, &u);
|
||||
TEST_EQ(u, 0, " BU oprom_needed");
|
||||
VbNvGet(&tmp_vnc, VBNV_TRY_B_COUNT, &u);
|
||||
TEST_EQ(u, 0, " BU try_b_count");
|
||||
|
||||
/*
|
||||
* If we change one of the non-backed-up NVRAM params and try
|
||||
* again, we shouldn't need to backup again.
|
||||
*/
|
||||
VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0);
|
||||
VbNvSet(&vnc, VBNV_TRY_B_COUNT, 2);
|
||||
/* Make sure they're clean */
|
||||
VbNvTeardown(&vnc);
|
||||
/* Normal mode call */
|
||||
TestVbInit(0, 0, "normal mode, expect no backup");
|
||||
TEST_EQ(shared->flags, 0, " shared flags");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
TEST_EQ(backup_write_called, 1, " Backup still only written once");
|
||||
|
||||
/* Now switch to dev-mode. */
|
||||
iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON;
|
||||
TestVbInit(0, 0, "Dev mode on");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER |
|
||||
VB_INIT_OUT_ENABLE_ALTERNATE_OS, " out flags");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
|
||||
TEST_EQ(backup_write_called, 1, " Still only one backup");
|
||||
|
||||
/* Now change some params that should be backed up. */
|
||||
VbNvSet(&vnc, VBNV_KERNEL_FIELD, 0xdeadbeef);
|
||||
VbNvSet(&vnc, VBNV_LOCALIZATION_INDEX, 0x5a);
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 1);
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 1);
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
|
||||
VbNvSet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, 1);
|
||||
VbNvSet(&vnc, VBNV_DEV_DEFAULT_BOOT, 1);
|
||||
VbNvSet(&vnc, VBNV_FASTBOOT_UNLOCK_IN_FW, 1);
|
||||
/* and some that don't */
|
||||
VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
|
||||
VbNvSet(&vnc, VBNV_TRY_B_COUNT, 4);
|
||||
/* Make sure they're clean */
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "Dev mode on");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER, " out flags");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
|
||||
TEST_EQ(backup_write_called, 1, " Once more, one backup");
|
||||
|
||||
/* But if we explicitly request a backup, they'll get saved. */
|
||||
VbNvSet(&vnc, VBNV_BACKUP_NVRAM_REQUEST, 1);
|
||||
VbNvTeardown(&vnc);
|
||||
TestVbInit(0, 0, "Dev mode on");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER, " out flags");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
|
||||
TEST_EQ(backup_write_called, 2, " Two backups now");
|
||||
VbNvGet(&vnc, VBNV_BACKUP_NVRAM_REQUEST, &u);
|
||||
TEST_EQ(u, 0, " backup_request cleared");
|
||||
/* Quick check that the non-backed-up stuff is still valid */
|
||||
VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u);
|
||||
TEST_EQ(u, 1, " NV oprom_needed");
|
||||
VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u);
|
||||
TEST_EQ(u, 4, " NV try_b_count");
|
||||
/* But only the stuff we care about was backed up */
|
||||
Memset(&tmp_vnc, 0, sizeof(tmp_vnc));
|
||||
TEST_EQ(0, RestoreNvFromBackup(&tmp_vnc), "read from backup");
|
||||
VbNvGet(&tmp_vnc, VBNV_KERNEL_FIELD, &u);
|
||||
TEST_EQ(u, 0xdeadbeef, " BU kernel field");
|
||||
VbNvGet(&tmp_vnc, VBNV_LOCALIZATION_INDEX, &u);
|
||||
TEST_EQ(u, 0x5a, " BU localization index");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_USB, &u);
|
||||
TEST_EQ(u, 1, " BU dev_boot_usb");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_LEGACY, &u);
|
||||
TEST_EQ(u, 1, " BU dev_boot_legacy");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u);
|
||||
TEST_EQ(u, 1, " BU dev_boot_signed_only");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, &u);
|
||||
TEST_EQ(u, 1, " BU dev_boot_fastboot_full_cap");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_DEFAULT_BOOT, &u);
|
||||
TEST_EQ(u, 1, " BU dev_default_boot");
|
||||
VbNvGet(&tmp_vnc, VBNV_FASTBOOT_UNLOCK_IN_FW, &u);
|
||||
TEST_EQ(u, 1, " BU fastboot_unlock_in_fw");
|
||||
/* but not the others */
|
||||
VbNvGet(&tmp_vnc, VBNV_OPROM_NEEDED, &u);
|
||||
TEST_EQ(u, 0, " BU oprom_needed");
|
||||
VbNvGet(&tmp_vnc, VBNV_TRY_B_COUNT, &u);
|
||||
TEST_EQ(u, 0, " BU try_b_count");
|
||||
|
||||
/* If we lose the NV storage, the backup bits will be restored */
|
||||
vnc.raw[0] = 0;
|
||||
bu_r = backup_read_called;
|
||||
nv_w = nv_write_called;
|
||||
TestVbInit(0, 0, "Dev mode on");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags,
|
||||
VB_INIT_OUT_CLEAR_RAM |
|
||||
VB_INIT_OUT_ENABLE_DISPLAY |
|
||||
VB_INIT_OUT_ENABLE_USB_STORAGE |
|
||||
VB_INIT_OUT_ENABLE_DEVELOPER, " out flags");
|
||||
TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
|
||||
TEST_EQ(backup_write_called, 2, " Still just two backups now");
|
||||
TEST_EQ(backup_read_called, bu_r + 1, " One more backup read");
|
||||
TEST_EQ(nv_write_called, nv_w + 1, " One more NV write");
|
||||
/* The non-backed-up stuff is reset to defaults */
|
||||
VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u);
|
||||
TEST_EQ(u, 0, " NV oprom_needed");
|
||||
VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u);
|
||||
TEST_EQ(u, 0, " NV try_b_count");
|
||||
/* And the backed up stuff is restored */
|
||||
VbNvGet(&vnc, VBNV_KERNEL_FIELD, &u);
|
||||
TEST_EQ(u, 0xdeadbeef, " BU kernel field");
|
||||
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
|
||||
TEST_EQ(u, 0x5a, " BU localization index");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &u);
|
||||
TEST_EQ(u, 1, " BU dev_boot_usb");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_LEGACY, &u);
|
||||
TEST_EQ(u, 1, " BU dev_boot_legacy");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u);
|
||||
TEST_EQ(u, 1, " BU dev_boot_signed_only");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, &u);
|
||||
TEST_EQ(u, 1, " BU dev_boot_fastboot_full_cap");
|
||||
VbNvGet(&tmp_vnc, VBNV_DEV_DEFAULT_BOOT, &u);
|
||||
TEST_EQ(u, 1, " BU dev_default_boot");
|
||||
VbNvGet(&vnc, VBNV_FASTBOOT_UNLOCK_IN_FW, &u);
|
||||
TEST_EQ(u, 1, " BU fastboot_unlock_in_fw");
|
||||
|
||||
/*
|
||||
* But if we lose the NV storage and go back to normal mode at the same
|
||||
* time, then the DEV_BOOT_* flags will be cleared.
|
||||
*/
|
||||
vnc.raw[0] = 0;
|
||||
bu_r = backup_read_called;
|
||||
nv_w = nv_write_called;
|
||||
iparams.flags = 0;
|
||||
TestVbInit(0, 0, "Back to normal mode");
|
||||
TEST_EQ(shared->recovery_reason, 0, " recovery reason");
|
||||
TEST_EQ(iparams.out_flags, 0, " out flags");
|
||||
TEST_EQ(shared->flags, 0, " shared flags");
|
||||
/* We read twice: once to restore, once for read-prior-to-write */
|
||||
TEST_EQ(backup_read_called, bu_r + 2, " Two more backup reads");
|
||||
TEST_EQ(backup_write_called, 3, " Backup write due clearing DEV_*");
|
||||
TEST_EQ(nv_write_called, nv_w + 1, " One more NV write");
|
||||
/* The non-backed-up stuff is reset to defaults */
|
||||
VbNvGet(&vnc, VBNV_OPROM_NEEDED, &u);
|
||||
TEST_EQ(u, 0, " NV oprom_needed");
|
||||
VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u);
|
||||
TEST_EQ(u, 0, " NV try_b_count");
|
||||
/* And the backed up stuff is restored */
|
||||
VbNvGet(&vnc, VBNV_KERNEL_FIELD, &u);
|
||||
TEST_EQ(u, 0xdeadbeef, " BU kernel field");
|
||||
VbNvGet(&vnc, VBNV_LOCALIZATION_INDEX, &u);
|
||||
TEST_EQ(u, 0x5a, " BU localization index");
|
||||
/* But not the DEV_BOOT_* flags */
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &u);
|
||||
TEST_EQ(u, 0, " BU dev_boot_usb");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_LEGACY, &u);
|
||||
TEST_EQ(u, 0, " BU dev_boot_legacy");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &u);
|
||||
TEST_EQ(u, 0, " BU dev_boot_signed_only");
|
||||
VbNvGet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, &u);
|
||||
TEST_EQ(u, 0, " BU dev_boot_fastboot_full_cap");
|
||||
VbNvGet(&vnc, VBNV_DEV_DEFAULT_BOOT, &u);
|
||||
TEST_EQ(u, 0, " BU dev_default_boot");
|
||||
VbNvGet(&vnc, VBNV_FASTBOOT_UNLOCK_IN_FW, &u);
|
||||
TEST_EQ(u, 0, " BU fastboot_unlock_in_fw");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
VbInitTest();
|
||||
VbInitTestTPM();
|
||||
VbInitTestBackup();
|
||||
|
||||
return gTestSuccess ? 0 : 255;
|
||||
}
|
||||
@@ -1,503 +0,0 @@
|
||||
/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* Tests for vboot_firmware library.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "2sysincludes.h"
|
||||
|
||||
#include "2common.h"
|
||||
#include "2sha.h"
|
||||
#include "gbb_header.h"
|
||||
#include "host_common.h"
|
||||
#include "load_firmware_fw.h"
|
||||
#include "test_common.h"
|
||||
#include "vboot_common.h"
|
||||
#include "vboot_nvstorage.h"
|
||||
#include "vboot_struct.h"
|
||||
|
||||
/* Mock data */
|
||||
static VbCommonParams cparams;
|
||||
static VbSelectFirmwareParams fparams;
|
||||
static VbKeyBlockHeader vblock[2];
|
||||
static VbFirmwarePreambleHeader mpreamble[2];
|
||||
static VbNvContext vnc;
|
||||
static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
|
||||
static VbSharedDataHeader* shared = (VbSharedDataHeader*)shared_data;
|
||||
static uint8_t gbb_data[sizeof(GoogleBinaryBlockHeader) + 2048];
|
||||
static GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)gbb_data;
|
||||
static RSAPublicKey data_key;
|
||||
static uint32_t digest_size;
|
||||
static uint8_t* digest_expect_ptr;
|
||||
static int hash_fw_index;
|
||||
|
||||
#define TEST_KEY_DATA \
|
||||
"Test contents for the root key this should be 64 chars long."
|
||||
|
||||
/* Reset mock data (for use before each test) */
|
||||
static void ResetMocks(void) {
|
||||
VbPublicKey *root_key;
|
||||
uint8_t *root_key_data;
|
||||
int i;
|
||||
|
||||
Memset(&cparams, 0, sizeof(cparams));
|
||||
cparams.shared_data_blob = shared_data;
|
||||
cparams.gbb_data = gbb_data;
|
||||
cparams.gbb_size = sizeof(gbb_data);
|
||||
cparams.gbb = gbb;
|
||||
|
||||
Memset(&fparams, 0, sizeof(fparams));
|
||||
fparams.verification_block_A = vblock;
|
||||
fparams.verification_size_A = sizeof(VbKeyBlockHeader);
|
||||
fparams.verification_block_B = vblock + 1;
|
||||
fparams.verification_size_B = sizeof(VbKeyBlockHeader);
|
||||
|
||||
Memset(vblock, 0, sizeof(vblock));
|
||||
Memset(mpreamble, 0, sizeof(mpreamble));
|
||||
for (i = 0; i < 2; i++) {
|
||||
/* Default verification blocks to working in all modes */
|
||||
vblock[i].key_block_flags = 0x0F;
|
||||
vblock[i].data_key.key_version = 2;
|
||||
/* Fix up offsets to preambles */
|
||||
vblock[i].key_block_size =
|
||||
(uint8_t*)(mpreamble + i) - (uint8_t*)(vblock + i);
|
||||
|
||||
mpreamble[i].header_version_minor = 1; /* Supports preamble flags */
|
||||
mpreamble[i].firmware_version = 4;
|
||||
/* Point kernel subkey to some data following the key header */
|
||||
PublicKeyInit(&mpreamble[i].kernel_subkey,
|
||||
(uint8_t*)&mpreamble[i].body_signature, 20);
|
||||
mpreamble[i].kernel_subkey.algorithm = 7 + i;
|
||||
mpreamble[i].body_signature.data_size = 20000 + 1000 * i;
|
||||
}
|
||||
|
||||
Memset(&vnc, 0, sizeof(vnc));
|
||||
VbNvSetup(&vnc);
|
||||
|
||||
Memset(&shared_data, 0, sizeof(shared_data));
|
||||
VbSharedDataInit(shared, sizeof(shared_data));
|
||||
shared->fw_version_tpm = 0x00020004;
|
||||
|
||||
Memset(&gbb_data, 0, sizeof(gbb_data));
|
||||
gbb->rootkey_offset = sizeof(GoogleBinaryBlockHeader);
|
||||
root_key = (VbPublicKey *)(gbb_data + gbb->rootkey_offset);
|
||||
root_key_data = (uint8_t *)(root_key + 1);
|
||||
strcpy((char *)root_key_data, TEST_KEY_DATA);
|
||||
PublicKeyInit(root_key, (uint8_t *)root_key_data, sizeof(TEST_KEY_DATA));
|
||||
|
||||
gbb->major_version = GBB_MAJOR_VER;
|
||||
gbb->minor_version = GBB_MINOR_VER;
|
||||
gbb->flags = 0;
|
||||
|
||||
Memset(&data_key, 0, sizeof(data_key));
|
||||
|
||||
digest_size = 1234;
|
||||
digest_expect_ptr = NULL;
|
||||
hash_fw_index = -1;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Mocked verification functions */
|
||||
|
||||
int KeyBlockVerify(const VbKeyBlockHeader* block, uint64_t size,
|
||||
const VbPublicKey *key, int hash_only) {
|
||||
|
||||
TEST_EQ(hash_only, 0, " Don't verify firmware with hash");
|
||||
|
||||
/*
|
||||
* We cannot check the address of key, since it will be allocated. We
|
||||
* check the contents instead.
|
||||
*/
|
||||
TEST_STR_EQ((char *)GetPublicKeyDataC(key), TEST_KEY_DATA,
|
||||
" Verify with root key");
|
||||
TEST_NEQ(block==vblock || block==vblock+1, 0, " Verify a valid key block");
|
||||
|
||||
/* Mock uses header_version_major to hold return value */
|
||||
return block->header_version_major;
|
||||
}
|
||||
|
||||
int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader* preamble,
|
||||
uint64_t size, const RSAPublicKey* key) {
|
||||
TEST_PTR_EQ(key, &data_key, " Verify preamble data key");
|
||||
TEST_NEQ(preamble==mpreamble || preamble==mpreamble+1, 0,
|
||||
" Verify a valid preamble");
|
||||
|
||||
/* Mock uses header_version_major to hold return value */
|
||||
return preamble->header_version_major;
|
||||
}
|
||||
|
||||
RSAPublicKey* PublicKeyToRSA(const VbPublicKey* key) {
|
||||
/* Mock uses algorithm!0 to mean invalid key */
|
||||
if (key->algorithm)
|
||||
return NULL;
|
||||
/* Mock uses data key len to hold number of alloc'd keys */
|
||||
data_key.len++;
|
||||
return &data_key;
|
||||
}
|
||||
|
||||
void RSAPublicKeyFree(RSAPublicKey* key) {
|
||||
TEST_PTR_EQ(key, &data_key, " RSA data key");
|
||||
data_key.len--;
|
||||
}
|
||||
|
||||
int vb2_digest_init(struct vb2_digest_context *dc,
|
||||
enum vb2_hash_algorithm hash_alg)
|
||||
{
|
||||
digest_size = 0;
|
||||
return VB2_SUCCESS;
|
||||
}
|
||||
|
||||
int vb2_digest_extend(struct vb2_digest_context *dc,
|
||||
const uint8_t *buf,
|
||||
uint32_t size)
|
||||
{
|
||||
TEST_PTR_EQ(buf, digest_expect_ptr, " Digesting expected data");
|
||||
digest_size += size;
|
||||
return VB2_SUCCESS;
|
||||
}
|
||||
|
||||
int vb2_digest_finalize(struct vb2_digest_context *dc,
|
||||
uint8_t *digest,
|
||||
uint32_t digest_size)
|
||||
{
|
||||
return VB2_SUCCESS;
|
||||
}
|
||||
|
||||
VbError_t VbExHashFirmwareBody(VbCommonParams* cparams,
|
||||
uint32_t firmware_index) {
|
||||
if (VB_SELECT_FIRMWARE_A == firmware_index)
|
||||
hash_fw_index = 0;
|
||||
else if (VB_SELECT_FIRMWARE_B == firmware_index)
|
||||
hash_fw_index = 1;
|
||||
else
|
||||
return VBERROR_INVALID_PARAMETER;
|
||||
|
||||
digest_expect_ptr = (uint8_t*)(vblock + hash_fw_index) + 5;
|
||||
VbUpdateFirmwareBodyHash(
|
||||
cparams, digest_expect_ptr,
|
||||
mpreamble[hash_fw_index].body_signature.data_size - 1024);
|
||||
VbUpdateFirmwareBodyHash(cparams, digest_expect_ptr, 1024);
|
||||
|
||||
/* If signature offset is 42, hash the wrong amount and return success */
|
||||
if (42 == mpreamble[hash_fw_index].body_signature.sig_offset) {
|
||||
VbUpdateFirmwareBodyHash(cparams, digest_expect_ptr, 4);
|
||||
return VBERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Otherwise, mocked function uses body signature offset as returned value */
|
||||
return mpreamble[hash_fw_index].body_signature.sig_offset;
|
||||
}
|
||||
|
||||
int VerifyDigest(const uint8_t* digest, const VbSignature *sig,
|
||||
const RSAPublicKey* key) {
|
||||
TEST_PTR_EQ(key, &data_key, "Verifying using data key");
|
||||
TEST_PTR_EQ(sig, &mpreamble[hash_fw_index].body_signature, "Verifying sig");
|
||||
/* Mocked function uses sig size as return value for verifying digest */
|
||||
return sig->sig_size;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* Test LoadFirmware() and check expected return value and recovery reason */
|
||||
static void TestLoadFirmware(VbError_t expected_retval,
|
||||
uint8_t expected_recovery, const char* desc) {
|
||||
uint32_t rr = 256;
|
||||
|
||||
TEST_EQ(LoadFirmware(&cparams, &fparams, &vnc), expected_retval, desc);
|
||||
VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &rr);
|
||||
TEST_EQ(rr, expected_recovery, " recovery request");
|
||||
TEST_EQ(data_key.len, 0, " Data key free must be paired with alloc");
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static void LoadFirmwareTest(void) {
|
||||
uint32_t u;
|
||||
|
||||
/* Require GBB */
|
||||
ResetMocks();
|
||||
cparams.gbb_data = NULL;
|
||||
TestLoadFirmware(VBERROR_INVALID_GBB, VBNV_RECOVERY_RO_UNSPECIFIED,
|
||||
"No GBB");
|
||||
|
||||
/* Key block flags must match */
|
||||
/* Normal boot */
|
||||
ResetMocks();
|
||||
vblock[0].key_block_flags = KEY_BLOCK_FLAG_DEVELOPER_1;
|
||||
vblock[1].key_block_flags =
|
||||
KEY_BLOCK_FLAG_DEVELOPER_0 | KEY_BLOCK_FLAG_RECOVERY_1;
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_REC_MISMATCH),
|
||||
"Flags mismatch dev=0");
|
||||
TEST_EQ(shared->flags & VBSD_LF_DEV_SWITCH_ON, 0,
|
||||
"Dev flag in shared.flags dev=0");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_DEV_MISMATCH,
|
||||
"Key block flag mismatch for dev=0");
|
||||
TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_REC_MISMATCH,
|
||||
"Key block flag mismatch for rec=0");
|
||||
/* Developer boot */
|
||||
ResetMocks();
|
||||
shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
|
||||
vblock[0].key_block_flags = KEY_BLOCK_FLAG_DEVELOPER_0;
|
||||
vblock[1].key_block_flags =
|
||||
KEY_BLOCK_FLAG_DEVELOPER_1 | KEY_BLOCK_FLAG_RECOVERY_1;
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_REC_MISMATCH),
|
||||
"Flags mismatch dev=1");
|
||||
TEST_NEQ(shared->flags & VBSD_LF_DEV_SWITCH_ON, 0,
|
||||
"Dev flag in shared.flags dev=1");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_DEV_MISMATCH,
|
||||
"Key block flag mismatch for dev=1");
|
||||
TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_REC_MISMATCH,
|
||||
"Key block flag mismatch for rec=1");
|
||||
|
||||
/* Test key block verification with A and key version rollback with B */
|
||||
ResetMocks();
|
||||
vblock[0].header_version_major = 1; /* Simulate failure */
|
||||
vblock[1].data_key.key_version = 1; /* Simulate rollback */
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_KEY_ROLLBACK),
|
||||
"Key block invalid / key version rollback");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VERIFY_KEYBLOCK,
|
||||
"Key block invalid");
|
||||
TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_KEY_ROLLBACK,
|
||||
"Key version rollback ");
|
||||
TEST_EQ(shared->fw_version_lowest, 0, "Lowest valid version");
|
||||
TEST_EQ(shared->fw_version_tpm, 0x20004, "TPM version");
|
||||
|
||||
/* Test invalid key version with A and bad data key with B */
|
||||
ResetMocks();
|
||||
vblock[0].data_key.key_version = 0x10003; /* Version > 0xFFFF is invalid */
|
||||
vblock[1].data_key.algorithm = 1; /* Simulate invalid data key */
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_DATA_KEY_PARSE),
|
||||
"Key version overflow / invalid data key");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_KEY_ROLLBACK,
|
||||
"Key version overflow");
|
||||
TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_DATA_KEY_PARSE,
|
||||
"Data key invalid");
|
||||
|
||||
/* Test invalid key version with GBB bypass-rollback flag */
|
||||
ResetMocks();
|
||||
vblock[0].data_key.key_version = 1; /* Simulate rollback */
|
||||
gbb->flags = GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK;
|
||||
TestLoadFirmware(VBERROR_SUCCESS, 0, "Key version check + GBB override");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID,
|
||||
"Key version rollback + GBB override");
|
||||
|
||||
/* Test invalid preamble with A */
|
||||
ResetMocks();
|
||||
mpreamble[0].header_version_major = 1; /* Simulate failure */
|
||||
vblock[1].key_block_flags = 0; /* Invalid */
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_VERIFY_PREAMBLE),
|
||||
"Preamble invalid");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VERIFY_PREAMBLE,
|
||||
"Preamble invalid A");
|
||||
|
||||
/* Test invalid firmware versions */
|
||||
ResetMocks();
|
||||
mpreamble[0].firmware_version = 3; /* Simulate rollback */
|
||||
mpreamble[1].firmware_version = 0x10001; /* Check overflow */
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_FW_ROLLBACK),
|
||||
"Firmware version check");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_FW_ROLLBACK,
|
||||
"Firmware version rollback");
|
||||
TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_FW_ROLLBACK,
|
||||
"Firmware version overflow");
|
||||
|
||||
/* Test invalid firmware versions with GBB bypass-rollback flag */
|
||||
ResetMocks();
|
||||
mpreamble[0].firmware_version = 3; /* Simulate rollback */
|
||||
mpreamble[1].firmware_version = 0x10001; /* Check overflow */
|
||||
gbb->flags = GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK;
|
||||
TestLoadFirmware(VBERROR_SUCCESS, 0, "Firmware version check + GBB bypass");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID,
|
||||
"Firmware version rollback + GBB override");
|
||||
TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_HEADER_VALID,
|
||||
"Firmware version overflow + GBB override");
|
||||
|
||||
/* Test RO normal with A */
|
||||
ResetMocks();
|
||||
mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
vblock[1].key_block_flags = 0; /* Invalid */
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_NO_RO_NORMAL),
|
||||
"Preamble asked for RO normal but fw doesn't support it");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_NO_RO_NORMAL,
|
||||
"No RO normal A");
|
||||
|
||||
/* If RO normal is supported, don't need to verify the firmware body */
|
||||
ResetMocks();
|
||||
mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
/* Mock bad sig, to ensure we didn't use it */
|
||||
mpreamble[0].body_signature.sig_size = 1;
|
||||
shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT;
|
||||
vblock[1].key_block_flags = 0; /* Invalid */
|
||||
TestLoadFirmware(VBERROR_SUCCESS, 0, "RO normal A");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, "RO normal A valid");
|
||||
TEST_EQ(shared->firmware_index, 0, "Boot A shared index");
|
||||
TEST_EQ(shared->fw_keyblock_flags, vblock[0].key_block_flags,
|
||||
"Copy key block flags");
|
||||
TEST_EQ(shared->kernel_subkey.algorithm, 7, "Copy kernel subkey");
|
||||
|
||||
/* If both A and B are valid and same version as TPM, A is selected
|
||||
* and B isn't attempted. */
|
||||
ResetMocks();
|
||||
mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
mpreamble[1].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT;
|
||||
TestLoadFirmware(VBERROR_SUCCESS, 0, "Check A then B");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, "RO normal A valid");
|
||||
TEST_EQ(shared->check_fw_b_result, 0, "RO normal B not checked ");
|
||||
TEST_EQ(shared->firmware_index, 0, "Boot A");
|
||||
TEST_EQ(shared->flags & VBSD_FWB_TRIED, 0, "Didn't try firmware B");
|
||||
TEST_EQ(shared->kernel_subkey.algorithm, 7, "Copy kernel subkey");
|
||||
/* But if try B flag is set, B is selected and A not attempted */
|
||||
ResetMocks();
|
||||
mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
mpreamble[1].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT;
|
||||
VbNvSet(&vnc, VBNV_TRY_B_COUNT, 5);
|
||||
TestLoadFirmware(VBERROR_SUCCESS, 0, "Check B then A");
|
||||
TEST_EQ(shared->check_fw_a_result, 0, "RO normal A not checked ");
|
||||
TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_VALID, "RO normal B valid");
|
||||
TEST_EQ(shared->firmware_index, 1, "Boot B");
|
||||
TEST_NEQ(shared->flags & VBSD_FWB_TRIED, 0, "Tried firmware B");
|
||||
TEST_EQ(shared->kernel_subkey.algorithm, 8, "Copy kernel subkey");
|
||||
VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u);
|
||||
TEST_EQ(u, 4, "Used up a try");
|
||||
|
||||
/* There's a optimistic boot mode that doesn't consume tries.
|
||||
* The behaviour should differ only in that the try count doesn't change. */
|
||||
/* Optimistic boot case 1: count == 0: Go for A */
|
||||
ResetMocks();
|
||||
mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
mpreamble[1].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT;
|
||||
shared->flags |= VBSD_NOFAIL_BOOT;
|
||||
VbNvSet(&vnc, VBNV_TRY_B_COUNT, 0);
|
||||
TestLoadFirmware(VBERROR_SUCCESS, 0, "Give up on B");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, "RO normal A valid");
|
||||
TEST_EQ(shared->check_fw_b_result, 0, "RO normal B not checked");
|
||||
TEST_EQ(shared->firmware_index, 0, "Boot A");
|
||||
TEST_EQ(shared->flags & VBSD_FWB_TRIED, 0, "Didn't try firmware B");
|
||||
TEST_EQ(shared->kernel_subkey.algorithm, 7, "Copy kernel subkey");
|
||||
VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u);
|
||||
TEST_EQ(u, 0, "try count still zero");
|
||||
/* Optimistic boot case 2: count > 0: count unchanged, use B */
|
||||
ResetMocks();
|
||||
mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
mpreamble[1].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT;
|
||||
shared->flags |= VBSD_NOFAIL_BOOT;
|
||||
VbNvSet(&vnc, VBNV_TRY_B_COUNT, 5);
|
||||
TestLoadFirmware(VBERROR_SUCCESS, 0, "Check B then A");
|
||||
TEST_EQ(shared->check_fw_a_result, 0, "RO normal A not checked ");
|
||||
TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_VALID, "RO normal B valid");
|
||||
TEST_EQ(shared->firmware_index, 1, "Boot B");
|
||||
TEST_NEQ(shared->flags & VBSD_FWB_TRIED, 0, "Tried firmware B");
|
||||
TEST_EQ(shared->kernel_subkey.algorithm, 8, "Copy kernel subkey");
|
||||
VbNvGet(&vnc, VBNV_TRY_B_COUNT, &u);
|
||||
TEST_EQ(u, 5, "Not used up a try");
|
||||
|
||||
/* If both A and B are valid and grater version than TPM, A is
|
||||
* selected and B preamble (but not body) is verified. */
|
||||
ResetMocks();
|
||||
mpreamble[0].flags = VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL;
|
||||
mpreamble[1].flags = 0;
|
||||
mpreamble[0].firmware_version = 5;
|
||||
mpreamble[1].firmware_version = 6;
|
||||
shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT;
|
||||
TestLoadFirmware(VBERROR_SUCCESS, 0, "Check A then B advancing version");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID, "RO normal A valid");
|
||||
TEST_EQ(shared->check_fw_b_result, VBSD_LF_CHECK_HEADER_VALID,
|
||||
"RO normal B header valid");
|
||||
TEST_EQ(shared->firmware_index, 0, "Boot A");
|
||||
TEST_EQ(shared->fw_keyblock_flags, vblock[0].key_block_flags, "Key block A");
|
||||
TEST_EQ(shared->kernel_subkey.algorithm, 7, "Copy kernel subkey");
|
||||
TEST_EQ(shared->fw_version_lowest, 0x20005, "Lowest valid version");
|
||||
TEST_EQ(shared->fw_version_tpm, 0x20005, "TPM version advanced");
|
||||
|
||||
/* Verify firmware data */
|
||||
ResetMocks();
|
||||
vblock[1].key_block_flags = 0; /* Invalid */
|
||||
TestLoadFirmware(VBERROR_SUCCESS, 0, "Verify firmware body");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID,
|
||||
"Firmware body A valid");
|
||||
TEST_EQ(shared->firmware_index, 0, "Boot A shared index");
|
||||
TEST_EQ(hash_fw_index, 0, "Hash firmware data A");
|
||||
TEST_EQ(digest_size, mpreamble[0].body_signature.data_size,
|
||||
"Verified all data expected");
|
||||
|
||||
/* Test error getting firmware body */
|
||||
ResetMocks();
|
||||
mpreamble[0].body_signature.sig_offset = VBERROR_UNKNOWN;
|
||||
vblock[1].key_block_flags = 0; /* Invalid */
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_GET_FW_BODY),
|
||||
"Error getting firmware body");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_GET_FW_BODY,
|
||||
"Firmware body A");
|
||||
|
||||
/* Test digesting the wrong amount */
|
||||
ResetMocks();
|
||||
mpreamble[0].body_signature.sig_offset = 42; /* Mock hashing wrong amount */
|
||||
vblock[1].key_block_flags = 0; /* Invalid */
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_HASH_WRONG_SIZE),
|
||||
"Hash wrong size");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_HASH_WRONG_SIZE,
|
||||
"Firmware hash wrong size A");
|
||||
|
||||
/* Test bad signature */
|
||||
ResetMocks();
|
||||
mpreamble[0].body_signature.sig_size = 1; /* Mock bad sig */
|
||||
vblock[1].key_block_flags = 0; /* Invalid */
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_VERIFY_BODY),
|
||||
"Bad signature");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VERIFY_BODY,
|
||||
"Bad signature A");
|
||||
|
||||
/* Test unable to store kernel data key */
|
||||
ResetMocks();
|
||||
mpreamble[0].kernel_subkey.key_size = VB_SHARED_DATA_MIN_SIZE + 1;
|
||||
vblock[1].key_block_flags = 0; /* Invalid */
|
||||
TestLoadFirmware(VBERROR_LOAD_FIRMWARE,
|
||||
(VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
|
||||
VBSD_LF_CHECK_VALID),
|
||||
"Kernel key too big");
|
||||
TEST_EQ(shared->check_fw_a_result, VBSD_LF_CHECK_VALID,
|
||||
"Kernel key too big");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int error_code = 0;
|
||||
|
||||
LoadFirmwareTest();
|
||||
|
||||
if (vboot_api_stub_check_memory())
|
||||
error_code = 255;
|
||||
if (!gTestSuccess)
|
||||
error_code = 255;
|
||||
|
||||
return error_code;
|
||||
}
|
||||
@@ -115,12 +115,6 @@ static void ResetMocks(void) {
|
||||
/****************************************************************************/
|
||||
/* Mocked verification functions */
|
||||
|
||||
uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode,
|
||||
uint64_t fw_keyblock_flags
|
||||
GoogleBinaryBlockHeader *gbb) {
|
||||
return VBERROR_SUCCESS;
|
||||
}
|
||||
|
||||
VbError_t VbExNvStorageRead(uint8_t* buf) {
|
||||
Memcpy(buf, vnc.raw, sizeof(vnc.raw));
|
||||
return VBERROR_SUCCESS;
|
||||
|
||||
Reference in New Issue
Block a user