未验证 提交 b8d552f1 编写于 作者: J John Davis 提交者: GitHub

OCAB: Implement Mac OS X 10.4/10.5 relocation block support (#373)

上级 18a231ee
......@@ -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-<hex addr of DriverInfo> 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-<hex addr of DriverInfo> in DevTree /chosen/memory-map.
//
......
......@@ -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;
......
......@@ -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;
///
......
......@@ -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.
//
......
......@@ -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.
......
......@@ -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);
}
//
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册