diff options
-rw-r--r-- | firmware/include/vboot_api.h | 4 | ||||
-rw-r--r-- | firmware/include/vboot_struct.h | 2 | ||||
-rw-r--r-- | firmware/lib/include/rollback_index.h | 15 | ||||
-rw-r--r-- | firmware/lib/mocked_rollback_index.c | 5 | ||||
-rw-r--r-- | firmware/lib/rollback_index.c | 68 | ||||
-rw-r--r-- | firmware/lib/vboot_api_firmware.c | 3 | ||||
-rw-r--r-- | firmware/lib/vboot_api_init.c | 55 | ||||
-rw-r--r-- | firmware/lib/vboot_api_kernel.c | 79 | ||||
-rw-r--r-- | firmware/lib/vboot_display.c | 8 | ||||
-rw-r--r-- | firmware/linktest/main.c | 2 | ||||
-rw-r--r-- | tests/rollback_index2_tests.c | 33 | ||||
-rw-r--r-- | tests/vboot_api_init_tests.c | 40 |
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"); } |