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: #6097
Signed-off-by: Yifan Liu <yifan1.liu@intel.com>
This commit is contained in:
Yifan Liu 2021-05-27 11:26:19 +08:00 committed by wenlingz
parent 1ba5b64b07
commit 701f6bf05d
3 changed files with 103 additions and 0 deletions

View File

@ -42,6 +42,7 @@
EFI_SYSTEM_TABLE *sys_table;
EFI_BOOT_SERVICES *boot;
EFI_RUNTIME_SERVICES *runtime;
HV_LOADER hvld;
static EFI_STATUS
@ -103,6 +104,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)
{
@ -518,6 +597,11 @@ run_acrn(EFI_HANDLE image, HV_LOADER hvld)
struct efi_memmap_info memmapinfo;
struct multiboot_info *mbi;
err = set_mor_bit();
/* If MOR not supported, emit a warning and proceed */
if (err != EFI_SUCCESS && err != EFI_NOT_FOUND)
goto out;
#ifdef CONFIG_MULTIBOOT2
/* MB2 has no fixed mbinfo layout. The mbi as output will
* NOT conform to the layout of struct multiboot_info.
@ -557,6 +641,7 @@ efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *_table)
InitializeLib(image, _table);
sys_table = _table;
boot = sys_table->BootServices;
runtime = sys_table->RuntimeServices;
if (CheckCrc(sys_table->Hdr.HeaderSize, &sys_table->Hdr) != TRUE)
return EFI_LOAD_ERROR;

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))

View File

@ -51,6 +51,7 @@
extern EFI_SYSTEM_TABLE *sys_table;
extern EFI_BOOT_SERVICES *boot;
extern EFI_RUNTIME_SERVICES *runtime;
extern EFI_STATUS
emalloc_reserved_aligned(EFI_PHYSICAL_ADDRESS *addr, UINTN size, UINTN align,
@ -223,6 +224,16 @@ static inline EFI_STATUS emalloc_fixed_addr(EFI_PHYSICAL_ADDRESS *addr,
EFI_SIZE_TO_PAGES(size), addr);
}
static inline EFI_STATUS get_variable(const CHAR16 *name, EFI_GUID *guid, UINT32 *attrs, UINTN *size, void *data)
{
return uefi_call_wrapper(runtime->GetVariable, 5, name, guid, attrs, size, data);
}
static inline EFI_STATUS set_variable(const CHAR16 *name, EFI_GUID *guid, UINT32 attrs, UINTN size, void *data)
{
return uefi_call_wrapper(runtime->SetVariable, 5, name, guid, attrs, size, data);
}
/**
* exit - Terminate a loaded EFI image
* @image: firmware-allocated handle that identifies the image