summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/include/vboot_api.h4
-rw-r--r--firmware/include/vboot_struct.h2
-rw-r--r--firmware/lib/include/rollback_index.h15
-rw-r--r--firmware/lib/mocked_rollback_index.c5
-rw-r--r--firmware/lib/rollback_index.c68
-rw-r--r--firmware/lib/vboot_api_firmware.c3
-rw-r--r--firmware/lib/vboot_api_init.c55
-rw-r--r--firmware/lib/vboot_api_kernel.c79
-rw-r--r--firmware/lib/vboot_display.c8
-rw-r--r--firmware/linktest/main.c2
-rw-r--r--tests/rollback_index2_tests.c33
-rw-r--r--tests/vboot_api_init_tests.c40
12 files changed, 231 insertions, 83 deletions
diff --git a/firmware/include/vboot_api.h b/firmware/include/vboot_api.h
index b6b73928..50d0f816 100644
--- a/firmware/include/vboot_api.h
+++ b/firmware/include/vboot_api.h
@@ -100,7 +100,7 @@ enum VbErrorPredefined_t {
/* VbExBeep() can't make sound in the background */
VBERROR_NO_BACKGROUND_SOUND = 0x10019,
/* Developer has requested a BIOS shell */
- VBERROR_BIOS_SHELL_REQUESTED = 0x10020
+ VBERROR_BIOS_SHELL_REQUESTED = 0x10020,
};
@@ -511,6 +511,8 @@ enum VbScreenType_t {
VB_SCREEN_RECOVERY_REMOVE = 0x201, /* Recovery - remove inserted devices */
VB_SCREEN_RECOVERY_INSERT = 0x202, /* Recovery - insert recovery image */
VB_SCREEN_RECOVERY_NO_GOOD = 0x203, /* Recovery - inserted image invalid */
+ VB_SCREEN_RECOVERY_TO_DEV = 0x204, /* Recovery - confirm dev mode */
+ VB_SCREEN_RECOVERY_TO_NORM = 0x205, /* Recovery - confirm normal mode */
};
/* Initialize and clear the display. Set width and height to the screen
diff --git a/firmware/include/vboot_struct.h b/firmware/include/vboot_struct.h
index 0f6b98d9..d894e23d 100644
--- a/firmware/include/vboot_struct.h
+++ b/firmware/include/vboot_struct.h
@@ -231,6 +231,8 @@ typedef struct VbKernelPreambleHeader {
#define VBSD_BOOT_S3_RESUME 0x00000100
/* Read-only firmware supports the normal/developer code path */
#define VBSD_BOOT_RO_NORMAL_SUPPORT 0x00000200
+/* VbInit was told that the system has a virtual dev-switch */
+#define VBSD_HONOR_VIRT_DEV_SWITCH 0x00000400
/* Result codes for VbSharedDataHeader.check_fw_a_result (and b_result) */
#define VBSD_LF_CHECK_NOT_DONE 0
diff --git a/firmware/lib/include/rollback_index.h b/firmware/lib/include/rollback_index.h
index 5a072446..20df5b31 100644
--- a/firmware/lib/include/rollback_index.h
+++ b/firmware/lib/include/rollback_index.h
@@ -67,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. 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);
+/* This must be called. */
+uint32_t RollbackFirmwareSetup(int recovery_mode, int is_hw_dev,
+ int disable_dev_request,
+ /* two outputs on success */
+ int *is_virt_dev, uint32_t *tpm_version);
/* Write may be called if the versions change */
uint32_t RollbackFirmwareWrite(uint32_t version);
@@ -118,6 +118,9 @@ uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware* rsf,
/* SetupTPM starts the TPM and establishes the root of trust for the
* anti-rollback mechanism. */
uint32_t SetupTPM(int recovery_mode, int developer_mode,
- RollbackSpaceFirmware* rsf);
+ int disable_dev_request, RollbackSpaceFirmware* rsf);
+
+/* Utility function to turn the virtual dev-mode flag on or off. 0=off, 1=on */
+uint32_t SetVirtualDevMode(int val);
#endif /* VBOOT_REFERENCE_ROLLBACK_INDEX_H_ */
diff --git a/firmware/lib/mocked_rollback_index.c b/firmware/lib/mocked_rollback_index.c
index 32082ddd..f884daec 100644
--- a/firmware/lib/mocked_rollback_index.c
+++ b/firmware/lib/mocked_rollback_index.c
@@ -27,8 +27,9 @@ uint32_t RollbackS3Resume(void) {
}
-uint32_t RollbackFirmwareSetup(int recovery_mode, int hw_dev_sw,
- int* dev_mode_ptr, uint32_t* version) {
+uint32_t RollbackFirmwareSetup(int recovery_mode, int is_hw_dev,
+ int disable_dev_request,
+ int *is_virt_dev, uint32_t *version) {
*version = 0;
return TPM_SUCCESS;
}
diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
index 5cd13566..668312e6 100644
--- a/firmware/lib/rollback_index.c
+++ b/firmware/lib/rollback_index.c
@@ -131,6 +131,28 @@ uint32_t WriteSpaceFirmware(RollbackSpaceFirmware* rsf) {
return TPM_E_CORRUPTED_STATE;
}
+uint32_t SetVirtualDevMode(int val) {
+ RollbackSpaceFirmware rsf;
+
+ VBDEBUG(("TPM: Entering %s()\n", __func__));
+ if (TPM_SUCCESS != ReadSpaceFirmware(&rsf))
+ return VBERROR_TPM_FIRMWARE_SETUP;
+
+ VBDEBUG(("TPM: flags were 0x%02x\n", rsf.flags));
+ if (val)
+ rsf.flags |= FLAG_VIRTUAL_DEV_MODE_ON;
+ else
+ rsf.flags &= ~FLAG_VIRTUAL_DEV_MODE_ON;
+ /* NOTE: This doesn't update the FLAG_LAST_BOOT_DEVELOPER bit */
+ VBDEBUG(("TPM: flags are now 0x%02x\n", rsf.flags));
+
+ if (TPM_SUCCESS != WriteSpaceFirmware(&rsf))
+ return VBERROR_TPM_SET_BOOT_MODE_STATE;
+
+ VBDEBUG(("TPM: Leaving %s()\n", __func__));
+ return VBERROR_SUCCESS;
+}
+
uint32_t ReadSpaceKernel(RollbackSpaceKernel* rsk) {
uint32_t r;
int attempts = 3;
@@ -276,10 +298,9 @@ uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware* rsf,
* the durability of the NVRAM.
*/
uint32_t SetupTPM(int recovery_mode, int developer_mode,
- RollbackSpaceFirmware* rsf) {
+ int disable_dev_request, RollbackSpaceFirmware* rsf) {
- int rsf_dirty = 0;
- uint8_t new_flags = 0;
+ uint8_t in_flags;
uint8_t disable;
uint8_t deactivated;
uint32_t result;
@@ -362,29 +383,36 @@ 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));
+ in_flags = rsf->flags;
+
+ /* If we've been asked to clear the virtual dev-mode flag, do so now */
+ if (disable_dev_request) {
+ rsf->flags &= ~FLAG_VIRTUAL_DEV_MODE_ON;
+ VBDEBUG(("TPM: Clearing virt dev-switch: f%x\n", rsf->flags));
+ }
/* The developer_mode value that's passed in is only set by a hardware
- * dev-switch. We should OR it with any enabled virtual switch. */
+ * dev-switch. We should OR it with the virtual switch, whether or not the
+ * virtual switch is used. If it's not used, it shouldn't change, so it
+ * doesn't matter. */
if (rsf->flags & FLAG_VIRTUAL_DEV_MODE_ON)
developer_mode = 1;
/* Clears ownership if developer flag has toggled */
if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) !=
- (rsf->flags & FLAG_LAST_BOOT_DEVELOPER)) {
+ (in_flags & FLAG_LAST_BOOT_DEVELOPER)) {
VBDEBUG(("TPM: Developer flag changed; clearing owner.\n"));
RETURN_ON_FAILURE(TPMClearAndReenable());
}
- /* Updates flags */
if (developer_mode)
- new_flags |= FLAG_LAST_BOOT_DEVELOPER;
- if (rsf->flags != new_flags) {
- rsf->flags = new_flags;
- rsf_dirty = 1;
- }
+ rsf->flags |= FLAG_LAST_BOOT_DEVELOPER;
+ else
+ rsf->flags &= ~FLAG_LAST_BOOT_DEVELOPER;
+
/* If firmware space is dirty, this flushes it back to the TPM */
- if (rsf_dirty) {
+ if (rsf->flags != in_flags) {
VBDEBUG(("TPM: Updating firmware space.\n"));
RETURN_ON_FAILURE(WriteSpaceFirmware(rsf));
}
@@ -411,8 +439,9 @@ uint32_t RollbackS3Resume(void) {
return TPM_SUCCESS;
}
-uint32_t RollbackFirmwareSetup(int recovery_mode, int hw_dev_sw,
- int* developer_mode, uint32_t* version) {
+uint32_t RollbackFirmwareSetup(int recovery_mode, int is_hw_dev,
+ int disable_dev_request,
+ int *is_virt_dev, uint32_t *version) {
#ifndef CHROMEOS_ENVIRONMENT
/* Initialize the TPM, but ignores return codes. In ChromeOS
* environment, don't even talk to the TPM. */
@@ -464,17 +493,18 @@ uint32_t RollbackS3Resume(void) {
return result;
}
-uint32_t RollbackFirmwareSetup(int recovery_mode, int hw_dev_sw,
- int* dev_mode_ptr, uint32_t* version) {
+uint32_t RollbackFirmwareSetup(int recovery_mode, int is_hw_dev,
+ int disable_dev_request,
+ int *is_virt_dev, uint32_t *version) {
RollbackSpaceFirmware rsf;
/* Set version to 0 in case we fail */
*version = 0;
- RETURN_ON_FAILURE(SetupTPM(recovery_mode, *dev_mode_ptr, &rsf));
+ RETURN_ON_FAILURE(SetupTPM(recovery_mode, is_hw_dev,
+ disable_dev_request, &rsf));
*version = rsf.fw_versions;
- if (!hw_dev_sw && (rsf.flags & FLAG_VIRTUAL_DEV_MODE_ON))
- *dev_mode_ptr = 1; /* OR with the TPM's value */
+ *is_virt_dev = (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 faae7dd0..cffc462b 100644
--- a/firmware/lib/vboot_api_firmware.c
+++ b/firmware/lib/vboot_api_firmware.c
@@ -33,8 +33,7 @@ VbError_t VbSelectFirmware(VbCommonParams* cparams,
if (is_rec) {
/* Recovery is requested; go straight to recovery without checking the
* RW firmware. */
- VBDEBUG(("VbSelectFirmware() detected recovery request, reason=%d.\n",
- (int)shared->recovery_reason));
+ VBDEBUG(("VbSelectFirmware() detected recovery request\n"));
/* Go directly to recovery mode */
fparams->selected_firmware = VB_SELECT_FIRMWARE_RECOVERY;
diff --git a/firmware/lib/vboot_api_init.c b/firmware/lib/vboot_api_init.c
index 34323094..bff57bd5 100644
--- a/firmware/lib/vboot_api_init.c
+++ b/firmware/lib/vboot_api_init.c
@@ -25,7 +25,10 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
uint32_t require_official_os = 0;
uint32_t tpm_version = 0;
uint32_t tpm_status = 0;
- int hw_dev_sw = 1;
+ int has_virt_dev_switch = 0;
+ int is_hw_dev = 0;
+ int is_virt_dev = 0;
+ uint32_t disable_dev_request = 0;
int is_dev = 0;
VBDEBUG(("VbInit() input flags 0x%x\n", iparams->flags));
@@ -45,11 +48,8 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
shared->timer_vb_init_enter = VbExGetTimer();
- /* Copy boot switch flags */
+ /* Copy some boot switch flags */
shared->flags = 0;
- 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)
@@ -80,6 +80,7 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
* it so we don't get stuck in recovery mode. */
if (!is_s3_resume) {
VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery);
+ VBDEBUG(("VbInit sees recovery request = %d\n", recovery));
if (VBNV_RECOVERY_NOT_REQUESTED != recovery)
VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, VBNV_RECOVERY_NOT_REQUESTED);
}
@@ -101,6 +102,7 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
/* 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;
+ VBDEBUG(("VbInit now sets shared->recovery_reason = %d\n", 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? */
@@ -112,25 +114,29 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
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;
+ /* Should we pay attention to the TPM's virtual dev-switch? */
+ if (iparams->flags & VB_INIT_FLAG_VIRTUAL_DEV_SWITCH) {
+ shared->flags |= VBSD_HONOR_VIRT_DEV_SWITCH;
+ has_virt_dev_switch = 1;
+ }
+ /* We always believe the HW dev-switch, since there's one attached to servo
+ * which may be active even on systems without a physical switch. The EC
+ * may also implement a fake dev-switch for testing. */
if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON)
- is_dev = 1;
+ is_hw_dev = 1;
+ /* We may be asked to clear the virtual dev-switch at boot. */
+ VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request);
+
/* FIXME: How about a GBB flag to force dev-switch on? */
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 the hardware dev-switch is enabled
- * (which includes the fake_dev switch from the EC). 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). The TPM just uses the input
- * value to clear ownership if the dev state has changed. */
- tpm_status = RollbackFirmwareSetup(recovery, hw_dev_sw,
- &is_dev, &tpm_version);
+ /* Initialize the TPM. If the developer mode state has changed since the
+ * last boot, we need to clear TPM ownership. If the TPM space is
+ * initialized by this call, the virtual dev-switch will be disabled by
+ * default) */
+ tpm_status = RollbackFirmwareSetup(recovery, is_hw_dev, disable_dev_request,
+ /* two outputs on success */
+ &is_virt_dev, &tpm_version);
VBPERFEND("VB_TPMI");
if (0 != tpm_status) {
VBDEBUG(("Unable to setup TPM and read firmware version.\n"));
@@ -157,10 +163,16 @@ VbError_t VbInit(VbCommonParams* cparams, VbInitParams* iparams) {
goto VbInit_exit;
}
}
+
+ /* TPM setup succeeded. What did we learn? */
shared->fw_version_tpm_start = tpm_version;
shared->fw_version_tpm = tpm_version;
- if (is_dev)
+ if (is_hw_dev || (has_virt_dev_switch && is_virt_dev)) {
+ is_dev = 1;
shared->flags |= VBSD_BOOT_DEV_SWITCH_ON;
+ }
+ if (disable_dev_request && !is_virt_dev)
+ VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 0);
}
/* Allow BIOS to load arbitrary option ROMs? */
@@ -207,5 +219,6 @@ VbInit_exit:
shared->timer_vb_init_exit = VbExGetTimer();
+ VBDEBUG(("VbInit() returning 0x%x\n", retval));
return retval;
}
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 891807a3..b0a04ac4 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -110,6 +110,7 @@ uint32_t VbTryLoadKernel(VbCommonParams* cparams, LoadKernelParams* p,
/* Handle a normal boot. */
VbError_t VbBootNormal(VbCommonParams* cparams, LoadKernelParams* p) {
/* Boot from fixed disk only */
+ VBDEBUG(("Entering %s()\n", __func__));
return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
}
@@ -118,6 +119,8 @@ VbError_t VbBootDeveloper(VbCommonParams* cparams, LoadKernelParams* p) {
uint32_t allow_usb = 0;
VbAudioContext* audio = 0;
+ VBDEBUG(("Entering %s()\n", __func__));
+
/* Check if USB booting is allowed */
VbNvGet(&vnc, VBNV_DEV_BOOT_USB, &allow_usb);
@@ -202,6 +205,49 @@ fallout:
}
+/* FIXME(crosbug.com/p/9953): The platform BIOS should implement this! */
+/* And not here: somewhere outside of vboot with the other VbEx functions */
+int VbExTrustEC(void) {
+ /* Only return true if the EC is running in its RO firmware *right now*. */
+ return 1;
+}
+
+/* Ask the user to confirm changing the virtual dev-mode switch. If they confirm
+ * we'll change it and return a reason to reboot. */
+static VbError_t VbConfirmChangeDevMode(VbCommonParams* cparams, int to_dev) {
+ uint32_t key;
+
+ VBDEBUG(("Entering %s(%d)\n", __func__, to_dev));
+ /* Show the dev-mode confirmation screen */
+ VbDisplayScreen(cparams, (to_dev ? VB_SCREEN_RECOVERY_TO_DEV
+ : VB_SCREEN_RECOVERY_TO_NORM), 0, &vnc);
+
+ /* Await further instructions */
+ while (1) {
+ if (VbExIsShutdownRequested())
+ return VBERROR_SHUTDOWN_REQUESTED;
+ /* ENTER is always yes, ESC is always no.
+ * SPACE is yes when leaving dev-mode, but is no when entering it. */
+ key = VbExKeyboardRead();
+ if (key == '\r' || (key == ' ' && !to_dev)) {
+ VBDEBUG(("%s() - Yes: virtual dev-mode switch => %d\n",
+ __func__, to_dev));
+ if (TPM_SUCCESS != SetVirtualDevMode(to_dev))
+ return VBERROR_TPM_SET_BOOT_MODE_STATE;
+ VBDEBUG(("%s() - Reboot so it will take effect\n", __func__));
+ return VBERROR_TPM_REBOOT_REQUIRED;
+ } else if (key == 0x1B || (key == ' ' && to_dev)) {
+ VBDEBUG(("%s() - No: don't change virtual dev-mode switch\n", __func__));
+ VbDisplayScreen(cparams, VB_SCREEN_RECOVERY_INSERT, 0, &vnc);
+ return VBERROR_SUCCESS;
+ } else if (key) {
+ /* Anything else, just keep waiting */
+ VbCheckDisplayKey(cparams, key, &vnc);
+ VbExSleepMs(1000);
+ }
+ }
+}
+
/* Delay between disk checks in recovery mode */
#define REC_DELAY_INCREMENT 250
@@ -209,6 +255,7 @@ fallout:
VbError_t VbBootRecovery(VbCommonParams* cparams, LoadKernelParams* p) {
VbSharedDataHeader* shared = (VbSharedDataHeader*)cparams->shared_data_blob;
uint32_t retval;
+ uint32_t key;
int i;
VBDEBUG(("VbBootRecovery() start\n"));
@@ -224,7 +271,7 @@ VbError_t VbBootRecovery(VbCommonParams* cparams, LoadKernelParams* p) {
while (1) {
if (VBERROR_SUCCESS != VbExDiskGetInfo(&disk_info, &disk_count,
- VB_DISK_FLAG_REMOVABLE))
+ VB_DISK_FLAG_REMOVABLE))
disk_count = 0;
VbExDiskFreeInfo(disk_info, NULL);
@@ -249,6 +296,18 @@ VbError_t VbBootRecovery(VbCommonParams* cparams, LoadKernelParams* p) {
}
}
+ /* See if we should disable the virtual dev-mode switch. */
+ VBDEBUG(("VbBootRecovery() shared->flags=0x%x, recovery_reason=%d\n",
+ shared->flags, shared->recovery_reason));
+ if (shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH &&
+ shared->flags & VBSD_BOOT_DEV_SWITCH_ON &&
+ shared->recovery_reason == VBNV_RECOVERY_RW_DEV_SCREEN) {
+ retval = VbConfirmChangeDevMode(cparams, 0); /* .. so go ask */
+ VBDEBUG(("VbConfirmChangeDevMode() returned %d\n", retval));
+ if (retval != VBERROR_SUCCESS)
+ return retval;
+ }
+
/* Loop and wait for a recovery image */
while (1) {
VBDEBUG(("VbBootRecovery() attempting to load kernel\n"));
@@ -260,7 +319,7 @@ VbError_t VbBootRecovery(VbCommonParams* cparams, LoadKernelParams* p) {
VbSetRecoveryRequest(VBNV_RECOVERY_NOT_REQUESTED);
if (VBERROR_SUCCESS == retval)
- break; /* Found a recovery kernel */
+ break; /* Found a recovery kernel */
VbDisplayScreen(cparams, VBERROR_NO_DISK_FOUND == retval ?
VB_SCREEN_RECOVERY_INSERT : VB_SCREEN_RECOVERY_NO_GOOD,
@@ -269,7 +328,19 @@ VbError_t VbBootRecovery(VbCommonParams* cparams, LoadKernelParams* p) {
/* Scan keyboard more frequently than media, since x86 platforms don't like
* to scan USB too rapidly. */
for (i = 0; i < 4; i++) {
- VbCheckDisplayKey(cparams, VbExKeyboardRead(), &vnc);
+ key = VbExKeyboardRead();
+ /* We might want to enter dev-mode from the Insert screen if... */
+ if (key == 0x04 && /* user pressed Ctrl-D */
+ shared->flags & VBSD_HONOR_VIRT_DEV_SWITCH && /* we can do that */
+ !(shared->flags & VBSD_BOOT_DEV_SWITCH_ON) && /* not in dev-mode */
+ (shared->flags & VBSD_BOOT_REC_SWITCH_ON) && /* user forced rec */
+ VbExTrustEC()) { /* EC isn't pwned */
+ retval = VbConfirmChangeDevMode(cparams, 1); /* .. so go ask */
+ VBDEBUG(("VbConfirmChangeDevMode() returned %d\n", retval));
+ if (retval != VBERROR_SUCCESS)
+ return retval;
+ } else
+ VbCheckDisplayKey(cparams, key, &vnc);
if (VbExIsShutdownRequested())
return VBERROR_SHUTDOWN_REQUESTED;
VbExSleepMs(REC_DELAY_INCREMENT);
@@ -287,8 +358,6 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams* cparams,
LoadKernelParams p;
uint32_t tpm_status = 0;
- VBDEBUG(("VbSelectAndLoadKernel() start\n"));
-
/* Start timer */
shared->timer_vb_select_and_load_kernel_enter = VbExGetTimer();
diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c
index 3649fd1f..e48623b5 100644
--- a/firmware/lib/vboot_display.c
+++ b/firmware/lib/vboot_display.c
@@ -219,6 +219,12 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams* cparams, uint32_t screen,
case VB_SCREEN_RECOVERY_INSERT:
screen_index = 3;
break;
+ case VB_SCREEN_RECOVERY_TO_DEV:
+ screen_index = 4;
+ break;
+ case VB_SCREEN_RECOVERY_TO_NORM:
+ screen_index = 5;
+ break;
case VB_SCREEN_BLANK:
case VB_SCREEN_DEVELOPER_EGG:
default:
@@ -328,6 +334,7 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams* cparams, uint32_t screen,
VbDisplayScreenFromGBB_exit:
+ VBDEBUG(("leaving VbDisplayScreenFromGBB() with %d\n",retval));
/* Free the bitmap data copy */
VbExFree(bmpfv);
return retval;
@@ -590,7 +597,6 @@ VbError_t VbCheckDisplayKey(VbCommonParams* cparams, uint32_t key,
if ('\t' == key) {
/* Tab = display debug info */
return VbDisplayDebugInfo(cparams, vncptr);
-
} else if (VB_KEY_LEFT == key || VB_KEY_RIGHT == key ||
VB_KEY_DOWN == key || VB_KEY_UP == key) {
/* Arrow keys = change localization */
diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c
index 9c1cf346..020b589a 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, 0);
+ RollbackFirmwareSetup(0, 0, 0, 0, 0);
RollbackFirmwareWrite(0);
RollbackFirmwareLock();
RollbackKernelRead(0);
diff --git a/tests/rollback_index2_tests.c b/tests/rollback_index2_tests.c
index 98d7dcde..6de33bcf 100644
--- a/tests/rollback_index2_tests.c
+++ b/tests/rollback_index2_tests.c
@@ -558,7 +558,7 @@ static void SetupTpmTest(void) {
/* Complete setup */
ResetMocks(0, 0);
- TEST_EQ(SetupTPM(0, 0, &rsf), 0, "SetupTPM()");
+ TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM()");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
"TlclStartup()\n"
@@ -570,7 +570,7 @@ static void SetupTpmTest(void) {
/* If TPM is disabled or deactivated, must enable it */
ResetMocks(0, 0);
mock_pflags.disable = 1;
- TEST_EQ(SetupTPM(0, 0, &rsf), TPM_E_MUST_REBOOT, "SetupTPM() disabled");
+ TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_MUST_REBOOT, "SetupTPM() disabled");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
"TlclStartup()\n"
@@ -582,7 +582,7 @@ static void SetupTpmTest(void) {
ResetMocks(0, 0);
mock_pflags.deactivated = 1;
- TEST_EQ(SetupTPM(0, 0, &rsf), TPM_E_MUST_REBOOT, "SetupTPM() deactivated");
+ TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_MUST_REBOOT, "SetupTPM() deactivated");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
"TlclStartup()\n"
@@ -594,7 +594,7 @@ static void SetupTpmTest(void) {
/* If physical presence command isn't enabled, should try to enable it */
ResetMocks(3, TPM_E_IOERROR);
- TEST_EQ(SetupTPM(0, 0, &rsf), 0, "SetupTPM() pp cmd");
+ TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() pp cmd");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
"TlclStartup()\n"
@@ -609,7 +609,7 @@ static void SetupTpmTest(void) {
ResetMocks(5, TPM_E_BADINDEX);
mock_pflags.physicalPresenceLifetimeLock = 1;
mock_pflags.nvLocked = 1;
- TEST_EQ(SetupTPM(0, 0, &rsf), 0, "SetupTPM() no firmware space");
+ TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() no firmware space");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
"TlclStartup()\n"
@@ -632,7 +632,7 @@ static void SetupTpmTest(void) {
/* Other firmware space error is passed through */
ResetMocks(5, TPM_E_IOERROR);
- TEST_EQ(SetupTPM(0, 0, &rsf), TPM_E_CORRUPTED_STATE,
+ TEST_EQ(SetupTPM(0, 0, 0, &rsf), TPM_E_CORRUPTED_STATE,
"SetupTPM() bad firmware space");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
@@ -644,7 +644,7 @@ static void SetupTpmTest(void) {
/* If developer flag has toggled, clear ownership and write new flag */
ResetMocks(0, 0);
- TEST_EQ(SetupTPM(0, 1, &rsf), 0, "SetupTPM() to dev");
+ TEST_EQ(SetupTPM(0, 1, 0, &rsf), 0, "SetupTPM() to dev");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
"TlclStartup()\n"
@@ -657,11 +657,11 @@ static void SetupTpmTest(void) {
"TlclWrite(0x1007, 10)\n"
"TlclRead(0x1007, 10)\n",
"tlcl calls");
- TEST_EQ(mock_rsf.flags, FLAG_LAST_BOOT_DEVELOPER, "fw space flags to dev");
+ 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, &rsf), 0, "SetupTPM() from dev");
+ TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM() from dev");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
"TlclStartup()\n"
@@ -674,7 +674,7 @@ static void SetupTpmTest(void) {
"TlclWrite(0x1007, 10)\n"
"TlclRead(0x1007, 10)\n",
"tlcl calls");
- TEST_EQ(mock_rsf.flags, 0, "fw space flags from dev");
+ TEST_EQ(mock_rsf.flags, 0, "fw space flags from dev 1");
/* Note: SetupTPM() recovery_mode parameter sets a global flag in
* rollback_index.c; this is tested along with RollbackKernelLock() below. */
@@ -691,7 +691,7 @@ static void RollbackFirmwareTest(void) {
dev_mode = 0;
version = 123;
mock_rsf.fw_versions = 0x12345678;
- TEST_EQ(RollbackFirmwareSetup(0, 0, &dev_mode, &version), 0,
+ TEST_EQ(RollbackFirmwareSetup(0, 0, dev_mode, &dev_mode, &version), 0,
"RollbackFirmwareSetup()");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
@@ -707,7 +707,8 @@ static void RollbackFirmwareTest(void) {
dev_mode = 0;
version = 123;
mock_rsf.fw_versions = 0x12345678;
- TEST_EQ(RollbackFirmwareSetup(0, 0, &dev_mode, &version), TPM_E_IOERROR,
+ TEST_EQ(RollbackFirmwareSetup(0, 0, dev_mode, &dev_mode, &version),
+ TPM_E_IOERROR,
"RollbackFirmwareSetup() error");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n",
@@ -717,7 +718,7 @@ static void RollbackFirmwareTest(void) {
/* Developer mode flag gets passed properly */
ResetMocks(0, 0);
dev_mode = 1;
- TEST_EQ(RollbackFirmwareSetup(0, 0, &dev_mode, &version), 0,
+ TEST_EQ(RollbackFirmwareSetup(0, dev_mode, 0, &dev_mode, &version), 0,
"RollbackFirmwareSetup() to dev");
TEST_STR_EQ(mock_calls,
"TlclLibInit()\n"
@@ -731,7 +732,7 @@ static void RollbackFirmwareTest(void) {
"TlclWrite(0x1007, 10)\n"
"TlclRead(0x1007, 10)\n",
"tlcl calls");
- TEST_EQ(mock_rsf.flags, FLAG_LAST_BOOT_DEVELOPER, "fw space flags to dev");
+ TEST_EQ(mock_rsf.flags, FLAG_LAST_BOOT_DEVELOPER, "fw space flags to dev 2");
/* Test write */
ResetMocks(0, 0);
@@ -769,7 +770,7 @@ static void RollbackKernelTest(void) {
/* 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, &rsf), 0, "SetupTPM()");
+ TEST_EQ(SetupTPM(0, 0, 0, &rsf), 0, "SetupTPM()");
/* Normal read */
ResetMocks(0, 0);
@@ -830,7 +831,7 @@ static void RollbackKernelTest(void) {
TEST_EQ(RollbackKernelLock(), TPM_E_IOERROR, "RollbackKernelLock() error");
/* Test lock with recovery on; shouldn't lock PP */
- SetupTPM(1, 0, &rsf);
+ SetupTPM(1, 0, 0, &rsf);
ResetMocks(0, 0);
TEST_EQ(RollbackKernelLock(), 0, "RollbackKernelLock() in recovery");
TEST_STR_EQ(mock_calls, "", "no tlcl calls");
diff --git a/tests/vboot_api_init_tests.c b/tests/vboot_api_init_tests.c
index 15907d49..ec1e7fa9 100644
--- a/tests/vboot_api_init_tests.c
+++ b/tests/vboot_api_init_tests.c
@@ -26,7 +26,7 @@ static uint64_t mock_timer;
static int rollback_s3_retval;
static int nv_write_called;
static GoogleBinaryBlockHeader gbb;
-static int mock_dev_mode;
+static int mock_virt_dev_sw;
static uint32_t mock_tpm_version;
static uint32_t mock_rfs_retval;
@@ -55,7 +55,7 @@ static void ResetMocks(void) {
rollback_s3_retval = TPM_SUCCESS;
nv_write_called = 0;
- mock_dev_mode = 0;
+ mock_virt_dev_sw = 0;
mock_tpm_version = 0x10001;
mock_rfs_retval = 0;
}
@@ -87,10 +87,11 @@ 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;
+uint32_t RollbackFirmwareSetup(int recovery_mode, int is_hw_dev,
+ int disable_dev_request,
+ /* two outputs on success */
+ int *is_virt_dev, uint32_t *version) {
+ *is_virt_dev = mock_virt_dev_sw;
*version = mock_tpm_version;
return mock_rfs_retval;
}
@@ -316,16 +317,16 @@ static void VbInitTestTPM(void) {
/* Virtual developer switch, but not enabled. */
ResetMocks();
- iparams.flags = VB_INIT_FLAG_DEV_SWITCH_ON | VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
+ 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, 0, " shared flags");
+ TEST_EQ(shared->flags, VBSD_HONOR_VIRT_DEV_SWITCH, " shared flags");
/* Virtual developer switch, enabled. */
ResetMocks();
iparams.flags = VB_INIT_FLAG_VIRTUAL_DEV_SWITCH;
- mock_dev_mode = 1;
+ 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,
@@ -333,6 +334,27 @@ static void VbInitTestTPM(void) {
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 | VBSD_HONOR_VIRT_DEV_SWITCH,
+ " shared flags");
+
+ /* 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_ALTERNATE_OS, " out flags");
TEST_EQ(shared->flags, VBSD_BOOT_DEV_SWITCH_ON, " shared flags");
}