mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
OcAppleBootCompatLib: Rework FwRuntime protocol logic and usage
This commit is contained in:
parent
5cc416d681
commit
7fe4fbb5d8
@ -20,25 +20,31 @@
|
||||
**/
|
||||
typedef struct OC_ABC_SETTINGS_ {
|
||||
///
|
||||
/// Protect from boot.efi from defragmenting runtime memory and setup virtual memory
|
||||
/// early mapping. This fixes NVRAM support on many firmwares.
|
||||
/// Protect from boot.efi from defragmenting runtime memory. This fixes UEFI runtime services
|
||||
/// (date and time, NVRAM, power control, etc.) support on many firmwares.
|
||||
/// Needed basically by everyone that uses SMM implementation of variable services.
|
||||
///
|
||||
BOOLEAN SetupAppleMap;
|
||||
BOOLEAN AvoidRuntimeDefrag;
|
||||
///
|
||||
/// Setup virtual memory mapping after SetVirtualAddresses call. This fixes crashes in many
|
||||
/// firmwares at early boot as they accidentally access virtual addresses after ExitBootServices.
|
||||
///
|
||||
BOOLEAN SetupVirtualMap;
|
||||
///
|
||||
/// Provide custom Apple KASLR slide calculation for firmwares with polluted low memory ranges.
|
||||
/// This also ensures that slide= argument is never passed to the operating system.
|
||||
///
|
||||
BOOLEAN SetupAppleSlide;
|
||||
BOOLEAN ProvideCustomSlide;
|
||||
///
|
||||
/// Discard UEFI memory map after waking from hibernation and preserve the original mapping.
|
||||
///
|
||||
BOOLEAN DiscardAppleS4Map;
|
||||
BOOLEAN DiscardHibernateMap;
|
||||
///
|
||||
/// Try to patch Apple bootloader to have KASLR enabled even in SafeMode.
|
||||
///
|
||||
BOOLEAN EnableAppleSmSlide;
|
||||
BOOLEAN EnableSafeModeSlide;
|
||||
///
|
||||
/// Attempt to protect certain CSM memory regions from being used by the kernel .
|
||||
/// Attempt to protect certain CSM memory regions from being used by the kernel.
|
||||
/// On older firmwares this caused wake issues.
|
||||
///
|
||||
BOOLEAN ProtectCsmRegion;
|
||||
@ -50,6 +56,16 @@ typedef struct OC_ABC_SETTINGS_ {
|
||||
/// Ensure that ExitBootServices call succeeds even with outdated MemoryMap key.
|
||||
///
|
||||
BOOLEAN ForceExitBootServices;
|
||||
///
|
||||
/// Disable NVRAM variable write support to protect from malware or to prevent
|
||||
/// buggy NVRAM implementations cause system issues.
|
||||
///
|
||||
BOOLEAN DisableVariableWrite;
|
||||
///
|
||||
/// Permit writing to executable memory in UEFI runtime services. Fixes crashes
|
||||
/// on many APTIO V firmwares.
|
||||
///
|
||||
BOOLEAN EnableWriteUnprotector;
|
||||
} OC_ABC_SETTINGS;
|
||||
|
||||
/**
|
||||
|
||||
@ -100,13 +100,16 @@
|
||||
/// Apple bootloader quirks.
|
||||
///
|
||||
#define OC_BOOTER_QUIRKS_FIELDS(_, __) \
|
||||
_(BOOLEAN , SetupAppleMap , , FALSE , ()) \
|
||||
_(BOOLEAN , SetupAppleSlide , , FALSE , ()) \
|
||||
_(BOOLEAN , DiscardAppleS4Map , , FALSE , ()) \
|
||||
_(BOOLEAN , EnableAppleSmSlide , , FALSE , ()) \
|
||||
_(BOOLEAN , ProtectCsmRegion , , FALSE , ()) \
|
||||
_(BOOLEAN , ShrinkMemoryMap , , FALSE , ()) \
|
||||
_(BOOLEAN , ForceExitBootServices , , FALSE , ())
|
||||
_(BOOLEAN , AvoidRuntimeDefrag , , FALSE , ()) \
|
||||
_(BOOLEAN , DisableVariableWrite , , FALSE , ()) \
|
||||
_(BOOLEAN , DiscardHibernateMap , , FALSE , ()) \
|
||||
_(BOOLEAN , EnableSafeModeSlide , , FALSE , ()) \
|
||||
_(BOOLEAN , EnableWriteUnprotector , , FALSE , ()) \
|
||||
_(BOOLEAN , ForceExitBootServices , , FALSE , ()) \
|
||||
_(BOOLEAN , ProtectCsmRegion , , FALSE , ()) \
|
||||
_(BOOLEAN , ProvideCustomSlide , , FALSE , ()) \
|
||||
_(BOOLEAN , SetupVirtualMap , , FALSE , ()) \
|
||||
_(BOOLEAN , ShrinkMemoryMap , , FALSE , ())
|
||||
OC_DECLARE (OC_BOOTER_QUIRKS)
|
||||
|
||||
///
|
||||
|
||||
@ -15,46 +15,110 @@
|
||||
#ifndef OC_FIRMWARE_RUNTIME_PROTOCOL_H
|
||||
#define OC_FIRMWARE_RUNTIME_PROTOCOL_H
|
||||
|
||||
#define OC_FIRMWARE_RUNTIME_REVISION 1
|
||||
#include <Uefi.h>
|
||||
|
||||
//
|
||||
// OC_FIRMWARE_RUNTIME_PROTOCOL_GUID
|
||||
// 9C820F96-F16C-4FFD-B266-DF0A8FDFC455
|
||||
//
|
||||
#define OC_FIRMWARE_RUNTIME_REVISION 2
|
||||
|
||||
/**
|
||||
OC_FIRMWARE_RUNTIME_PROTOCOL_GUID
|
||||
570332E4-FC50-4B21-ABE8-AE72F05B4FF7
|
||||
**/
|
||||
#define OC_FIRMWARE_RUNTIME_PROTOCOL_GUID \
|
||||
{ 0x9C820F96, 0xF16C, 0x4FFD, \
|
||||
{ 0xB2, 0x66, 0xDF, 0x0A, 0x8F, 0xDF, 0xC4, 0x55 } }
|
||||
{ 0x570332E4, 0xFC50, 0x4B21, \
|
||||
{ 0xAB, 0xE8, 0xAE, 0x72, 0xF0, 0x5B, 0x4F, 0xF7 } }
|
||||
/**
|
||||
Configuration request to change firmware runtime behaviour.
|
||||
**/
|
||||
typedef struct OC_FWRT_CONFIG_ {
|
||||
///
|
||||
/// Enforce restricted access to OpenCore read-only and write-only GUIDs.
|
||||
///
|
||||
BOOLEAN RestrictedVariables;
|
||||
///
|
||||
/// Enforce BootXXXX variable redirection to OpenCore vendor GUID.
|
||||
///
|
||||
BOOLEAN BootVariableRedirect;
|
||||
///
|
||||
/// Make SetVariable do nothing and always return EFI_SECURITY_VIOLATION.
|
||||
/// When we do not want variables to be stored in NVRAM or NVRAM implementation
|
||||
/// is buggy we can disable variable writing.
|
||||
///
|
||||
BOOLEAN WriteProtection;
|
||||
///
|
||||
/// Make UEFI runtime services drop CR0 WP bit on calls to allow writing
|
||||
/// to read only memory. This workarounds a bug in many APTIO firmwares
|
||||
/// that do not survive W^X.
|
||||
/// Latest Windows brings Virtualization-based security and monitors
|
||||
/// CR0 by launching itself under a hypevisor. Since we need WP disable
|
||||
/// on macOS to let NVRAM work, and for the time being no other OS
|
||||
/// requires it, here we decide to use it for macOS exclusively.
|
||||
///
|
||||
BOOLEAN WriteUnprotector;
|
||||
} OC_FWRT_CONFIG;
|
||||
|
||||
//
|
||||
// Set NVRAM routing, returns previous value.
|
||||
//
|
||||
/**
|
||||
Get current used configuration data.
|
||||
|
||||
@param[out] Config Current configuration to store.
|
||||
**/
|
||||
typedef
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
(*OC_FWRT_NVRAM_REDIRECT) (
|
||||
IN BOOLEAN NewValue
|
||||
VOID
|
||||
(EFIAPI *OC_FWRT_GET_CURRENT_CONFIG) (
|
||||
OUT OC_FWRT_CONFIG *Config
|
||||
);
|
||||
|
||||
//
|
||||
// Set GetVariable override for customising values.
|
||||
//
|
||||
/**
|
||||
Set main configuration.
|
||||
|
||||
@param[in] Config Runtime services configuration to apply.
|
||||
**/
|
||||
typedef
|
||||
VOID
|
||||
(EFIAPI *OC_FWRT_SET_MAIN_CONFIG) (
|
||||
IN CONST OC_FWRT_CONFIG *Config
|
||||
);
|
||||
|
||||
/**
|
||||
Perform configuration override, NULL Config implies disable override.
|
||||
|
||||
@param[in] Config Runtime services configuration to apply, optional.
|
||||
**/
|
||||
typedef
|
||||
VOID
|
||||
(EFIAPI *OC_FWRT_SET_OVERRIDE_CONFIG) (
|
||||
IN CONST OC_FWRT_CONFIG *Config OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Set GetVariable override for customising values.
|
||||
|
||||
@param[in] GetVariable GetVariable to call on each call.
|
||||
@param[out] OrgGetVariable Original GetVariable to call from GetVariable.
|
||||
|
||||
@retval EFI_SUCCESS on successful override.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
(*OC_FWRT_ON_GET_VARIABLE) (
|
||||
(EFIAPI *OC_FWRT_ON_GET_VARIABLE) (
|
||||
IN EFI_GET_VARIABLE GetVariable,
|
||||
OUT EFI_GET_VARIABLE *OrgGetVariable OPTIONAL
|
||||
);
|
||||
|
||||
//
|
||||
// Check for revision to ensure binary compatibility.
|
||||
//
|
||||
/**
|
||||
Firmware runtime protocol instance.
|
||||
Check for revision to ensure binary compatibility.
|
||||
**/
|
||||
typedef struct {
|
||||
UINTN Revision;
|
||||
OC_FWRT_NVRAM_REDIRECT SetNvram;
|
||||
OC_FWRT_ON_GET_VARIABLE OnGetVariable;
|
||||
UINTN Revision;
|
||||
OC_FWRT_GET_CURRENT_CONFIG GetCurrent;
|
||||
OC_FWRT_SET_MAIN_CONFIG SetMain;
|
||||
OC_FWRT_SET_OVERRIDE_CONFIG SetOverride;
|
||||
OC_FWRT_ON_GET_VARIABLE OnGetVariable;
|
||||
} OC_FIRMWARE_RUNTIME_PROTOCOL;
|
||||
|
||||
/**
|
||||
Firmware runtime protocol GUID.
|
||||
**/
|
||||
extern EFI_GUID gOcFirmwareRuntimeProtocolGuid;
|
||||
|
||||
#endif // OC_FIRMWARE_RUNTIME_PROTOCOL_H
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include <Library/OcMemoryLib.h>
|
||||
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Protocol/OcFirmwareRuntime.h>
|
||||
|
||||
#ifdef MDE_CPU_X64
|
||||
#include "X64/ContextSwitch.h"
|
||||
@ -161,31 +162,35 @@ typedef struct SERVICES_OVERRIDE_STATE_ {
|
||||
///
|
||||
/// GetVariable arrival event.
|
||||
///
|
||||
EFI_EVENT GetVariableEvent;
|
||||
EFI_EVENT GetVariableEvent;
|
||||
///
|
||||
/// Firmware runtime protocol instance.
|
||||
///
|
||||
OC_FIRMWARE_RUNTIME_PROTOCOL *FwRuntime;
|
||||
///
|
||||
/// Minimum address allocated by AlocatePages.
|
||||
///
|
||||
EFI_PHYSICAL_ADDRESS MinAllocatedAddr;
|
||||
EFI_PHYSICAL_ADDRESS MinAllocatedAddr;
|
||||
///
|
||||
/// Apple hibernate image address allocated by AlocatePages.
|
||||
///
|
||||
EFI_PHYSICAL_ADDRESS HibernateImageAddress;
|
||||
EFI_PHYSICAL_ADDRESS HibernateImageAddress;
|
||||
///
|
||||
/// Last descriptor size obtained from GetMemoryMap.
|
||||
///
|
||||
UINTN MemoryMapDescriptorSize;
|
||||
UINTN MemoryMapDescriptorSize;
|
||||
///
|
||||
/// Amount of nested boot.efi detected.
|
||||
///
|
||||
UINTN AppleBootNestedCount;
|
||||
UINTN AppleBootNestedCount;
|
||||
///
|
||||
/// TRUE if we are doing boot.efi hibernate wake.
|
||||
///
|
||||
BOOLEAN AppleHibernateWake;
|
||||
BOOLEAN AppleHibernateWake;
|
||||
///
|
||||
/// TRUE if we are using custom KASLR slide (via boot arg).
|
||||
///
|
||||
BOOLEAN AppleCustomSlide;
|
||||
BOOLEAN AppleCustomSlide;
|
||||
} SERVICES_OVERRIDE_STATE;
|
||||
|
||||
/**
|
||||
@ -328,7 +333,7 @@ GetBootCompatContext (
|
||||
**/
|
||||
VOID
|
||||
InstallServiceOverrides (
|
||||
IN OUT BOOT_COMPAT_CONTEXT *ServicePtrs
|
||||
IN OUT BOOT_COMPAT_CONTEXT *BootCompat
|
||||
);
|
||||
|
||||
/**
|
||||
@ -382,14 +387,16 @@ AppleMapPrepareKernelJump (
|
||||
);
|
||||
|
||||
/**
|
||||
Patch kernel entry point with KernelJump to later land in AppleMapPrepareKernelState.
|
||||
Prepare memory state and perform virtual address translation.
|
||||
|
||||
@param[in,out] BootCompat Boot compatibility context.
|
||||
@param[in] ImageAddress Kernel or hibernation image address.
|
||||
@param[in] AppleHibernateWake TRUE when ImageAddress points to hibernation image.
|
||||
@param[in] MemoryMapSize SetVirtualAddresses memory map size argument.
|
||||
@param[in] DescriptorSize SetVirtualAddresses descriptor size argument.
|
||||
@param[in] DescriptorVersion SetVirtualAddresses descriptor version argument.
|
||||
@param[in] MemoryMap SetVirtualAddresses memory map argument.
|
||||
**/
|
||||
EFI_STATUS
|
||||
AppleMapPrepareVmState (
|
||||
AppleMapPrepareMemState (
|
||||
IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
|
||||
IN UINTN MemoryMapSize,
|
||||
IN UINTN DescriptorSize,
|
||||
|
||||
@ -334,25 +334,29 @@ AppleMapPrepareForBooting (
|
||||
|
||||
OcParseBootArgs (&BA, BootArgs);
|
||||
|
||||
//
|
||||
// Restore the variables we tampered with to support custom slides.
|
||||
//
|
||||
AppleSlideRestore (BootCompat, &BA);
|
||||
if (BootCompat->Settings.ProvideCustomSlide) {
|
||||
//
|
||||
// Restore the variables we tampered with to support custom slides.
|
||||
//
|
||||
AppleSlideRestore (BootCompat, &BA);
|
||||
}
|
||||
|
||||
MemoryMapSize = *BA.MemoryMapSize;
|
||||
MemoryMap = (EFI_MEMORY_DESCRIPTOR *)(UINTN) (*BA.MemoryMap);
|
||||
DescriptorSize = *BA.MemoryMapDescriptorSize;
|
||||
if (BootCompat->Settings.AvoidRuntimeDefrag) {
|
||||
MemoryMapSize = *BA.MemoryMapSize;
|
||||
MemoryMap = (EFI_MEMORY_DESCRIPTOR *)(UINTN) (*BA.MemoryMap);
|
||||
DescriptorSize = *BA.MemoryMapDescriptorSize;
|
||||
|
||||
//
|
||||
// We must restore EfiRuntimeServicesCode memory area types, because otherwise
|
||||
// RuntimeServices won't be mapped.
|
||||
//
|
||||
RestoreProtectedRtMemoryTypes (
|
||||
&BootCompat->RtReloc,
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
MemoryMap
|
||||
);
|
||||
//
|
||||
// We must restore EfiRuntimeServicesCode memory area types, because otherwise
|
||||
// RuntimeServices won't be mapped.
|
||||
//
|
||||
RestoreProtectedRtMemoryTypes (
|
||||
&BootCompat->RtReloc,
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
MemoryMap
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -398,7 +402,7 @@ AppleMapPrepareForHibernateWake (
|
||||
Handoff = (IOHibernateHandoff *) EFI_PAGES_TO_SIZE ((UINTN) ImageHeader->handoffPages);
|
||||
while (Handoff->type != kIOHibernateHandoffTypeEnd) {
|
||||
if (Handoff->type == kIOHibernateHandoffTypeMemoryMap) {
|
||||
if (BootCompat->Settings.DiscardAppleS4Map) {
|
||||
if (BootCompat->Settings.DiscardHibernateMap) {
|
||||
//
|
||||
// Route 1. Discard the new memory map here, and let XNU use what it had.
|
||||
// It is unknown whether there still are any firmwares that need this.
|
||||
@ -414,12 +418,17 @@ AppleMapPrepareForHibernateWake (
|
||||
return;
|
||||
}
|
||||
|
||||
RestoreProtectedRtMemoryTypes (
|
||||
&BootCompat->RtReloc,
|
||||
Handoff->bytecount,
|
||||
BootCompat->KernelState.VmMapDescSize,
|
||||
(EFI_MEMORY_DESCRIPTOR *)(UINTN) Handoff->data
|
||||
);
|
||||
if (BootCompat->Settings.AvoidRuntimeDefrag) {
|
||||
//
|
||||
// I think we should not be there, but ideally all quirks are relatively independent.
|
||||
//
|
||||
RestoreProtectedRtMemoryTypes (
|
||||
&BootCompat->RtReloc,
|
||||
Handoff->bytecount,
|
||||
BootCompat->KernelState.VmMapDescSize,
|
||||
(EFI_MEMORY_DESCRIPTOR *)(UINTN) Handoff->data
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@ -458,52 +467,54 @@ AppleMapPrepareBooterState (
|
||||
//
|
||||
// This function may be called twice, do not redo in this case.
|
||||
//
|
||||
if (BootCompat->KernelState.SysTableRtArea == 0) {
|
||||
AppleMapPlatformSaveState (
|
||||
&BootCompat->KernelState.AsmState,
|
||||
&BootCompat->KernelState.KernelJump
|
||||
);
|
||||
AppleMapPlatformSaveState (
|
||||
&BootCompat->KernelState.AsmState,
|
||||
&BootCompat->KernelState.KernelJump
|
||||
);
|
||||
|
||||
//
|
||||
// Allocate RT data pages for copy of UEFI system table for kernel.
|
||||
// This one also has to be 32-bit due to XNU BootArgs structure.
|
||||
// The reason for this allocation to be required is because XNU uses static
|
||||
// mapping for directly passed pointers (see ProtectRtMemoryFromRelocation).
|
||||
//
|
||||
BootCompat->KernelState.SysTableRtArea = BASE_4GB;
|
||||
BootCompat->KernelState.SysTableRtAreaSize = gST->Hdr.HeaderSize;
|
||||
Status = AllocatePagesFromTop (
|
||||
EfiRuntimeServicesData,
|
||||
EFI_SIZE_TO_PAGES (gST->Hdr.HeaderSize),
|
||||
&BootCompat->KernelState.SysTableRtArea,
|
||||
GetMemoryMap,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"OCABC: Failed to allocate system table memory - %r\n",
|
||||
Status
|
||||
));
|
||||
BootCompat->KernelState.SysTableRtArea = 0;
|
||||
return;
|
||||
if (BootCompat->Settings.AvoidRuntimeDefrag) {
|
||||
if (BootCompat->KernelState.SysTableRtArea == 0) {
|
||||
//
|
||||
// Allocate RT data pages for copy of UEFI system table for kernel.
|
||||
// This one also has to be 32-bit due to XNU BootArgs structure.
|
||||
// The reason for this allocation to be required is because XNU uses static
|
||||
// mapping for directly passed pointers (see ProtectRtMemoryFromRelocation).
|
||||
//
|
||||
BootCompat->KernelState.SysTableRtArea = BASE_4GB;
|
||||
BootCompat->KernelState.SysTableRtAreaSize = gST->Hdr.HeaderSize;
|
||||
Status = AllocatePagesFromTop (
|
||||
EfiRuntimeServicesData,
|
||||
EFI_SIZE_TO_PAGES (gST->Hdr.HeaderSize),
|
||||
&BootCompat->KernelState.SysTableRtArea,
|
||||
GetMemoryMap,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"OCABC: Failed to allocate system table memory - %r\n",
|
||||
Status
|
||||
));
|
||||
BootCompat->KernelState.SysTableRtArea = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Copy UEFI system table to the new location.
|
||||
//
|
||||
CopyMem (
|
||||
(VOID *)(UINTN) BootCompat->KernelState.SysTableRtArea,
|
||||
gST,
|
||||
gST->Hdr.HeaderSize
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Copy UEFI system table to the new location.
|
||||
// Assign loaded image with custom system table.
|
||||
//
|
||||
CopyMem (
|
||||
(VOID *)(UINTN) BootCompat->KernelState.SysTableRtArea,
|
||||
gST,
|
||||
gST->Hdr.HeaderSize
|
||||
);
|
||||
LoadedImage->SystemTable =
|
||||
(EFI_SYSTEM_TABLE *)(UINTN) BootCompat->KernelState.SysTableRtArea;
|
||||
}
|
||||
|
||||
//
|
||||
// Assign loaded image with custom system table.
|
||||
//
|
||||
LoadedImage->SystemTable =
|
||||
(EFI_SYSTEM_TABLE *)(UINTN) BootCompat->KernelState.SysTableRtArea;
|
||||
}
|
||||
|
||||
VOID
|
||||
@ -517,6 +528,21 @@ AppleMapPrepareKernelJump (
|
||||
UINT32 KernelEntry;
|
||||
IOHibernateImageHeader *ImageHeader;
|
||||
|
||||
//
|
||||
// There is no reason to patch the kernel when we do not need it.
|
||||
//
|
||||
if (!BootCompat->Settings.AvoidRuntimeDefrag && !BootCompat->Settings.DiscardHibernateMap) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check whether we have image address and abort if not.
|
||||
//
|
||||
if (ImageAddress == 0) {
|
||||
RUNTIME_DEBUG ((DEBUG_ERROR, "OCABC: Failed to find image address, hibernate %d\n", AppleHibernateWake));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AppleHibernateWake) {
|
||||
//
|
||||
// ImageAddress points to the first kernel segment, __HIB.
|
||||
@ -572,7 +598,7 @@ AppleMapPrepareKernelJump (
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
AppleMapPrepareVmState (
|
||||
AppleMapPrepareMemState (
|
||||
IN OUT BOOT_COMPAT_CONTEXT *BootCompat,
|
||||
IN UINTN MemoryMapSize,
|
||||
IN UINTN DescriptorSize,
|
||||
@ -585,34 +611,47 @@ AppleMapPrepareVmState (
|
||||
//
|
||||
// Protect RT areas from relocation by marking then MemMapIO.
|
||||
//
|
||||
ProtectRtMemoryFromRelocation (
|
||||
&BootCompat->RtReloc,
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
MemoryMap,
|
||||
BootCompat->KernelState.SysTableRtArea,
|
||||
BootCompat->KernelState.SysTableRtAreaSize
|
||||
);
|
||||
if (BootCompat->Settings.AvoidRuntimeDefrag) {
|
||||
ProtectRtMemoryFromRelocation (
|
||||
&BootCompat->RtReloc,
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
MemoryMap,
|
||||
BootCompat->KernelState.SysTableRtArea,
|
||||
BootCompat->KernelState.SysTableRtAreaSize
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Virtualize RT services with all needed fixes.
|
||||
//
|
||||
Status = PerformRtMemoryVirtualMapping (
|
||||
&BootCompat->KernelState,
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
DescriptorVersion,
|
||||
MemoryMap
|
||||
);
|
||||
if (BootCompat->Settings.SetupVirtualMap) {
|
||||
Status = PerformRtMemoryVirtualMapping (
|
||||
&BootCompat->KernelState,
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
DescriptorVersion,
|
||||
MemoryMap
|
||||
);
|
||||
} else {
|
||||
Status = gRT->SetVirtualAddressMap (
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
DescriptorVersion,
|
||||
MemoryMap
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Copy now virtualized UEFI system table for boot.efi to hand it to the kernel.
|
||||
//
|
||||
CopyMem (
|
||||
(VOID *)(UINTN) BootCompat->KernelState.SysTableRtArea,
|
||||
gST,
|
||||
gST->Hdr.HeaderSize
|
||||
);
|
||||
if (BootCompat->Settings.AvoidRuntimeDefrag) {
|
||||
CopyMem (
|
||||
(VOID *)(UINTN) BootCompat->KernelState.SysTableRtArea,
|
||||
gST,
|
||||
gST->Hdr.HeaderSize
|
||||
);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
@ -15,9 +15,12 @@
|
||||
|
||||
#include "BootCompatInternal.h"
|
||||
|
||||
#include <Guid/OcVariables.h>
|
||||
|
||||
#include <IndustryStandard/AppleHibernate.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/OcBootManagementLib.h>
|
||||
#include <Library/OcMemoryLib.h>
|
||||
@ -178,6 +181,8 @@ OcStartImage (
|
||||
EFI_STATUS Status;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *AppleLoadedImage;
|
||||
BOOT_COMPAT_CONTEXT *BootCompat;
|
||||
OC_FWRT_CONFIG Config;
|
||||
UINTN DataSize;
|
||||
|
||||
BootCompat = GetBootCompatContext ();
|
||||
AppleLoadedImage = OcGetAppleBootLoadedImage (ImageHandle);
|
||||
@ -200,20 +205,57 @@ OcStartImage (
|
||||
L_STR_LEN ("slide=")
|
||||
);
|
||||
|
||||
if (BootCompat->Settings.EnableAppleSmSlide) {
|
||||
if (BootCompat->Settings.EnableSafeModeSlide) {
|
||||
AppleSlideUnlockForSafeMode (
|
||||
(UINT8 *) AppleLoadedImage->ImageBase,
|
||||
AppleLoadedImage->ImageSize
|
||||
);
|
||||
}
|
||||
|
||||
if (BootCompat->Settings.SetupAppleMap) {
|
||||
AppleMapPrepareBooterState (
|
||||
BootCompat,
|
||||
AppleLoadedImage,
|
||||
BootCompat->ServicePtrs.GetMemoryMap
|
||||
);
|
||||
AppleMapPrepareBooterState (
|
||||
BootCompat,
|
||||
AppleLoadedImage,
|
||||
BootCompat->ServicePtrs.GetMemoryMap
|
||||
);
|
||||
}
|
||||
|
||||
if (BootCompat->ServiceState.FwRuntime != NULL) {
|
||||
BootCompat->ServiceState.FwRuntime->GetCurrent (&Config);
|
||||
|
||||
//
|
||||
// Support for ReadOnly and WriteOnly variables is OpenCore & Lilu security basics.
|
||||
// For now always enable it.
|
||||
//
|
||||
Config.RestrictedVariables = TRUE;
|
||||
|
||||
//
|
||||
// Enable Boot#### variable redirection if OpenCore requested it.
|
||||
// Do NOT disable it once enabled for stability reasons.
|
||||
//
|
||||
DataSize = sizeof (Config.BootVariableRedirect);
|
||||
BootCompat->ServicePtrs.GetVariable (
|
||||
OC_BOOT_REDIRECT_VARIABLE_NAME,
|
||||
&gOcVendorVariableGuid,
|
||||
NULL,
|
||||
&DataSize,
|
||||
&Config.BootVariableRedirect
|
||||
);
|
||||
|
||||
//
|
||||
// Enable Apple-specific changes if requested.
|
||||
// Disable them when this is no longer Apple.
|
||||
//
|
||||
if (BootCompat->ServiceState.AppleBootNestedCount > 0) {
|
||||
Config.WriteProtection = BootCompat->Settings.DisableVariableWrite;
|
||||
Config.WriteUnprotector = BootCompat->Settings.EnableWriteUnprotector;
|
||||
} else {
|
||||
Config.WriteProtection = FALSE;
|
||||
Config.WriteUnprotector = FALSE;
|
||||
}
|
||||
|
||||
BootCompat->ServiceState.FwRuntime->SetMain (
|
||||
&Config
|
||||
);
|
||||
}
|
||||
|
||||
Status = BootCompat->ServicePtrs.StartImage (
|
||||
@ -369,18 +411,6 @@ OcExitBootServices (
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// We need hibernate image address for wake, check it quickly before
|
||||
// killing boot services to be able to print the error.
|
||||
//
|
||||
if (BootCompat->Settings.SetupAppleMap
|
||||
&& BootCompat->ServiceState.AppleHibernateWake
|
||||
&& BootCompat->ServiceState.HibernateImageAddress == 0) {
|
||||
DEBUG ((DEBUG_ERROR, "OCABC: Failed to find hibernate image address\n"));
|
||||
gBS->Stall (SECONDS_TO_MICROSECONDS (5));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (BootCompat->Settings.ForceExitBootServices) {
|
||||
Status = ForceExitBootServices (
|
||||
ImageHandle,
|
||||
@ -396,9 +426,9 @@ OcExitBootServices (
|
||||
}
|
||||
|
||||
//
|
||||
// Abort on error or when we are not supposed to do extra mapping.
|
||||
// Abort on error.
|
||||
//
|
||||
if (EFI_ERROR (Status) || !BootCompat->Settings.SetupAppleMap) {
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
@ -447,27 +477,13 @@ OcSetVirtualAddressMap (
|
||||
gRT->Hdr.CRC32 = 0;
|
||||
gRT->Hdr.CRC32 = CalculateCrc32 (gRT, gRT->Hdr.HeaderSize);
|
||||
|
||||
//
|
||||
// For non-macOS operating systems return directly.
|
||||
// Also do nothing for custom mapping.
|
||||
//
|
||||
if (BootCompat->ServiceState.AppleBootNestedCount == 0
|
||||
|| !BootCompat->Settings.SetupAppleMap) {
|
||||
Status = gRT->SetVirtualAddressMap (
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
DescriptorVersion,
|
||||
MemoryMap
|
||||
);
|
||||
} else {
|
||||
Status = AppleMapPrepareVmState (
|
||||
BootCompat,
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
DescriptorVersion,
|
||||
MemoryMap
|
||||
);
|
||||
}
|
||||
Status = AppleMapPrepareMemState (
|
||||
BootCompat,
|
||||
MemoryMapSize,
|
||||
DescriptorSize,
|
||||
DescriptorVersion,
|
||||
MemoryMap
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
@ -493,7 +509,7 @@ OcGetVariable (
|
||||
BootCompat = GetBootCompatContext ();
|
||||
|
||||
if (BootCompat->ServiceState.AppleBootNestedCount > 0
|
||||
&& BootCompat->Settings.SetupAppleSlide) {
|
||||
&& BootCompat->Settings.ProvideCustomSlide) {
|
||||
Status = AppleSlideGetVariable (
|
||||
BootCompat,
|
||||
BootCompat->ServicePtrs.GetVariable,
|
||||
@ -522,7 +538,7 @@ OcGetVariable (
|
||||
We do not override GetVariable ourselves but let our runtime do that.
|
||||
|
||||
@param[in] Event Event handle.
|
||||
@param[in] Context Services pointers context.
|
||||
@param[in] Context Apple boot compatibility context.
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
@ -534,11 +550,11 @@ SetGetVariableHookHandler (
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
OC_FIRMWARE_RUNTIME_PROTOCOL *FwRuntime;
|
||||
UEFI_SERVICES_POINTERS *ServicePtrs;
|
||||
BOOT_COMPAT_CONTEXT *BootCompat;
|
||||
|
||||
ServicePtrs = (UEFI_SERVICES_POINTERS *) Context;
|
||||
BootCompat = (BOOT_COMPAT_CONTEXT *) Context;
|
||||
|
||||
if (ServicePtrs->GetVariable == NULL) {
|
||||
if (BootCompat->ServicePtrs.GetVariable == NULL) {
|
||||
Status = gBS->LocateProtocol (
|
||||
&gOcFirmwareRuntimeProtocolGuid,
|
||||
NULL,
|
||||
@ -546,7 +562,16 @@ SetGetVariableHookHandler (
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status) && FwRuntime->Revision == OC_FIRMWARE_RUNTIME_REVISION) {
|
||||
FwRuntime->OnGetVariable (OcGetVariable, &ServicePtrs->GetVariable);
|
||||
Status = FwRuntime->OnGetVariable (OcGetVariable, &BootCompat->ServicePtrs.GetVariable);
|
||||
} else {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Mark protocol as useable.
|
||||
//
|
||||
if (!EFI_ERROR (Status)) {
|
||||
BootCompat->ServiceState.FwRuntime = FwRuntime;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -588,7 +613,7 @@ InstallServiceOverrides (
|
||||
//
|
||||
// Allocate memory pool if needed.
|
||||
//
|
||||
if (BootCompat->Settings.SetupAppleMap) {
|
||||
if (BootCompat->Settings.SetupVirtualMap) {
|
||||
AppleMapPrepareMemoryPool (
|
||||
BootCompat
|
||||
);
|
||||
@ -597,9 +622,9 @@ InstallServiceOverrides (
|
||||
//
|
||||
// Update GetVariable handle with the help of external runtime services.
|
||||
//
|
||||
SetGetVariableHookHandler (NULL, ServicePtrs);
|
||||
SetGetVariableHookHandler (NULL, BootCompat);
|
||||
|
||||
if (ServicePtrs->GetVariable != NULL) {
|
||||
if (BootCompat->ServicePtrs.GetVariable != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -607,7 +632,7 @@ InstallServiceOverrides (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
SetGetVariableHookHandler,
|
||||
ServicePtrs,
|
||||
BootCompat,
|
||||
&BootCompat->ServiceState.GetVariableEvent
|
||||
);
|
||||
|
||||
|
||||
@ -147,13 +147,16 @@ mAcpiConfigurationSchema[] = {
|
||||
STATIC
|
||||
OC_SCHEMA
|
||||
mBooterQuirksSchema[] = {
|
||||
OC_SCHEMA_BOOLEAN_IN ("DiscardAppleS4Map", OC_GLOBAL_CONFIG, Booter.Quirks.DiscardAppleS4Map),
|
||||
OC_SCHEMA_BOOLEAN_IN ("EnableAppleSmSlide", OC_GLOBAL_CONFIG, Booter.Quirks.EnableAppleSmSlide),
|
||||
OC_SCHEMA_BOOLEAN_IN ("ForceExitBootServices", OC_GLOBAL_CONFIG, Booter.Quirks.ForceExitBootServices),
|
||||
OC_SCHEMA_BOOLEAN_IN ("ProtectCsmRegion", OC_GLOBAL_CONFIG, Booter.Quirks.ProtectCsmRegion),
|
||||
OC_SCHEMA_BOOLEAN_IN ("SetupAppleMap", OC_GLOBAL_CONFIG, Booter.Quirks.SetupAppleMap),
|
||||
OC_SCHEMA_BOOLEAN_IN ("SetupAppleSlide", OC_GLOBAL_CONFIG, Booter.Quirks.SetupAppleSlide),
|
||||
OC_SCHEMA_BOOLEAN_IN ("ShrinkMemoryMap", OC_GLOBAL_CONFIG, Booter.Quirks.ShrinkMemoryMap),
|
||||
OC_SCHEMA_BOOLEAN_IN ("AvoidRuntimeDefrag", OC_GLOBAL_CONFIG, Booter.Quirks.AvoidRuntimeDefrag),
|
||||
OC_SCHEMA_BOOLEAN_IN ("DisableVariableWrite", OC_GLOBAL_CONFIG, Booter.Quirks.DisableVariableWrite),
|
||||
OC_SCHEMA_BOOLEAN_IN ("DiscardHibernateMap", OC_GLOBAL_CONFIG, Booter.Quirks.DiscardHibernateMap),
|
||||
OC_SCHEMA_BOOLEAN_IN ("EnableSafeModeSlide", OC_GLOBAL_CONFIG, Booter.Quirks.EnableSafeModeSlide),
|
||||
OC_SCHEMA_BOOLEAN_IN ("EnableWriteUnprotector", OC_GLOBAL_CONFIG, Booter.Quirks.EnableWriteUnprotector),
|
||||
OC_SCHEMA_BOOLEAN_IN ("ForceExitBootServices", OC_GLOBAL_CONFIG, Booter.Quirks.ForceExitBootServices),
|
||||
OC_SCHEMA_BOOLEAN_IN ("ProtectCsmRegion", OC_GLOBAL_CONFIG, Booter.Quirks.ProtectCsmRegion),
|
||||
OC_SCHEMA_BOOLEAN_IN ("ProvideCustomSlide", OC_GLOBAL_CONFIG, Booter.Quirks.ProvideCustomSlide),
|
||||
OC_SCHEMA_BOOLEAN_IN ("SetupVirtualMap", OC_GLOBAL_CONFIG, Booter.Quirks.SetupVirtualMap),
|
||||
OC_SCHEMA_BOOLEAN_IN ("ShrinkMemoryMap", OC_GLOBAL_CONFIG, Booter.Quirks.ShrinkMemoryMap),
|
||||
};
|
||||
|
||||
STATIC
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
gOcAppleBootCompatProtocolGuid = { 0xC7CBA84E, 0xCC77, 0x461D, { 0x9E, 0x3C, 0x6B, 0xE0, 0xCB, 0x79, 0xA7, 0xC1 } }
|
||||
|
||||
## Include/Protocol/OcFirmwareRuntime.h
|
||||
gOcFirmwareRuntimeProtocolGuid = { 0x9C820F96, 0xF16C, 0x4FFD, { 0xB2, 0x66, 0xDF, 0x0A, 0x8F, 0xDF, 0xC4, 0x55 }}
|
||||
gOcFirmwareRuntimeProtocolGuid = { 0x570332E4, 0xFC50, 0x4B21, { 0xAB, 0xE8, 0xAE, 0x72, 0xF0, 0x5B, 0x4F, 0xF7 }}
|
||||
|
||||
## Include/Protocol/LegacyRegion.h
|
||||
gEfiLegacyRegionProtocolGuid = { 0x0fc9013a, 0x0568, 0x4ba9, { 0x9b, 0x7e, 0xc9, 0xc3, 0x90, 0xa6, 0x60, 0x9b }}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user