OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
CpuidPatches.c
Go to the documentation of this file.
1
15#include <Base.h>
16
18#include <Library/BaseMemoryLib.h>
21#include <Library/PrintLib.h>
22#include <Library/OcFileLib.h>
23#include <Library/OcStringLib.h>
24#include <Library/UefiLib.h>
25
26//
27// CPUID EAX=0x2 Cache descriptor values
28//
29STATIC
30CONST struct {
31 UINT8 value;
33 UINT32 size;
35 UINT8 linesize;
38 { 0x06, L1I, SIZE_8KB, 4, 32, 1 },
39 { 0x08, L1I, SIZE_16KB, 4, 32, 1 },
40 { 0x0A, L1D, SIZE_8KB, 2, 32, 1 },
41 { 0x0C, L1D, SIZE_16KB, 4, 32, 1 },
42 { 0x0E, L1D, 24*SIZE_1KB, 6, 64, 1 },
43 { 0x22, L3U, SIZE_512KB, 4, 64, 2 },
44 { 0x23, L3U, SIZE_1MB, 8, 64, 2 },
45 { 0x25, L3U, SIZE_2MB, 8, 64, 2 },
46 { 0x29, L3U, SIZE_4MB, 8, 64, 2 },
47 { 0x2C, L1D, SIZE_32KB, 8, 64, 2 },
48 { 0x30, L1I, SIZE_32KB, 8, 64, 1 },
49 { 0x41, L2U, SIZE_128KB, 4, 32, 1 },
50 { 0x42, L2U, SIZE_256KB, 4, 32, 1 },
51 { 0x43, L2U, SIZE_512KB, 4, 32, 1 },
52 { 0x44, L2U, SIZE_1MB, 4, 32, 1 },
53 { 0x45, L2U, SIZE_2MB, 4, 32, 1 },
54 { 0x46, L3U, SIZE_4MB, 4, 64, 1 },
55 { 0x47, L3U, SIZE_8MB, 8, 64, 1 },
56 { 0x48, L2U, 3*SIZE_1MB, 12, 64, 1 },
57 { 0x49, L2U, SIZE_4MB, 16, 64, 1 }, // for Xeons family Fh model 6h it's L3U instead
58 { 0x4A, L3U, 6*SIZE_1MB, 12, 64, 1 },
59 { 0x4B, L3U, SIZE_8MB, 16, 64, 1 },
60 { 0x4C, L3U, 12*SIZE_1MB, 12, 64, 1 },
61 { 0x4D, L3U, SIZE_16MB, 16, 64, 1 },
62 { 0x4E, L2U, 6*SIZE_1MB, 24, 64, 1 },
63 { 0x60, L1D, SIZE_16KB, 8, 64, 1 },
64 { 0x66, L1D, SIZE_8KB, 4, 64, 1 },
65 { 0x67, L1D, SIZE_16KB, 4, 64, 1 },
66 { 0x68, L1D, SIZE_32KB, 4, 64, 1 },
67 { 0x78, L2U, SIZE_1MB, 4, 64, 1 },
68 { 0x79, L2U, SIZE_128KB, 8, 64, 2 },
69 { 0x7A, L2U, SIZE_256KB, 8, 64, 2 },
70 { 0x7B, L2U, SIZE_512KB, 8, 64, 2 },
71 { 0x7C, L2U, SIZE_1MB, 8, 64, 2 },
72 { 0x7D, L2U, SIZE_2MB, 8, 64, 1 },
73 { 0x7F, L2U, SIZE_512KB, 2, 64, 1 },
74 { 0x80, L2U, SIZE_512KB, 8, 64, 1 },
75 { 0x82, L2U, SIZE_256KB, 8, 32, 1 },
76 { 0x83, L2U, SIZE_512KB, 8, 32, 1 },
77 { 0x84, L2U, SIZE_1MB, 8, 32, 1 },
78 { 0x85, L2U, SIZE_2MB, 8, 32, 1 },
79 { 0x86, L2U, SIZE_512KB, 4, 64, 1 },
80 { 0x87, L2U, SIZE_1MB, 8, 64, 1 },
81 { 0xD0, L3U, SIZE_512KB, 4, 64, 1 },
82 { 0xD1, L3U, SIZE_1MB, 4, 64, 1 },
83 { 0xD2, L3U, SIZE_2MB, 4, 64, 1 },
84 { 0xD6, L3U, SIZE_1MB, 8, 64, 1 },
85 { 0xD7, L3U, SIZE_2MB, 8, 64, 1 },
86 { 0xD8, L3U, SIZE_4MB, 8, 64, 1 },
87 { 0xDC, L3U, (UINT32)(1.5*SIZE_1MB), 12, 64, 1 },
88 { 0xDD, L3U, 3*SIZE_1MB, 12, 64, 1 },
89 { 0xDE, L3U, 6*SIZE_1MB, 12, 64, 1 },
90 { 0xE2, L3U, SIZE_2MB, 16, 64, 1 },
91 { 0xE3, L3U, SIZE_4MB, 16, 64, 1 },
92 { 0xE4, L3U, SIZE_8MB, 16, 64, 1 },
93 { 0xEA, L3U, 12*SIZE_1MB, 24, 64, 1 },
94 { 0xEB, L3U, 18*SIZE_1MB, 24, 64, 1 },
95 { 0xEC, L3U, 24*SIZE_1MB, 24, 64, 1 }
96};
97
98STATIC
99CONST UINT8
101 0xB9, 0x8B, 0x00, 0x00, 0x00, // mov ecx, 8Bh
102 0x31, 0xC0, // xor eax, eax
103 0x31, 0xD2, // xor edx, edx
104 0x0F, 0x30, // wrmsr
105 0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 1
106 0x31, 0xDB, // xor ebx, ebx
107 0x31, 0xC9, // xor ecx, ecx
108 0x31, 0xD2, // xor edx, edx
109 0x0F, 0xA2 // cpuid
110};
111
112STATIC
113CONST UINT8
115 0xB9, 0x8B, 0x00, 0x00, 0x00, // mov ecx, 8Bh
116 0x31, 0xD2, // xor edx, edx
117 0x0F, 0x30, // wrmsr
118 0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 1
119 0x31, 0xDB, // xor ebx, ebx
120 0x31, 0xC9, // xor ecx, ecx
121 0x31, 0xD2, // xor edx, edx
122 0x0F, 0xA2 // cpuid
123};
124
125STATIC
126CONST UINT8
128 0xB9, 0x8B, 0x00, 0x00, 0x00, // mov ecx, 8Bh
129 0x0F, 0x32 // rdmsr
130};
131
146STATIC
147CONST UINT8
149 0xC7, 0x47, 0x68, 0x11, 0x11, 0x11, 0x11, // mov dword ptr [rdi+68h], 11111111h
150 0xC6, 0x47, 0x50, 0x22, // mov byte ptr [rdi+50h], 22h
151 0x48, 0xB8, 0x55, 0x55, 0x55, 0x55, 0x44, 0x33, 0x66, 0x77, // mov rax, 7766334455555555h
152 0x48, 0x89, 0x47, 0x48, // mov [rdi+48h], rax
153 0x48, 0xB8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, // mov rax, 8888888888888888h
154 0x48, 0x89, 0x47, 0x58, // mov [rdi+58h], rax
155 0xC7, 0x87, 0xCC, 0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, // mov dword ptr [rdi+0CCh], 99999999h
156 0xC7, 0x87, 0x88, 0x01, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, // mov dword ptr [rdi+188h], AAAAAAAAh
157 0xB8, 0xAA, 0xAA, 0xAA, 0xAA, // mov eax, AAAAAAAAh
158 0xC3 // retn
159};
160
161#pragma pack(push, 1)
162
163typedef struct {
164 UINT8 Code1[3];
165 UINT32 Signature;
166 UINT8 Code2[3];
167 UINT8 Stepping;
168 UINT8 Code3[2];
169 UINT32 Type;
170 UINT8 Family;
171 UINT8 Model;
172 UINT8 ExtModel;
174 UINT8 Code4[6];
175 UINT64 Features;
176 UINT8 Code5[10];
178 UINT8 Code6[6];
180 UINT8 Code7;
182 UINT8 Code8;
184
187 "Check your CPUID patch layout"
188 );
189
190typedef struct {
191 UINT8 EaxCmd;
192 UINT32 EaxVal;
193 UINT8 EbxCmd;
194 UINT32 EbxVal;
195 UINT8 EcxCmd;
196 UINT32 EcxVal;
197 UINT8 EdxCmd;
198 UINT32 EdxVal;
200
201typedef struct {
202 UINT8 EdxCmd;
203 UINT32 EdxVal;
205
206#pragma pack(pop)
207
208STATIC
209EFI_STATUS
211 IN OUT PATCHER_CONTEXT *Patcher,
212 IN UINT32 KernelVersion,
213 IN OC_CPU_INFO *CpuInfo,
214 IN UINT32 *Data,
215 IN UINT32 *DataMask,
216 IN UINT8 *Start,
217 IN UINT8 *Last
218 )
219{
220 EFI_STATUS Status;
221
222 UINT8 *Record;
223 UINT8 *BlockClearFunc;
224 UINT8 *StartPointer;
225 UINT8 *EndPointer;
226 UINT32 StructAddr;
227 UINT8 *Location;
228 UINT8 *LocationEnd;
229 UINT8 *LocationSnow32;
230 UINT8 *LocationTigerTsc;
231 UINT8 *LocationTigerTscEnd;
232 UINT32 Signature[3];
233 BOOLEAN IsTiger;
234 BOOLEAN IsTigerTscInit;
235 BOOLEAN IsTigerTscInitOld;
236 BOOLEAN IsLeopard;
237 BOOLEAN IsSnow;
238 BOOLEAN IsLion;
239 UINT32 Index;
240 UINT32 MaxExt;
241 INT32 Delta;
243
244 //
245 // XNU 8.7.2 to 8.10.1 require an additional patch to _tsc_init.
246 //
248 IsTigerTscInit = OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION (8, 8, 0), KERNEL_VERSION (8, 10, 1));
249 IsTigerTscInitOld = OcMatchDarwinVersion (KernelVersion, KERNEL_VERSION (8, 7, 2), KERNEL_VERSION (8, 7, 2));
253 StructAddr = 0;
254
255 LocationSnow32 = NULL;
256 LocationTigerTsc = NULL;
257 LocationTigerTscEnd = NULL;
258
259 //
260 // Locate _cpuid_set_info or _cpuid_get_info.
261 // _cpuid_set_info is also patched in 10.4, and is located below _cpuid_get_info.
262 //
263 Status = PatcherGetSymbolAddress (Patcher, IsTiger ? "_cpuid_get_info" : "_cpuid_set_info", (UINT8 **)&Record);
264 if (EFI_ERROR (Status) || (Record >= Last)) {
265 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to locate _cpuid_%a_info (%p) - %r\n", IsTiger ? "get" : "set", Record, Status));
266 return EFI_NOT_FOUND;
267 }
268
269 //
270 // Start of patch area.
271 //
272 // The existing code here will be replaced with a hardcoded vendor string (CPUID (0)).
273 // We'll also hardcode the CPUID (1) data here, jumped to from the next patch location area.
274 //
275 // 10.4 is in _cpuid_get_info.
276 // Others are in _cpuid_set_info.
277 //
278 // 10.4 has the struct in esi.
279 // 10.5 and 32-bit 10.6 have the struct hardcoded. This can be
280 // pulled right below the call to _blkclr, as below.
281 // 64-bit 10.6 has the struct in rdi, a bit before lea rsi... below.
282 // 32-bit 10.7 has the struct hardcoded, and can be pulled right
283 // before the call to _bzero
284 //
285 STATIC CONST UINT8 mKernelCpuidFindPatchTigerStart[4] = {
286 0x8D, 0x45, 0xEC, // lea eax, dword [...]
287 0xC7 // mov from mov dword [...], 4
288 };
289
290 STATIC CONST UINT8 mKernelCpuidFindPatchLeoSnowLionStruct32[2] = {
291 0x00, // 0 from end of mov dword [...], [struct address]
292 0xE8 // call from call _blkclr or _bzero
293 };
294
295 STATIC CONST UINT8 mKernelCpuidFindPatchLeoSnowLionStart32[5] = {
296 0x04, 0x00, 0x00, 0x00, // 4 from mov dword [...], 4
297 0xC7 // mov...
298 };
299
300 STATIC CONST UINT8 mKernelCpuidFindPatchSnowStart64[8] = {
301 0xBA, 0x04, 0x00, 0x00, 0x00, // mov edx, 4
302 0x48, 0x8D, 0x35 // lea rsi, ...
303 };
304
305 if (Patcher->Is32Bit) {
306 if (IsTiger) {
307 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
308 if ( (Record[0] == mKernelCpuidFindPatchTigerStart[0])
309 && (Record[1] == mKernelCpuidFindPatchTigerStart[1])
310 && (Record[2] == mKernelCpuidFindPatchTigerStart[2])
311 && (Record[3] == mKernelCpuidFindPatchTigerStart[3]))
312 {
313 break;
314 }
315 }
316 } else {
317 //
318 // We need to get the address of _blkclr or _bzero first for proper matching.
319 //
320 Status = PatcherGetSymbolAddress (Patcher, IsLion ? "_bzero" : "_blkclr", (UINT8 **)&BlockClearFunc);
321 if (EFI_ERROR (Status) || (Record >= Last)) {
322 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to locate %a (%p) - %r\n", IsLion ? "_bzero" : "_blkclr", Record, Status));
323 return EFI_NOT_FOUND;
324 }
325
326 //
327 // Get struct address first.
328 //
329 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
330 if ( (Record[0] == mKernelCpuidFindPatchLeoSnowLionStruct32[0])
331 && (Record[1] == mKernelCpuidFindPatchLeoSnowLionStruct32[1])
332 && (*((INT32 *)&Record[2]) == (INT32)(BlockClearFunc - (Record + sizeof (mKernelCpuidFindPatchLeoSnowLionStruct32) + sizeof (UINT32)))))
333 {
334 break;
335 }
336 }
337
338 if (Index >= EFI_PAGE_SIZE) {
339 return EFI_NOT_FOUND;
340 }
341
342 StructAddr = *((UINT32 *)(Record - 3));
343
344 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
345 if ( (Record[0] == mKernelCpuidFindPatchLeoSnowLionStart32[0])
346 && (Record[1] == mKernelCpuidFindPatchLeoSnowLionStart32[1])
347 && (Record[2] == mKernelCpuidFindPatchLeoSnowLionStart32[2])
348 && (Record[3] == mKernelCpuidFindPatchLeoSnowLionStart32[3])
349 && (Record[4] == mKernelCpuidFindPatchLeoSnowLionStart32[4]))
350 {
351 break;
352 }
353 }
354 }
355 } else {
356 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
357 if ( (Record[0] == mKernelCpuidFindPatchSnowStart64[0])
358 && (Record[1] == mKernelCpuidFindPatchSnowStart64[1])
359 && (Record[2] == mKernelCpuidFindPatchSnowStart64[2])
360 && (Record[3] == mKernelCpuidFindPatchSnowStart64[3])
361 && (Record[4] == mKernelCpuidFindPatchSnowStart64[4])
362 && (Record[5] == mKernelCpuidFindPatchSnowStart64[5])
363 && (Record[6] == mKernelCpuidFindPatchSnowStart64[6])
364 && (Record[7] == mKernelCpuidFindPatchSnowStart64[7]))
365 {
366 break;
367 }
368 }
369 }
370
371 if (Index >= EFI_PAGE_SIZE) {
372 return EFI_NOT_FOUND;
373 }
374
375 if (Patcher->Is32Bit) {
376 StartPointer = IsTiger ? Record : Record - 4;
377 } else {
378 StartPointer = Record + sizeof (mKernelCpuidFindPatchSnowStart64) + sizeof (UINT32);
379 }
380
381 //
382 // End of patch area.
383 //
384 STATIC CONST UINT8 mKernelCpuidFindPatchTigerEnd[4] = {
385 0x00, // 0 from mov byte [...], 0
386 0x31, 0xDB, // xor ebx, ebx
387 0x8B // mov ...
388 };
389
390 STATIC UINT8 mKernelCpuidFindPatchSnowLionEnd32[7] = {
391 0xC6, 0x05, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 // mov byte [struct_addr], 0
392 };
393 STATIC UINT32 *mKernelCpuidFindPatchSnowLionEndPtr32 = (UINT32 *)&mKernelCpuidFindPatchSnowLionEnd32[2];
394
395 *mKernelCpuidFindPatchSnowLionEndPtr32 = StructAddr + sizeof (Signature[0]) * 3;
396
397 STATIC CONST UINT8 mKernelCpuidFindPatchLeoEnd1[5] = {
398 0xB8, 0x00, 0x00, 0x00, 0x80 // mov eax/edx, 80000000h
399 };
400 STATIC CONST UINT8 mKernelCpuidFindPatchLeoEnd1Mask = 0xFD;
401
402 if (IsTiger) {
403 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
404 if ( (Record[0] == mKernelCpuidFindPatchTigerEnd[0])
405 && (Record[1] == mKernelCpuidFindPatchTigerEnd[1])
406 && (Record[2] == mKernelCpuidFindPatchTigerEnd[2])
407 && (Record[3] == mKernelCpuidFindPatchTigerEnd[3]))
408 {
409 break;
410 }
411 }
412 } else if ((IsSnow || IsLion) && Patcher->Is32Bit) {
413 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
414 if ( (Record[0] == mKernelCpuidFindPatchSnowLionEnd32[0])
415 && (Record[1] == mKernelCpuidFindPatchSnowLionEnd32[1])
416 && (Record[2] == mKernelCpuidFindPatchSnowLionEnd32[2])
417 && (Record[3] == mKernelCpuidFindPatchSnowLionEnd32[3])
418 && (Record[4] == mKernelCpuidFindPatchSnowLionEnd32[4])
419 && (Record[5] == mKernelCpuidFindPatchSnowLionEnd32[5])
420 && (Record[6] == mKernelCpuidFindPatchSnowLionEnd32[6]))
421 {
422 break;
423 }
424 }
425 } else {
426 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
427 if ( ((Record[0] & mKernelCpuidFindPatchLeoEnd1Mask) == mKernelCpuidFindPatchLeoEnd1[0])
428 && (Record[1] == mKernelCpuidFindPatchLeoEnd1[1])
429 && (Record[2] == mKernelCpuidFindPatchLeoEnd1[2])
430 && (Record[3] == mKernelCpuidFindPatchLeoEnd1[3])
431 && (Record[4] == mKernelCpuidFindPatchLeoEnd1[4]))
432 {
433 break;
434 }
435 }
436 }
437
438 if (Index >= EFI_PAGE_SIZE) {
439 return EFI_NOT_FOUND;
440 }
441
442 if (IsSnow && !Patcher->Is32Bit) {
443 STATIC CONST UINT8 mKernelCpuidFindPatchLeoEnd2[3] = {
444 0x0F, 0xA2, // cpuid
445 0x89 // mov ...
446 };
447
448 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
449 if ( (Record[0] == mKernelCpuidFindPatchLeoEnd2[0])
450 && (Record[1] == mKernelCpuidFindPatchLeoEnd2[1])
451 && (Record[2] == mKernelCpuidFindPatchLeoEnd2[2]))
452 {
453 break;
454 }
455 }
456
457 if (Index >= EFI_PAGE_SIZE) {
458 return EFI_NOT_FOUND;
459 }
460 }
461
462 EndPointer = IsTiger ? Record - 3 : Record;
463
464 //
465 // Start of CPUID location.
466 //
467 // We'll replace this with a call to the previous patched section to
468 // populate the CPUID (1) info.
469 //
470 // 32-bit 10.6 has two different mov eax, 0x1 pairs for 32-bit and 64-bit.
471 // The first is patched out with nops, and we'll use the second for the jmp.
472 //
473 // 32-bit 10.7 has a call to a function that is very similar to 32-bit 10.6, and calls
474 // cpuid in 64-bit mode if supported. We can simply replace this call with one to the patched area.
475 //
476 STATIC CONST UINT8 mKernelCpuidFindLocLeoTigerStart[7] = {
477 0xB9, 0x01, 0x00, 0x00, 0x00, // mov ecx, 1
478 0x89, 0xC8 // mov eax, ecx
479 };
480
481 STATIC CONST UINT8 mKernelCpuidFindLocSnowStart[5] = {
482 0xB8, 0x01, 0x00, 0x00, 0x00 // mov eax, 1
483 };
484
485 STATIC CONST UINT8 mKernelCpuidFindLocSnowStart32[6] = {
486 0xE8, 0xFF, 0xFF, 0xFF, 0xFF, // call _cpuid64
487 0xEB // jmp ...
488 };
489
490 STATIC CONST UINT8 mKernelCpuidFindLocLionStart32[8] = {
491 0xB9, 0x01, 0x00, 0x00, 0x00, // mov ecx, 1
492 0x8D, 0x55, 0xD0 // lea edx, dword [...]
493 };
494
495 if (IsTiger || IsLeopard) {
496 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
497 if ( (Record[0] == mKernelCpuidFindLocLeoTigerStart[0])
498 && (Record[1] == mKernelCpuidFindLocLeoTigerStart[1])
499 && (Record[2] == mKernelCpuidFindLocLeoTigerStart[2])
500 && (Record[3] == mKernelCpuidFindLocLeoTigerStart[3])
501 && (Record[4] == mKernelCpuidFindLocLeoTigerStart[4])
502 && (Record[5] == mKernelCpuidFindLocLeoTigerStart[5])
503 && (Record[6] == mKernelCpuidFindLocLeoTigerStart[6]))
504 {
505 break;
506 }
507 }
508 } else if (IsSnow) {
509 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
510 if ( (Record[0] == mKernelCpuidFindLocSnowStart[0])
511 && (Record[1] == mKernelCpuidFindLocSnowStart[1])
512 && (Record[2] == mKernelCpuidFindLocSnowStart[2])
513 && (Record[3] == mKernelCpuidFindLocSnowStart[3])
514 && (Record[4] == mKernelCpuidFindLocSnowStart[4]))
515 {
516 break;
517 }
518 }
519
520 if (Index >= EFI_PAGE_SIZE) {
521 return EFI_NOT_FOUND;
522 }
523
524 //
525 // Find where call _cpuid64 is located.
526 // We'll then look for the second mov eax, 0x1 after that.
527 //
528 if (Patcher->Is32Bit) {
529 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
530 if ( (Record[0] == mKernelCpuidFindLocSnowStart32[0])
531 && (Record[5] == mKernelCpuidFindLocSnowStart32[5]))
532 {
533 break;
534 }
535 }
536
537 if (Index >= EFI_PAGE_SIZE) {
538 return EFI_NOT_FOUND;
539 }
540
541 LocationSnow32 = Record;
542
543 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
544 if ( (Record[0] == mKernelCpuidFindLocSnowStart[0])
545 && (Record[1] == mKernelCpuidFindLocSnowStart[1])
546 && (Record[2] == mKernelCpuidFindLocSnowStart[2])
547 && (Record[3] == mKernelCpuidFindLocSnowStart[3])
548 && (Record[4] == mKernelCpuidFindLocSnowStart[4]))
549 {
550 break;
551 }
552 }
553 }
554 } else {
555 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
556 if ( (Record[0] == mKernelCpuidFindLocLionStart32[0])
557 && (Record[1] == mKernelCpuidFindLocLionStart32[1])
558 && (Record[2] == mKernelCpuidFindLocLionStart32[2])
559 && (Record[3] == mKernelCpuidFindLocLionStart32[3])
560 && (Record[4] == mKernelCpuidFindLocLionStart32[4])
561 && (Record[5] == mKernelCpuidFindLocLionStart32[5])
562 && (Record[6] == mKernelCpuidFindLocLionStart32[6])
563 && (Record[7] == mKernelCpuidFindLocLionStart32[7]))
564 {
565 break;
566 }
567 }
568 }
569
570 if (Index >= EFI_PAGE_SIZE) {
571 return EFI_NOT_FOUND;
572 }
573
574 Location = IsLion ? Record + sizeof (mKernelCpuidFindLocLionStart32) : Record;
575
576 //
577 // End of CPUID location. Not applicable to 10.7.
578 //
579 STATIC CONST UINT8 mKernelCpuidFindLegacyLocEnd[3] = {
580 0x0F, 0xA2, // cpuid
581 0x89 // mov ...
582 };
583
584 if (!IsLion) {
585 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
586 if ( (Record[0] == mKernelCpuidFindLegacyLocEnd[0])
587 && (Record[1] == mKernelCpuidFindLegacyLocEnd[1])
588 && (Record[2] == mKernelCpuidFindLegacyLocEnd[2]))
589 {
590 break;
591 }
592 }
593
594 if (Index >= EFI_PAGE_SIZE) {
595 return EFI_NOT_FOUND;
596 }
597
598 LocationEnd = Record + 2;
599 } else {
600 LocationEnd = Location;
601 }
602
603 //
604 // Locate _tsc_init on 10.4, as there is a CPUID (1) call that needs to be patched.
605 // This only applies to XNU 8.7.2 to XNU 8.10.1. Some recovery versions of
606 // 10.4.10 have a newer XNU 8.10.3 kernel with code changes to _tsc_init.
607 //
608 // It's possible 8.10.2 may require the patch, but there are no sources or kernels
609 // available to verify.
610 //
611 if (IsTigerTscInit || IsTigerTscInitOld) {
612 Status = PatcherGetSymbolAddress (Patcher, "_tsc_init", (UINT8 **)&Record);
613 if (EFI_ERROR (Status) || (Record >= Last)) {
614 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to locate _tsc_init (%p) - %r\n", Record, Status));
615 return EFI_NOT_FOUND;
616 }
617
618 if (IsTigerTscInit) {
619 //
620 // Start of _tsc_init CPUID location on XNU 8.8.0 to XNU 8.10.1
621 //
622 // We'll replace this with a call to the previous patched section to
623 // populate the CPUID (1) info.
624 //
625 STATIC CONST UINT8 mKernelCpuidFindTscLocTigerStart[7] = {
626 0xBA, 0x01, 0x00, 0x00, 0x00, // mov edx, 1
627 0x89, 0xD0 // mov eax, edx
628 };
629
630 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
631 if ( (Record[0] == mKernelCpuidFindTscLocTigerStart[0])
632 && (Record[1] == mKernelCpuidFindTscLocTigerStart[1])
633 && (Record[2] == mKernelCpuidFindTscLocTigerStart[2])
634 && (Record[3] == mKernelCpuidFindTscLocTigerStart[3])
635 && (Record[4] == mKernelCpuidFindTscLocTigerStart[4])
636 && (Record[5] == mKernelCpuidFindTscLocTigerStart[5])
637 && (Record[6] == mKernelCpuidFindTscLocTigerStart[6]))
638 {
639 break;
640 }
641 }
642 } else {
643 //
644 // Start of _tsc_init CPUID location on XNU 8.8.0 to XNU 8.10.1
645 //
646 // We'll replace this with a call to the previous patched section to
647 // populate the CPUID (1) info.
648 //
649 STATIC CONST UINT8 mKernelCpuidFindTscLocTigerOldStart[7] = {
650 0xB8, 0x01, 0x00, 0x00, 0x00, // mov eax, 1
651 0x0F, 0xA2 // cpuid
652 };
653
654 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
655 if ( (Record[0] == mKernelCpuidFindTscLocTigerOldStart[0])
656 && (Record[1] == mKernelCpuidFindTscLocTigerOldStart[1])
657 && (Record[2] == mKernelCpuidFindTscLocTigerOldStart[2])
658 && (Record[3] == mKernelCpuidFindTscLocTigerOldStart[3])
659 && (Record[4] == mKernelCpuidFindTscLocTigerOldStart[4])
660 && (Record[5] == mKernelCpuidFindTscLocTigerOldStart[5])
661 && (Record[6] == mKernelCpuidFindTscLocTigerOldStart[6]))
662 {
663 break;
664 }
665 }
666 }
667
668 if (Index >= EFI_PAGE_SIZE) {
669 return EFI_NOT_FOUND;
670 }
671
672 LocationTigerTsc = Record;
673
674 //
675 // End of _tsc_init CPUID location.
676 //
677 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
678 if ( (Record[0] == mKernelCpuidFindLegacyLocEnd[0])
679 && (Record[1] == mKernelCpuidFindLegacyLocEnd[1])
680 && (Record[2] == mKernelCpuidFindLegacyLocEnd[2]))
681 {
682 break;
683 }
684 }
685
686 if (Index >= EFI_PAGE_SIZE) {
687 return EFI_NOT_FOUND;
688 }
689
690 LocationTigerTscEnd = Record + 2;
691 }
692
693 DEBUG ((
694 DEBUG_INFO,
695 "OCAK: Legacy CPUID patch %p:%p, loc %p:%p, tsc loc %p:%p, struct @ 0x%X\n",
696 StartPointer - Start,
697 EndPointer - Start,
698 Location - Start,
699 LocationEnd - Start,
700 (IsTigerTscInit || IsTigerTscInitOld) ? LocationTigerTsc - Start : 0,
701 (IsTigerTscInit || IsTigerTscInitOld) ? LocationTigerTscEnd - Start : 0,
702 StructAddr
703 ));
704
705 //
706 // Free 2 more bytes in the end by assigning EAX directly.
707 //
708 if (IsSnow && !Patcher->Is32Bit) {
709 AsmCpuid (0x80000000, &MaxExt, NULL, NULL, NULL);
710 EndPointer[0] = 0xB8;
711 CopyMem (&EndPointer[1], &MaxExt, sizeof (MaxExt));
712 }
713
714 //
715 // Short-write CPU signature to create space for CPUID (1) patch.
716 //
717 // 29 bytes.
718 //
719 AsmCpuid (0, NULL, &Signature[0], &Signature[2], &Signature[1]);
720 for (Index = 0; Index < 3; ++Index) {
721 //
722 // mov eax, <signature>
723 //
724 *StartPointer++ = 0xB8;
725 CopyMem (StartPointer, &Signature[Index], sizeof (Signature[0]));
726 StartPointer += sizeof (Signature[0]);
727
728 if (IsLeopard || ((IsSnow || IsLion) && Patcher->Is32Bit)) {
729 //
730 // mov dword [struct_addr], eax
731 //
732 *StartPointer++ = 0xA3;
733 CopyMem (StartPointer, &StructAddr, sizeof (StructAddr));
734 StartPointer += sizeof (StructAddr);
735 StructAddr += sizeof (Signature[0]);
736 } else if (IsTiger) {
737 //
738 // mov [esi+offset], eax
739 //
740 *StartPointer++ = 0x89;
741 *StartPointer++ = 0x46;
742 *StartPointer++ = (UINT8)(Index * sizeof (Signature[0]));
743 } else {
744 //
745 // mov [rsi], eax
746 //
747 *StartPointer++ = 0x89;
748 *StartPointer++ = 0x06;
749
750 if (Index < 2) {
751 //
752 // add rsi, 4
753 //
754 *StartPointer++ = 0x48;
755 *StartPointer++ = 0x83;
756 *StartPointer++ = 0xC6;
757 *StartPointer++ = 0x04;
758 }
759 }
760 }
761
762 //
763 // Ensure that we still have room, which is within 2-byte jmp (127)
764 // and has at least 2-byte jmp and patch + 1-byte ret.
765 //
766 if ( (StartPointer >= EndPointer)
767 || (EndPointer - StartPointer > 128)
768 || ((UINTN)(EndPointer - StartPointer) < sizeof (INTERNAL_CPUID_PATCH) + 3))
769 {
770 return EFI_OUT_OF_RESOURCES;
771 }
772
773 //
774 // Short jmp to EndPointer.
775 //
776 StartPointer[0] = 0xEB;
777 StartPointer[1] = (UINT8)(EndPointer - StartPointer - 2);
778 StartPointer += 2;
779
780 //
781 // Workaround incorrect OSXSAVE handling, see below.
782 //
783 if ( (CpuInfo->CpuidVerEcx.Bits.XSAVE != 0)
784 && (CpuInfo->CpuidVerEcx.Bits.OSXSAVE == 0)
785 && (CpuInfo->CpuidVerEcx.Bits.AVX != 0))
786 {
787 CpuInfo->CpuidVerEcx.Bits.OSXSAVE = 1;
788 }
789
790 //
791 // NOP out call _cpuid64 in 32-bit 10.6.
792 //
793 if (IsSnow && Patcher->Is32Bit) {
794 while (LocationSnow32 < LocationEnd) {
795 *LocationSnow32++ = 0x90;
796 }
797 }
798
799 //
800 // Call from location to patch area.
801 //
802 Delta = (INT32)(StartPointer - (Location + 5));
803 *Location++ = 0xE8;
804 CopyMem (Location, &Delta, sizeof (Delta));
805 Location += sizeof (Delta);
806 while (Location < LocationEnd) {
807 *Location++ = 0x90;
808 }
809
810 //
811 // In 10.4, we need to replace a call to CPUID (1) with a call to
812 // the patch area like above in _tsc_init.
813 //
814 if (IsTigerTscInit || IsTigerTscInitOld) {
815 Delta = (INT32)(StartPointer - (LocationTigerTsc + 5));
816 *LocationTigerTsc++ = 0xE8;
817 CopyMem (LocationTigerTsc, &Delta, sizeof (Delta));
818 LocationTigerTsc += sizeof (Delta);
819 while (LocationTigerTsc < LocationTigerTscEnd) {
820 *LocationTigerTsc++ = 0x90;
821 }
822 }
823
824 //
825 // Write virtualised CPUID.
826 // 20 bytes.
827 // 10.7 requires the registers to be copied to a memory location in EDX, so we'll use ESI instead.
828 //
829 Patch.EaxCmd = 0xB8;
830 Patch.EaxVal = (Data[0] & DataMask[0]) | (CpuInfo->CpuidVerEax.Uint32 & ~DataMask[0]);
831 Patch.EbxCmd = 0xBB;
832 Patch.EbxVal = (Data[1] & DataMask[1]) | (CpuInfo->CpuidVerEbx.Uint32 & ~DataMask[1]);
833 Patch.EcxCmd = 0xB9;
834 Patch.EcxVal = (Data[2] & DataMask[2]) | (CpuInfo->CpuidVerEcx.Uint32 & ~DataMask[2]);
835 Patch.EdxCmd = IsLion ? 0xBE : 0xBA;
836 Patch.EdxVal = (Data[3] & DataMask[3]) | (CpuInfo->CpuidVerEdx.Uint32 & ~DataMask[3]);
837 CopyMem (StartPointer, &Patch, sizeof (Patch));
838 StartPointer += sizeof (Patch);
839
840 //
841 // Under 10.7, we need to copy registers to memory in EDX.
842 //
843 if (IsLion) {
844 //
845 // mov [edx], eax
846 //
847 *StartPointer++ = 0x89;
848 *StartPointer++ = 0x02;
849 //
850 // mov [edx+4], ebx
851 //
852 *StartPointer++ = 0x89;
853 *StartPointer++ = 0x5A;
854 *StartPointer++ = 0x04;
855 //
856 // mov [edx+8], ecx
857 //
858 *StartPointer++ = 0x89;
859 *StartPointer++ = 0x4A;
860 *StartPointer++ = 0x08;
861 //
862 // mov [edx+12], esi
863 //
864 *StartPointer++ = 0x89;
865 *StartPointer++ = 0x72;
866 *StartPointer++ = 0x0C;
867 }
868
869 //
870 // Return to the end of location.
871 //
872 *StartPointer++ = 0xC3;
873
874 DEBUG ((DEBUG_INFO, "OCAK: [OK] Legacy CPUID patch completed @ %p\n", StartPointer - Start));
875 return EFI_SUCCESS;
876}
877
878EFI_STATUS
880 IN OUT PATCHER_CONTEXT *Patcher,
881 IN OC_CPU_INFO *CpuInfo,
882 IN UINT32 *Data,
883 IN UINT32 *DataMask,
884 IN UINT32 KernelVersion
885 )
886{
887 EFI_STATUS Status;
888 UINT8 *CpuidSetInfo;
889 UINT8 *Record;
890 UINT8 *Start;
891 UINT8 *Last;
892 UINT32 Index;
893 UINT32 FoundSize;
894 INTERNAL_CPUID_PATCH *CpuidPatch;
897 CPUID_VERSION_INFO_EAX Eax;
898 CPUID_VERSION_INFO_EBX Ebx;
899 CPUID_VERSION_INFO_ECX Ecx;
900 CPUID_VERSION_INFO_EDX Edx;
901 BOOLEAN FoundReleaseKernel;
902
903 ASSERT (Patcher != NULL);
904
907 "Kernel CPUID patch seems wrong"
908 );
909
910 ASSERT (
915 );
916
917 Start = ((UINT8 *)MachoGetMachHeader (&Patcher->MachContext));
918 Last = Start + MachoGetInnerSize (&Patcher->MachContext) - EFI_PAGE_SIZE * 2 - sizeof (mKernelCpuIdFindRelNew);
919
920 //
921 // Do legacy patching for 32-bit 10.7, and 10.6 and older.
922 //
925 {
926 Status = PatchKernelCpuIdLegacy (Patcher, KernelVersion, CpuInfo, Data, DataMask, Start, Last);
927 if (EFI_ERROR (Status)) {
928 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to patch legacy CPUID - %r\n", Status));
929 }
930
931 return Status;
932 }
933
934 Status = PatcherGetSymbolAddress (Patcher, "_cpuid_set_info", (UINT8 **)&CpuidSetInfo);
935 if (EFI_ERROR (Status) || (CpuidSetInfo >= Last)) {
936 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to locate _cpuid_set_info (%p) - %r\n", CpuidSetInfo, Status));
937 return EFI_NOT_FOUND;
938 }
939
940 Record = CpuidSetInfo;
941 FoundSize = 0;
942
943 for (Index = 0; Index < EFI_PAGE_SIZE; ++Index, ++Record) {
944 if ( (Record[0] == mKernelCpuIdFindRelNew[0])
945 && (Record[1] == mKernelCpuIdFindRelNew[1])
946 && (Record[2] == mKernelCpuIdFindRelNew[2])
947 && (Record[3] == mKernelCpuIdFindRelNew[3]))
948 {
949 if (CompareMem (Record, mKernelCpuIdFindRelNew, sizeof (mKernelCpuIdFindRelNew)) == 0) {
950 FoundSize = sizeof (mKernelCpuIdFindRelNew);
951 break;
952 } else if (CompareMem (Record, mKernelCpuIdFindRelOld, sizeof (mKernelCpuIdFindRelOld)) == 0) {
953 FoundSize = sizeof (mKernelCpuIdFindRelOld);
954 break;
955 }
956 }
957 }
958
959 FoundReleaseKernel = FoundSize > 0;
960
961 //
962 // When patching the release kernel we do not allow reevaluating CPUID information,
963 // which is used to report OSXSAVE availability. This causes issues with some programs,
964 // like Docker using Hypervisor.framework, which rely on sysctl to track CPU feature.
965 //
966 // To workaround this we make sure to always report OSXSAVE bit when it is available
967 // regardless of the reevaluation performed by init_fpu in XNU.
968 //
969 // REF: https://github.com/acidanthera/bugtracker/issues/1035
970 //
971 if ( FoundReleaseKernel
972 && (CpuInfo->CpuidVerEcx.Bits.XSAVE != 0)
973 && (CpuInfo->CpuidVerEcx.Bits.OSXSAVE == 0)
974 && (CpuInfo->CpuidVerEcx.Bits.AVX != 0))
975 {
976 CpuInfo->CpuidVerEcx.Bits.OSXSAVE = 1;
977 }
978
979 Eax.Uint32 = (Data[0] & DataMask[0]) | (CpuInfo->CpuidVerEax.Uint32 & ~DataMask[0]);
980 Ebx.Uint32 = (Data[1] & DataMask[1]) | (CpuInfo->CpuidVerEbx.Uint32 & ~DataMask[1]);
981 Ecx.Uint32 = (Data[2] & DataMask[2]) | (CpuInfo->CpuidVerEcx.Uint32 & ~DataMask[2]);
982 Edx.Uint32 = (Data[3] & DataMask[3]) | (CpuInfo->CpuidVerEdx.Uint32 & ~DataMask[3]);
983
984 if (FoundReleaseKernel) {
985 CpuidPatch = (INTERNAL_CPUID_PATCH *)Record;
986 CpuidPatch->EaxCmd = 0xB8;
987 CpuidPatch->EaxVal = Eax.Uint32;
988 CpuidPatch->EbxCmd = 0xBB;
989 CpuidPatch->EbxVal = Ebx.Uint32;
990 CpuidPatch->EcxCmd = 0xB9;
991 CpuidPatch->EcxVal = Ecx.Uint32;
992 CpuidPatch->EdxCmd = 0xBA;
993 CpuidPatch->EdxVal = Edx.Uint32;
994 SetMem (
995 Record + sizeof (INTERNAL_CPUID_PATCH),
996 FoundSize - sizeof (INTERNAL_CPUID_PATCH),
997 0x90
998 );
999 Record += FoundSize;
1000
1001 for (Index = 0; Index < EFI_PAGE_SIZE - sizeof (mKernelCpuidFindMcRel); ++Index, ++Record) {
1002 if (CompareMem (Record, mKernelCpuidFindMcRel, sizeof (mKernelCpuidFindMcRel)) == 0) {
1003 McPatch = (INTERNAL_MICROCODE_PATCH *)Record;
1004 McPatch->EdxCmd = 0xBA;
1005 McPatch->EdxVal = CpuInfo->MicrocodeRevision;
1006 SetMem (
1007 Record + sizeof (INTERNAL_MICROCODE_PATCH),
1009 0x90
1010 );
1011
1012 DEBUG ((DEBUG_INFO, "OCAK: [OK] Patch success CPUID release\n"));
1013 return EFI_SUCCESS;
1014 }
1015 }
1016 } else {
1017 //
1018 // Handle debug kernel here...
1019 //
1020 Status = PatcherGetSymbolAddress (Patcher, "_cpuid_set_cpufamily", (UINT8 **)&Record);
1021 if (EFI_ERROR (Status) || (Record >= Last)) {
1022 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to locate _cpuid_set_cpufamily (%p) - %r\n", Record, Status));
1023 return EFI_NOT_FOUND;
1024 }
1025
1027 FnPatch = (INTERNAL_CPUID_FN_PATCH *)Record;
1028 FnPatch->Signature = Eax.Uint32;
1029 FnPatch->Stepping = (UINT8)Eax.Bits.SteppingId;
1030 FnPatch->ExtModel = (UINT8)Eax.Bits.ExtendedModelId;
1031 FnPatch->Model = (UINT8)Eax.Bits.Model | (UINT8)(Eax.Bits.ExtendedModelId << 4U);
1032 FnPatch->Family = (UINT8)Eax.Bits.FamilyId;
1033 FnPatch->Type = (UINT8)Eax.Bits.ProcessorType;
1034 FnPatch->ExtFamily = (UINT8)Eax.Bits.ExtendedFamilyId;
1035 FnPatch->Features = LShiftU64 (Ecx.Uint32, 32) | (UINT64)Edx.Uint32;
1036 if (FnPatch->Features & CPUID_FEATURE_HTT) {
1037 FnPatch->LogicalPerPkg = (UINT16)Ebx.Bits.MaximumAddressableIdsForLogicalProcessors;
1038 } else {
1039 FnPatch->LogicalPerPkg = 1;
1040 }
1041
1042 FnPatch->AppleFamily1 = FnPatch->AppleFamily2 = OcCpuModelToAppleFamily (Eax);
1043
1044 DEBUG ((DEBUG_INFO, "OCAK: [OK] Patch success CPUID debug\n"));
1045 return EFI_SUCCESS;
1046 }
1047
1048 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to find either CPUID patch (%u)\n", FoundSize));
1049
1050 return EFI_UNSUPPORTED;
1051}
1052
1053STATIC
1054UINT8
1056 // ret
1057 0xC3
1058};
1059
1060STATIC
1063 .Comment = DEBUG_POINTER ("ProvideCurrentCpuInfoTopologyValidation"),
1064 .Base = "_x86_validate_topology",
1065 .Find = NULL,
1066 .Mask = NULL,
1068 .ReplaceMask = NULL,
1070 .Count = 1,
1071 .Skip = 0,
1072 .Limit = 0
1073};
1074
1075// Offset of value in below patch.
1076#define CURRENT_CPU_INFO_CORE_COUNT_OFFSET 1
1077
1078STATIC
1079UINT8
1081 // mov ecx, 0x10001
1082 0xB9, 0x01, 0x00, 0x01, 0x00
1083};
1084
1085STATIC
1086UINT8
1088 // mov ecx, core/thread count
1089 0xB9, 0x00, 0x00, 0x00, 0x00
1090};
1091
1092STATIC
1095 .Comment = DEBUG_POINTER ("ProvideCurrentCpuInfoZeroMsrThreadCoreCount"),
1096 .Base = "_cpuid_set_info",
1098 .Mask = NULL,
1100 .ReplaceMask = NULL,
1102 .Count = 1,
1103 .Skip = 0,
1104 .Limit = 0
1105};
1106
1107STATIC
1108UINT8 *
1110 IN OUT UINT8 *Location,
1111 IN BOOLEAN Is32Bit,
1112 IN OUT UINT64 *FuncAddr,
1113 IN UINT64 VarSymAddr,
1114 IN UINT64 Value
1115 )
1116{
1117 UINT8 *Start;
1118 INT32 Delta;
1119 UINT32 VarAddr32;
1120 UINT32 ValueLower;
1121 UINT32 ValueUpper;
1122
1123 Start = Location;
1124 DEBUG ((DEBUG_VERBOSE, "OCAK: Current TSC func address: 0x%llX, variable address: 0x%llX\n", *FuncAddr, VarSymAddr));
1125
1126 if (Is32Bit) {
1127 ValueLower = (UINT32)Value;
1128 ValueUpper = (UINT32)(Value >> 32);
1129
1130 //
1131 // 32-bit uses absolute addressing
1132 //
1133 // mov [var], value lower
1134 //
1135 VarAddr32 = (UINT32)(VarSymAddr);
1136 *Location++ = 0xC7;
1137 *Location++ = 0x05;
1138 CopyMem (Location, &VarAddr32, sizeof (VarAddr32));
1139 Location += sizeof (VarAddr32);
1140 CopyMem (Location, &ValueLower, sizeof (ValueLower));
1141 Location += sizeof (ValueLower);
1142
1143 //
1144 // mov [var+4], value upper
1145 //
1146 VarAddr32 += sizeof (UINT32);
1147 *Location++ = 0xC7;
1148 *Location++ = 0x05;
1149 CopyMem (Location, &VarAddr32, sizeof (VarAddr32));
1150 Location += sizeof (VarAddr32);
1151 CopyMem (Location, &ValueUpper, sizeof (ValueUpper));
1152 Location += sizeof (ValueUpper);
1153
1154 *FuncAddr += (Location - Start);
1155 } else {
1156 //
1157 // mov rax, value
1158 //
1159 *Location++ = 0x48;
1160 *Location++ = 0xB8;
1161 CopyMem (Location, &Value, sizeof (Value));
1162 Location += sizeof (Value);
1163 *FuncAddr += sizeof (Value) + 2;
1164
1165 //
1166 // mov [var], rax
1167 //
1168 Delta = (INT32)(VarSymAddr - (*FuncAddr + 7));
1169 DEBUG ((DEBUG_VERBOSE, "OCAK: TSC func delta 0x%X\n", Delta));
1170 *Location++ = 0x48;
1171 *Location++ = 0x89;
1172 *Location++ = 0x05;
1173 CopyMem (Location, &Delta, sizeof (Delta));
1174 Location += sizeof (Delta);
1175 *FuncAddr += sizeof (Delta) + 3;
1176 }
1177
1178 return Location;
1179}
1180
1181// 10.14:
1182// 44 89 E8 mov eax, r13d
1183// C1 E8 1A shr eax, 0x1a
1184// FF C0 inc eax
1185// 89 05 68 60 98 00 mov dword [dword_ffffff8000e4b1c8], eax
1186
1187// 10.15
1188// 44 89 EA mov edx, r13d
1189// C1 EA 1A shr edx, 26
1190// FF C2 inc edx
1191// 89 15 2F 55 A2 00 mov dword [dword_FFFFFF8000E551D8], edx
1192
1193// 11.0.1
1194// 44 89 EA mov edx, r13d
1195// C1 EA 1A shr edx, 0x1a
1196// FF C2 inc edx
1197// 89 15 9F 9C A8 00 mov dword [dword_ffffff8000e4b1d8], edx
1198
1199// 12.0.1
1200// 44 89 EA mov edx, r13d
1201// C1 EA 1A shr edx, 0x1a
1202// 83 C2 01 add edx, 0x1
1203// 89 15 DD F9 AA 00 mov dword [dword_ffffff8000e6e1d8], edx
1204
1205STATIC
1206CONST UINT8
1208 0xB9, 0x35, 0x00, 0x00, 0x00, 0x0F, 0x32
1209};
1210
1211STATIC
1212UINT8
1214 0xB8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xD2
1215};
1216
1217STATIC
1220 .Comment = DEBUG_POINTER ("Set core count to thread count"),
1221 .Base = "_cpuid_set_info",
1223 .Mask = NULL,
1225 .ReplaceMask = NULL,
1227 .Count = 2,
1228 .Skip = 0,
1229 .Limit = 0
1230};
1231
1232STATIC
1233CONST UINT8
1235 // mov eax, r13d
1236 // shr eax, 0x1a <--- start
1237 // inc eax
1238 // mov dword[], eax
1239 0xC1, 0xE8, 0x1A, 0xFF, 0xC0, 0x89
1240};
1241
1242STATIC
1243CONST UINT8
1245 // mov eax, r13d
1246 // mov eax, 0x80 <--- start
1247 // mov dword[], eax
1248 0xB8, 0x80, 0x00, 0x00, 0x00, 0x89
1249};
1250
1251STATIC
1254 .Comment = DEBUG_POINTER ("Set core per package count to 128 V1"),
1255 .Base = NULL,
1257 .Mask = NULL,
1259 .ReplaceMask = NULL,
1261 .Count = 1,
1262 .Skip = 0,
1263 .Limit = 0
1264};
1265
1266STATIC
1267CONST UINT8
1269 // mov edx, r13d
1270 // shr edx, 0x1a <--- start
1271 // inc edx
1272 // mov dword[], edx
1273 0xC1, 0xEA, 0x1A, 0xFF, 0xC2, 0x89
1274};
1275
1276STATIC
1277CONST UINT8
1279 // mov edx, r13d
1280 // mov edx, 0x80 <--- start
1281 // mov dword[], edx
1282 0xBA, 0x80, 0x00, 0x00, 0x00, 0x89
1283};
1284
1285STATIC
1288 .Comment = DEBUG_POINTER ("Set core per package count to 128 V1_5"),
1289 .Base = NULL,
1291 .Mask = NULL,
1293 .ReplaceMask = NULL,
1295 .Count = 1,
1296 .Skip = 0,
1297 .Limit = 0
1298};
1299
1300STATIC
1301CONST UINT8
1303 // mov eax/edx, r13d
1304 // shr eax/edx, 0x1a <--- start
1305 // add eax/edx, 1
1306 // mov dword[], eax/edx
1307 0xC1, 0xE8 /* 0xEA */, 0x1A, 0x83, 0xC0 /* 0xC2 */, 0x01, 0x89
1308};
1309
1310STATIC
1311CONST UINT8
1313 0xFF, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF
1314};
1315
1316STATIC
1317CONST UINT8
1319 // mov eax/edx, r13d
1320 // shr eax/edx, 0x1a <--- start
1321 // nop
1322 // mov al/dl, 128
1323 // mov dword[], eax/edx
1324 0xC1, 0xE8 /* 0xEA */, 0x1A, 0x90, 0xB0 /* 0xB2 */, 0x80, 0x89
1325};
1326
1327STATIC
1330 .Comment = DEBUG_POINTER ("Set core per package count to 128 V2"),
1331 .Base = NULL,
1337 .Count = 1,
1338 .Skip = 0,
1339 .Limit = 0
1340};
1341
1342STATIC
1343EFI_STATUS
1345 IN OUT PATCHER_CONTEXT *Patcher,
1346 IN OC_CPU_INFO *CpuInfo,
1347 IN UINT32 KernelVersion
1348 )
1349{
1350 EFI_STATUS Status;
1351 UINT32 CoreThreadCount;
1352 BOOLEAN IsAmpCpu;
1353
1354 //
1355 // TODO: We can support older, just there is no real need.
1356 // Anyone can test/contribute as needed.
1357 //
1359 DEBUG ((DEBUG_INFO, "OCAK: [OK] Ignoring CPU INFO for AMP below macOS 10.14\n"));
1360 return EFI_SUCCESS;
1361 }
1362
1363 IsAmpCpu = (CpuInfo->ThreadCount % CpuInfo->CoreCount) != 0;
1364
1365 //
1366 // Provide real values for normal CPUs.
1367 // Provide Thread=Thread for AMP (ADL) CPUs.
1368 //
1369 if (IsAmpCpu) {
1370 CoreThreadCount =
1371 (((UINT32)CpuInfo->ThreadCount) << 16U) | ((UINT32)CpuInfo->ThreadCount);
1372 } else {
1373 CoreThreadCount =
1374 (((UINT32)CpuInfo->CoreCount) << 16U) | ((UINT32)CpuInfo->ThreadCount);
1375 }
1376
1377 CopyMem (
1379 &CoreThreadCount,
1380 sizeof (UINT32)
1381 );
1382
1383 Status = PatcherApplyGenericPatch (
1384 Patcher,
1386 );
1387
1388 DEBUG ((DEBUG_INFO, "OCAK: Patching MSR 35h to %08x - %r\n", CoreThreadCount, Status));
1389
1390 if (EFI_ERROR (Status) || !IsAmpCpu) {
1391 return Status;
1392 }
1393
1395 Status = PatcherApplyGenericPatch (
1396 Patcher,
1398 );
1399 } else {
1400 Status = PatcherApplyGenericPatch (
1401 Patcher,
1403 );
1404 }
1405
1406 if (EFI_ERROR (Status)) {
1407 Status = PatcherApplyGenericPatch (
1408 Patcher,
1410 );
1411 }
1412
1413 DEBUG ((DEBUG_INFO, "OCAK: Patching core per package count - %r\n", Status));
1414
1415 return Status;
1416}
1417
1418STATIC
1419CONST UINT8
1421 0xE8, 0x00, 0x00, 0x00, 0x00, // call _ml_cpu_cache_sharing / _ml_cpu_cache_size
1422 0xC7, 0x04, 0x24, 0x02, 0x00, 0x00, 0x00 // mov dword ptr [esp], 0x2/0x3
1423};
1424
1425STATIC
1426CONST UINT8
1428 0xFF, 0x00, 0x00, 0x00, 0x00,
1429 0xFF, 0xFF, 0xFF, 0xFE, 0xFF,0xFF, 0xFF
1430};
1431
1432STATIC
1433UINT8
1435 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, (UINT32 value for func param 1 or 2)
1436 0x31, 0xD2, // xor edx, edx
1437 0x90, // nop
1438 0x90, // nop
1439 0x90, // nop
1440 0x90, // nop
1441 0x90 // nop
1442};
1443
1444STATIC
1447 .Comment = DEBUG_POINTER ("_sysctl_mib_init Leopard patch 1"),
1448 .Base = "_sysctl_mib_init",
1452 .ReplaceMask = NULL,
1454 .Count = 1,
1455 .Skip = 0,
1456 .Limit = 0
1457};
1458
1459STATIC
1460CONST UINT8
1462 0xE8, 0x00, 0x00, 0x00, 0x00, // call _ml_cpu_cache_sharing / _ml_cpu_cache_size
1463 0xC7, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00 // mov dword ptr [esp], 0x0
1464};
1465
1466STATIC
1467CONST UINT8
1469 0xFF, 0x00, 0x00, 0x00, 0x00,
1470 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,0xFF, 0xFF
1471};
1472
1473STATIC
1474UINT8
1476 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, (UINT32 value for func param = 3)
1477 0xC7, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00 // mov dword ptr [esp], 0x0
1478};
1479
1480STATIC
1483 .Comment = DEBUG_POINTER ("_sysctl_mib_init Leopard patch 2"),
1484 .Base = "_sysctl_mib_init",
1488 .ReplaceMask = NULL,
1490 .Count = 1,
1491 .Skip = 0,
1492 .Limit = 0
1493};
1494
1495STATIC
1496CONST UINT8
1498 0xA3, 0x00, 0x00, 0x00, 0x00, // mov dword [...], eax
1499 0x89, 0x15, 0x00, 0x00, 0x00, 0x00, // mov dword [...], edx
1500 0xC7, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, // mov dword ptr [esp], 0x2/0x3
1501 0xE8, 0x00, 0x00, 0x00, 0x00 // call _ml_cpu_cache_sharing / _ml_cpu_cache_size
1502};
1503
1504STATIC
1505CONST UINT8
1507 0xFF, 0x00, 0x00, 0x00, 0x00,
1508 0xFF, 0xFF, 0x00, 0x00, 0x00,0x00,
1509 0xFF, 0xFF, 0xFF, 0x00, 0x00,0x00, 0x00,
1510 0xFF, 0x00, 0x00, 0x00, 0x00
1511};
1512
1513STATIC
1514UINT8
1516 0xA3, 0x00, 0x00, 0x00, 0x00, // mov dword [...], eax
1517 0x89, 0x15, 0x00, 0x00, 0x00, 0x00, // mov dword [...], edx
1518 0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, (UINT32 value for func param 1 or 2)
1519 0x31, 0xD2, // xor edx, edx
1520 0x90, // nop
1521 0x90, // nop
1522 0x90, // nop
1523 0x90, // nop
1524 0x90 // nop
1525};
1526
1527STATIC
1528CONST UINT8
1530 0x00, 0x00, 0x00, 0x00, 0x00,
1531 0x00, 0x00, 0x00, 0x00, 0x00,0x00,
1532 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
1533 0xFF, 0xFF,
1534 0xFF,
1535 0xFF,
1536 0xFF,
1537 0xFF,
1538 0xFF
1539};
1540
1541STATIC
1544 .Comment = DEBUG_POINTER ("_sysctl_mib_init Snow Leopard patch"),
1545 .Base = "_sysctl_mib_init",
1551 .Count = 1,
1552 .Skip = 0,
1553 .Limit = 0
1554};
1555
1556EFI_STATUS
1558 IN OUT PATCHER_CONTEXT *Patcher,
1559 IN OC_CPU_INFO *CpuInfo,
1560 IN UINT32 KernelVersion
1561 )
1562{
1563 EFI_STATUS Status;
1564
1565 INT32 Delta;
1566 UINT32 VarAddr32;
1567 UINT32 ValueLower;
1568 UINT32 ValueUpper;
1569 UINT8 *Record;
1570 UINT8 *Start;
1571 UINT8 *Last;
1572 UINT32 Index;
1573 UINT32 Index2;
1574
1575 UINT8 *TscInitFunc;
1576 UINT8 *TmrCvtFunc;
1577
1578 UINT64 TscInitFuncSymAddr;
1579 UINT64 BusFreqSymAddr;
1580 UINT64 BusFCvtt2nSymAddr;
1581 UINT64 BusFCvtn2tSymAddr;
1582 UINT64 TscFreqSymAddr;
1583 UINT64 TscFCvtt2nSymAddr;
1584 UINT64 TscFCvtn2tSymAddr;
1585 UINT64 TscGranularitySymAddr;
1586 UINT64 Bus2TscSymAddr;
1587
1588 UINT8 *TscLocation;
1589
1590 UINT64 busFreqValue;
1591 UINT64 busFCvtt2nValue;
1592 UINT64 busFCvtn2tValue;
1593 UINT64 tscFreqValue;
1594 UINT64 tscFCvtt2nValue;
1595 UINT64 tscFCvtn2tValue;
1596 UINT64 tscGranularityValue;
1597
1598 BOOLEAN IsLeaf4CacheSupported;
1599
1600 BOOLEAN IsTigerOld;
1601 BOOLEAN IsTigerNew;
1602 BOOLEAN IsLeopard;
1603 BOOLEAN IsSnowLeopard;
1604 BOOLEAN IsTigerCacheUnsupported;
1605 UINT8 *LocationTigerCache;
1606 UINT8 *LocationTigerCacheEnd;
1607
1609 CPUID_CACHE_PARAMS_EAX CpuidCacheParamsEax;
1610 CPUID_CACHE_PARAMS_EBX CpuidCacheParamsEbx;
1611 CPUID_CACHE_INFO_CACHE_TLB CpuidCacheInfo[4];
1612 UINT8 CpuidCacheDescriptors[64];
1613 UINT32 CacheSets;
1614 UINT32 CacheSizes[LCACHE_MAX];
1615 UINT32 CacheSize;
1616 UINT32 CacheLineSizes[LCACHE_MAX];
1617 UINT32 CacheLineSize;
1618 UINT32 CacheSharings[LCACHE_MAX];
1619 BOOLEAN CacheDescriptorFound;
1620 cache_type_t CacheDescriptorType;
1621 UINT32 CacheDescriptorSize;
1622
1623 UINT32 msrCoreThreadCount;
1624
1625 ASSERT (Patcher != NULL);
1626
1627 LocationTigerCache = NULL;
1628 LocationTigerCacheEnd = NULL;
1629
1630 Start = ((UINT8 *)MachoGetMachHeader (&Patcher->MachContext));
1631 Last = Start + MachoGetInnerSize (&Patcher->MachContext) - EFI_PAGE_SIZE * 2;
1632
1633 IsLeaf4CacheSupported = CpuInfo->MaxId >= CPUID_CACHE_PARAMS;
1634
1639
1640 //
1641 // 10.4 does not support pulling CPUID leaf 4 that may contain cache info instead of leaf 2.
1642 // On processors that support leaf 4, use that instead.
1643 //
1644 IsTigerCacheUnsupported = (IsTigerOld || IsTigerNew) && IsLeaf4CacheSupported;
1645
1646 Status = EFI_SUCCESS;
1647 Status |= PatchProvideCurrentCpuInfoMSR35h (Patcher, CpuInfo, KernelVersion);
1648
1649 //
1650 // Pull required symbols.
1651 //
1652 // _tsc_init only exists on XNU 8.7.2 and newer.
1653 //
1654 if (!IsTigerOld) {
1655 Status |= PatcherGetSymbolAddressValue (Patcher, "_tsc_init", (UINT8 **)&TscInitFunc, &TscInitFuncSymAddr);
1656 } else {
1657 Status |= PatcherGetSymbolAddressValue (Patcher, "_power_management_init", (UINT8 **)&TscInitFunc, &TscInitFuncSymAddr);
1658 }
1659
1660 Status |= PatcherGetSymbolAddress (Patcher, "_tmrCvt", (UINT8 **)&TmrCvtFunc);
1661
1662 //
1663 // _busFreq only exists on older versions of 10.4 (XNU 8.7.1 or older), or 10.5 and higher.
1664 //
1665 if (!IsTigerNew) {
1666 Status |= PatcherGetSymbolValue (Patcher, "_busFreq", &BusFreqSymAddr);
1667 }
1668
1669 Status |= PatcherGetSymbolValue (Patcher, "_busFCvtt2n", &BusFCvtt2nSymAddr);
1670 Status |= PatcherGetSymbolValue (Patcher, "_busFCvtn2t", &BusFCvtn2tSymAddr);
1671 Status |= PatcherGetSymbolValue (Patcher, "_tscFreq", &TscFreqSymAddr);
1672 Status |= PatcherGetSymbolValue (Patcher, "_tscFCvtt2n", &TscFCvtt2nSymAddr);
1673 Status |= PatcherGetSymbolValue (Patcher, "_tscFCvtn2t", &TscFCvtn2tSymAddr);
1674 Status |= PatcherGetSymbolValue (Patcher, "_tscGranularity", &TscGranularitySymAddr);
1675 Status |= PatcherGetSymbolValue (Patcher, "_bus2tsc", &Bus2TscSymAddr);
1676
1677 if (EFI_ERROR (Status)) {
1678 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to locate one or more TSC symbols - %r\n", Status));
1679 return EFI_NOT_FOUND;
1680 }
1681
1682 //
1683 // Perform TSC and FSB calculations. This is traditionally done in tsc.c in XNU.
1684 //
1685 // For AMD Processors
1686 if ((CpuInfo->Family == 0xF) && ((CpuInfo->ExtFamily == 0x8) || (CpuInfo->ExtFamily == 0xA) || (CpuInfo->ExtFamily == 0xB))) {
1687 DEBUG ((DEBUG_INFO, "OCAK: Setting FSB and TSC for Family 0x%x and ExtFamily 0x%x\n", (UINT16)CpuInfo->Family, (UINT16)CpuInfo->ExtFamily));
1688 busFreqValue = CpuInfo->FSBFrequency;
1689
1690 // Handle case where FSBFrequency is zero, providing a fallback
1691 if (busFreqValue == 0) {
1692 busFreqValue = 100000000; // Assume 100 MHz FSB as fallback
1693 DEBUG ((DEBUG_WARN, "OCAK: FSBFrequency is zero, using fallback value: 100 MHz\n"));
1694 }
1695
1696 busFCvtt2nValue = DivU64x64Remainder ((1000000000ULL << 32), busFreqValue, NULL);
1697 busFCvtn2tValue = DivU64x64Remainder ((1000000000ULL << 32), busFCvtt2nValue, NULL);
1698
1699 tscFreqValue = CpuInfo->CPUFrequency;
1700 tscFCvtt2nValue = DivU64x64Remainder ((1000000000ULL << 32), tscFreqValue, NULL);
1701 tscFCvtn2tValue = DivU64x64Remainder ((1000000000ULL << 32), tscFCvtt2nValue, NULL);
1702 }
1703 // For all other processors
1704 else {
1705 busFreqValue = CpuInfo->FSBFrequency;
1706 busFCvtt2nValue = DivU64x64Remainder ((1000000000ULL << 32), busFreqValue, NULL);
1707 busFCvtn2tValue = DivU64x64Remainder (0xFFFFFFFFFFFFFFFFULL, busFCvtt2nValue, NULL);
1708
1709 tscFreqValue = CpuInfo->CPUFrequency;
1710 tscFCvtt2nValue = DivU64x64Remainder ((1000000000ULL << 32), tscFreqValue, NULL);
1711 tscFCvtn2tValue = DivU64x64Remainder (0xFFFFFFFFFFFFFFFFULL, tscFCvtt2nValue, NULL);
1712 }
1713
1714 tscGranularityValue = DivU64x64Remainder (tscFreqValue, busFreqValue, NULL);
1715
1716 DEBUG ((DEBUG_INFO, "OCAK: BusFreq = %LuHz, BusFCvtt2n = %Lu, BusFCvtn2t = %Lu\n", busFreqValue, busFCvtt2nValue, busFCvtn2tValue));
1717 DEBUG ((DEBUG_INFO, "OCAK: TscFreq = %LuHz, TscFCvtt2n = %Lu, TscFCvtn2t = %Lu\n", tscFreqValue, tscFCvtt2nValue, tscFCvtn2tValue));
1718
1719 //
1720 // Patch _tsc_init with above values.
1721 //
1722 TscLocation = TscInitFunc;
1723
1724 if (!IsTigerNew) {
1725 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, BusFreqSymAddr, busFreqValue);
1726 }
1727
1728 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, BusFCvtt2nSymAddr, busFCvtt2nValue);
1729 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, BusFCvtn2tSymAddr, busFCvtn2tValue);
1730 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, TscFreqSymAddr, tscFreqValue);
1731 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, TscFCvtt2nSymAddr, tscFCvtt2nValue);
1732 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, TscFCvtn2tSymAddr, tscFCvtn2tValue);
1733 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, TscGranularitySymAddr, tscGranularityValue);
1734
1735 if (Patcher->Is32Bit) {
1736 //
1737 // push ebp
1738 // move ebp, esp
1739 //
1740 *TscLocation++ = 0x55;
1741 *TscLocation++ = 0x89;
1742 *TscLocation++ = 0xE5;
1743
1744 ValueLower = (UINT32)busFreqValue;
1745 ValueUpper = (UINT32)(busFreqValue >> 32);
1746
1747 //
1748 // mov eax, FSB freq (lower)
1749 //
1750 *TscLocation++ = 0xB8;
1751 CopyMem (TscLocation, &ValueLower, sizeof (ValueLower));
1752 TscLocation += sizeof (ValueLower);
1753
1754 //
1755 // push eax
1756 //
1757 *TscLocation++ = 0x50;
1758
1759 //
1760 // mov eax, FSB freq (higher)
1761 //
1762 *TscLocation++ = 0xB8;
1763 CopyMem (TscLocation, &ValueUpper, sizeof (ValueUpper));
1764 TscLocation += sizeof (ValueUpper);
1765
1766 //
1767 // push eax
1768 //
1769 *TscLocation++ = 0x50;
1770
1771 ValueLower = (UINT32)tscFreqValue;
1772 ValueUpper = (UINT32)(tscFreqValue >> 32);
1773
1774 //
1775 // mov eax, TSC freq (lower)
1776 //
1777 *TscLocation++ = 0xB8;
1778 CopyMem (TscLocation, &ValueLower, sizeof (ValueLower));
1779 TscLocation += sizeof (ValueLower);
1780
1781 //
1782 // push eax
1783 //
1784 *TscLocation++ = 0x50;
1785
1786 //
1787 // mov eax, TSC freq (higher)
1788 //
1789 *TscLocation++ = 0xB8;
1790 CopyMem (TscLocation, &ValueUpper, sizeof (ValueUpper));
1791 TscLocation += sizeof (ValueUpper);
1792
1793 //
1794 // push eax
1795 //
1796 *TscLocation++ = 0x50;
1797
1798 //
1799 // call _tmrCvt(busFCvtt2n, tscFCvtn2t)
1800 //
1801 Delta = (INT32)(TmrCvtFunc - (TscLocation + 5));
1802 *TscLocation++ = 0xE8;
1803 CopyMem (TscLocation, &Delta, sizeof (Delta));
1804 TscLocation += sizeof (Delta);
1805
1806 //
1807 // mov [_bus2tsc], eax
1808 //
1809 VarAddr32 = (UINT32)(Bus2TscSymAddr);
1810 *TscLocation++ = 0xA3;
1811 CopyMem (TscLocation, &VarAddr32, sizeof (VarAddr32));
1812 TscLocation += sizeof (VarAddr32);
1813
1814 //
1815 // mov [_bus2tsc+4], edx
1816 //
1817 VarAddr32 += sizeof (UINT32);
1818 *TscLocation++ = 0x89;
1819 *TscLocation++ = 0x15;
1820 CopyMem (TscLocation, &VarAddr32, sizeof (VarAddr32));
1821 TscLocation += sizeof (VarAddr32);
1822
1823 //
1824 // pop eax (x4)
1825 // leave
1826 //
1827 *TscLocation++ = 0x58;
1828 *TscLocation++ = 0x58;
1829 *TscLocation++ = 0x58;
1830 *TscLocation++ = 0x58;
1831 *TscLocation++ = 0xC9;
1832 } else {
1833 //
1834 // mov rdi, FSB freq
1835 //
1836 *TscLocation++ = 0x48;
1837 *TscLocation++ = 0xBF;
1838 CopyMem (TscLocation, &busFreqValue, sizeof (busFreqValue));
1839 TscLocation += sizeof (busFreqValue);
1840 TscInitFuncSymAddr += sizeof (busFreqValue) + 2;
1841
1842 //
1843 // mov rsi, TSC freq
1844 //
1845 *TscLocation++ = 0x48;
1846 *TscLocation++ = 0xBE;
1847 CopyMem (TscLocation, &tscFreqValue, sizeof (tscFreqValue));
1848 TscLocation += sizeof (tscFreqValue);
1849 TscInitFuncSymAddr += sizeof (tscFreqValue) + 2;
1850
1851 //
1852 // call _tmrCvt(busFCvtt2n, tscFCvtn2t)
1853 //
1854 Delta = (INT32)(TmrCvtFunc - (TscLocation + 5));
1855 *TscLocation++ = 0xE8;
1856 CopyMem (TscLocation, &Delta, sizeof (Delta));
1857 TscLocation += sizeof (Delta);
1858 TscInitFuncSymAddr += sizeof (Delta) + 1;
1859
1860 //
1861 // mov [_bus2tsc], rax
1862 //
1863 Delta = (INT32)(Bus2TscSymAddr - (TscInitFuncSymAddr + 7));
1864
1865 *TscLocation++ = 0x48;
1866 *TscLocation++ = 0x89;
1867 *TscLocation++ = 0x05;
1868 CopyMem (TscLocation, &Delta, sizeof (Delta));
1869 TscLocation += sizeof (Delta);
1870 }
1871
1872 //
1873 // ret
1874 //
1875 *TscLocation++ = 0xC3;
1876
1877 //
1878 // Find patch region for injecting CPU cache information
1879 // into set_intel_cache_info.
1880 //
1881 if (IsTigerCacheUnsupported) {
1882 Status = PatcherGetSymbolAddress (Patcher, "_cpuid_info", (UINT8 **)&Record);
1883 if (EFI_ERROR (Status) || (Record >= Last)) {
1884 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to locate _cpuid_info (%p) - %r\n", Record, Status));
1885 return EFI_NOT_FOUND;
1886 }
1887
1888 //
1889 // Start of patch area.
1890 // We'll use this area to populate info_p.
1891 //
1892 STATIC CONST UINT8 mKernelCpuidFindCacheLocTigerStart[9] = {
1893 0x8B, 0x45, 0x08, // mov eax, dword [ebp+0x8] (*info_p argument)
1894 0x8B, 0x50, 0x74, // mov edx, dword [eax+0x74]
1895 0x85, 0xD2, // test edx, edx
1896 0x75 // jne ...
1897 };
1898
1899 //
1900 // End of patch area.
1901 //
1902 STATIC CONST UINT8 mKernelCpuidFindCacheLocTigerEnd[5] = {
1903 0x31, 0xC0, // xor eax, eax
1904 0x0F, 0xA2, // cpuid
1905 0x89 // mov ...
1906 };
1907
1908 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
1909 if ( (Record[0] == mKernelCpuidFindCacheLocTigerStart[0])
1910 && (Record[1] == mKernelCpuidFindCacheLocTigerStart[1])
1911 && (Record[2] == mKernelCpuidFindCacheLocTigerStart[2])
1912 && (Record[3] == mKernelCpuidFindCacheLocTigerStart[3])
1913 && (Record[4] == mKernelCpuidFindCacheLocTigerStart[4])
1914 && (Record[5] == mKernelCpuidFindCacheLocTigerStart[5])
1915 && (Record[6] == mKernelCpuidFindCacheLocTigerStart[6])
1916 && (Record[7] == mKernelCpuidFindCacheLocTigerStart[7])
1917 && (Record[8] == mKernelCpuidFindCacheLocTigerStart[8]))
1918 {
1919 break;
1920 }
1921 }
1922
1923 if (Index >= EFI_PAGE_SIZE) {
1924 return EFI_NOT_FOUND;
1925 }
1926
1927 LocationTigerCache = Record + 3;
1928
1929 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
1930 if ( (Record[0] == mKernelCpuidFindCacheLocTigerEnd[0])
1931 && (Record[1] == mKernelCpuidFindCacheLocTigerEnd[1])
1932 && (Record[2] == mKernelCpuidFindCacheLocTigerEnd[2])
1933 && (Record[3] == mKernelCpuidFindCacheLocTigerEnd[3])
1934 && (Record[4] == mKernelCpuidFindCacheLocTigerEnd[4]))
1935 {
1936 break;
1937 }
1938 }
1939
1940 if (Index >= EFI_PAGE_SIZE) {
1941 return EFI_NOT_FOUND;
1942 }
1943
1944 LocationTigerCacheEnd = Record;
1945
1946 DEBUG ((
1947 DEBUG_INFO,
1948 "OCAK: CPU info cache loc %p:%p\n",
1949 LocationTigerCache - Start,
1950 LocationTigerCacheEnd - Start
1951 ));
1952
1953 ZeroMem (CacheLineSizes, sizeof (CacheLineSizes));
1954
1955 //
1956 // Build CPU info struct
1957 //
1958 Index = 0;
1959 do {
1960 AsmCpuidEx (CPUID_CACHE_PARAMS, Index, &CpuidCacheParamsEax.Uint32, &CpuidCacheParamsEbx.Uint32, &CacheSets, NULL);
1961 if (CpuidCacheParamsEax.Bits.CacheType == 0) {
1962 break;
1963 }
1964
1965 switch (CpuidCacheParamsEax.Bits.CacheLevel) {
1966 case 1:
1967 CacheType = (CpuidCacheParamsEax.Bits.CacheType == 1) ? L1D :
1968 (CpuidCacheParamsEax.Bits.CacheType == 2) ? L1I :
1969 Lnone;
1970 break;
1971
1972 case 2:
1973 CacheType = (CpuidCacheParamsEax.Bits.CacheType == 3) ? L2U :
1974 Lnone;
1975 break;
1976
1977 case 3:
1978 CacheType = (CpuidCacheParamsEax.Bits.CacheType == 3) ? L3U :
1979 Lnone;
1980 break;
1981
1982 default:
1983 CacheType = Lnone;
1984 }
1985
1986 if (CacheType != Lnone) {
1987 CacheSizes[CacheType] = (CpuidCacheParamsEbx.Bits.LineSize + 1) * (CacheSets + 1) * (CpuidCacheParamsEbx.Bits.Ways + 1);
1988 CacheLineSizes[CacheType] = CpuidCacheParamsEbx.Bits.LineSize + 1;
1989 }
1990
1991 Index++;
1992 } while (TRUE);
1993
1994 if (CacheLineSizes[L2U]) {
1995 CacheLineSize = CacheLineSizes[L2U];
1996 } else if (CacheLineSizes[L1D]) {
1997 CacheLineSize = CacheLineSizes[L1D];
1998 } else {
1999 //
2000 // XNU would panic here.
2001 //
2002 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Unable to determine CPU cache line size\n"));
2003 return EFI_UNSUPPORTED;
2004 }
2005
2006 //
2007 // Populate cache sizes.
2008 // EAX = address of *info_p struct in stack; 0x68 = offset of cache size array in *info_p struct.
2009 //
2010 for (Index = L1I; Index < LCACHE_MAX; Index++) {
2011 *LocationTigerCache++ = 0xC7;
2012 *LocationTigerCache++ = 0x40;
2013 *LocationTigerCache++ = 0x68 + ((UINT8)(sizeof (UINT32) * Index));
2014 CopyMem (LocationTigerCache, &CacheSizes[Index], sizeof (CacheSizes[Index]));
2015 LocationTigerCache += sizeof (CacheSizes[Index]);
2016 DEBUG ((DEBUG_INFO, "OCAK: Cache size (L%u): %u bytes\n", (Index >= 3) ? (Index - 1) : 1, CacheSizes[Index]));
2017 }
2018
2019 //
2020 // Populate cache line size.
2021 // 0x7C = offset of cache line size in *info_p struct.
2022 //
2023 *LocationTigerCache++ = 0xC7;
2024 *LocationTigerCache++ = 0x40;
2025 *LocationTigerCache++ = 0x7C;
2026 CopyMem (LocationTigerCache, &CacheLineSize, sizeof (CacheLineSize));
2027 LocationTigerCache += sizeof (CacheLineSize);
2028 DEBUG ((DEBUG_INFO, "OCAK: Cache line size: %u bytes\n", CacheLineSize));
2029
2030 while (LocationTigerCache < LocationTigerCacheEnd) {
2031 *LocationTigerCache++ = 0x90;
2032 }
2033 }
2034
2035 //
2036 // Patch sysctl reporting if leaf 0x4 is unsupported on 10.5 and 10.6.
2037 // This applies only to processors that are older than Prescott, and only on IA32.
2038 //
2039 if (Patcher->Is32Bit && !IsLeaf4CacheSupported && (IsLeopard || IsSnowLeopard)) {
2040 ZeroMem (CpuidCacheDescriptors, sizeof (CpuidCacheDescriptors));
2041 ZeroMem (CacheSizes, sizeof (CacheSizes));
2042 ZeroMem (CacheSharings, sizeof (CacheSharings));
2043 AsmCpuid (CPUID_CACHE_INFO, &CpuidCacheInfo[0].Uint32, &CpuidCacheInfo[1].Uint32, &CpuidCacheInfo[2].Uint32, &CpuidCacheInfo[3].Uint32);
2044
2045 for (Index = 0; Index < 4; Index++) {
2046 if (CpuidCacheInfo[Index].Bits.NotValid) {
2047 continue;
2048 }
2049
2050 ((UINT32 *)CpuidCacheDescriptors)[Index] = CpuidCacheInfo[Index].Uint32;
2051 }
2052
2053 for (Index = 1; Index < CpuidCacheDescriptors[0]; Index++) {
2054 if ((Index * 16) > sizeof (CpuidCacheDescriptors)) {
2055 break;
2056 }
2057
2058 AsmCpuid (CPUID_CACHE_INFO, &CpuidCacheInfo[0].Uint32, &CpuidCacheInfo[1].Uint32, &CpuidCacheInfo[2].Uint32, &CpuidCacheInfo[3].Uint32);
2059
2060 for (Index2 = 0; Index2 < 4; Index2++) {
2061 if (CpuidCacheInfo[Index2].Bits.NotValid) {
2062 continue;
2063 }
2064
2065 ((UINT32 *)CpuidCacheDescriptors)[sizeof (UINT32) * Index * Index2] = CpuidCacheInfo[Index2].Uint32;
2066 }
2067 }
2068
2069 //
2070 // Get cache sizes.
2071 //
2072 for (Index = 0; Index < sizeof (CpuidCacheDescriptors); Index++) {
2073 CacheDescriptorFound = FALSE;
2074 for (Index2 = 0; Index2 < (sizeof (mCpuCacheDescriptorValues) / sizeof (mCpuCacheDescriptorValues[0])); Index2++) {
2075 if (mCpuCacheDescriptorValues[Index2].value == CpuidCacheDescriptors[Index]) {
2076 CacheDescriptorType = mCpuCacheDescriptorValues[Index2].type;
2077 CacheDescriptorSize = mCpuCacheDescriptorValues[Index2].size;
2078 CacheDescriptorFound = TRUE;
2079 break;
2080 }
2081 }
2082
2083 if (!CacheDescriptorFound) {
2084 continue;
2085 }
2086
2087 CacheSizes[CacheDescriptorType] = CacheDescriptorSize;
2088 CacheSharings[CacheDescriptorType] = 1;
2089 }
2090
2091 DEBUG ((DEBUG_INFO, "OCAK: Caches L1I: %u, L1D: %u, L2: %u, L3: %u\n", CacheSizes[L1I], CacheSizes[L1D], CacheSizes[L2U], CacheSizes[L3U]));
2092
2093 if (IsLeopard) {
2094 //
2095 // Patch _ml_cpu_cache_sharing (0x1)
2096 //
2097 CacheSize = MAX (CacheSharings[L1I], CacheSharings[L1D]);
2098 CopyMem (
2100 &CacheSize,
2101 sizeof (UINT32)
2102 );
2103 Status |= PatcherApplyGenericPatch (
2104 Patcher,
2106 );
2107
2108 //
2109 // Patch _ml_cpu_cache_sharing (0x2)
2110 //
2111 CopyMem (
2113 &CacheSharings[L2U],
2114 sizeof (UINT32)
2115 );
2116 Status |= PatcherApplyGenericPatch (
2117 Patcher,
2119 );
2120
2121 //
2122 // Patch _ml_cpu_cache_sharing (0x3)
2123 //
2124 CopyMem (
2126 &CacheSharings[L3U],
2127 sizeof (UINT32)
2128 );
2129 Status |= PatcherApplyGenericPatch (
2130 Patcher,
2132 );
2133
2134 //
2135 // Patch _ml_cpu_cache_size (0x1) - L1
2136 //
2137 CacheSize = MAX (CacheSizes[L1I], CacheSizes[L1D]);
2138 CopyMem (
2140 &CacheSize,
2141 sizeof (UINT32)
2142 );
2143 Status |= PatcherApplyGenericPatch (
2144 Patcher,
2146 );
2147
2148 //
2149 // Patch _ml_cpu_cache_size (0x2) - L2
2150 //
2151 CopyMem (
2153 &CacheSizes[L2U],
2154 sizeof (UINT32)
2155 );
2156 Status |= PatcherApplyGenericPatch (
2157 Patcher,
2159 );
2160
2161 //
2162 // Patch _ml_cpu_cache_size (0x3) - L3
2163 //
2164 CopyMem (
2166 &CacheSizes[L3U],
2167 sizeof (UINT32)
2168 );
2169 Status |= PatcherApplyGenericPatch (
2170 Patcher,
2172 );
2173 } else {
2174 //
2175 // Patch _ml_cpu_cache_sharing (0x1)
2176 //
2177 CacheSize = MAX (CacheSharings[L1I], CacheSharings[L1D]);
2178 CopyMem (
2180 &CacheSize,
2181 sizeof (UINT32)
2182 );
2183 Status |= PatcherApplyGenericPatch (
2184 Patcher,
2186 );
2187
2188 //
2189 // Patch _ml_cpu_cache_sharing (0x2)
2190 //
2191 CopyMem (
2193 &CacheSharings[L2U],
2194 sizeof (UINT32)
2195 );
2196 Status |= PatcherApplyGenericPatch (
2197 Patcher,
2199 );
2200
2201 //
2202 // Patch _ml_cpu_cache_sharing (0x3)
2203 //
2204 CopyMem (
2206 &CacheSharings[L3U],
2207 sizeof (UINT32)
2208 );
2209 Status |= PatcherApplyGenericPatch (
2210 Patcher,
2212 );
2213
2214 //
2215 // Patch _ml_cpu_cache_size (0x1) - L1
2216 //
2217 CacheSize = MAX (CacheSizes[L1I], CacheSizes[L1D]);
2218 CopyMem (
2220 &CacheSize,
2221 sizeof (UINT32)
2222 );
2223 Status |= PatcherApplyGenericPatch (
2224 Patcher,
2226 );
2227
2228 //
2229 // Patch _ml_cpu_cache_size (0x2) - L2
2230 //
2231 CopyMem (
2233 &CacheSizes[L2U],
2234 sizeof (UINT32)
2235 );
2236 Status |= PatcherApplyGenericPatch (
2237 Patcher,
2239 );
2240
2241 //
2242 // Patch _ml_cpu_cache_size (0x3) - L3
2243 //
2244 CopyMem (
2246 &CacheSizes[L3U],
2247 sizeof (UINT32)
2248 );
2249 Status |= PatcherApplyGenericPatch (
2250 Patcher,
2252 );
2253 }
2254
2255 if (EFI_ERROR (Status)) {
2256 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to patch or more areas in _sysctl_mib_init - %r\n", Status));
2257 return EFI_NOT_FOUND;
2258 }
2259 }
2260
2261 //
2262 // Patch MSR 0x35 fallback value on 10.13 and above.
2263 //
2264 // This value is used if the MSR 0x35 is read as zero, typically on VMs or AMD processors.
2265 //
2267 //
2268 // 10.15 and above have two instances that need patching.
2269 //
2272 }
2273
2274 msrCoreThreadCount = (CpuInfo->CoreCount << 16) | CpuInfo->ThreadCount;
2275
2276 CopyMem (
2278 &msrCoreThreadCount,
2279 sizeof (msrCoreThreadCount)
2280 );
2281
2282 Status = PatcherApplyGenericPatch (
2283 Patcher,
2285 );
2286 if (EFI_ERROR (Status)) {
2287 DEBUG ((DEBUG_INFO, "OCAK: [FAIL] Failed to find CPU MSR 0x35 default value patch - %r\n", Status));
2288 }
2289 } else {
2290 DEBUG ((DEBUG_INFO, "OCAK: [OK] Skipping CPU MSR 0x35 default value patch on %u\n", KernelVersion));
2291 }
2292
2293 //
2294 // Disable _x86_validate_topology on 10.13 and above.
2295 //
2297 Status = PatcherApplyGenericPatch (
2298 Patcher,
2300 );
2301 if (EFI_ERROR (Status)) {
2302 DEBUG ((DEBUG_INFO, "OCAK: [FAIL] Failed to find CPU topology validation patch - %r\n", Status));
2303 }
2304 } else {
2305 DEBUG ((DEBUG_INFO, "OCAK: [OK] Skipping CPU topology validation patch on %u\n", KernelVersion));
2306 }
2307
2308 return EFI_SUCCESS;
2309}
cache_type_t
@ Lnone
@ LCACHE_MAX
UINT64 Start
UINT8 Signature[8]
Definition BiosId.h:67
#define CPUID_FEATURE_HTT
Hyper-Threading Technology.
Definition CpuId.h:51
STATIC PATCHER_GENERIC_PATCH mProvideCurrentCpuInfoLeopardSysctlMibInitPatch2
STATIC CONST UINT8 mKernelCpuIdFindRelOld[]
STATIC CONST UINT8 mProvideCurrentCpuInfoTopologyCoreCountFind[]
STATIC PATCHER_GENERIC_PATCH mProvideCurrentCpuInfoZeroMsrThreadCoreCountPatch
cache_type_t type
STATIC CONST UINT8 mKernelCpuidReplaceDbg[]
STATIC PATCHER_GENERIC_PATCH mProvideCurrentCpuInfoTopologyValidationPatch
STATIC CONST UINT8 mProvideCurrentCpuInfoTopologyCorePerPackageV2Replace[]
UINT8 value
STATIC_ASSERT(sizeof(INTERNAL_CPUID_FN_PATCH)==sizeof(mKernelCpuidReplaceDbg), "Check your CPUID patch layout")
STATIC PATCHER_GENERIC_PATCH mProvideCurrentCpuInfoTopologyCoreCountPatch
#define CURRENT_CPU_INFO_CORE_COUNT_OFFSET
STATIC EFI_STATUS PatchProvideCurrentCpuInfoMSR35h(IN OUT PATCHER_CONTEXT *Patcher, IN OC_CPU_INFO *CpuInfo, IN UINT32 KernelVersion)
STATIC CONST UINT8 mProvideCurrentCpuInfoTopologyCorePerPackageV1_5Replace[]
UINT8 associativity
STATIC CONST UINT8 mProvideCurrentCpuInfoSnowLeopardSysctlMibInitReplaceMask[]
STATIC CONST struct @85 mCpuCacheDescriptorValues[]
STATIC CONST UINT8 mProvideCurrentCpuInfoTopologyCorePerPackageV1Find[]
STATIC UINT8 mProvideCurrentCpuInfoZeroMsrThreadCoreCountReplace[]
STATIC UINT8 mProvideCurrentCpuInfoTopologyCoreCountReplace[]
UINT32 size
STATIC CONST UINT8 mProvideCurrentCpuInfoSnowLeopardSysctlMibInitFind[]
STATIC PATCHER_GENERIC_PATCH mProvideCurrentCpuInfoTopologyCorePerPackageV2Patch
STATIC CONST UINT8 mProvideCurrentCpuInfoLeopardSysctlMibInitFind1[]
STATIC CONST UINT8 mKernelCpuIdFindRelNew[]
STATIC CONST UINT8 mProvideCurrentCpuInfoSnowLeopardSysctlMibInitFindMask[]
STATIC PATCHER_GENERIC_PATCH mProvideCurrentCpuInfoTopologyCorePerPackageV1Patch
UINT8 partitions
STATIC PATCHER_GENERIC_PATCH mProvideCurrentCpuInfoSnowLeopardSysctlMibInitPatch
STATIC UINT8 mProvideCurrentCpuInfoTopologyValidationReplace[]
STATIC PATCHER_GENERIC_PATCH mProvideCurrentCpuInfoTopologyCorePerPackageV1_5Patch
STATIC CONST UINT8 mProvideCurrentCpuInfoLeopardSysctlMibInitMask2[]
STATIC UINT8 mProvideCurrentCpuInfoSnowLeopardSysctlMibInitReplace[]
STATIC CONST UINT8 mProvideCurrentCpuInfoTopologyCorePerPackageV1_5Find[]
STATIC UINT8 mProvideCurrentCpuInfoZeroMsrThreadCoreCountFind[]
EFI_STATUS PatchProvideCurrentCpuInfo(IN OUT PATCHER_CONTEXT *Patcher, IN OC_CPU_INFO *CpuInfo, IN UINT32 KernelVersion)
UINT8 linesize
STATIC EFI_STATUS PatchKernelCpuIdLegacy(IN OUT PATCHER_CONTEXT *Patcher, IN UINT32 KernelVersion, IN OC_CPU_INFO *CpuInfo, IN UINT32 *Data, IN UINT32 *DataMask, IN UINT8 *Start, IN UINT8 *Last)
STATIC UINT8 mProvideCurrentCpuInfoLeopardSysctlMibInitReplace2[]
STATIC CONST UINT8 mProvideCurrentCpuInfoLeopardSysctlMibInitMask1[]
STATIC UINT8 mProvideCurrentCpuInfoLeopardSysctlMibInitReplace1[]
STATIC PATCHER_GENERIC_PATCH mProvideCurrentCpuInfoLeopardSysctlMibInitPatch1
STATIC CONST UINT8 mProvideCurrentCpuInfoLeopardSysctlMibInitFind2[]
STATIC CONST UINT8 mKernelCpuidFindMcRel[]
STATIC CONST UINT8 mProvideCurrentCpuInfoTopologyCorePerPackageV1Replace[]
STATIC CONST UINT8 mProvideCurrentCpuInfoTopologyCorePerPackageV2Find[]
STATIC CONST UINT8 mProvideCurrentCpuInfoTopologyCorePerPackageV2Mask[]
STATIC UINT8 * PatchMovVar(IN OUT UINT8 *Location, IN BOOLEAN Is32Bit, IN OUT UINT64 *FuncAddr, IN UINT64 VarSymAddr, IN UINT64 Value)
EFI_STATUS PatchKernelCpuId(IN OUT PATCHER_CONTEXT *Patcher, IN OC_CPU_INFO *CpuInfo, IN UINT32 *Data, IN UINT32 *DataMask, IN UINT32 KernelVersion)
STATIC UINT32 KernelVersion
Definition KextInject.c:28
#define KERNEL_VERSION_SNOW_LEOPARD_MIN
EFI_STATUS PatcherGetSymbolValue(IN OUT PATCHER_CONTEXT *Context, IN CONST CHAR8 *Name, IN OUT UINT64 *Value)
#define KERNEL_VERSION_MONTEREY_MIN
#define KERNEL_VERSION_LEOPARD_MIN
#define KERNEL_VERSION_HIGH_SIERRA_MIN
#define KERNEL_VERSION_TIGER_MAX
EFI_STATUS PatcherGetSymbolAddressValue(IN OUT PATCHER_CONTEXT *Context, IN CONST CHAR8 *Name, IN OUT UINT8 **Address, IN OUT UINT64 *Value)
EFI_STATUS PatcherGetSymbolAddress(IN OUT PATCHER_CONTEXT *Context, IN CONST CHAR8 *Name, IN OUT UINT8 **Address)
#define KERNEL_VERSION_CATALINA_MIN
#define KERNEL_VERSION_SNOW_LEOPARD_MAX
BOOLEAN OcMatchDarwinVersion(IN UINT32 CurrentVersion OPTIONAL, IN UINT32 MinVersion OPTIONAL, IN UINT32 MaxVersion OPTIONAL)
#define KERNEL_VERSION(A, B, C)
EFI_STATUS PatcherApplyGenericPatch(IN OUT PATCHER_CONTEXT *Context, IN PATCHER_GENERIC_PATCH *Patch)
#define KERNEL_VERSION_LION_MAX
#define KERNEL_VERSION_MOJAVE_MIN
#define KERNEL_VERSION_LEOPARD_MAX
#define KERNEL_VERSION_TIGER_MIN
#define KERNEL_VERSION_LION_MIN
UINT32 OcCpuModelToAppleFamily(IN CPUID_VERSION_INFO_EAX VersionEax)
UINT32 MachoGetInnerSize(IN OUT OC_MACHO_CONTEXT *Context)
Definition Header.c:55
MACH_HEADER_ANY * MachoGetMachHeader(IN OUT OC_MACHO_CONTEXT *Context)
Definition Header.c:44
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
Definition UserMath.c:59
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition UserMath.c:76
UINT32 AsmCpuid(IN UINT32 Index, OUT UINT32 *Eax, OPTIONAL OUT UINT32 *Ebx, OPTIONAL OUT UINT32 *Ecx, OPTIONAL OUT UINT32 *Edx OPTIONAL)
Definition UserMisc.c:45
UINT32 AsmCpuidEx(IN UINT32 Index, IN UINT32 SubIndex, OUT UINT32 *Eax, OPTIONAL OUT UINT32 *Ebx, OPTIONAL OUT UINT32 *Ecx, OPTIONAL OUT UINT32 *Edx OPTIONAL)
Definition UserMisc.c:109
#define ASSERT(x)
Definition coder.h:55
#define MAX(a, b)
Definition coder.h:59