OpenCore  1.0.6
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
1701 // Handle case where CPUFrequency is zero, providing a fallback
1702 if (tscFreqValue == 0) {
1703 tscFreqValue = 1000000000; // Assume 1 GHz TSC as fallback
1704 DEBUG ((DEBUG_WARN, "OCAK: CPUFrequency is zero, using fallback value: 1 GHz\n"));
1705 }
1706
1707 tscFCvtt2nValue = DivU64x64Remainder ((1000000000ULL << 32), tscFreqValue, NULL);
1708 tscFCvtn2tValue = DivU64x64Remainder ((1000000000ULL << 32), tscFCvtt2nValue, NULL);
1709 }
1710 // For all other processors
1711 else {
1712 busFreqValue = CpuInfo->FSBFrequency;
1713 busFCvtt2nValue = DivU64x64Remainder ((1000000000ULL << 32), busFreqValue, NULL);
1714 busFCvtn2tValue = DivU64x64Remainder (0xFFFFFFFFFFFFFFFFULL, busFCvtt2nValue, NULL);
1715
1716 tscFreqValue = CpuInfo->CPUFrequency;
1717 tscFCvtt2nValue = DivU64x64Remainder ((1000000000ULL << 32), tscFreqValue, NULL);
1718 tscFCvtn2tValue = DivU64x64Remainder (0xFFFFFFFFFFFFFFFFULL, tscFCvtt2nValue, NULL);
1719 }
1720
1721 tscGranularityValue = DivU64x64Remainder (tscFreqValue, busFreqValue, NULL);
1722
1723 DEBUG ((DEBUG_INFO, "OCAK: BusFreq = %LuHz, BusFCvtt2n = %Lu, BusFCvtn2t = %Lu\n", busFreqValue, busFCvtt2nValue, busFCvtn2tValue));
1724 DEBUG ((DEBUG_INFO, "OCAK: TscFreq = %LuHz, TscFCvtt2n = %Lu, TscFCvtn2t = %Lu\n", tscFreqValue, tscFCvtt2nValue, tscFCvtn2tValue));
1725
1726 //
1727 // Patch _tsc_init with above values.
1728 //
1729 TscLocation = TscInitFunc;
1730
1731 if (!IsTigerNew) {
1732 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, BusFreqSymAddr, busFreqValue);
1733 }
1734
1735 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, BusFCvtt2nSymAddr, busFCvtt2nValue);
1736 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, BusFCvtn2tSymAddr, busFCvtn2tValue);
1737 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, TscFreqSymAddr, tscFreqValue);
1738 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, TscFCvtt2nSymAddr, tscFCvtt2nValue);
1739 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, TscFCvtn2tSymAddr, tscFCvtn2tValue);
1740 TscLocation = PatchMovVar (TscLocation, Patcher->Is32Bit, &TscInitFuncSymAddr, TscGranularitySymAddr, tscGranularityValue);
1741
1742 if (Patcher->Is32Bit) {
1743 //
1744 // push ebp
1745 // move ebp, esp
1746 //
1747 *TscLocation++ = 0x55;
1748 *TscLocation++ = 0x89;
1749 *TscLocation++ = 0xE5;
1750
1751 ValueLower = (UINT32)busFreqValue;
1752 ValueUpper = (UINT32)(busFreqValue >> 32);
1753
1754 //
1755 // mov eax, FSB freq (lower)
1756 //
1757 *TscLocation++ = 0xB8;
1758 CopyMem (TscLocation, &ValueLower, sizeof (ValueLower));
1759 TscLocation += sizeof (ValueLower);
1760
1761 //
1762 // push eax
1763 //
1764 *TscLocation++ = 0x50;
1765
1766 //
1767 // mov eax, FSB freq (higher)
1768 //
1769 *TscLocation++ = 0xB8;
1770 CopyMem (TscLocation, &ValueUpper, sizeof (ValueUpper));
1771 TscLocation += sizeof (ValueUpper);
1772
1773 //
1774 // push eax
1775 //
1776 *TscLocation++ = 0x50;
1777
1778 ValueLower = (UINT32)tscFreqValue;
1779 ValueUpper = (UINT32)(tscFreqValue >> 32);
1780
1781 //
1782 // mov eax, TSC freq (lower)
1783 //
1784 *TscLocation++ = 0xB8;
1785 CopyMem (TscLocation, &ValueLower, sizeof (ValueLower));
1786 TscLocation += sizeof (ValueLower);
1787
1788 //
1789 // push eax
1790 //
1791 *TscLocation++ = 0x50;
1792
1793 //
1794 // mov eax, TSC freq (higher)
1795 //
1796 *TscLocation++ = 0xB8;
1797 CopyMem (TscLocation, &ValueUpper, sizeof (ValueUpper));
1798 TscLocation += sizeof (ValueUpper);
1799
1800 //
1801 // push eax
1802 //
1803 *TscLocation++ = 0x50;
1804
1805 //
1806 // call _tmrCvt(busFCvtt2n, tscFCvtn2t)
1807 //
1808 Delta = (INT32)(TmrCvtFunc - (TscLocation + 5));
1809 *TscLocation++ = 0xE8;
1810 CopyMem (TscLocation, &Delta, sizeof (Delta));
1811 TscLocation += sizeof (Delta);
1812
1813 //
1814 // mov [_bus2tsc], eax
1815 //
1816 VarAddr32 = (UINT32)(Bus2TscSymAddr);
1817 *TscLocation++ = 0xA3;
1818 CopyMem (TscLocation, &VarAddr32, sizeof (VarAddr32));
1819 TscLocation += sizeof (VarAddr32);
1820
1821 //
1822 // mov [_bus2tsc+4], edx
1823 //
1824 VarAddr32 += sizeof (UINT32);
1825 *TscLocation++ = 0x89;
1826 *TscLocation++ = 0x15;
1827 CopyMem (TscLocation, &VarAddr32, sizeof (VarAddr32));
1828 TscLocation += sizeof (VarAddr32);
1829
1830 //
1831 // pop eax (x4)
1832 // leave
1833 //
1834 *TscLocation++ = 0x58;
1835 *TscLocation++ = 0x58;
1836 *TscLocation++ = 0x58;
1837 *TscLocation++ = 0x58;
1838 *TscLocation++ = 0xC9;
1839 } else {
1840 //
1841 // mov rdi, FSB freq
1842 //
1843 *TscLocation++ = 0x48;
1844 *TscLocation++ = 0xBF;
1845 CopyMem (TscLocation, &busFreqValue, sizeof (busFreqValue));
1846 TscLocation += sizeof (busFreqValue);
1847 TscInitFuncSymAddr += sizeof (busFreqValue) + 2;
1848
1849 //
1850 // mov rsi, TSC freq
1851 //
1852 *TscLocation++ = 0x48;
1853 *TscLocation++ = 0xBE;
1854 CopyMem (TscLocation, &tscFreqValue, sizeof (tscFreqValue));
1855 TscLocation += sizeof (tscFreqValue);
1856 TscInitFuncSymAddr += sizeof (tscFreqValue) + 2;
1857
1858 //
1859 // call _tmrCvt(busFCvtt2n, tscFCvtn2t)
1860 //
1861 Delta = (INT32)(TmrCvtFunc - (TscLocation + 5));
1862 *TscLocation++ = 0xE8;
1863 CopyMem (TscLocation, &Delta, sizeof (Delta));
1864 TscLocation += sizeof (Delta);
1865 TscInitFuncSymAddr += sizeof (Delta) + 1;
1866
1867 //
1868 // mov [_bus2tsc], rax
1869 //
1870 Delta = (INT32)(Bus2TscSymAddr - (TscInitFuncSymAddr + 7));
1871
1872 *TscLocation++ = 0x48;
1873 *TscLocation++ = 0x89;
1874 *TscLocation++ = 0x05;
1875 CopyMem (TscLocation, &Delta, sizeof (Delta));
1876 TscLocation += sizeof (Delta);
1877 }
1878
1879 //
1880 // ret
1881 //
1882 *TscLocation++ = 0xC3;
1883
1884 //
1885 // Find patch region for injecting CPU cache information
1886 // into set_intel_cache_info.
1887 //
1888 if (IsTigerCacheUnsupported) {
1889 Status = PatcherGetSymbolAddress (Patcher, "_cpuid_info", (UINT8 **)&Record);
1890 if (EFI_ERROR (Status) || (Record >= Last)) {
1891 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to locate _cpuid_info (%p) - %r\n", Record, Status));
1892 return EFI_NOT_FOUND;
1893 }
1894
1895 //
1896 // Start of patch area.
1897 // We'll use this area to populate info_p.
1898 //
1899 STATIC CONST UINT8 mKernelCpuidFindCacheLocTigerStart[9] = {
1900 0x8B, 0x45, 0x08, // mov eax, dword [ebp+0x8] (*info_p argument)
1901 0x8B, 0x50, 0x74, // mov edx, dword [eax+0x74]
1902 0x85, 0xD2, // test edx, edx
1903 0x75 // jne ...
1904 };
1905
1906 //
1907 // End of patch area.
1908 //
1909 STATIC CONST UINT8 mKernelCpuidFindCacheLocTigerEnd[5] = {
1910 0x31, 0xC0, // xor eax, eax
1911 0x0F, 0xA2, // cpuid
1912 0x89 // mov ...
1913 };
1914
1915 for (Index = 0; Index < EFI_PAGE_SIZE; Index++, Record++) {
1916 if ( (Record[0] == mKernelCpuidFindCacheLocTigerStart[0])
1917 && (Record[1] == mKernelCpuidFindCacheLocTigerStart[1])
1918 && (Record[2] == mKernelCpuidFindCacheLocTigerStart[2])
1919 && (Record[3] == mKernelCpuidFindCacheLocTigerStart[3])
1920 && (Record[4] == mKernelCpuidFindCacheLocTigerStart[4])
1921 && (Record[5] == mKernelCpuidFindCacheLocTigerStart[5])
1922 && (Record[6] == mKernelCpuidFindCacheLocTigerStart[6])
1923 && (Record[7] == mKernelCpuidFindCacheLocTigerStart[7])
1924 && (Record[8] == mKernelCpuidFindCacheLocTigerStart[8]))
1925 {
1926 break;
1927 }
1928 }
1929
1930 if (Index >= EFI_PAGE_SIZE) {
1931 return EFI_NOT_FOUND;
1932 }
1933
1934 LocationTigerCache = Record + 3;
1935
1936 for ( ; Index < EFI_PAGE_SIZE; Index++, Record++) {
1937 if ( (Record[0] == mKernelCpuidFindCacheLocTigerEnd[0])
1938 && (Record[1] == mKernelCpuidFindCacheLocTigerEnd[1])
1939 && (Record[2] == mKernelCpuidFindCacheLocTigerEnd[2])
1940 && (Record[3] == mKernelCpuidFindCacheLocTigerEnd[3])
1941 && (Record[4] == mKernelCpuidFindCacheLocTigerEnd[4]))
1942 {
1943 break;
1944 }
1945 }
1946
1947 if (Index >= EFI_PAGE_SIZE) {
1948 return EFI_NOT_FOUND;
1949 }
1950
1951 LocationTigerCacheEnd = Record;
1952
1953 DEBUG ((
1954 DEBUG_INFO,
1955 "OCAK: CPU info cache loc %p:%p\n",
1956 LocationTigerCache - Start,
1957 LocationTigerCacheEnd - Start
1958 ));
1959
1960 ZeroMem (CacheLineSizes, sizeof (CacheLineSizes));
1961
1962 //
1963 // Build CPU info struct
1964 //
1965 Index = 0;
1966 do {
1967 AsmCpuidEx (CPUID_CACHE_PARAMS, Index, &CpuidCacheParamsEax.Uint32, &CpuidCacheParamsEbx.Uint32, &CacheSets, NULL);
1968 if (CpuidCacheParamsEax.Bits.CacheType == 0) {
1969 break;
1970 }
1971
1972 switch (CpuidCacheParamsEax.Bits.CacheLevel) {
1973 case 1:
1974 CacheType = (CpuidCacheParamsEax.Bits.CacheType == 1) ? L1D :
1975 (CpuidCacheParamsEax.Bits.CacheType == 2) ? L1I :
1976 Lnone;
1977 break;
1978
1979 case 2:
1980 CacheType = (CpuidCacheParamsEax.Bits.CacheType == 3) ? L2U :
1981 Lnone;
1982 break;
1983
1984 case 3:
1985 CacheType = (CpuidCacheParamsEax.Bits.CacheType == 3) ? L3U :
1986 Lnone;
1987 break;
1988
1989 default:
1990 CacheType = Lnone;
1991 }
1992
1993 if (CacheType != Lnone) {
1994 CacheSizes[CacheType] = (CpuidCacheParamsEbx.Bits.LineSize + 1) * (CacheSets + 1) * (CpuidCacheParamsEbx.Bits.Ways + 1);
1995 CacheLineSizes[CacheType] = CpuidCacheParamsEbx.Bits.LineSize + 1;
1996 }
1997
1998 Index++;
1999 } while (TRUE);
2000
2001 if (CacheLineSizes[L2U]) {
2002 CacheLineSize = CacheLineSizes[L2U];
2003 } else if (CacheLineSizes[L1D]) {
2004 CacheLineSize = CacheLineSizes[L1D];
2005 } else {
2006 //
2007 // XNU would panic here.
2008 //
2009 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Unable to determine CPU cache line size\n"));
2010 return EFI_UNSUPPORTED;
2011 }
2012
2013 //
2014 // Populate cache sizes.
2015 // EAX = address of *info_p struct in stack; 0x68 = offset of cache size array in *info_p struct.
2016 //
2017 for (Index = L1I; Index < LCACHE_MAX; Index++) {
2018 *LocationTigerCache++ = 0xC7;
2019 *LocationTigerCache++ = 0x40;
2020 *LocationTigerCache++ = 0x68 + ((UINT8)(sizeof (UINT32) * Index));
2021 CopyMem (LocationTigerCache, &CacheSizes[Index], sizeof (CacheSizes[Index]));
2022 LocationTigerCache += sizeof (CacheSizes[Index]);
2023 DEBUG ((DEBUG_INFO, "OCAK: Cache size (L%u): %u bytes\n", (Index >= 3) ? (Index - 1) : 1, CacheSizes[Index]));
2024 }
2025
2026 //
2027 // Populate cache line size.
2028 // 0x7C = offset of cache line size in *info_p struct.
2029 //
2030 *LocationTigerCache++ = 0xC7;
2031 *LocationTigerCache++ = 0x40;
2032 *LocationTigerCache++ = 0x7C;
2033 CopyMem (LocationTigerCache, &CacheLineSize, sizeof (CacheLineSize));
2034 LocationTigerCache += sizeof (CacheLineSize);
2035 DEBUG ((DEBUG_INFO, "OCAK: Cache line size: %u bytes\n", CacheLineSize));
2036
2037 while (LocationTigerCache < LocationTigerCacheEnd) {
2038 *LocationTigerCache++ = 0x90;
2039 }
2040 }
2041
2042 //
2043 // Patch sysctl reporting if leaf 0x4 is unsupported on 10.5 and 10.6.
2044 // This applies only to processors that are older than Prescott, and only on IA32.
2045 //
2046 if (Patcher->Is32Bit && !IsLeaf4CacheSupported && (IsLeopard || IsSnowLeopard)) {
2047 ZeroMem (CpuidCacheDescriptors, sizeof (CpuidCacheDescriptors));
2048 ZeroMem (CacheSizes, sizeof (CacheSizes));
2049 ZeroMem (CacheSharings, sizeof (CacheSharings));
2050 AsmCpuid (CPUID_CACHE_INFO, &CpuidCacheInfo[0].Uint32, &CpuidCacheInfo[1].Uint32, &CpuidCacheInfo[2].Uint32, &CpuidCacheInfo[3].Uint32);
2051
2052 for (Index = 0; Index < 4; Index++) {
2053 if (CpuidCacheInfo[Index].Bits.NotValid) {
2054 continue;
2055 }
2056
2057 ((UINT32 *)CpuidCacheDescriptors)[Index] = CpuidCacheInfo[Index].Uint32;
2058 }
2059
2060 for (Index = 1; Index < CpuidCacheDescriptors[0]; Index++) {
2061 if ((Index * 16) > sizeof (CpuidCacheDescriptors)) {
2062 break;
2063 }
2064
2065 AsmCpuid (CPUID_CACHE_INFO, &CpuidCacheInfo[0].Uint32, &CpuidCacheInfo[1].Uint32, &CpuidCacheInfo[2].Uint32, &CpuidCacheInfo[3].Uint32);
2066
2067 for (Index2 = 0; Index2 < 4; Index2++) {
2068 if (CpuidCacheInfo[Index2].Bits.NotValid) {
2069 continue;
2070 }
2071
2072 ((UINT32 *)CpuidCacheDescriptors)[sizeof (UINT32) * Index * Index2] = CpuidCacheInfo[Index2].Uint32;
2073 }
2074 }
2075
2076 //
2077 // Get cache sizes.
2078 //
2079 for (Index = 0; Index < sizeof (CpuidCacheDescriptors); Index++) {
2080 CacheDescriptorFound = FALSE;
2081 for (Index2 = 0; Index2 < (sizeof (mCpuCacheDescriptorValues) / sizeof (mCpuCacheDescriptorValues[0])); Index2++) {
2082 if (mCpuCacheDescriptorValues[Index2].value == CpuidCacheDescriptors[Index]) {
2083 CacheDescriptorType = mCpuCacheDescriptorValues[Index2].type;
2084 CacheDescriptorSize = mCpuCacheDescriptorValues[Index2].size;
2085 CacheDescriptorFound = TRUE;
2086 break;
2087 }
2088 }
2089
2090 if (!CacheDescriptorFound) {
2091 continue;
2092 }
2093
2094 CacheSizes[CacheDescriptorType] = CacheDescriptorSize;
2095 CacheSharings[CacheDescriptorType] = 1;
2096 }
2097
2098 DEBUG ((DEBUG_INFO, "OCAK: Caches L1I: %u, L1D: %u, L2: %u, L3: %u\n", CacheSizes[L1I], CacheSizes[L1D], CacheSizes[L2U], CacheSizes[L3U]));
2099
2100 if (IsLeopard) {
2101 //
2102 // Patch _ml_cpu_cache_sharing (0x1)
2103 //
2104 CacheSize = MAX (CacheSharings[L1I], CacheSharings[L1D]);
2105 CopyMem (
2107 &CacheSize,
2108 sizeof (UINT32)
2109 );
2110 Status |= PatcherApplyGenericPatch (
2111 Patcher,
2113 );
2114
2115 //
2116 // Patch _ml_cpu_cache_sharing (0x2)
2117 //
2118 CopyMem (
2120 &CacheSharings[L2U],
2121 sizeof (UINT32)
2122 );
2123 Status |= PatcherApplyGenericPatch (
2124 Patcher,
2126 );
2127
2128 //
2129 // Patch _ml_cpu_cache_sharing (0x3)
2130 //
2131 CopyMem (
2133 &CacheSharings[L3U],
2134 sizeof (UINT32)
2135 );
2136 Status |= PatcherApplyGenericPatch (
2137 Patcher,
2139 );
2140
2141 //
2142 // Patch _ml_cpu_cache_size (0x1) - L1
2143 //
2144 CacheSize = MAX (CacheSizes[L1I], CacheSizes[L1D]);
2145 CopyMem (
2147 &CacheSize,
2148 sizeof (UINT32)
2149 );
2150 Status |= PatcherApplyGenericPatch (
2151 Patcher,
2153 );
2154
2155 //
2156 // Patch _ml_cpu_cache_size (0x2) - L2
2157 //
2158 CopyMem (
2160 &CacheSizes[L2U],
2161 sizeof (UINT32)
2162 );
2163 Status |= PatcherApplyGenericPatch (
2164 Patcher,
2166 );
2167
2168 //
2169 // Patch _ml_cpu_cache_size (0x3) - L3
2170 //
2171 CopyMem (
2173 &CacheSizes[L3U],
2174 sizeof (UINT32)
2175 );
2176 Status |= PatcherApplyGenericPatch (
2177 Patcher,
2179 );
2180 } else {
2181 //
2182 // Patch _ml_cpu_cache_sharing (0x1)
2183 //
2184 CacheSize = MAX (CacheSharings[L1I], CacheSharings[L1D]);
2185 CopyMem (
2187 &CacheSize,
2188 sizeof (UINT32)
2189 );
2190 Status |= PatcherApplyGenericPatch (
2191 Patcher,
2193 );
2194
2195 //
2196 // Patch _ml_cpu_cache_sharing (0x2)
2197 //
2198 CopyMem (
2200 &CacheSharings[L2U],
2201 sizeof (UINT32)
2202 );
2203 Status |= PatcherApplyGenericPatch (
2204 Patcher,
2206 );
2207
2208 //
2209 // Patch _ml_cpu_cache_sharing (0x3)
2210 //
2211 CopyMem (
2213 &CacheSharings[L3U],
2214 sizeof (UINT32)
2215 );
2216 Status |= PatcherApplyGenericPatch (
2217 Patcher,
2219 );
2220
2221 //
2222 // Patch _ml_cpu_cache_size (0x1) - L1
2223 //
2224 CacheSize = MAX (CacheSizes[L1I], CacheSizes[L1D]);
2225 CopyMem (
2227 &CacheSize,
2228 sizeof (UINT32)
2229 );
2230 Status |= PatcherApplyGenericPatch (
2231 Patcher,
2233 );
2234
2235 //
2236 // Patch _ml_cpu_cache_size (0x2) - L2
2237 //
2238 CopyMem (
2240 &CacheSizes[L2U],
2241 sizeof (UINT32)
2242 );
2243 Status |= PatcherApplyGenericPatch (
2244 Patcher,
2246 );
2247
2248 //
2249 // Patch _ml_cpu_cache_size (0x3) - L3
2250 //
2251 CopyMem (
2253 &CacheSizes[L3U],
2254 sizeof (UINT32)
2255 );
2256 Status |= PatcherApplyGenericPatch (
2257 Patcher,
2259 );
2260 }
2261
2262 if (EFI_ERROR (Status)) {
2263 DEBUG ((DEBUG_WARN, "OCAK: [FAIL] Failed to patch or more areas in _sysctl_mib_init - %r\n", Status));
2264 return EFI_NOT_FOUND;
2265 }
2266 }
2267
2268 //
2269 // Patch MSR 0x35 fallback value on 10.13 and above.
2270 //
2271 // This value is used if the MSR 0x35 is read as zero, typically on VMs or AMD processors.
2272 //
2274 //
2275 // 10.15 and above have two instances that need patching.
2276 //
2279 }
2280
2281 msrCoreThreadCount = (CpuInfo->CoreCount << 16) | CpuInfo->ThreadCount;
2282
2283 CopyMem (
2285 &msrCoreThreadCount,
2286 sizeof (msrCoreThreadCount)
2287 );
2288
2289 Status = PatcherApplyGenericPatch (
2290 Patcher,
2292 );
2293 if (EFI_ERROR (Status)) {
2294 DEBUG ((DEBUG_INFO, "OCAK: [FAIL] Failed to find CPU MSR 0x35 default value patch - %r\n", Status));
2295 }
2296 } else {
2297 DEBUG ((DEBUG_INFO, "OCAK: [OK] Skipping CPU MSR 0x35 default value patch on %u\n", KernelVersion));
2298 }
2299
2300 //
2301 // Disable _x86_validate_topology on 10.13 and above.
2302 //
2304 Status = PatcherApplyGenericPatch (
2305 Patcher,
2307 );
2308 if (EFI_ERROR (Status)) {
2309 DEBUG ((DEBUG_INFO, "OCAK: [FAIL] Failed to find CPU topology validation patch - %r\n", Status));
2310 }
2311 } else {
2312 DEBUG ((DEBUG_INFO, "OCAK: [OK] Skipping CPU topology validation patch on %u\n", KernelVersion));
2313 }
2314
2315 return EFI_SUCCESS;
2316}
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