diff --git a/Changelog.md b/Changelog.md index 1215dd0c5e24bf3f3228020d71c9d9bb7f67e189..affa059be0ca024b1c073fe609325fd767a64395 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,6 +8,7 @@ OpenCore Changelog - Added `SSN` (and `HW_SSN`) variable support - Added onscreen early logging in DEBUG builds for legacy firmware - Added workaround for firmware not specifying DeviceHandle at bootstrap +- Added support for R/O page tables in `SetupVirtualMap` quirk #### v0.6.6 - Added keyboard and pointer entry scroll support in OpenCanopy diff --git a/Include/Intel/IndustryStandard/VirtualMemory.h b/Include/Intel/IndustryStandard/VirtualMemory.h index a9c81c2d89979dcbbfee21bc6a490dda41c191b6..12790ba2789b4a15d1c4d888bf012a4a423d45fc 100755 --- a/Include/Intel/IndustryStandard/VirtualMemory.h +++ b/Include/Intel/IndustryStandard/VirtualMemory.h @@ -142,6 +142,8 @@ typedef union { #pragma pack(pop) +#define CR0_WP BIT16 + #define CR3_ADDR_MASK 0x000FFFFFFFFFF000ull #define CR3_FLAG_PWT 0x0000000000000008ull #define CR3_FLAG_PCD 0x0000000000000010ull diff --git a/Library/OcMemoryLib/VirtualMemory.c b/Library/OcMemoryLib/VirtualMemory.c index c97738bd33ab29c5ae350969a5e3986b0981afac..7c0fa307617e583c4d9413676734084e59e56081 100755 --- a/Library/OcMemoryLib/VirtualMemory.c +++ b/Library/OcMemoryLib/VirtualMemory.c @@ -26,19 +26,49 @@ OcGetCurrentPageTable ( ) { PAGE_MAP_AND_DIRECTORY_POINTER *PageTable; - UINTN CR3; + UINTN Cr3; - CR3 = AsmReadCr3 (); + Cr3 = AsmReadCr3 (); - PageTable = (PAGE_MAP_AND_DIRECTORY_POINTER *)(UINTN) (CR3 & CR3_ADDR_MASK); + PageTable = (PAGE_MAP_AND_DIRECTORY_POINTER *)(UINTN) (Cr3 & CR3_ADDR_MASK); if (Flags != NULL) { - *Flags = CR3 & (CR3_FLAG_PWT | CR3_FLAG_PCD); + *Flags = Cr3 & (CR3_FLAG_PWT | CR3_FLAG_PCD); } return PageTable; } +STATIC +BOOLEAN +DisablePageTableWriteProtection ( + VOID + ) +{ + UINTN Cr0; + + Cr0 = AsmReadCr0 (); + + if ((Cr0 & CR0_WP) != 0) { + AsmWriteCr0 (Cr0 & ~CR0_WP); + return TRUE; + } + + return FALSE; +} + +STATIC +VOID +EnablePageTableWriteProtection ( + VOID + ) +{ + UINTN Cr0; + + Cr0 = AsmReadCr0 (); + AsmWriteCr0 (Cr0 | CR0_WP); +} + EFI_STATUS OcGetPhysicalAddress ( IN PAGE_MAP_AND_DIRECTORY_POINTER *PageTable OPTIONAL, @@ -208,11 +238,14 @@ VmMapVirtualPage ( PAGE_TABLE_2M_ENTRY *PTE2M; PAGE_TABLE_1G_ENTRY *PTE1G; UINTN Index; + BOOLEAN WriteProtected; if (PageTable == NULL) { PageTable = OcGetCurrentPageTable (NULL); } + WriteProtected = DisablePageTableWriteProtection (); + VA.Uint64 = (UINT64) VirtualAddr; // @@ -242,6 +275,9 @@ VmMapVirtualPage ( PDPE = (PAGE_MAP_AND_DIRECTORY_POINTER *) VmAllocatePages (Context, 1); if (PDPE == NULL) { + if (WriteProtected) { + EnablePageTableWriteProtection (); + } return EFI_NO_MAPPING; } @@ -282,6 +318,9 @@ VmMapVirtualPage ( PDE = (PAGE_MAP_AND_DIRECTORY_POINTER *) VmAllocatePages(Context, 1); if (PDE == NULL) { + if (WriteProtected) { + EnablePageTableWriteProtection (); + } return EFI_NO_MAPPING; } @@ -325,6 +364,9 @@ VmMapVirtualPage ( PTE4K = (PAGE_TABLE_4K_ENTRY *) VmAllocatePages (Context, 1); if (PTE4K == NULL) { + if (WriteProtected) { + EnablePageTableWriteProtection (); + } return EFI_NO_MAPPING; } @@ -370,6 +412,10 @@ VmMapVirtualPage ( PTE4K->Bits.ReadWrite = 1; PTE4K->Bits.Present = 1; + if (WriteProtected) { + EnablePageTableWriteProtection (); + } + return EFI_SUCCESS; }