diff --git a/Include/Acidanthera/Library/OcDeviceTreeLib.h b/Include/Acidanthera/Library/OcDeviceTreeLib.h index 08499dcf..cf7c688a 100644 --- a/Include/Acidanthera/Library/OcDeviceTreeLib.h +++ b/Include/Acidanthera/Library/OcDeviceTreeLib.h @@ -16,7 +16,25 @@ #define OC_DEVICE_TREE_LIB_H // -// Struct at the beginning of every loaded kext. +// Device tree property name prefixes for loaded kexts or mkext. +// +#define DT_BOOTER_KEXT_PREFIX "Driver-" +#define DT_BOOTER_MKEXT_PREFIX "DriversPackage-" + +// +// Struct at the beginning of every loaded kext (10.4 and 10.5). +// Pointers to every loaded kext (to this struct) are +// properties Driver- in DevTree /chosen/memory-map. +// +typedef struct DTBootxDriverInfo_ { + UINT32 PlistPhysAddr; + UINT32 PlistLength; + UINT32 ModuleAddress; + UINT32 ModuleLength; +} DTBootxDriverInfo; + +// +// Struct at the beginning of every loaded kext (10.6 and newer). // Pointers to every loaded kext (to this struct) are // properties Driver- in DevTree /chosen/memory-map. // diff --git a/Include/Apple/IndustryStandard/AppleBootArgs.h b/Include/Apple/IndustryStandard/AppleBootArgs.h index e2a79ed6..c60e3b5e 100644 --- a/Include/Apple/IndustryStandard/AppleBootArgs.h +++ b/Include/Apple/IndustryStandard/AppleBootArgs.h @@ -111,9 +111,9 @@ typedef struct { UINT8 efiMode; /* 32 = 32-bit, 64 = 64-bit */ UINT8 __reserved1[3]; UINT32 __reserved2[1]; - UINT32 performanceDataStart; /* physical address of log */ + UINT32 performanceDataStart; /* physical address of log, 10.6 and up */ UINT32 performanceDataSize; - UINT64 efiRuntimeServicesVirtualPageStart; /* virtual address of defragmented runtime pages */ + UINT64 efiRuntimeServicesVirtualPageStart; /* virtual address of defragmented runtime pages, 10.6 and up */ UINT32 __reserved3[2]; } BootArgs1; diff --git a/Library/OcAfterBootCompatLib/BootCompatInternal.h b/Library/OcAfterBootCompatLib/BootCompatInternal.h index e4536343..b46b79c1 100644 --- a/Library/OcAfterBootCompatLib/BootCompatInternal.h +++ b/Library/OcAfterBootCompatLib/BootCompatInternal.h @@ -64,20 +64,30 @@ #define KERNEL_HIB_VADDR ((UINTN) (0xFFFFFF8000100000ULL & MAX_UINTN)) /** - Kernel __TEXT segment virtual address. + Kernel __TEXT segment virtual address (macOS 10.6 and higher). **/ #define KERNEL_TEXT_VADDR ((UINTN) (0xFFFFFF8000200000ULL & MAX_UINTN)) +/** + Kernel __TEXT segment virtual address (macOS 10.4 and 10.5). +**/ +#define KERNEL_TEXT_VADDR_LEGACY 0x111000 + /** Kernel physical base address. **/ #define KERNEL_BASE_PADDR ((UINT32) (KERNEL_HIB_VADDR & MAX_UINT32)) /** - Kernel physical base address. + Kernel __TEXT physical base address (macOS 10.6 and higher). **/ #define KERNEL_TEXT_PADDR ((UINT32) (KERNEL_TEXT_VADDR & MAX_UINT32)) +/** + Kernel __TEXT physical base address (macOS 10.4 and 10.5). +**/ +#define KERNEL_TEXT_PADDR_LEGACY (KERNEL_TEXT_VADDR_LEGACY) + /** Slide offset per slide entry **/ @@ -355,6 +365,10 @@ typedef struct KERNEL_SUPPORT_STATE_ { /// This value should match ksize in XNU BootArgs. /// UINTN RelocationBlockUsed; + /// + /// Relocation block is being used on macOS 10.4 or 10.5. + /// + BOOLEAN RelocationBlockLegacy; } KERNEL_SUPPORT_STATE; /** @@ -413,7 +427,7 @@ typedef struct SLIDE_SUPPORT_STATE_ { **/ typedef struct BOOT_COMPAT_CONTEXT_ { /// - /// Apple Coot Compatibility settings. + /// Apple Boot Compatibility settings. /// OC_ABC_SETTINGS Settings; /// diff --git a/Library/OcAfterBootCompatLib/KernelSupport.c b/Library/OcAfterBootCompatLib/KernelSupport.c index b8d279af..8a9d72a9 100644 --- a/Library/OcAfterBootCompatLib/KernelSupport.c +++ b/Library/OcAfterBootCompatLib/KernelSupport.c @@ -384,10 +384,10 @@ AppleMapPrepareForBooting ( } } - if (BootCompat->KernelState.RelocationBlock != 0) { + if ((BootCompat->KernelState.RelocationBlock != 0) && !BootCompat->KernelState.RelocationBlockLegacy) { // - // When using Relocation Block EfiBoot will not virtualize the addresses since they - // cannot be mapped 1:1 due to any region from the relocation block being outside + // When using Relocation Block, EfiBoot on macOS 10.6 and newer will not virtualize the addresses + // since they cannot be mapped 1:1 due to any region from the relocation block being outside // of static XNU vaddr to paddr mapping. This causes a clean early exit in their // SetVirtualAddressMap calling routine avoiding gRT->SetVirtualAddressMap. // @@ -687,7 +687,10 @@ AppleMapPrepareMemState ( IN EFI_MEMORY_DESCRIPTOR *MemoryMap ) { - EFI_STATUS Status; + EFI_STATUS Status; + UINTN NumEntries; + UINTN Index; + EFI_MEMORY_DESCRIPTOR *Desc; // // Protect RT areas from relocation by marking then MemMapIO. @@ -703,6 +706,25 @@ AppleMapPrepareMemState ( ); } + // + // macOS 10.4 and 10.5 always call SetVirtualAddressMap, even when using a relocation block. + // Perform adjustment of virtual addresses here to their final positions. + // + if (BootCompat->KernelState.RelocationBlockLegacy) { + Desc = MemoryMap; + NumEntries = MemoryMapSize / DescriptorSize; + + for (Index = 0; Index < NumEntries; ++Index) { + if ( (Desc->VirtualStart >= BootCompat->KernelState.RelocationBlock + BootCompat->KernelState.RelocationBlockUsed) + && (Desc->VirtualStart < BootCompat->KernelState.RelocationBlock + ESTIMATED_KERNEL_SIZE)) + { + Desc->VirtualStart -= BootCompat->KernelState.RelocationBlock - KERNEL_BASE_PADDR; + } + + Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize); + } + } + // // Virtualize RT services with all needed fixes. // diff --git a/Library/OcAfterBootCompatLib/RelocationBlock.c b/Library/OcAfterBootCompatLib/RelocationBlock.c index 130d918a..3fa512b1 100644 --- a/Library/OcAfterBootCompatLib/RelocationBlock.c +++ b/Library/OcAfterBootCompatLib/RelocationBlock.c @@ -59,16 +59,17 @@ AppleRelocationAllocatePages ( // this quirk anyway due to AllocatePages in AllocateAddress mode Address pointer // no longer being reread after the allocation in EfiBoot. // - if ((*Memory == KERNEL_TEXT_PADDR) && (BootCompat->KernelState.RelocationBlock == 0)) { - BootCompat->KernelState.RelocationBlock = BASE_4GB; - Status = OcAllocatePagesFromTop ( - EfiLoaderData, - EFI_SIZE_TO_PAGES (EssentialSize), - &BootCompat->KernelState.RelocationBlock, - GetMemoryMap, - AllocatePages, - NULL - ); + if (((*Memory == KERNEL_TEXT_PADDR) || (*Memory == KERNEL_TEXT_PADDR_LEGACY)) && (BootCompat->KernelState.RelocationBlock == 0)) { + BootCompat->KernelState.RelocationBlock = BASE_4GB; + BootCompat->KernelState.RelocationBlockLegacy = *Memory == KERNEL_TEXT_PADDR_LEGACY; + Status = OcAllocatePagesFromTop ( + EfiLoaderData, + EFI_SIZE_TO_PAGES (EssentialSize), + &BootCompat->KernelState.RelocationBlock, + GetMemoryMap, + AllocatePages, + NULL + ); if (EFI_ERROR (Status)) { DEBUG (( DEBUG_INFO, @@ -82,6 +83,18 @@ AppleRelocationAllocatePages ( BootCompat->KernelState.RelocationBlockUsed = 0; } + // + // macOS 10.4 and 10.5 do not request original lower addresses when allocating additional kernel structures (boot args, MKEXT, etc). + // If such addresses are requested within the range of our allocated relocation block, adjust them. + // + if ( (BootCompat->KernelState.RelocationBlock != 0) + && BootCompat->KernelState.RelocationBlockLegacy + && (*Memory > BootCompat->KernelState.RelocationBlock) + && (*Memory < BootCompat->KernelState.RelocationBlock + EssentialSize)) + { + *Memory -= (BootCompat->KernelState.RelocationBlock - KERNEL_BASE_PADDR); + } + // // Not our allocation. // @@ -130,8 +143,9 @@ AppleRelocationRelease ( EFI_SIZE_TO_PAGES (EssentialSize) ); - BootCompat->KernelState.RelocationBlock = 0; - BootCompat->KernelState.RelocationBlockUsed = 0; + BootCompat->KernelState.RelocationBlock = 0; + BootCompat->KernelState.RelocationBlockUsed = 0; + BootCompat->KernelState.RelocationBlockLegacy = FALSE; return Status; } @@ -247,6 +261,15 @@ AppleRelocationRebase ( DTMemMapEntry *PropValue; OpaqueDTPropertyIterator OPropIter; DTPropertyIterator PropIter; + DTBooterKextFileInfo *BooterKextFileInfo; + DTBootxDriverInfo *BootxDriverInfo; + UINT32 MemoryMapSize; + UINT32 DescriptorSize; + EFI_MEMORY_DESCRIPTOR *MemoryMap; + UINT32 NumEntries; + UINT32 Index; + EFI_MEMORY_DESCRIPTOR *Desc; + EFI_PHYSICAL_ADDRESS PrevDescAddress; UINT32 RelocDiff; PropIter = &OPropIter; @@ -282,6 +305,25 @@ AppleRelocationRebase ( continue; } + // + // Fix Driver-* entries for kexts used during a cacheless boot. + // + if (AsciiStrnCmp (PropName, DT_BOOTER_KEXT_PREFIX, L_STR_LEN (DT_BOOTER_KEXT_PREFIX)) == 0) { + // + // 10.6 and newer use a different format from 10.4 and 10.5. + // + if (!BootCompat->KernelState.RelocationBlockLegacy) { + BooterKextFileInfo = (DTBooterKextFileInfo *)((UINTN)PropValue->Address); + BooterKextFileInfo->InfoDictPhysAddr -= RelocDiff; + BooterKextFileInfo->ExecutablePhysAddr -= RelocDiff; + BooterKextFileInfo->BundlePathPhysAddr -= RelocDiff; + } else { + BootxDriverInfo = (DTBootxDriverInfo *)((UINTN)PropValue->Address); + BootxDriverInfo->PlistPhysAddr -= RelocDiff; + BootxDriverInfo->ModuleAddress -= RelocDiff; + } + } + // // Patch the addresses up. // @@ -290,9 +332,40 @@ AppleRelocationRebase ( } } + // + // On macOS 10.4 and 10.5, EfiBoot has already set the system table address to the correct virtual one. + // The memory map also contains additional trashed entries that must be removed, this seems to occur on Macs as well. + // + // On macOS 10.6 and newer, we need to adjust it like the others. + // + if (!BootCompat->KernelState.RelocationBlockLegacy) { + *BA->SystemTableP -= RelocDiff; + } else { + MemoryMapSize = *BA->MemoryMapSize; + DescriptorSize = *BA->MemoryMapDescriptorSize; + MemoryMap = (EFI_MEMORY_DESCRIPTOR *)(UINTN)*BA->MemoryMap; + + Desc = MemoryMap; + PrevDescAddress = Desc->PhysicalStart; + NumEntries = MemoryMapSize / DescriptorSize; + + // + // Locate end of valid memory map. It is assumed that the entries are + // sorted smallest to largest (performed by AllowRelocationBlock or RebuildAppleMemoryMap). + // + for (Index = 0; Index < NumEntries; ++Index) { + if (Desc->PhysicalStart < PrevDescAddress) { + *BA->MemoryMapSize -= (DescriptorSize * (NumEntries - Index)); + break; + } + + PrevDescAddress = Desc->PhysicalStart; + Desc = NEXT_MEMORY_DESCRIPTOR (Desc, DescriptorSize); + } + } + *BA->MemoryMap -= RelocDiff; *BA->KernelAddrP -= RelocDiff; - *BA->SystemTableP -= RelocDiff; *BA->RuntimeServicesPG -= EFI_SIZE_TO_PAGES (RelocDiff); // // Note, this one does not seem to be used by XNU but we set it anyway. diff --git a/Library/OcAfterBootCompatLib/ServiceOverrides.c b/Library/OcAfterBootCompatLib/ServiceOverrides.c index 58911618..5c76dd48 100644 --- a/Library/OcAfterBootCompatLib/ServiceOverrides.c +++ b/Library/OcAfterBootCompatLib/ServiceOverrides.c @@ -674,6 +674,11 @@ OcGetMemoryMap ( MemoryMap, *DescriptorSize ); + } else if (BootCompat->Settings.AllowRelocationBlock) { + // + // A sorted memory map is required when using a relocation block. + // + OcSortMemoryMap (*MemoryMapSize, MemoryMap, *DescriptorSize); } //