diff --git a/sysutils/edk2/files/patch-OvmfPkg_Bhyve_BhyveX64.dsc b/sysutils/edk2/files/patch-OvmfPkg_Bhyve_BhyveX64.dsc new file mode 100644 --- /dev/null +++ b/sysutils/edk2/files/patch-OvmfPkg_Bhyve_BhyveX64.dsc @@ -0,0 +1,10 @@ +--- OvmfPkg/Bhyve/BhyveX64.dsc.orig 2023-09-04 06:31:31 UTC ++++ OvmfPkg/Bhyve/BhyveX64.dsc +@@ -291,6 +291,7 @@ + !endif + CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf + PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf ++ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf + + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf + diff --git a/sysutils/edk2/files/patch-OvmfPkg_Bhyve_PlatformPei_MemDetect.c b/sysutils/edk2/files/patch-OvmfPkg_Bhyve_PlatformPei_MemDetect.c new file mode 100644 --- /dev/null +++ b/sysutils/edk2/files/patch-OvmfPkg_Bhyve_PlatformPei_MemDetect.c @@ -0,0 +1,101 @@ +--- OvmfPkg/Bhyve/PlatformPei/MemDetect.c.orig 2023-08-25 01:54:50 UTC ++++ OvmfPkg/Bhyve/PlatformPei/MemDetect.c +@@ -30,6 +30,7 @@ Module Name: + #include + #include + #include ++#include + #include + #include + +@@ -357,6 +358,9 @@ PublishPeiMemory ( + VOID + ) + { ++ EFI_E820_ENTRY64 E820Entry; ++ FIRMWARE_CONFIG_ITEM Item; ++ UINTN ItemSize; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemoryBase; + UINT64 MemorySize; +@@ -414,6 +418,80 @@ PublishPeiMemory ( + if (MemorySize > PeiMemoryCap) { + MemoryBase = LowerMemorySize - PeiMemoryCap; + MemorySize = PeiMemoryCap; ++ } ++ } ++ ++ // ++ // Bhyve uses an E820 table to reserve certain kinds of memory like Graphics ++ // Stolen Memory. These reserved memory regions could overlap with the PEI ++ // core memory which leads to undefined behaviour. Check the E820 table for ++ // a memory region starting at or below MemoryBase which is equal or larger ++ // than MemorySize. ++ // ++ if (!EFI_ERROR (QemuFwCfgFindFile ("etc/e820", &Item, &ItemSize))) { ++ // ++ // Set a new base address based on E820 table. ++ // ++ ++ EFI_PHYSICAL_ADDRESS MaxAddress; ++ UINT64 EntryEnd; ++ UINT64 EndAddr; ++ ++ if (ItemSize % sizeof (E820Entry) != 0) { ++ DEBUG ((DEBUG_INFO, "%a: invalid E820 size\n", __FUNCTION__)); ++ return EFI_PROTOCOL_ERROR; ++ } ++ ++ QemuFwCfgSelectItem (Item); ++ ++ MaxAddress = MemoryBase + MemorySize; ++ MemoryBase = 0; ++ ++ for (UINTN i = 0; i < ItemSize; i += sizeof (E820Entry)) { ++ QemuFwCfgReadBytes (sizeof (E820Entry), &E820Entry); ++ ++ if (E820Entry.BaseAddr > MaxAddress) { ++ // ++ // E820 is always sorted in ascending order. For that reason, BaseAddr ++ // will always be larger than MaxAddress for the following entries. ++ // ++ break; ++ } else if (E820Entry.Type != EfiAcpiAddressRangeMemory) { ++ continue; ++ } ++ ++ // ++ // Since MemoryBase should be at top of the memory, calculate the end ++ // address of the entry. Additionally, MemoryBase and MemorySize are page ++ // aligned. For that reason, page align EntryEnd too. ++ // ++ EntryEnd = (E820Entry.BaseAddr + E820Entry.Length) & ~EFI_PAGE_MASK; ++ if (E820Entry.BaseAddr > EntryEnd) { ++ // ++ // Either BaseAddr + Length overflows or the entry is smaller than a ++ // page. In both cases, we can't use it. ++ // ++ continue; ++ } ++ ++ EndAddr = MIN (EntryEnd, MaxAddress); ++ if (EndAddr - E820Entry.BaseAddr < MemorySize) { ++ // ++ // E820 entry is too small for the Pei core memory. ++ // ++ continue; ++ } ++ ++ MemoryBase = EndAddr - MemorySize; ++ } ++ ++ if (MemoryBase == 0) { ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: Unable to find suitable PeiCore address\n", ++ __FUNCTION__ ++ )); ++ return EFI_OUT_OF_RESOURCES; + } + } + diff --git a/sysutils/edk2/files/patch-OvmfPkg_Bhyve_PlatformPei_Platform.c b/sysutils/edk2/files/patch-OvmfPkg_Bhyve_PlatformPei_Platform.c new file mode 100644 --- /dev/null +++ b/sysutils/edk2/files/patch-OvmfPkg_Bhyve_PlatformPei_Platform.c @@ -0,0 +1,157 @@ +--- OvmfPkg/Bhyve/PlatformPei/Platform.c.orig 2023-08-25 01:54:50 UTC ++++ OvmfPkg/Bhyve/PlatformPei/Platform.c +@@ -29,6 +29,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -493,6 +494,118 @@ DebugDumpCmos ( + } + } + ++STATIC ++EFI_STATUS ++E820ReserveMemory ( ++ VOID ++ ) ++{ ++ EFI_E820_ENTRY64 E820Entry; ++ FIRMWARE_CONFIG_ITEM Item; ++ UINTN Size; ++ EFI_STATUS Status; ++ ++ Status = QemuFwCfgFindFile ("etc/e820", &Item, &Size); ++ if (EFI_ERROR (Status)) { ++ DEBUG ((DEBUG_INFO, "%a: E820 not found: %r\n", __FUNCTION__, Status)); ++ return Status; ++ } ++ ++ if (Size % sizeof (E820Entry) != 0) { ++ DEBUG ((DEBUG_INFO, "%a: invalid E820 size\n", __FUNCTION__)); ++ return EFI_PROTOCOL_ERROR; ++ } ++ ++ QemuFwCfgSelectItem (Item); ++ for (UINTN i = 0; i < Size; i += sizeof (E820Entry)) { ++ UINT64 Base; ++ UINT64 End; ++ ++ QemuFwCfgReadBytes (sizeof (E820Entry), &E820Entry); ++ ++ DEBUG_CODE ( ++ CHAR8 *E820TypeName; ++ switch (E820Entry.Type) { ++ case EfiAcpiAddressRangeMemory: ++ E820TypeName = "RAM "; ++ break; ++ case EfiAcpiAddressRangeReserved: ++ E820TypeName = "Reserved"; ++ break; ++ case EfiAcpiAddressRangeACPI: ++ E820TypeName = "ACPI "; ++ break; ++ case EfiAcpiAddressRangeNVS: ++ E820TypeName = "NVS "; ++ break; ++ default: ++ E820TypeName = "Unknown "; ++ break; ++ } ++ ++ DEBUG (( ++ DEBUG_INFO, ++ "E820 entry [ %16lx, %16lx] (%a)\n", ++ E820Entry.BaseAddr, ++ E820Entry.BaseAddr + E820Entry.Length, ++ E820TypeName ++ )); ++ ); ++ ++ // ++ // Round down base and round up length to page boundary ++ // ++ Base = E820Entry.BaseAddr & ~(UINT64)EFI_PAGE_MASK; ++ End = ALIGN_VALUE ( ++ E820Entry.BaseAddr + E820Entry.Length, ++ (UINT64)EFI_PAGE_SIZE ++ ); ++ ++ switch (E820Entry.Type) { ++ case EfiAcpiAddressRangeReserved: ++ BuildMemoryAllocationHob ( ++ Base, ++ End - Base, ++ EfiReservedMemoryType ++ ); ++ break; ++ ++ case EfiAcpiAddressRangeACPI: ++ BuildMemoryAllocationHob ( ++ Base, ++ End - Base, ++ EfiACPIReclaimMemory ++ ); ++ break; ++ ++ case EfiAcpiAddressRangeNVS: ++ BuildMemoryAllocationHob ( ++ Base, ++ End - Base, ++ EfiACPIMemoryNVS ++ ); ++ break; ++ ++ case EfiAcpiAddressRangeMemory: ++ // ++ // EfiAcpiAddressRangeMemory is usable. Do not build an Allocation HOB. ++ // ++ break; ++ ++ default: ++ DEBUG (( ++ DEBUG_ERROR, ++ "%a: Unknown E820 type %d\n", ++ __FUNCTION__, ++ E820Entry.Type ++ )); ++ return EFI_PROTOCOL_ERROR; ++ } ++ } ++ ++ return EFI_SUCCESS; ++} ++ + /** + Fetch the number of boot CPUs from QEMU and expose it to UefiCpuPkg modules. + Set the mMaxCpuCount variable. +@@ -570,6 +683,10 @@ InitializePlatform ( + IN CONST EFI_PEI_SERVICES **PeiServices + ) + { ++ EFI_STATUS Status; ++ FIRMWARE_CONFIG_ITEM Item; ++ UINTN Size; ++ + DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n")); + BuildPlatformInfoHob (); + +@@ -582,6 +699,16 @@ InitializePlatform ( + DisableApicTimerInterrupt (); + + DebugDumpCmos (); ++ ++ // ++ // If an E820 table exists, Memory should be reserved by E820. ++ // ++ if (!EFI_ERROR (QemuFwCfgFindFile ("etc/e820", &Item, &Size))) { ++ Status = E820ReserveMemory (); ++ if (EFI_ERROR (Status)) { ++ return Status; ++ } ++ } + + BootModeInitialization (); + AddressWidthInitialization (); diff --git a/sysutils/edk2/files/patch-OvmfPkg_Bhyve_PlatformPei_PlatformPei.inf b/sysutils/edk2/files/patch-OvmfPkg_Bhyve_PlatformPei_PlatformPei.inf new file mode 100644 --- /dev/null +++ b/sysutils/edk2/files/patch-OvmfPkg_Bhyve_PlatformPei_PlatformPei.inf @@ -0,0 +1,10 @@ +--- OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf.orig 2023-08-25 01:54:50 UTC ++++ OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf +@@ -60,6 +60,7 @@ + PeiServicesLib + PeiServicesTablePointerLib + PcdLib ++ QemuFwCfgLib + ResourcePublicationLib + + [Pcd]