mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
497 lines
13 KiB
C
497 lines
13 KiB
C
/** @file
|
|
Library handling KEXT prelinking.
|
|
Currently limited to Intel 64 architectures.
|
|
|
|
Copyright (c) 2018, Download-Fritz. All rights reserved.<BR>
|
|
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.
|
|
|
|
**/
|
|
|
|
#ifndef OC_MACHO_PRELINK_INTERNAL_H
|
|
#define OC_MACHO_PRELINK_INTERNAL_H
|
|
|
|
#include <IndustryStandard/AppleMachoImage.h>
|
|
|
|
#include <Library/OcAppleKernelLib.h>
|
|
#include <Library/OcMachoLib.h>
|
|
#include <Library/OcXmlLib.h>
|
|
|
|
typedef struct {
|
|
//
|
|
// These data are used to construct linked lists of dependency information
|
|
// for each KEXT. It is declared hear for every dependency will
|
|
// eventually be part of a list and to save separate allocations per KEXT.
|
|
//
|
|
UINT32 Signature;
|
|
LIST_ENTRY Link;
|
|
//
|
|
// Kext CFBundleIdentifier.
|
|
//
|
|
CONST CHAR8 *Identifier;
|
|
//
|
|
// Patcher context containing useful data.
|
|
//
|
|
PATCHER_CONTEXT Context;
|
|
//
|
|
// Dependencies dictionary (OSBundleLibraries).
|
|
//
|
|
XML_NODE *BundleLibraries;
|
|
//
|
|
// Compatible version, may be NULL.
|
|
//
|
|
CONST CHAR8 *CompatibleVersion;
|
|
} PRELINKED_KEXT;
|
|
|
|
#define PRELINKED_KEXT_SIGNATURE SIGNATURE_32 ('P', 'K', 'X', 'T')
|
|
|
|
/**
|
|
Gets the next element in a linked list of PRELINKED_KEXT.
|
|
|
|
@param[in] This The current ListEntry.
|
|
**/
|
|
#define GET_PRELINKED_KEXT_FROM_LINK(This) \
|
|
(CR ( \
|
|
(This), \
|
|
PRELINKED_KEXT, \
|
|
Link, \
|
|
PRELINKED_KEXT_SIGNATURE \
|
|
))
|
|
|
|
/**
|
|
Gets cached PRELINKED_KEXT from PRELINKED_CONTEXT.
|
|
**/
|
|
PRELINKED_KEXT *
|
|
InternalGetPrelinkedKext (
|
|
IN OUT PRELINKED_CONTEXT *Prelinked,
|
|
IN CONST CHAR8 *Identifier
|
|
);
|
|
|
|
/**
|
|
Frees PRELINKED_KEXT list.
|
|
**/
|
|
VOID
|
|
InternalFreePrelinkedKexts (
|
|
LIST_ENTRY *Kexts
|
|
);
|
|
|
|
#define KXLD_WEAK_TEST_SYMBOL "_gOSKextUnresolved"
|
|
|
|
#define OS_METACLASS_VTABLE_NAME "__ZTV11OSMetaClass"
|
|
|
|
#define X86_64_RIP_RELATIVE_LIMIT 0x80000000ULL
|
|
|
|
#define SYM_MAX_NAME_LEN 256U
|
|
|
|
#define VTABLE_ENTRY_SIZE_64 8U
|
|
#define VTABLE_HEADER_LEN_64 2U
|
|
#define VTABLE_HEADER_SIZE_64 (VTABLE_HEADER_LEN_64 * VTABLE_ENTRY_SIZE_64)
|
|
|
|
typedef struct {
|
|
UINT32 StringIndex; ///< index into the string table
|
|
UINT64 Value; ///< value of this symbol (or stab offset)
|
|
} OC_SYMBOL_64;
|
|
|
|
#define OC_SYMBOL_TABLE_64_SIGNATURE SIGNATURE_32 ('O', 'S', '6', '4')
|
|
|
|
/**
|
|
Gets the next element in a linked list of OC_SYMBOL_TABLE_64.
|
|
|
|
@param[in] This The current ListEntry.
|
|
|
|
**/
|
|
#define GET_OC_SYMBOL_TABLE_64_FROM_LINK(This) \
|
|
CR ( \
|
|
(This), \
|
|
OC_SYMBOL_TABLE_64, \
|
|
Link, \
|
|
OC_SYMBOL_TABLE_64_SIGNATURE \
|
|
)
|
|
|
|
typedef struct {
|
|
///
|
|
/// These data are used to construct linked lists of dependency information
|
|
/// for each KEXT. It is declared hear for every dependency will
|
|
/// eventually be part of a list and to save separate allocations per KEXT.
|
|
///
|
|
UINT32 Signature;
|
|
LIST_ENTRY Link;
|
|
BOOLEAN IsIndirect;
|
|
///
|
|
/// The String Table associated with this symbol table.
|
|
///
|
|
CONST CHAR8 *StringTable;
|
|
///
|
|
/// The number of symbols in the entire symbols buffer.
|
|
///
|
|
UINT32 NumSymbols;
|
|
///
|
|
/// The number of C++ symbols at the end of the symbols buffer.
|
|
///
|
|
UINT32 NumCxxSymbols;
|
|
OC_SYMBOL_64 Symbols[]; ///< The symbol buffer.
|
|
} OC_SYMBOL_TABLE_64;
|
|
|
|
typedef struct {
|
|
CONST CHAR8 *Name; ///< The symbol's name.
|
|
UINT64 Address; ///< The symbol's address.
|
|
} OC_VTABLE_ENTRY;
|
|
|
|
#define GET_NEXT_OC_VTABLE(This) \
|
|
((OC_VTABLE *)(&(This)->Entries[(This)->NumEntries]))
|
|
|
|
typedef struct {
|
|
CONST CHAR8 *Name; ///< The VTable's name.
|
|
UINT32 NumEntries; ///< The number of VTable entries.
|
|
OC_VTABLE_ENTRY Entries[]; ///< The VTable entries.
|
|
} OC_VTABLE;
|
|
|
|
#define OC_VTABLE_ARRAY_SIGNATURE SIGNATURE_32 ('O', 'V', 'T', 'A')
|
|
|
|
/**
|
|
Gets the next element in a linked list of OC_VTABLE_ARRAY.
|
|
|
|
@param[in] This The current ListEntry.
|
|
|
|
**/
|
|
#define GET_OC_VTABLE_ARRAY_FROM_LINK(This) \
|
|
CR ( \
|
|
(This), \
|
|
OC_VTABLE_ARRAY, \
|
|
Link, \
|
|
OC_VTABLE_ARRAY_SIGNATURE \
|
|
)
|
|
|
|
#define GET_FIRST_OC_VTABLE(This) \
|
|
((OC_VTABLE *)((This) + 1))
|
|
|
|
typedef struct {
|
|
///
|
|
/// These data are used to construct linked lists of dependency information
|
|
/// for each KEXT. It is declared hear for every dependency will
|
|
/// eventually be part of a list and to save separate allocations per KEXT.
|
|
///
|
|
UINT32 Signature;
|
|
LIST_ENTRY Link;
|
|
///
|
|
/// The number of VTables in the array.
|
|
///
|
|
UINT32 NumVtables;
|
|
//
|
|
// NOTE: This is an array that cannot be declared as such as OC_VTABLE
|
|
// contains a flexible array itself. As the size is dynamic, do not
|
|
// try to use pointer arithmetics.
|
|
//
|
|
///
|
|
/// VTable array.
|
|
///
|
|
OC_VTABLE Vtables;
|
|
} OC_VTABLE_ARRAY;
|
|
|
|
typedef union {
|
|
struct {
|
|
UINT32 Major : 14;
|
|
UINT32 Minor : 7;
|
|
UINT32 Revision : 7;
|
|
UINT32 Stage : 4;
|
|
UINT32 StageLevel : 8;
|
|
} Bits;
|
|
UINT64 Value;
|
|
} OC_KEXT_VERSION;
|
|
|
|
typedef enum {
|
|
OcKextVersionStageDevelopment = 1,
|
|
OcKextVersionStageAlpha = 3,
|
|
OcKextVersionStageBeta = 5,
|
|
OcKextVersionStageCandidate = 7,
|
|
OcKextVersionStageRelease = 9
|
|
} OC_KEXT_VERSION_STAGE;
|
|
|
|
typedef struct {
|
|
OC_SYMBOL_TABLE_64 *SymbolTable;
|
|
OC_VTABLE_ARRAY *Vtables;
|
|
} OC_DEPENDENCY_DATA;
|
|
|
|
#define OC_DEPENDENCY_INFO_ENTRY_SIGNATURE \
|
|
SIGNATURE_32 ('O', 'D', 'I', 'E')
|
|
|
|
#define OC_DEP_INFO_FROM_LINK(This) \
|
|
(CR ( \
|
|
(This), \
|
|
OC_DEPENDENCY_INFO_ENTRY, \
|
|
Link, \
|
|
OC_DEPENDENCY_INFO_ENTRY_SIGNATURE \
|
|
))
|
|
|
|
typedef struct OC_DEPENDENCY_INFO_ENTRY_ OC_DEPENDENCY_INFO_ENTRY;
|
|
|
|
typedef struct {
|
|
MACH_HEADER_64 *MachHeader;
|
|
UINT32 MachoSize;
|
|
CONST CHAR8 *Name;
|
|
OC_KEXT_VERSION Version;
|
|
OC_KEXT_VERSION CompatibleVersion;
|
|
UINTN NumDependencies;
|
|
OC_DEPENDENCY_INFO_ENTRY *Dependencies[];
|
|
} OC_DEPENDENCY_INFO;
|
|
|
|
struct OC_DEPENDENCY_INFO_ENTRY_ {
|
|
UINT32 Signature;
|
|
LIST_ENTRY Link;
|
|
BOOLEAN Prelinked;
|
|
OC_DEPENDENCY_DATA Data;
|
|
OC_DEPENDENCY_INFO Info;
|
|
};
|
|
|
|
typedef struct {
|
|
struct {
|
|
OC_MACHO_CONTEXT *MachoContext;
|
|
XML_NODE *Plist;
|
|
} Input;
|
|
|
|
struct {
|
|
BOOLEAN Linked;
|
|
} Output;
|
|
//
|
|
// Private data.
|
|
//
|
|
struct {
|
|
OC_DEPENDENCY_INFO_ENTRY *Info;
|
|
MACH_SEGMENT_COMMAND_64 *LinkEdit;
|
|
BOOLEAN IsDependedOn;
|
|
} Private;
|
|
} OC_KEXT_REQUEST;
|
|
|
|
typedef struct {
|
|
CONST MACH_NLIST_64 *Smcp;
|
|
CONST MACH_NLIST_64 *Vtable;
|
|
CONST MACH_NLIST_64 *MetaVtable;
|
|
} OC_VTABLE_PATCH_ENTRY;
|
|
|
|
typedef struct {
|
|
UINTN NumEntries;
|
|
OC_VTABLE_PATCH_ENTRY Entries[];
|
|
} OC_VTABLE_PATCH_ARRAY;
|
|
|
|
typedef struct {
|
|
UINT32 NumSymbols;
|
|
CONST MACH_NLIST_64 *Symbols[];
|
|
} OC_VTABLE_EXPORT_ARRAY;
|
|
|
|
//
|
|
// Dependencies
|
|
//
|
|
|
|
OC_DEPENDENCY_INFO_ENTRY *
|
|
InternalKextCollectInformation (
|
|
IN XML_NODE *Plist,
|
|
IN OUT OC_MACHO_CONTEXT *MachoContext OPTIONAL,
|
|
IN UINT64 KextsVirtual OPTIONAL,
|
|
IN UINTN KextsPhysical OPTIONAL,
|
|
IN UINT64 RequestedVersion OPTIONAL
|
|
);
|
|
|
|
VOID
|
|
InternalFreeDependencyEntry (
|
|
IN OC_DEPENDENCY_INFO_ENTRY *Entry
|
|
);
|
|
|
|
BOOLEAN
|
|
InternalResolveDependencies (
|
|
IN LIST_ENTRY *Dependencies,
|
|
IN UINTN NumRequests, OPTIONAL
|
|
IN OUT OC_KEXT_REQUEST *Requests, OPTIONAL
|
|
IN CONST CHAR8 *PrelinkedPlist,
|
|
IN OC_DEPENDENCY_INFO_ENTRY *KextInfo,
|
|
IN UINT64 KextsVirtual,
|
|
IN UINTN KextsPhysical
|
|
);
|
|
|
|
LIST_ENTRY *
|
|
InternalRemoveDependency (
|
|
IN CONST LIST_ENTRY *Dependencies,
|
|
IN UINTN NumRequests,
|
|
IN OUT OC_KEXT_REQUEST *Requests,
|
|
IN OC_DEPENDENCY_INFO_ENTRY *DepInfo
|
|
);
|
|
|
|
VOID
|
|
InternalInvalidateKextRequest (
|
|
IN CONST LIST_ENTRY *Dependencies,
|
|
IN UINTN NumRequests,
|
|
IN OUT OC_KEXT_REQUEST *Requests,
|
|
IN OC_KEXT_REQUEST *Request
|
|
);
|
|
|
|
BOOLEAN
|
|
InternalConstructDependencyArrays (
|
|
IN UINTN NumDependencies,
|
|
IN OC_DEPENDENCY_INFO_ENTRY **Dependencies,
|
|
OUT OC_DEPENDENCY_DATA *DependencyData
|
|
);
|
|
|
|
VOID
|
|
InternalDestructDependencyArrays (
|
|
OUT CONST OC_DEPENDENCY_DATA *DependencyData
|
|
);
|
|
|
|
UINT64
|
|
InternalGetNewPrelinkedKextLoadAddress (
|
|
IN OUT OC_MACHO_CONTEXT *KernelContext,
|
|
IN CONST MACH_SEGMENT_COMMAND_64 *PrelinkedKextsSegment,
|
|
IN CONST CHAR8 *PrelinkedPlist
|
|
);
|
|
|
|
/**
|
|
Fills SymbolTable with the symbols provided in Symbols. For performance
|
|
reasons, the C++ symbols are continuously added to the top of the buffer.
|
|
Their order is not preserved. SymbolTable->SymbolTable is expected to be
|
|
a valid buffer that can store at least NumSymbols symbols.
|
|
|
|
@param[in] MachoContext Context of the Mach-O.
|
|
@param[in] NumSymbols The number of symbols to copy.
|
|
@param[in] Symbols The source symbol array.
|
|
@param[in,out] SymbolTable The desination Symbol List. Must be able to
|
|
hold at least NumSymbols symbols.
|
|
|
|
**/
|
|
VOID
|
|
InternalFillSymbolTable64 (
|
|
IN OUT OC_MACHO_CONTEXT *MachoContext,
|
|
IN UINT32 NumSymbols,
|
|
IN CONST MACH_NLIST_64 *Symbols,
|
|
IN OUT OC_SYMBOL_TABLE_64 *SymbolTable
|
|
);
|
|
|
|
//
|
|
// PLIST
|
|
//
|
|
|
|
CONST CHAR8 *
|
|
InternalPlistStrStrSameLevelUp (
|
|
IN CONST CHAR8 *AnchorString,
|
|
IN CONST CHAR8 *FindString,
|
|
IN UINTN FindStringLen
|
|
);
|
|
|
|
CONST CHAR8 *
|
|
InternalPlistStrStrSameLevelDown (
|
|
IN CONST CHAR8 *AnchorString,
|
|
IN CONST CHAR8 *FindString,
|
|
IN UINTN FindStringLen
|
|
);
|
|
|
|
CONST CHAR8 *
|
|
InternalPlistStrStrSameLevel (
|
|
IN CONST CHAR8 *AnchorString,
|
|
IN CONST CHAR8 *FindString,
|
|
IN UINTN FindStringLen,
|
|
IN UINTN DownwardsOffset
|
|
);
|
|
|
|
UINT64
|
|
InternalPlistGetIntValue (
|
|
IN CONST CHAR8 **Tag
|
|
);
|
|
|
|
//
|
|
// VTables
|
|
//
|
|
|
|
UINT32
|
|
InternalGetVtableSize64 (
|
|
IN CONST UINT64 *VtableData
|
|
);
|
|
|
|
BOOLEAN
|
|
InternalGetVtableSizeWithRelocs64 (
|
|
IN OUT OC_MACHO_CONTEXT *MachoContext,
|
|
IN CONST UINT64 *VtableData,
|
|
OUT UINT32 *VtableSize
|
|
);
|
|
|
|
BOOLEAN
|
|
InternalPrepareVtableCreationNonPrelinked64 (
|
|
IN OUT OC_MACHO_CONTEXT *MachoContext,
|
|
IN UINT32 NumSymbols,
|
|
IN CONST MACH_NLIST_64 *SymbolTable,
|
|
OUT OC_VTABLE_PATCH_ARRAY *PatchData
|
|
);
|
|
|
|
BOOLEAN
|
|
InternalCreateVtablesNonPrelinked64 (
|
|
IN OUT OC_MACHO_CONTEXT *MachoContext,
|
|
IN CONST OC_DEPENDENCY_DATA *DependencyData,
|
|
IN OC_VTABLE_PATCH_ARRAY *PatchData,
|
|
OUT OC_VTABLE_ARRAY *VtableArray
|
|
);
|
|
|
|
BOOLEAN
|
|
InternalPrepareCreateVtablesPrelinked64 (
|
|
IN OC_MACHO_CONTEXT *MachoContext,
|
|
OUT OC_VTABLE_EXPORT_ARRAY *VtableExport,
|
|
IN UINT32 VtableExportSize
|
|
);
|
|
|
|
BOOLEAN
|
|
InternalCreateVtablesPrelinked64 (
|
|
IN OC_MACHO_CONTEXT *MachoContext,
|
|
IN CONST OC_SYMBOL_TABLE_64 *DefinedSymbols,
|
|
IN OC_VTABLE_EXPORT_ARRAY *VtableExport,
|
|
OUT OC_VTABLE *VtableBuffer
|
|
);
|
|
|
|
//
|
|
// Prelink
|
|
//
|
|
|
|
// TODO: Move?
|
|
CONST OC_SYMBOL_64 *
|
|
InternalOcGetSymbolByName (
|
|
IN CONST OC_SYMBOL_TABLE_64 *DefinedSymbols,
|
|
IN CONST CHAR8 *Name,
|
|
IN BOOLEAN CheckIndirect
|
|
);
|
|
|
|
VOID
|
|
InternalSolveSymbolValue64 (
|
|
IN UINT64 Value,
|
|
OUT MACH_NLIST_64 *Symbol
|
|
);
|
|
|
|
/**
|
|
Prelinks the specified KEXT against the specified LinkAddress and the data
|
|
of its dependencies.
|
|
|
|
@param[in,out] MachoContext Mach-O context of the KEXT to prelink.
|
|
@param[in] LinkEditSegment __LINKEDIT segment of the KEXT to prelink.
|
|
@param[in] LinkAddress The address this KEXT shall be linked
|
|
against.
|
|
@param[in] DependencyData List of data of all dependencies.
|
|
@param[in] ExposeSymbols Whether the symbol table shall be exposed.
|
|
@param[out] OutputData Buffer to output data into.
|
|
@param[out] ScratchMemory Scratch memory buffer that is at least as big
|
|
as the KEXT's __LINKEDIT segment.
|
|
|
|
@retval Returned is whether the prelinking process has been successful.
|
|
The state of the KEXT is undefined in case this routine fails.
|
|
|
|
**/
|
|
BOOLEAN
|
|
InternalPrelinkKext64 (
|
|
IN OUT OC_MACHO_CONTEXT *MachoContext,
|
|
IN MACH_SEGMENT_COMMAND_64 *LinkEditSegment,
|
|
IN UINT64 LinkAddress,
|
|
IN OC_DEPENDENCY_DATA *DependencyData,
|
|
IN BOOLEAN ExposeSymbols,
|
|
IN OUT OC_DEPENDENCY_DATA *OutputData,
|
|
OUT VOID *ScratchMemory
|
|
);
|
|
|
|
#endif // OC_MACHO_PRELINK_INTERNAL_H
|