mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
645 lines
19 KiB
C
645 lines
19 KiB
C
/** @file
|
|
Copyright (C) 2020, vit9696. All rights reserved.
|
|
|
|
All rights reserved.
|
|
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
**/
|
|
|
|
#include <Base.h>
|
|
|
|
#include <IndustryStandard/AppleKxldState.h>
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/OcAppleKernelLib.h>
|
|
#include <Library/OcMachoLib.h>
|
|
#include <Library/OcStringLib.h>
|
|
#include <Library/OcXmlLib.h>
|
|
|
|
#include "PrelinkedInternal.h"
|
|
|
|
STATIC
|
|
CONST KXLD_LINK_STATE_HEADER *
|
|
InternalGetKxldHeader (
|
|
IN CONST VOID *KxldState,
|
|
IN UINT32 KxldStateSize,
|
|
IN MACH_CPU_TYPE CpuType
|
|
)
|
|
{
|
|
CONST KXLD_LINK_STATE_HEADER *Header;
|
|
|
|
if ( (KxldStateSize < sizeof (KXLD_LINK_STATE_HEADER))
|
|
|| !OC_TYPE_ALIGNED (KXLD_LINK_STATE_HEADER, KxldState))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
Header = KxldState;
|
|
|
|
if ( (Header->Signature != KXLD_LINK_STATE_SIGNATURE)
|
|
|| (Header->Version != KXLD_LINK_STATE_VERSION)
|
|
|| (Header->CpuType != CpuType))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return Header;
|
|
}
|
|
|
|
STATIC
|
|
CONST KXLD_VTABLE_HEADER *
|
|
InternalGetKxldVtables (
|
|
IN CONST VOID *KxldState,
|
|
IN UINT32 KxldStateSize,
|
|
IN MACH_CPU_TYPE CpuType,
|
|
OUT UINT32 *NumVtables
|
|
)
|
|
{
|
|
CONST KXLD_LINK_STATE_HEADER *Header;
|
|
CONST KXLD_VTABLE_HEADER *Vtables;
|
|
UINT32 SymbolSize;
|
|
UINT32 Index;
|
|
UINT32 End;
|
|
|
|
Header = InternalGetKxldHeader (KxldState, KxldStateSize, CpuType);
|
|
if (Header == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (Header->NumVtables == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
if (CpuType == MachCpuTypeX86) {
|
|
SymbolSize = sizeof (KXLD_SYM_ENTRY_32);
|
|
if (!OC_TYPE_ALIGNED (UINT32, Header->VtableOffset)) {
|
|
return NULL;
|
|
}
|
|
} else if (CpuType == MachCpuTypeX8664) {
|
|
SymbolSize = sizeof (KXLD_SYM_ENTRY_64);
|
|
if (!OC_TYPE_ALIGNED (UINT64, Header->VtableOffset)) {
|
|
return NULL;
|
|
}
|
|
} else {
|
|
return NULL;
|
|
}
|
|
|
|
if ( OcOverflowMulAddU32 (Header->NumVtables, sizeof (KXLD_VTABLE_HEADER), Header->VtableOffset, &End)
|
|
|| (End > KxldStateSize))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
Vtables = (KXLD_VTABLE_HEADER *)((UINT8 *)KxldState + Header->VtableOffset);
|
|
|
|
for (Index = 0; Index < Header->NumVtables; ++Index) {
|
|
if ( OcOverflowMulAddU32 (Vtables[Index].NumEntries, SymbolSize, Vtables[Index].EntryOffset, &End)
|
|
|| (End > KxldStateSize))
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
*NumVtables = Header->NumVtables;
|
|
return Vtables;
|
|
}
|
|
|
|
STATIC
|
|
CONST VOID *
|
|
InternalGetKxldSymbols (
|
|
IN CONST VOID *KxldState,
|
|
IN UINT32 KxldStateSize,
|
|
IN MACH_CPU_TYPE CpuType,
|
|
OUT UINT32 *NumSymbols
|
|
)
|
|
{
|
|
CONST KXLD_LINK_STATE_HEADER *Header;
|
|
UINT32 SymbolSize;
|
|
UINT32 End;
|
|
|
|
Header = InternalGetKxldHeader (KxldState, KxldStateSize, CpuType);
|
|
if (Header == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
if (Header->NumSymbols == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
if (CpuType == MachCpuTypeX86) {
|
|
SymbolSize = sizeof (KXLD_SYM_ENTRY_32);
|
|
if (!OC_TYPE_ALIGNED (UINT32, Header->SymbolOffset)) {
|
|
return NULL;
|
|
}
|
|
} else if (CpuType == MachCpuTypeX8664) {
|
|
SymbolSize = sizeof (KXLD_SYM_ENTRY_64);
|
|
if (!OC_TYPE_ALIGNED (UINT64, Header->SymbolOffset)) {
|
|
return NULL;
|
|
}
|
|
} else {
|
|
return NULL;
|
|
}
|
|
|
|
if ( OcOverflowMulAddU32 (Header->NumSymbols, SymbolSize, Header->SymbolOffset, &End)
|
|
|| (End > KxldStateSize))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
*NumSymbols = Header->NumSymbols;
|
|
return ((UINT8 *)KxldState + Header->SymbolOffset);
|
|
}
|
|
|
|
STATIC
|
|
CONST CHAR8 *
|
|
InternalGetKxldString (
|
|
IN CONST VOID *KxldState,
|
|
IN UINT32 KxldStateSize,
|
|
IN UINT32 Offset
|
|
)
|
|
{
|
|
CONST CHAR8 *SymbolWalker;
|
|
CONST CHAR8 *SymbolWalkerEnd;
|
|
|
|
if (Offset >= KxldStateSize) {
|
|
return NULL;
|
|
}
|
|
|
|
SymbolWalker = (CONST CHAR8 *)KxldState + Offset;
|
|
SymbolWalkerEnd = (CONST CHAR8 *)KxldState + KxldStateSize;
|
|
|
|
while (SymbolWalker < SymbolWalkerEnd) {
|
|
if (*SymbolWalker == '\0') {
|
|
return (CONST CHAR8 *)KxldState + Offset;
|
|
}
|
|
|
|
++SymbolWalker;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
EFI_STATUS
|
|
InternalKxldStateBuildLinkedSymbolTable (
|
|
IN OUT PRELINKED_KEXT *Kext,
|
|
IN PRELINKED_CONTEXT *Context
|
|
)
|
|
{
|
|
PRELINKED_KEXT_SYMBOL *SymbolTable;
|
|
PRELINKED_KEXT_SYMBOL *WalkerBottom;
|
|
PRELINKED_KEXT_SYMBOL *WalkerTop;
|
|
CONST CHAR8 *Name;
|
|
CONST KXLD_SYM_ENTRY_ANY *KxldSymbols;
|
|
UINT64 KxldAddress;
|
|
UINT32 Index;
|
|
UINT32 NumSymbols;
|
|
UINT32 NumCxxSymbols;
|
|
BOOLEAN Result;
|
|
|
|
ASSERT (Kext->Context.KxldState != NULL);
|
|
ASSERT (Kext->Context.KxldStateSize > 0);
|
|
|
|
if (Kext->LinkedSymbolTable != NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
KxldSymbols = InternalGetKxldSymbols (
|
|
Kext->Context.KxldState,
|
|
Kext->Context.KxldStateSize,
|
|
Context->Is32Bit ? MachCpuTypeI386 : MachCpuTypeX8664,
|
|
&NumSymbols
|
|
);
|
|
|
|
if (KxldSymbols == NULL) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
SymbolTable = AllocatePool (NumSymbols * sizeof (*SymbolTable));
|
|
if (SymbolTable == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
WalkerBottom = &SymbolTable[0];
|
|
WalkerTop = &SymbolTable[NumSymbols - 1];
|
|
|
|
NumCxxSymbols = 0;
|
|
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"OCAK: Processing %a-bit %a KXLD state with %u symbols\n",
|
|
Context->Is32Bit ? "32" : "64",
|
|
Kext->Identifier,
|
|
NumSymbols
|
|
));
|
|
|
|
for (Index = 0; Index < NumSymbols; ++Index) {
|
|
Name = InternalGetKxldString (
|
|
Kext->Context.KxldState,
|
|
Kext->Context.KxldStateSize,
|
|
Context->Is32Bit ? KxldSymbols->Kxld32.NameOffset : KxldSymbols->Kxld64.NameOffset
|
|
);
|
|
if (Name == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Result = MachoSymbolNameIsCxx (Name);
|
|
|
|
KxldAddress = Context->Is32Bit ? KxldSymbols->Kxld32.Address : KxldSymbols->Kxld64.Address;
|
|
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"OCAK: Adding %a-bit symbol %a with %Lx value (flags %u)\n",
|
|
Context->Is32Bit ? "32" : "64",
|
|
Name,
|
|
KxldAddress,
|
|
Context->Is32Bit ? KxldSymbols->Kxld32.Flags : KxldSymbols->Kxld64.Flags
|
|
));
|
|
|
|
if (!Result) {
|
|
WalkerBottom->Value = KxldAddress;
|
|
WalkerBottom->Name = Name;
|
|
WalkerBottom->Length = (UINT32)AsciiStrLen (WalkerBottom->Name);
|
|
++WalkerBottom;
|
|
} else {
|
|
WalkerTop->Value = KxldAddress;
|
|
WalkerTop->Name = Name;
|
|
WalkerTop->Length = (UINT32)AsciiStrLen (WalkerTop->Name);
|
|
--WalkerTop;
|
|
|
|
++NumCxxSymbols;
|
|
}
|
|
|
|
KxldSymbols = KXLD_ANY_NEXT (Context->Is32Bit, KxldSymbols);
|
|
}
|
|
|
|
Kext->NumberOfSymbols = NumSymbols;
|
|
Kext->NumberOfCxxSymbols = NumCxxSymbols;
|
|
Kext->LinkedSymbolTable = SymbolTable;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
InternalKxldStateBuildLinkedVtables (
|
|
IN OUT PRELINKED_KEXT *Kext,
|
|
IN PRELINKED_CONTEXT *Context
|
|
)
|
|
{
|
|
PRELINKED_VTABLE *LinkedVtables;
|
|
PRELINKED_VTABLE *CurrentVtable;
|
|
CONST KXLD_SYM_ENTRY_ANY *KxldSymbols;
|
|
CONST KXLD_VTABLE_HEADER *KxldVtables;
|
|
UINT32 Index;
|
|
UINT32 Index2;
|
|
UINT32 NumVtables;
|
|
UINT32 NumEntries;
|
|
UINT32 ResultingSize;
|
|
|
|
ASSERT (Kext->Context.KxldState != NULL);
|
|
ASSERT (Kext->Context.KxldStateSize > 0);
|
|
|
|
if (Kext->LinkedVtables != NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
KxldVtables = InternalGetKxldVtables (
|
|
Kext->Context.KxldState,
|
|
Kext->Context.KxldStateSize,
|
|
Context->Is32Bit ? MachCpuTypeI386 : MachCpuTypeX8664,
|
|
&NumVtables
|
|
);
|
|
|
|
//
|
|
// Some KPIs may not have vtables (e.g. BSD).
|
|
//
|
|
if (KxldVtables == NULL) {
|
|
Kext->LinkedVtables = NULL;
|
|
Kext->NumberOfVtables = 0;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
NumEntries = 0;
|
|
|
|
for (Index = 0; Index < NumVtables; ++Index) {
|
|
if (OcOverflowAddU32 (NumEntries, KxldVtables[Index].NumEntries, &NumEntries)) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
|
|
if ( OcOverflowMulU32 (NumVtables, sizeof (*LinkedVtables), &ResultingSize)
|
|
|| OcOverflowMulAddU32 (NumEntries, sizeof (*LinkedVtables->Entries), ResultingSize, &ResultingSize))
|
|
{
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
LinkedVtables = AllocatePool (ResultingSize);
|
|
if (LinkedVtables == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
CurrentVtable = LinkedVtables;
|
|
for (Index = 0; Index < NumVtables; ++Index) {
|
|
CurrentVtable->Name = InternalGetKxldString (
|
|
Kext->Context.KxldState,
|
|
Kext->Context.KxldStateSize,
|
|
KxldVtables[Index].NameOffset
|
|
);
|
|
if (CurrentVtable->Name == NULL) {
|
|
FreePool (LinkedVtables);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
KxldSymbols = (KXLD_SYM_ENTRY_ANY *)((UINT8 *)Kext->Context.KxldState + KxldVtables[Index].EntryOffset);
|
|
CurrentVtable->NumEntries = KxldVtables[Index].NumEntries;
|
|
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"OCAK: Adding vtable %a (%u/%u) for %a of %u entries\n",
|
|
CurrentVtable->Name,
|
|
Index + 1,
|
|
NumVtables,
|
|
Kext->Identifier,
|
|
CurrentVtable->NumEntries
|
|
));
|
|
|
|
for (Index2 = 0; Index2 < CurrentVtable->NumEntries; ++Index2) {
|
|
CurrentVtable->Entries[Index2].Address = Context->Is32Bit ? KxldSymbols->Kxld32.Address : KxldSymbols->Kxld64.Address;
|
|
CurrentVtable->Entries[Index2].Name = InternalGetKxldString (
|
|
Kext->Context.KxldState,
|
|
Kext->Context.KxldStateSize,
|
|
Context->Is32Bit ? KxldSymbols->Kxld32.NameOffset : KxldSymbols->Kxld64.NameOffset
|
|
);
|
|
if (CurrentVtable->Entries[Index2].Name == NULL) {
|
|
FreePool (LinkedVtables);
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
KxldSymbols = KXLD_ANY_NEXT (Context->Is32Bit, KxldSymbols);
|
|
}
|
|
|
|
CurrentVtable = GET_NEXT_PRELINKED_VTABLE (CurrentVtable);
|
|
}
|
|
|
|
Kext->LinkedVtables = LinkedVtables;
|
|
Kext->NumberOfVtables = NumVtables;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
InternalKxldStateRebasePlist (
|
|
IN OUT PRELINKED_CONTEXT *Context,
|
|
IN INT64 Delta
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
UINT32 KextCount;
|
|
UINT32 FieldIndex;
|
|
UINT32 FieldCount;
|
|
XML_NODE *KextPlist;
|
|
CONST CHAR8 *KextPlistKey;
|
|
CHAR8 *ScratchWalker;
|
|
XML_NODE *KextPlistValue;
|
|
UINT64 KxldState;
|
|
|
|
KextCount = XmlNodeChildren (Context->KextList);
|
|
|
|
Context->KextScratchBuffer = ScratchWalker = AllocatePool (KextCount * KEXT_OFFSET_STR_LEN);
|
|
if (Context->KextScratchBuffer == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
for (Index = 0; Index < KextCount; ++Index) {
|
|
KextPlist = PlistNodeCast (XmlNodeChild (Context->KextList, Index), PLIST_NODE_TYPE_DICT);
|
|
|
|
if (KextPlist == NULL) {
|
|
continue;
|
|
}
|
|
|
|
FieldCount = PlistDictChildren (KextPlist);
|
|
for (FieldIndex = 0; FieldIndex < FieldCount; ++FieldIndex) {
|
|
KextPlistKey = PlistKeyValue (PlistDictChild (KextPlist, FieldIndex, &KextPlistValue));
|
|
if (KextPlistKey == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if (AsciiStrCmp (KextPlistKey, PRELINK_INFO_LINK_STATE_ADDR_KEY) == 0) {
|
|
if (!PlistIntegerValue (KextPlistValue, &KxldState, sizeof (KxldState), TRUE)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "OCAK: Shifting 0x%Lx to 0x%Lx\n", KxldState, KxldState + Delta));
|
|
|
|
KxldState += Delta;
|
|
|
|
if (!AsciiUint64ToLowerHex (ScratchWalker, KEXT_OFFSET_STR_LEN, KxldState)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
XmlNodeChangeContent (KextPlistValue, ScratchWalker);
|
|
ScratchWalker += AsciiStrSize (ScratchWalker);
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
InternalKxldStateRebuild (
|
|
IN OUT PRELINKED_CONTEXT *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 AlignedSize;
|
|
UINT32 NewSize;
|
|
|
|
//
|
|
// This is a requirement from 10.6.8, should be guaranteed?
|
|
//
|
|
ASSERT (OC_POT_ALIGNED (MACHO_PAGE_SIZE, Context->PrelinkedLastAddress));
|
|
|
|
//
|
|
// Append prelink state for 10.6.8
|
|
//
|
|
AlignedSize = MACHO_ALIGN (Context->PrelinkedStateKernelSize);
|
|
if ( OcOverflowAddU32 (Context->PrelinkedSize, AlignedSize, &NewSize)
|
|
|| (NewSize > Context->PrelinkedAllocSize))
|
|
{
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
if (Context->Is32Bit) {
|
|
Context->PrelinkedStateSegment->Segment32.VirtualAddress = (UINT32)Context->PrelinkedLastAddress;
|
|
Context->PrelinkedStateSegment->Segment32.Size = AlignedSize;
|
|
Context->PrelinkedStateSegment->Segment32.FileOffset = Context->PrelinkedSize;
|
|
Context->PrelinkedStateSegment->Segment32.FileSize = AlignedSize;
|
|
Context->PrelinkedStateSectionKernel->Section32.Address = (UINT32)Context->PrelinkedLastAddress;
|
|
Context->PrelinkedStateSectionKernel->Section32.Offset = Context->PrelinkedSize;
|
|
Context->PrelinkedStateSectionKernel->Section32.Size = Context->PrelinkedStateKernelSize;
|
|
} else {
|
|
Context->PrelinkedStateSegment->Segment64.VirtualAddress = Context->PrelinkedLastAddress;
|
|
Context->PrelinkedStateSegment->Segment64.Size = AlignedSize;
|
|
Context->PrelinkedStateSegment->Segment64.FileOffset = Context->PrelinkedSize;
|
|
Context->PrelinkedStateSegment->Segment64.FileSize = AlignedSize;
|
|
Context->PrelinkedStateSectionKernel->Section64.Address = Context->PrelinkedLastAddress;
|
|
Context->PrelinkedStateSectionKernel->Section64.Offset = Context->PrelinkedSize;
|
|
Context->PrelinkedStateSectionKernel->Section64.Size = Context->PrelinkedStateKernelSize;
|
|
}
|
|
|
|
CopyMem (
|
|
&Context->Prelinked[Context->PrelinkedSize],
|
|
Context->PrelinkedStateKernel,
|
|
Context->PrelinkedStateKernelSize
|
|
);
|
|
ZeroMem (
|
|
&Context->Prelinked[Context->PrelinkedSize + Context->PrelinkedStateKernelSize],
|
|
AlignedSize - Context->PrelinkedStateKernelSize
|
|
);
|
|
|
|
Context->PrelinkedLastAddress += AlignedSize;
|
|
Context->PrelinkedSize += AlignedSize;
|
|
|
|
AlignedSize = MACHO_ALIGN (Context->PrelinkedStateKextsSize);
|
|
if ( OcOverflowAddU32 (Context->PrelinkedSize, AlignedSize, &NewSize)
|
|
|| (NewSize > Context->PrelinkedAllocSize))
|
|
{
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
if (Context->Is32Bit) {
|
|
Context->PrelinkedStateSegment->Segment32.Size += AlignedSize;
|
|
Context->PrelinkedStateSegment->Segment32.FileSize += AlignedSize;
|
|
Context->PrelinkedStateSectionKexts->Section32.Address = (UINT32)Context->PrelinkedLastAddress;
|
|
Context->PrelinkedStateSectionKexts->Section32.Offset = Context->PrelinkedSize;
|
|
Context->PrelinkedStateSectionKexts->Section32.Size = Context->PrelinkedStateKextsSize;
|
|
} else {
|
|
Context->PrelinkedStateSegment->Segment64.Size += AlignedSize;
|
|
Context->PrelinkedStateSegment->Segment64.FileSize += AlignedSize;
|
|
Context->PrelinkedStateSectionKexts->Section64.Address = Context->PrelinkedLastAddress;
|
|
Context->PrelinkedStateSectionKexts->Section64.Offset = Context->PrelinkedSize;
|
|
Context->PrelinkedStateSectionKexts->Section64.Size = Context->PrelinkedStateKextsSize;
|
|
}
|
|
|
|
CopyMem (
|
|
&Context->Prelinked[Context->PrelinkedSize],
|
|
Context->PrelinkedStateKexts,
|
|
Context->PrelinkedStateKextsSize
|
|
);
|
|
ZeroMem (
|
|
&Context->Prelinked[Context->PrelinkedSize + Context->PrelinkedStateKextsSize],
|
|
AlignedSize - Context->PrelinkedStateKextsSize
|
|
);
|
|
|
|
Context->PrelinkedLastAddress += AlignedSize;
|
|
Context->PrelinkedSize += AlignedSize;
|
|
|
|
if ((Context->Is32Bit ?
|
|
Context->PrelinkedStateSectionKexts->Section32.Address : Context->PrelinkedStateSectionKexts->Section64.Address)
|
|
!= Context->PrelinkedStateKextsAddress)
|
|
{
|
|
Status = InternalKxldStateRebasePlist (
|
|
Context,
|
|
(INT64)((Context->Is32Bit ?
|
|
Context->PrelinkedStateSectionKexts->Section32.Address : Context->PrelinkedStateSectionKexts->Section64.Address)
|
|
- Context->PrelinkedStateKextsAddress)
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
Context->PrelinkedStateKextsAddress = Context->Is32Bit ?
|
|
Context->PrelinkedStateSectionKexts->Section32.Address : Context->PrelinkedStateSectionKexts->Section64.Address;
|
|
}
|
|
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OCAK: Rebasing %a-bit KXLD state from %Lx to %Lx - %r\n",
|
|
Context->Is32Bit ? "32" : "64",
|
|
Context->PrelinkedStateKextsAddress,
|
|
Context->Is32Bit ?
|
|
Context->PrelinkedStateSectionKexts->Section32.Address : Context->PrelinkedStateSectionKexts->Section64.Address,
|
|
Status
|
|
));
|
|
} else {
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
UINT64
|
|
InternalKxldSolveSymbol (
|
|
IN BOOLEAN Is32Bit,
|
|
IN CONST VOID *KxldState,
|
|
IN UINT32 KxldStateSize,
|
|
IN CONST CHAR8 *Name
|
|
)
|
|
{
|
|
CONST CHAR8 *LocalName;
|
|
CONST KXLD_SYM_ENTRY_ANY *KxldSymbols;
|
|
UINT64 KxldAddress;
|
|
UINT32 Index;
|
|
UINT32 NumSymbols;
|
|
|
|
ASSERT (KxldState != NULL);
|
|
ASSERT (KxldStateSize > 0);
|
|
ASSERT (Name != NULL);
|
|
|
|
KxldSymbols = InternalGetKxldSymbols (
|
|
KxldState,
|
|
KxldStateSize,
|
|
Is32Bit ? MachCpuTypeI386 : MachCpuTypeX8664,
|
|
&NumSymbols
|
|
);
|
|
|
|
if (KxldSymbols == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"OCAK: Processing %a-bit KXLD state for %a with %u symbols\n",
|
|
Is32Bit ? "32" : "64",
|
|
Name,
|
|
NumSymbols
|
|
));
|
|
|
|
for (Index = 0; Index < NumSymbols; ++Index) {
|
|
LocalName = InternalGetKxldString (
|
|
KxldState,
|
|
KxldStateSize,
|
|
Is32Bit ? KxldSymbols->Kxld32.NameOffset : KxldSymbols->Kxld64.NameOffset
|
|
);
|
|
if (LocalName == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
KxldAddress = Is32Bit ? KxldSymbols->Kxld32.Address : KxldSymbols->Kxld64.Address;
|
|
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"OCAK: Checking %a-bit symbol %a with %Lx value (flags %u)\n",
|
|
Is32Bit ? "32" : "64",
|
|
LocalName,
|
|
KxldAddress,
|
|
Is32Bit ? KxldSymbols->Kxld32.Flags : KxldSymbols->Kxld64.Flags
|
|
));
|
|
|
|
if (AsciiStrCmp (LocalName, Name) == 0) {
|
|
return KxldAddress;
|
|
}
|
|
|
|
KxldSymbols = KXLD_ANY_NEXT (Is32Bit, KxldSymbols);
|
|
}
|
|
|
|
return 0;
|
|
}
|