OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
PrelinkedInternal.h
Go to the documentation of this file.
1
16#ifndef PRELINKED_INTERNAL_H
17#define PRELINKED_INTERNAL_H
18
20
22#include <Library/OcMachoLib.h>
23#include <Library/OcXmlLib.h>
24
25//
26// Some sane maximum value.
27//
28#define MAX_KEXT_DEPEDENCIES 16
29
30//
31// Aligned maximum virtual address size with 0x prefix and \0 terminator.
32//
33#define KEXT_OFFSET_STR_LEN 24
34
35//
36// Kernel quirks array.
37//
39
41
42typedef struct {
43 //
44 // Value is declared first as it has shown to improve comparison performance.
45 //
46 UINT64 Value;
47 CONST CHAR8 *Name;
48 UINT32 Length;
50
51typedef struct {
52 CONST CHAR8 *Name;
53 UINT64 Address;
55
56#define GET_NEXT_PRELINKED_VTABLE(This) \
57 (PRELINKED_VTABLE *)( \
58 (UINTN)((This) + 1) + ((This)->NumEntries * sizeof (*(This)->Entries)) \
59 )
60
61typedef struct {
62 CONST CHAR8 *Name;
63 UINT32 NumEntries;
66
68 //
69 // These data are used to construct linked lists of dependency information
70 // for each KEXT. It is declared hear for every dependency will
71 // eventually be part of a list and to save separate allocations per KEXT.
72 //
73 UINT32 Signature;
74 //
75 // Link for global list (PRELINKED_CONTEXT -> PrelinkedKexts).
76 //
77 LIST_ENTRY Link;
78 //
79 // Link for local list (PRELINKED_CONTEXT -> InjectedKexts).
80 //
81 LIST_ENTRY InjectedLink;
82 //
83 // Kext CFBundleIdentifier.
84 //
85 CONST CHAR8 *Identifier;
86 //
87 // Patcher context containing useful data.
88 //
90 //
91 // Dependencies dictionary (OSBundleLibraries).
92 // May be NULL for KPI kexts or after Dependencies are set.
93 //
95 //
96 // Compatible version, may be NULL.
97 //
98 CONST CHAR8 *CompatibleVersion;
99 //
100 // Scanned dependencies (PRELINKED_KEXT) from BundleLibraries.
101 // Not resolved by default. See InternalScanPrelinkedKext for fields below.
102 //
104 //
105 // Linkedit segment reference.
106 //
108 //
109 // The String Table associated with this symbol table.
110 //
111 CONST CHAR8 *StringTable;
112 //
113 // Symbol table.
114 //
116 //
117 // Symbol table size.
118 //
120 //
121 // Number of C++ symbols. They are put at the end of LinkedSymbolTable.
122 // Calculated at LinkedSymbolTable construction.
123 //
125 //
126 // Sorted symbol table used only for dependencies.
127 //
129 //
130 // A flag set during dependency walk BFS to avoid going through the same path.
131 //
132 BOOLEAN Processed;
133 //
134 // Number of vtables in this kext.
135 //
137 //
138 // Scanned vtable buffer. Iterated with GET_NEXT_PRELINKED_VTABLE.
139 //
141};
142
143//
144// PRELINKED_KEXT signature for list identification.
145//
146#define PRELINKED_KEXT_SIGNATURE SIGNATURE_32 ('P', 'K', 'X', 'T')
147
153#define GET_PRELINKED_KEXT_FROM_LINK(This) \
154 (CR ( \
155 (This), \
156 PRELINKED_KEXT, \
157 Link, \
158 PRELINKED_KEXT_SIGNATURE \
159 ))
160
166#define GET_INJECTED_KEXT_FROM_LINK(This) \
167 (CR ( \
168 (This), \
169 PRELINKED_KEXT, \
170 InjectedLink, \
171 PRELINKED_KEXT_SIGNATURE \
172 ))
173
179 IN OC_MACHO_CONTEXT *Context,
180 IN XML_NODE *KextPlist
181 );
182
186VOID
188 IN PRELINKED_KEXT *Kext
189 );
190
196 IN OUT PRELINKED_CONTEXT *Prelinked,
197 IN CONST CHAR8 *Identifier
198 );
199
203EFI_STATUS
205 IN OUT PRELINKED_CONTEXT *Prelinked,
206 IN CONST CHAR8 *Identifier
207 );
208
214 IN OUT PRELINKED_CONTEXT *Prelinked
215 );
216
220EFI_STATUS
222 IN OUT PRELINKED_KEXT *Kext,
223 IN OUT PRELINKED_CONTEXT *Context,
224 IN BOOLEAN Dependency
225 );
226
232VOID
234 IN PRELINKED_CONTEXT *Context
235 );
236
251 IN OUT PRELINKED_CONTEXT *Context,
252 IN OUT OC_MACHO_CONTEXT *Executable,
253 IN XML_NODE *PlistRoot,
254 IN UINT64 LoadAddress,
255 IN UINT64 KmodAddress,
256 IN UINT64 FileOffset
257 );
258
259EFI_STATUS
261 IN OUT OC_MACHO_CONTEXT *Context,
262 OUT OC_MACHO_CONTEXT *InnerContext,
263 IN UINT8 *Buffer,
264 IN UINT32 BufferSize,
265 OUT BOOLEAN *KernelCollection OPTIONAL
266 );
267
268#define KXLD_WEAK_TEST_SYMBOL "_gOSKextUnresolved"
269
270#define KXLD_ANY_NEXT(a, b) ((VOID *) (((UINTN)(b)) + ((a) ? sizeof ((b)->Kxld32) : sizeof ((b)->Kxld64))))
271
272#define OS_METACLASS_VTABLE_NAME "__ZTV11OSMetaClass"
273
274#define X86_64_RIP_RELATIVE_LIMIT 0x80000000ULL
275
276#define SYM_MAX_NAME_LEN 256U
277
278#define VTABLE_ENTRY_SIZE_32 4U
279#define VTABLE_ENTRY_SIZE_64 8U
280#define VTABLE_HEADER_LEN 2U
281#define VTABLE_HEADER_SIZE_32 (VTABLE_HEADER_LEN * VTABLE_ENTRY_SIZE_32)
282#define VTABLE_HEADER_SIZE_64 (VTABLE_HEADER_LEN * VTABLE_ENTRY_SIZE_64)
283
284#define KERNEL_ADDRESS_MASK 0xFFFFFFFF00000000ULL
285#define KERNEL_ADDRESS_KEXT 0xFFFFFF7F00000000ULL
286#define KERNEL_ADDRESS_BASE 0xFFFFFF8000000000ULL
287#define KERNEL_FIXUP_OFFSET BASE_1MB
288
289#define VTABLE_ENTRY_X(a, b, c) ((a) ? ((UINT32 *)(b))[(c)] : ((UINT64 *)(b))[(c)])
290#define VTABLE_ENTRY_SIZE_X(a) ((a) ? VTABLE_ENTRY_SIZE_32 : VTABLE_ENTRY_SIZE_64)
291#define VTABLE_HEADER_SIZE_X(a) ((a) ? VTABLE_HEADER_SIZE_32 : VTABLE_HEADER_SIZE_64)
292
293typedef union {
294 struct {
295 UINT32 Major : 14;
296 UINT32 Minor : 7;
297 UINT32 Revision : 7;
298 UINT32 Stage : 4;
299 UINT32 StageLevel : 8;
300 } Bits;
301 UINT64 Value;
303
311
312#define GET_NEXT_OC_VTABLE_PATCH_ENTRY(Entry) \
313 (OC_VTABLE_PATCH_ENTRY *)( \
314 (UINTN)((Entry) + 1) \
315 + ((Entry)->NumSolveSymbols * sizeof (*(Entry)->SolveSymbols)) \
316 )
317
318typedef struct {
319 CONST CHAR8 *Name;
320 union {
321 UINT64 Value;
322 CONST VOID *Data;
323 } Vtable;
325
327 (sizeof (OC_PRELINKED_VTABLE_LOOKUP_ENTRY) <= sizeof (MACH_NLIST_64)),
328 "Prelinked VTable lookup data might not safely fit LinkBuffer"
329 );
330
341//
342// This ASSERT is very dirty, but it is unlikely to trigger nevertheless.
343// One symbol pointer, for which LinkBuffer is guaranteed to be able to fit one
344// NLIST, has either 1 pointer or 2 UINT32s following in the struct.
345// Due to the location logic, the three symbols pointers will not be equal.
346//
348 ((sizeof (MACH_NLIST_64 *) + MAX ((2 * sizeof (UINT32)), sizeof (UINT64 *))) <= sizeof (MACH_NLIST_64)),
349 "VTable Patch data might not safely fit LinkBuffer"
350 );
351
352//
353// VTables
354//
355
356BOOLEAN
358 IN BOOLEAN Is32Bit,
359 IN CONST VOID *VtableData,
360 IN UINT32 MaxSize,
361 OUT UINT32 *NumEntries
362 );
363
364BOOLEAN
366 IN PRELINKED_CONTEXT *Context,
367 IN OUT PRELINKED_KEXT *Kext
368 );
369
370BOOLEAN
372 IN PRELINKED_KEXT *Kext,
373 IN UINT32 MaxSize,
374 OUT UINT32 *NumVtables,
376 );
377
378VOID
380 IN PRELINKED_CONTEXT *Context,
381 IN OUT PRELINKED_KEXT *Kext,
382 IN UINT32 NumVtables,
383 IN CONST OC_PRELINKED_VTABLE_LOOKUP_ENTRY *VtableLookups,
384 OUT PRELINKED_VTABLE *VtableBuffer
385 );
386
387CONST PRELINKED_VTABLE *
389 IN PRELINKED_CONTEXT *Context,
390 IN PRELINKED_KEXT *Kext,
391 IN CONST CHAR8 *Name
392 );
393
394//
395// Prelink
396//
397
402
408
411 IN PRELINKED_CONTEXT *Context,
412 IN PRELINKED_KEXT *Kext,
413 IN CONST CHAR8 *LookupValue,
414 IN OC_GET_SYMBOL_LEVEL SymbolLevel
415 );
416
419 IN PRELINKED_CONTEXT *Context,
420 IN PRELINKED_KEXT *Kext,
421 IN UINT64 LookupValue,
422 IN OC_GET_SYMBOL_LEVEL SymbolLevel
423 );
424
425VOID
427 IN BOOLEAN Is32Bit,
428 IN UINT64 Value,
429 OUT MACH_NLIST_ANY *Symbol
430 );
431
445EFI_STATUS
447 IN OUT PRELINKED_CONTEXT *Context,
448 IN PRELINKED_KEXT *Kext,
449 IN UINT64 LoadAddress,
450 IN UINT64 FileOffset
451 );
452
461EFI_STATUS
463 IN OUT PRELINKED_KEXT *Kext,
464 IN PRELINKED_CONTEXT *Context
465 );
466
475EFI_STATUS
477 IN OUT PRELINKED_KEXT *Kext,
478 IN PRELINKED_CONTEXT *Context
479 );
480
488EFI_STATUS
490 IN OUT PRELINKED_CONTEXT *Context
491 );
492
504UINT64
506 IN BOOLEAN Is32Bit,
507 IN CONST VOID *KxldState,
508 IN UINT32 KxldStateSize,
509 IN CONST CHAR8 *Name
510 );
511
512#endif // PRELINKED_INTERNAL_H
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
EFI_STATUS InternalPrelinkKext(IN OUT PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, IN UINT64 LoadAddress, IN UINT64 FileOffset)
Definition Link.c:1503
VOID InternalFreePrelinkedKext(IN PRELINKED_KEXT *Kext)
CONST PRELINKED_VTABLE * InternalGetOcVtableByName(IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, IN CONST CHAR8 *Name)
Definition Vtables.c:75
EFI_STATUS InternalKxldStateRebuild(IN OUT PRELINKED_CONTEXT *Context)
Definition KxldState.c:459
EFI_STATUS InternalScanPrelinkedKext(IN OUT PRELINKED_KEXT *Kext, IN OUT PRELINKED_CONTEXT *Context, IN BOOLEAN Dependency)
VOID InternalCreateVtablesPrelinked(IN PRELINKED_CONTEXT *Context, IN OUT PRELINKED_KEXT *Kext, IN UINT32 NumVtables, IN CONST OC_PRELINKED_VTABLE_LOOKUP_ENTRY *VtableLookups, OUT PRELINKED_VTABLE *VtableBuffer)
Definition Vtables.c:235
CONST PRELINKED_KEXT_SYMBOL * InternalOcGetSymbolName(IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, IN CONST CHAR8 *LookupValue, IN OC_GET_SYMBOL_LEVEL SymbolLevel)
Definition Link.c:191
UINT64 InternalKxldSolveSymbol(IN BOOLEAN Is32Bit, IN CONST VOID *KxldState, IN UINT32 KxldStateSize, IN CONST CHAR8 *Name)
Definition KxldState.c:579
PRELINKED_KEXT * InternalNewPrelinkedKext(IN OC_MACHO_CONTEXT *Context, IN XML_NODE *KextPlist)
CONST PRELINKED_KEXT_SYMBOL * InternalOcGetSymbolValue(IN PRELINKED_CONTEXT *Context, IN PRELINKED_KEXT *Kext, IN UINT64 LookupValue, IN OC_GET_SYMBOL_LEVEL SymbolLevel)
Definition Link.c:246
KERNEL_QUIRK gKernelQuirks[]
BOOLEAN InternalPatchByVtables(IN PRELINKED_CONTEXT *Context, IN OUT PRELINKED_KEXT *Kext)
Definition Vtables.c:584
PRELINKED_KEXT * InternalCachedPrelinkedKext(IN OUT PRELINKED_CONTEXT *Prelinked, IN CONST CHAR8 *Identifier)
OC_GET_SYMBOL_LEVEL
@ OcGetSymbolFirstLevel
@ OcGetSymbolOnlyCxx
@ OcGetSymbolAnyLevel
EFI_STATUS InternalKxldStateBuildLinkedSymbolTable(IN OUT PRELINKED_KEXT *Kext, IN PRELINKED_CONTEXT *Context)
Definition KxldState.c:192
OC_KEXT_VERSION_STAGE
@ OcKextVersionStageAlpha
@ OcKextVersionStageRelease
@ OcKextVersionStageCandidate
@ OcKextVersionStageBeta
@ OcKextVersionStageDevelopment
EFI_STATUS InternalKxldStateBuildLinkedVtables(IN OUT PRELINKED_KEXT *Kext, IN PRELINKED_CONTEXT *Context)
Definition KxldState.c:292
#define MAX_KEXT_DEPEDENCIES
EFI_STATUS InternalConnectExternalSymtab(IN OUT OC_MACHO_CONTEXT *Context, OUT OC_MACHO_CONTEXT *InnerContext, IN UINT8 *Buffer, IN UINT32 BufferSize, OUT BOOLEAN *KernelCollection OPTIONAL)
PRELINKED_KEXT * InternalCachedPrelinkedKernel(IN OUT PRELINKED_CONTEXT *Prelinked)
EFI_STATUS InternalDropCachedPrelinkedKext(IN OUT PRELINKED_CONTEXT *Prelinked, IN CONST CHAR8 *Identifier)
BOOLEAN InternalGetVtableEntries(IN BOOLEAN Is32Bit, IN CONST VOID *VtableData, IN UINT32 MaxSize, OUT UINT32 *NumEntries)
Definition Vtables.c:151
STATIC_ASSERT((sizeof(OC_PRELINKED_VTABLE_LOOKUP_ENTRY)<=sizeof(MACH_NLIST_64)), "Prelinked VTable lookup data might not safely fit LinkBuffer")
VOID InternalUnlockContextKexts(IN PRELINKED_CONTEXT *Context)
VOID InternalSolveSymbolValue(IN BOOLEAN Is32Bit, IN UINT64 Value, OUT MACH_NLIST_ANY *Symbol)
Definition Link.c:294
OC_GET_SYMBOL_TYPE
@ OcGetSymbolByValue
@ OcGetSymbolByName
PRELINKED_KEXT * InternalLinkPrelinkedKext(IN OUT PRELINKED_CONTEXT *Context, IN OUT OC_MACHO_CONTEXT *Executable, IN XML_NODE *PlistRoot, IN UINT64 LoadAddress, IN UINT64 KmodAddress, IN UINT64 FileOffset)
BOOLEAN InternalPrepareCreateVtablesPrelinked(IN PRELINKED_KEXT *Kext, IN UINT32 MaxSize, OUT UINT32 *NumVtables, OUT OC_PRELINKED_VTABLE_LOOKUP_ENTRY *Vtables)
Definition Vtables.c:179
#define MAX(a, b)
Definition coder.h:59
CONST MACH_NLIST_ANY * MetaVtable
CONST MACH_NLIST_ANY * Smcp
CONST MACH_NLIST_ANY * Vtable
XML_NODE * BundleLibraries
CONST CHAR8 * StringTable
CONST MACH_NLIST_ANY * SymbolTable
LIST_ENTRY InjectedLink
PRELINKED_KEXT * Dependencies[MAX_KEXT_DEPEDENCIES]
PATCHER_CONTEXT Context
CONST CHAR8 * Identifier
CONST CHAR8 * CompatibleVersion
MACH_SEGMENT_COMMAND_ANY * LinkEditSegment
PRELINKED_VTABLE * LinkedVtables
PRELINKED_KEXT_SYMBOL * LinkedSymbolTable
CONST CHAR8 * Name
name of this symbol
UINT64 Value
value of this symbol (or stab offset)
UINT64 Address
The symbol's address.
CONST CHAR8 * Name
The symbol's name.
UINT32 NumEntries
The number of VTable entries.
CONST CHAR8 * Name
The VTable's name.