misc: efi-stub: Set MOR bit before jumping to hypervisor

This patch sets the MemoryOverwriteRequestControl (MORCtrl for short)
EFI variable before jumping to hypervisor.

Setting variable MemoryOverwriteRequestControlLock (MORCtrlLock for
short) can also be enabled by manually adding -DMORCTRL_LOCK_ENABLED to
CFLAGS.

Setting MORCtrl indicates to the platform firmware that memory be
cleared upon system reset. Setting MORCtrlLock for the first time will
render both MORCtrl and MORCtrlLock to read-only, until next reset.

Tracked-On: #6241
Signed-off-by: Yifan Liu <yifan1.liu@intel.com>
This commit is contained in:
Yifan Liu 2021-06-23 08:47:07 +08:00 committed by wenlingz
parent c2217aa5d4
commit 4252bc247d
2 changed files with 90 additions and 0 deletions

View File

@ -102,6 +102,84 @@ out:
return err;
}
static EFI_STATUS
set_mor_bit()
{
EFI_STATUS err;
UINT32 attrs;
UINTN size = 1;
uint8_t data = 0;
EFI_GUID efi_var_morctl_guid = EFI_VAR_MORCTL_GUID;
#ifdef MORCTRL_LOCK_ENABLED
EFI_GUID efi_var_morctllock_guid = EFI_VAR_MORCTLLOCK_GUID;
#endif
/*
* Per TCG Platform Reset Attack Mitigation Spec 1.10 rev 17, Chp 4.1
* MORCtrl is a 1-byte unsigned number and should be created by the firmware.
*/
err = get_variable(EFI_VAR_MORCTL_NAME, &efi_var_morctl_guid, &attrs, &size, (void *)&data);
if (err != EFI_SUCCESS) {
if (err == EFI_BUFFER_TOO_SMALL) {
Print(L"Wrong MORCtrl variable size: 0x%x byte, should be 1 byte\n", size);
} else if (err == EFI_NOT_FOUND) {
Print(L"Warning: MORCtrl variable not found\n");
}
goto out;
}
if (attrs != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) {
Print(L"Wrong MORCtrl attributes: 0x%x\n", attrs);
goto out;
}
/* Bit 0 set: Firmware MUST set the MOR bit */
/* Bit 4 cleared: Firmware MAY autodetect a clean shutdown of the Static RTM OS. */
data = 0x1;
err = set_variable(EFI_VAR_MORCTL_NAME, &efi_var_morctl_guid, attrs, size, &data);
if (err != EFI_SUCCESS)
goto out;
#ifdef MORCTRL_LOCK_ENABLED
/*
* MORCTRL_LOCK_ENABLED is NOT part of the board configuration.
* To activate MORCTRL_LOCK_ENABLED, manually add -DMORCTRL_LOCK_ENABLED to the CFLAGS.
*/
/* Lock MORCtrl with MORCtrlLock */
size = 1;
err = get_variable(EFI_VAR_MORCTLLOCK_NAME, &efi_var_morctllock_guid, &attrs, &size, (void *)&data);
if (err != EFI_SUCCESS)
goto out;
if (attrs != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS)) {
Print(L"Wrong MORCtrlLock attributes: 0x%x\n", attrs);
goto out;
}
if (data == 0x1 || data == 0x2) {
Print(L"Warning: MORCtrl already locked. No locking operation performed.\n");
goto out;
}
/*
* Input value 1, size 1: Lock without key
* Try to lock MemoryOverwriteRequestControlLock and MemoryOverwriteRequestControl
* If success, MORCtrl and MORCtrlLock will be read-only until next boot, and reboot
* is the only way to unlock these variables.
*/
data = 0x1;
size = 0x1;
err = set_variable(EFI_VAR_MORCTLLOCK_NAME, &efi_var_morctllock_guid, attrs, size, (void *)&data);
if (err != EFI_SUCCESS)
goto out;
#endif
out:
return err;
}
static EFI_STATUS
terminate_boot_services(EFI_HANDLE image, struct efi_memmap_info *mmap_info)
{
@ -517,6 +595,11 @@ run_acrn(EFI_HANDLE image, HV_LOADER hvld)
void *mbi;
int32_t mb_version = hvld->get_multiboot_version(hvld);
err = set_mor_bit();
/* If MOR not supported, emit a warning and proceed */
if (err != EFI_SUCCESS && err != EFI_NOT_FOUND)
goto out;
if (mb_version == 2) {
err = construct_mbi2(hvld, &mbi, &memmapinfo);
}

View File

@ -59,6 +59,13 @@
#define UEFI_BOOT_LOADER_NAME "ACRN UEFI loader"
#define EFI_VAR_MORCTL_NAME L"MemoryOverwriteRequestControl"
#define EFI_VAR_MORCTL_GUID \
{ 0xe20939be, 0x32d4, 0x41be, { 0xa1, 0x50, 0x89, 0x7f, 0x85, 0xd4, 0x98, 0x29 } }
#define EFI_VAR_MORCTLLOCK_NAME L"MemoryOverwriteRequestControlLock"
#define EFI_VAR_MORCTLLOCK_GUID \
{ 0xBB983CCF, 0x151D, 0x40E1, { 0xA0, 0x7B, 0x4A, 0x17, 0xBE, 0x16, 0x82, 0x92 } }
#define ALIGN_UP(addr, align) \
(((addr) + (typeof (addr)) (align) - 1) & ~((typeof (addr)) (align) - 1))