diff --git a/misc/efi-stub/boot.c b/misc/efi-stub/boot.c index 2893dba89..ee117b1d1 100644 --- a/misc/efi-stub/boot.c +++ b/misc/efi-stub/boot.c @@ -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); } diff --git a/misc/efi-stub/boot.h b/misc/efi-stub/boot.h index b16b193f1..95354c73e 100644 --- a/misc/efi-stub/boot.h +++ b/misc/efi-stub/boot.h @@ -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))