summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/include/vboot_api.h4
-rw-r--r--firmware/lib/include/rollback_index.h21
-rw-r--r--firmware/lib/mocked_rollback_index.c4
-rw-r--r--firmware/lib/rollback_index.c18
-rw-r--r--firmware/lib/vboot_api_firmware.c47
-rw-r--r--firmware/lib/vboot_api_init.c117
-rw-r--r--firmware/linktest/main.c2
-rw-r--r--tests/rollback_index2_tests.c11
-rw-r--r--tests/vboot_api_firmware_tests.c48
-rw-r--r--tests/vboot_api_init_tests.c76
10 files changed, 206 insertions, 142 deletions
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index a5b061b7..b6b73928 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -165,6 +165,10 @@ typedef struct VbCommonParams {
/* Calling firmware supports read only firmware for normal/developer
* boot path. */
#define VB_INIT_FLAG_RO_NORMAL_SUPPORT 0x00000020
+/* This platform does not have a physical dev-switch, so we must rely on a
+ * virtual switch (kept in the TPM) instead. When this flag is set,
+ * VB_INIT_FLAG_DEV_SWITCH_ON is ignored. */
+#define VB_INIT_FLAG_VIRTUAL_DEV_SWITCH 0x00000040
/* Output flags for VbInitParams.out_flags. Used to indicate
* potential boot paths and configuration to the calling firmware
diff --git a/firmware/lib/include/rollback_index.h b/firmware/lib/include/rollback_index.h
index 4d847626..5a072446 100644
--- a/firmware/lib/include/rollback_index.h
+++ b/firmware/lib/include/rollback_index.h
@@ -37,10 +37,13 @@ typedef struct RollbackSpaceKernel {
/* Last boot was developer mode. TPM ownership is cleared when
* transitioning to/from developer mode. */
#define FLAG_LAST_BOOT_DEVELOPER 0x01
-/* There have been one or more boots which left PP unlocked, so the
- * contents of the kernel space are untrusted and must be restored
- * from the backup copy. */
-#define FLAG_KERNEL_SPACE_USE_BACKUP 0x02
+/* Some systems may not have a dedicated dev-mode switch, but enter and leave
+ * dev-mode through some recovery-mode magic keypresses. For those systems,
+ * the dev-mode "switch" state is in this bit (0=normal, 1=dev). To make it
+ * work, a new flag is passed to VbInit(), indicating that the system lacks a
+ * physical dev-mode switch. If a physical switch is present, this bit is
+ * ignored. */
+#define FLAG_VIRTUAL_DEV_MODE_ON 0x02
#define ROLLBACK_SPACE_FIRMWARE_VERSION 2
/* Firmware space - FIRMWARE_NV_INDEX, locked with global lock. */
@@ -64,11 +67,11 @@ uint32_t RollbackS3Resume(void);
/* These functions are callable from VbSelectFirmware(). They cannot use
* global variables. */
-/* Setup must be called. Pass recovery_mode=nonzero if in recovery
- * mode. Pass developer_mode=nonzero if in developer
- * mode. */
-uint32_t RollbackFirmwareSetup(int recovery_mode, int developer_mode,
- uint32_t* version);
+/* Setup must be called. Pass recovery_mode=nonzero if in recovery mode. Pass
+ * *developer_mode=nonzero if in developer mode. Set hw_dev_sw if there's a
+ * hardware developer switch. Duh. */
+uint32_t RollbackFirmwareSetup(int recovery_mode, int hw_dev_sw,
+ int* dev_mode_ptr, uint32_t* version);
/* Write may be called if the versions change */
uint32_t RollbackFirmwareWrite(uint32_t version);
diff --git a/firmware/lib/mocked_rollback_index.c b/firmware/lib/mocked_rollback_index.c
index f36bed8a..32082ddd 100644
--- a/firmware/lib/mocked_rollback_index.c
+++ b/firmware/lib/mocked_rollback_index.c
@@ -27,8 +27,8 @@ uint32_t RollbackS3Resume(void) {
}
-uint32_t RollbackFirmwareSetup(int recovery_mode, int developer_mode,
- uint32_t* version) {
+uint32_t RollbackFirmwareSetup(int recovery_mode, int hw_dev_sw,
+ int* dev_mode_ptr, uint32_t* version) {
*version = 0;
return TPM_SUCCESS;
}
diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
index 3b4e4665..038188a8 100644
--- a/firmware/lib/rollback_index.c
+++ b/firmware/lib/rollback_index.c
@@ -363,6 +363,12 @@ uint32_t SetupTPM(int recovery_mode, int developer_mode,
VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n",
rsf->struct_version, rsf->flags, rsf->fw_versions));
+ /* The developer_mode value that's passed in is only set by a hardware
+ * dev-switch. We should OR it with any enabled virtual switch, since it
+ * can only be set by doing the keyboard-based dev-mode dance. */
+ if (rsf->flags & FLAG_VIRTUAL_DEV_MODE_ON)
+ developer_mode = 1;
+
/* Clears ownership if developer flag has toggled */
if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) !=
(rsf->flags & FLAG_LAST_BOOT_DEVELOPER)) {
@@ -406,8 +412,8 @@ uint32_t RollbackS3Resume(void) {
return TPM_SUCCESS;
}
-uint32_t RollbackFirmwareSetup(int recovery_mode, int developer_mode,
- uint32_t* version) {
+uint32_t RollbackFirmwareSetup(int recovery_mode, int hw_dev_sw,
+ int* developer_mode, uint32_t* version) {
#ifndef CHROMEOS_ENVIRONMENT
/* Initialize the TPM, but ignores return codes. In ChromeOS
* environment, don't even talk to the TPM. */
@@ -459,15 +465,17 @@ uint32_t RollbackS3Resume(void) {
return result;
}
-uint32_t RollbackFirmwareSetup(int recovery_mode, int developer_mode,
- uint32_t* version) {
+uint32_t RollbackFirmwareSetup(int recovery_mode, int hw_dev_sw,
+ int* dev_mode_ptr, uint32_t* version) {
RollbackSpaceFirmware rsf;
/* Set version to 0 in case we fail */
*version = 0;
- RETURN_ON_FAILURE(SetupTPM(recovery_mode, developer_mode, &rsf));
+ RETURN_ON_FAILURE(SetupTPM(recovery_mode, *dev_mode_ptr, &rsf));
*version = rsf.fw_versions;
+ if (!hw_dev_sw)
+ *dev_mode_ptr = rsf.flags & FLAG_VIRTUAL_DEV_MODE_ON ? 1 : 0;
VBDEBUG(("TPM: RollbackFirmwareSetup %x\n", (int)rsf.fw_versions));
return TPM_SUCCESS;
}
diff --git a/firmware/lib/vboot_api_firmware.c b/firmware/lib/vboot_api_firmware.c
index 284dff24..faae7dd0 100644
--- a/firmware/lib/vboot_api_firmware.c
+++ b/firmware/lib/vboot_api_firmware.c
@@ -14,14 +14,6 @@
#include "vboot_common.h"
#include "vboot_nvstorage.h"
-
-/* Set recovery request */
-static void VbSfRequestRecovery(VbNvContext *vnc, uint32_t recovery_request) {
- VBDEBUG(("VbSfRequestRecovery(%d)\n", (int)recovery_request));
- VbNvSet(vnc, VBNV_RECOVERY_REQUEST, recovery_request);
-}
-
-
VbError_t VbSelectFirmware(VbCommonParams* cparams,
VbSelectFirmwareParams* fparams) {
VbSharedDataHeader* shared = (VbSharedDataHeader*)cparams->shared_data_blob;
@@ -29,7 +21,6 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
VbError_t retval = VBERROR_UNKNOWN; /* Assume error until proven successful */
int is_rec = (shared->recovery_reason ? 1 : 0);
int is_dev = (shared->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0);
- uint32_t tpm_version = 0;
uint32_t tpm_status = 0;
/* Start timer */
@@ -39,38 +30,6 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
VbExNvStorageRead(vnc.raw);
VbNvSetup(&vnc);
- /* Initialize the TPM */
- VBPERFSTART("VB_TPMI");
- tpm_status = RollbackFirmwareSetup(is_rec, is_dev, &tpm_version);
- VBPERFEND("VB_TPMI");
- if (0 != tpm_status) {
- VBDEBUG(("Unable to setup TPM and read firmware version.\n"));
-
- if (TPM_E_MUST_REBOOT == tpm_status) {
- /* TPM wants to reboot into the same mode we're in now */
- VBDEBUG(("TPM requires a reboot.\n"));
- if (!is_rec) {
- /* Not recovery mode. Just reboot (not into recovery). */
- retval = VBERROR_TPM_REBOOT_REQUIRED;
- goto VbSelectFirmware_exit;
- } else if (VBNV_RECOVERY_RO_TPM_REBOOT != shared->recovery_reason) {
- /* In recovery mode now, and we haven't requested a TPM reboot yet,
- * so request one. */
- VbSfRequestRecovery(&vnc, VBNV_RECOVERY_RO_TPM_REBOOT);
- retval = VBERROR_TPM_REBOOT_REQUIRED;
- goto VbSelectFirmware_exit;
- }
- }
-
- if (!is_rec) {
- VbSfRequestRecovery(&vnc, VBNV_RECOVERY_RO_TPM_ERROR);
- retval = VBERROR_TPM_FIRMWARE_SETUP;
- goto VbSelectFirmware_exit;
- }
- }
- shared->fw_version_tpm_start = tpm_version;
- shared->fw_version_tpm = tpm_version;
-
if (is_rec) {
/* Recovery is requested; go straight to recovery without checking the
* RW firmware. */
@@ -104,7 +63,7 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
VBPERFEND("VB_TPMU");
if (0 != tpm_status) {
VBDEBUG(("Unable to write firmware version to TPM.\n"));
- VbSfRequestRecovery(&vnc, VBNV_RECOVERY_RO_TPM_ERROR);
+ VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_ERROR);
retval = VBERROR_TPM_WRITE_FIRMWARE;
goto VbSelectFirmware_exit;
}
@@ -116,7 +75,7 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
VBPERFEND("VB_TPML");
if (0 != tpm_status) {
VBDEBUG(("Unable to lock firmware version in TPM.\n"));
- VbSfRequestRecovery(&vnc, VBNV_RECOVERY_RO_TPM_ERROR);
+ VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_ERROR);
retval = VBERROR_TPM_LOCK_FIRMWARE;
goto VbSelectFirmware_exit;
}
@@ -128,7 +87,7 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
if (0 != tpm_status) {
VBDEBUG(("Unable to update the TPM with boot mode information.\n"));
if (!is_rec) {
- VbSfRequestRecovery(&vnc, VBNV_RECOVERY_RO_TPM_ERROR);
+ VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_ERROR);
retval = VBERROR_TPM_SET_BOOT_MODE_STATE;
goto VbSelectFirmware_exit;
}
diff --git a/firmware/lib/vboot_api_init.c b/firmware/lib/vboot_api_init.c
index b03c3d5a..d64590c4 100644
--- a/firmware/lib/vboot_api_init.c
+++ b/firmware/lib/vboot_api_init.c
@@ -23,6 +23,10 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
int is_s3_resume = 0;
uint32_t s3_debug_boot = 0;
uint32_t require_official_os = 0;
+ uint32_t tpm_version = 0;
+ uint32_t tpm_status = 0;
+ int hw_dev_sw = 1;
+ int is_dev = 0;
VBDEBUG(("VbInit() input flags 0x%x\n", iparams->flags));
@@ -43,8 +47,9 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
/* Copy boot switch flags */
shared->flags = 0;
- if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON)
- shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
+ if (!(iparams->flags & VB_INIT_FLAG_VIRTUAL_DEV_SWITCH) &&
+ (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON))
+ is_dev = 1;
if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED)
shared->flags |= VBSD_BOOT_REC_SWITCH_ON;
if (iparams->flags & VB_INIT_FLAG_WP_ENABLED)
@@ -62,7 +67,7 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
if (is_s3_resume) {
VBDEBUG(("VbInit() requesting S3 debug boot\n"));
iparams->out_flags |= VB_INIT_OUT_S3_DEBUG_BOOT;
- is_s3_resume = 0; /* Proceed as if this is a normal boot */
+ is_s3_resume = 0; /* Proceed as if this is a normal boot */
}
/* Clear the request even if this is a normal boot, since we don't
@@ -93,19 +98,91 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED)
recovery = VBNV_RECOVERY_RO_MANUAL;
+ /* Copy current recovery reason to shared data. If we fail later on, it
+ * won't matter, since we'll just reboot. */
+ shared->recovery_reason = (uint8_t)recovery;
+
+ /* If this is a S3 resume, resume the TPM. */
+ /* FIXME: I think U-Boot won't ever ask us to do this. Can we remove it? */
+ if (is_s3_resume) {
+ if (TPM_SUCCESS != RollbackS3Resume()) {
+ /* If we can't resume, just do a full reboot. No need to go to recovery
+ * mode here, since if the TPM is really broken we'll catch it on the
+ * next boot. */
+ retval = VBERROR_TPM_S3_RESUME;
+ }
+ } else {
+
+ /* We need to know about dev mode now */
+ if (iparams->flags & VB_INIT_FLAG_VIRTUAL_DEV_SWITCH)
+ hw_dev_sw = 0;
+ else if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON)
+ is_dev = 1;
+
+ VBPERFSTART("VB_TPMI");
+ /* Initialize the TPM. *is_dev is both an input and output. The only time
+ * it should be 1 on input is when we have a hardware dev-switch and it's
+ * enabled. The only time it's promoted from 0 to 1 on return is when we
+ * have a virtual dev-switch and the TPM has a valid rollback space with
+ * the virtual switch already enabled. If the TPM space is initialized by
+ * this call, its virtual dev-switch will be disabled by default. */
+ tpm_status = RollbackFirmwareSetup(recovery, hw_dev_sw,
+ &is_dev, &tpm_version);
+ VBPERFEND("VB_TPMI");
+ if (0 != tpm_status) {
+ VBDEBUG(("Unable to setup TPM and read firmware version.\n"));
+
+ if (TPM_E_MUST_REBOOT == tpm_status) {
+ /* TPM wants to reboot into the same mode we're in now */
+ VBDEBUG(("TPM requires a reboot.\n"));
+ if (!recovery) {
+ /* Not recovery mode. Just reboot (not into recovery). */
+ retval = VBERROR_TPM_REBOOT_REQUIRED;
+ goto VbInit_exit;
+ } else if (VBNV_RECOVERY_RO_TPM_REBOOT != shared->recovery_reason) {
+ /* In recovery mode now, and we haven't requested a TPM reboot yet,
+ * so request one. */
+ VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_REBOOT);
+ retval = VBERROR_TPM_REBOOT_REQUIRED;
+ goto VbInit_exit;
+ }
+ }
+
+ if (!recovery) {
+ VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_RO_TPM_ERROR);
+ retval = VBERROR_TPM_FIRMWARE_SETUP;
+ goto VbInit_exit;
+ }
+ }
+ shared->fw_version_tpm_start = tpm_version;
+ shared->fw_version_tpm = tpm_version;
+ if (is_dev)
+ shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
+ }
+
+ /* FIXME: May need a GBB flag for initial value of virtual dev-switch */
+
+ /* Allow BIOS to load arbitrary option ROMs? */
+ if (gbb->flags & GBB_FLAG_LOAD_OPTION_ROMS)
+ iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM;
+
+ /* The factory may need to boot custom OSes whenever the dev-switch is on */
+ if (is_dev && (gbb->flags & GBB_FLAG_ENABLE_ALTERNATE_OS))
+ iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS;
+
/* Set output flags */
if (VBNV_RECOVERY_NOT_REQUESTED != recovery) {
/* Requesting recovery mode */
iparams->out_flags |= (VB_INIT_OUT_ENABLE_RECOVERY |
- VB_INIT_OUT_CLEAR_RAM |
- VB_INIT_OUT_ENABLE_DISPLAY |
- VB_INIT_OUT_ENABLE_USB_STORAGE);
+ VB_INIT_OUT_CLEAR_RAM |
+ VB_INIT_OUT_ENABLE_DISPLAY |
+ VB_INIT_OUT_ENABLE_USB_STORAGE);
}
- else if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON) {
+ else if (is_dev) {
/* Developer switch is on, so need to support dev mode */
iparams->out_flags |= (VB_INIT_OUT_CLEAR_RAM |
- VB_INIT_OUT_ENABLE_DISPLAY |
- VB_INIT_OUT_ENABLE_USB_STORAGE);
+ VB_INIT_OUT_ENABLE_DISPLAY |
+ VB_INIT_OUT_ENABLE_USB_STORAGE);
/* ... which may or may not include custom OSes */
VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &require_official_os);
if (!require_official_os)
@@ -118,27 +195,7 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 0);
}
- /* Allow BIOS to load arbitrary option ROMs? */
- if (gbb->flags & GBB_FLAG_LOAD_OPTION_ROMS)
- iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM;
-
- /* The factory may need to boot custom OSes whenever the dev-switch is on */
- if ((gbb->flags & GBB_FLAG_ENABLE_ALTERNATE_OS) &&
- (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON))
- iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS;
-
- /* copy current recovery reason to shared data */
- shared->recovery_reason = (uint8_t)recovery;
-
- /* If this is a S3 resume, resume the TPM */
- if (is_s3_resume) {
- if (TPM_SUCCESS != RollbackS3Resume()) {
- /* If we can't resume, just do a full reboot. No need to go to recovery
- * mode here, since if the TPM is really broken we'll catch it on the
- * next boot. */
- retval = VBERROR_TPM_S3_RESUME;
- }
- }
+VbInit_exit:
/* Tear down NV storage */
VbNvTeardown(&vnc);
diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c
index af5d8d65..9c1cf346 100644
--- a/firmware/linktest/main.c
+++ b/firmware/linktest/main.c
@@ -29,7 +29,7 @@ int main(void)
/* rollback_index.h */
RollbackS3Resume();
- RollbackFirmwareSetup(0, 0, 0);
+ RollbackFirmwareSetup(0, 0, 0, 0);
RollbackFirmwareWrite(0);
RollbackFirmwareLock();
RollbackKernelRead(0);
diff --git a/tests/rollback_index2_tests.c b/tests/rollback_index2_tests.c
index 1307ed08..98d7dcde 100644
--- a/tests/rollback_index2_tests.c
+++ b/tests/rollback_index2_tests.c
@@ -684,12 +684,15 @@ static void SetupTpmTest(void) {
/* 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, 0, &version), 0, "RollbackFirmwareSetup()");
+ TEST_EQ(RollbackFirmwareSetup(0, 0, &dev_mode, &version), 0,
+ "RollbackFirmwareSetup()");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
"TlclStartup()\n"
@@ -701,9 +704,10 @@ static void RollbackFirmwareTest(void) {
/* 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, 0, &version), TPM_E_IOERROR,
+ TEST_EQ(RollbackFirmwareSetup(0, 0, &dev_mode, &version), TPM_E_IOERROR,
"RollbackFirmwareSetup() error");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n",
@@ -712,7 +716,8 @@ static void RollbackFirmwareTest(void) {
/* Developer mode flag gets passed properly */
ResetMocks(0, 0);
- TEST_EQ(RollbackFirmwareSetup(0, 1, &version), 0,
+ dev_mode = 1;
+ TEST_EQ(RollbackFirmwareSetup(0, 0, &dev_mode, &version), 0,
"RollbackFirmwareSetup() to dev");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
diff --git a/tests/vboot_api_firmware_tests.c b/tests/vboot_api_firmware_tests.c
index c3c651af..03f67b5b 100644
--- a/tests/vboot_api_firmware_tests.c
+++ b/tests/vboot_api_firmware_tests.c
@@ -31,12 +31,10 @@ static int nv_write_called;
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_rfs_got_flags;
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_rfs_retval;
static VbError_t mock_rfw_retval;
static VbError_t mock_rfl_retval;
static VbError_t mock_lf_retval;
@@ -61,11 +59,12 @@ static void ResetMocks(void) {
mock_timer = 10;
nv_write_called = mock_rfl_called = 0;
- mock_rfs_got_flags = mock_stbms_got_flags = 0;
+ mock_stbms_got_flags = 0;
mock_stbms_got_fw_flags = 0;
mock_tpm_version = mock_lf_tpm_version = 0x20004;
- mock_rfs_retval = mock_rfw_retval = mock_rfl_retval = 0;
+ shared->fw_version_tpm_start = mock_tpm_version;
+ mock_rfw_retval = mock_rfl_retval = 0;
mock_lf_retval = mock_stbms_retval = 0;
}
@@ -92,17 +91,6 @@ uint64_t VbExGetTimer(void) {
return mock_timer;
}
-uint32_t RollbackFirmwareSetup(int recovery_mode, int developer_mode,
- uint32_t* version) {
- if (recovery_mode)
- mock_rfs_got_flags |= MOCK_REC_FLAG;
- if (developer_mode)
- mock_rfs_got_flags |= MOCK_DEV_FLAG;
-
- *version = mock_tpm_version;
- return mock_rfs_retval;
-}
-
uint32_t RollbackFirmwareWrite(uint32_t version) {
mock_tpm_version = version;
return mock_rfw_retval;
@@ -153,7 +141,6 @@ static void VbSelectFirmwareTest(void) {
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_rfs_got_flags, 0, " RollbackFirmwareSetup() flags");
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");
@@ -162,7 +149,6 @@ static void VbSelectFirmwareTest(void) {
ResetMocks();
shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
TestVbSf(0, 0, "Developer mode");
- TEST_EQ(mock_rfs_got_flags, MOCK_DEV_FLAG, " RollbackFirmwareSetup() flags");
TEST_EQ(mock_stbms_got_flags, MOCK_DEV_FLAG, " SetTPMBootModeState() flags");
TEST_EQ(mock_rfl_called, 1, " RollbackFirmwareLock() called");
@@ -175,7 +161,6 @@ static void VbSelectFirmwareTest(void) {
TestVbSf(0, 0, "Recovery mode");
TEST_EQ(fparams.selected_firmware, VB_SELECT_FIRMWARE_RECOVERY,
" select recovery");
- TEST_EQ(mock_rfs_got_flags, MOCK_REC_FLAG, " RollbackFirmwareSetup() flags");
TEST_EQ(mock_stbms_got_flags, MOCK_REC_FLAG, " SetTPMBootModeState() flags");
TEST_EQ(mock_rfl_called, 0, " RollbackFirmwareLock() not called");
@@ -186,37 +171,10 @@ static void VbSelectFirmwareTest(void) {
TestVbSf(0, 0, "Recovery+developer mode");
TEST_EQ(fparams.selected_firmware, VB_SELECT_FIRMWARE_RECOVERY,
" select recovery");
- TEST_EQ(mock_rfs_got_flags, MOCK_DEV_FLAG|MOCK_REC_FLAG,
- " RollbackFirmwareSetup() flags");
TEST_EQ(mock_stbms_got_flags, MOCK_DEV_FLAG|MOCK_REC_FLAG,
" SetTPMBootModeState() flags");
TEST_EQ(mock_rfl_called, 0, " RollbackFirmwareLock() not called");
- /* Rollback setup needs to reboot */
- ResetMocks();
- mock_rfs_retval = TPM_E_MUST_REBOOT;
- TestVbSf(VBERROR_TPM_REBOOT_REQUIRED, 0, "Rollback TPM reboot (rec=0)");
- ResetMocks();
- mock_rfs_retval = TPM_E_MUST_REBOOT;
- shared->recovery_reason = VBNV_RECOVERY_US_TEST;
- TestVbSf(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;
- shared->recovery_reason = VBNV_RECOVERY_RO_TPM_REBOOT;
- TestVbSf(0, 0, "Rollback TPM reboot, in recovery, already retried");
-
- /* Other rollback setup errors */
- ResetMocks();
- mock_rfs_retval = TPM_E_IOERROR;
- TestVbSf(VBERROR_TPM_FIRMWARE_SETUP, VBNV_RECOVERY_RO_TPM_ERROR,
- "Rollback TPM setup error");
- ResetMocks();
- mock_rfs_retval = TPM_E_IOERROR;
- shared->recovery_reason = VBNV_RECOVERY_US_TEST;
- TestVbSf(0, 0, "Rollback TPM setup error ignored in recovery");
-
/* LoadFirmware() error code passed through */
ResetMocks();
mock_lf_retval = 0x12345;
diff --git a/tests/vboot_api_init_tests.c b/tests/vboot_api_init_tests.c
index 09c210bf..15907d49 100644
--- a/tests/vboot_api_init_tests.c
+++ b/tests/vboot_api_init_tests.c
@@ -26,7 +26,9 @@ static uint64_t mock_timer;
static int rollback_s3_retval;
static int nv_write_called;
static GoogleBinaryBlockHeader gbb;
-
+static int mock_dev_mode;
+static uint32_t mock_tpm_version;
+static uint32_t mock_rfs_retval;
/* Reset mock data (for use before each test) */
static void ResetMocks(void) {
@@ -44,7 +46,7 @@ static void ResetMocks(void) {
Memset(&vnc, 0, sizeof(vnc));
VbNvSetup(&vnc);
- VbNvTeardown(&vnc); /* So CRC gets generated */
+ VbNvTeardown(&vnc); /* So CRC gets generated */
Memset(&shared_data, 0, sizeof(shared_data));
VbSharedDataInit(shared, sizeof(shared_data));
@@ -52,6 +54,10 @@ static void ResetMocks(void) {
mock_timer = 10;
rollback_s3_retval = TPM_SUCCESS;
nv_write_called = 0;
+
+ mock_dev_mode = 0;
+ mock_tpm_version = 0x10001;
+ mock_rfs_retval = 0;
}
/****************************************************************************/
@@ -81,6 +87,14 @@ uint32_t RollbackS3Resume(void) {
return rollback_s3_retval;
}
+uint32_t RollbackFirmwareSetup(int recovery_mode, int hw_dev_sw,
+ int* dev_mode_ptr, uint32_t* version) {
+ if (!hw_dev_sw)
+ *dev_mode_ptr = mock_dev_mode;
+ *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,
@@ -89,7 +103,7 @@ static void TestVbInit(VbError_t expected_retval,
TEST_EQ(VbInit(&cparams, &iparams), expected_retval, desc);
VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &rr);
- TEST_EQ(rr, expected_recovery, " recovery request");
+ TEST_EQ(rr, expected_recovery, " (recovery request)");
}
/****************************************************************************/
@@ -267,6 +281,61 @@ static void VbInitTest(void) {
VBSD_BOOT_REC_SWITCH_ON | VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
}
+static void VbInitTestTPM(void) {
+
+ /* 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_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();
+ iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON | 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, 0, " shared flags");
+
+ /* Virtual developer switch, enabled. */
+ ResetMocks();
+ iparams.flags = VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
+ mock_dev_mode = 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_ALTERNATE_OS, " out flags");
+ TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
+}
+
/* disable MSVC warnings on unused arguments */
__pragma(warning (disable: 4100))
@@ -275,6 +344,7 @@ int main(int argc, char* argv[]) {
int error_code = 0;
VbInitTest();
+ VbInitTestTPM();
if (!gTestSuccess)
error_code = 255;