CloverBootloader/rEFIt_UEFI/Platform/cpu.cpp

1636 lines
62 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
cpu.c
implementation for cpu
Remade by Slice 2011 based on Apple's XNU sources
Portion copyright from Chameleon project. Thanks to all who involved to it.
*/
/*
* Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#include <Platform.h> // Only use angled for Platform, else, xcode project won't compile
#include "cpu.h"
#include "smbios.h"
#include "kernel_patcher.h"
#include "../Platform/Settings.h"
#include <Register/Intel/ArchitecturalMsr.h>
#ifndef DEBUG_ALL
#define DEBUG_CPU 1
//#define DEBUG_PCI 1
#else
#define DEBUG_CPU DEBUG_ALL
//#define DEBUG_PCI DEBUG_ALL
#endif
#if DEBUG_CPU == 0
#define DBG(...)
#else
#define DBG(...) DebugLog(DEBUG_CPU, __VA_ARGS__)
#endif
#define VIRTUAL 0
#if VIRTUAL == 1
#define AsmReadMsr64(x) 0ULL
#define AsmWriteMsr64(m, x)
#endif
#define DivU64(x, y) DivU64x64Remainder((x), (y), NULL)
UINT8 gDefaultType;
CPU_STRUCTURE gCPUStructure;
UINT64 TurboMsr;
//this must not be defined at LegacyBios calls
#define EAX 0
#define EBX 1
#define ECX 2
#define EDX 3
#define MSR_AMD_INT_PENDING_CMP_HALT 0xC0010055
#define AMD_ACTONCMPHALT_SHIFT 27
#define AMD_ACTONCMPHALT_MASK 3
// Bronya C1E fix
// * Portions Copyright 2009 Advanced Micro Devices, Inc.
void post_startup_cpu_fixups(void)
{
/*
* Some AMD processors support C1E state. Entering this state will
* cause the local APIC timer to stop, which we can't deal with at
* this time.
*/
UINT64 reg;
DBG("\tLooking to disable C1E if is already enabled by the BIOS:\n");
reg = AsmReadMsr64(MSR_AMD_INT_PENDING_CMP_HALT);
/* Disable C1E state if it is enabled by the BIOS */
if ((reg >> AMD_ACTONCMPHALT_SHIFT) & AMD_ACTONCMPHALT_MASK)
{
reg &= ~(AMD_ACTONCMPHALT_MASK << AMD_ACTONCMPHALT_SHIFT);
AsmWriteMsr64(MSR_AMD_INT_PENDING_CMP_HALT, reg);
DBG("\tC1E disabled!\n");
}
}
void DoCpuid(UINT32 selector, UINT32 *data)
{
AsmCpuid(selector, data, data+1, data+2, data+3);
}
//
// Should be used after PrepatchSmbios() but before users's config.plist reading
//
void GetCPUProperties (void)
{
UINT32 reg[4];
UINT64 msr = 0;
EFI_STATUS Status;
EFI_HANDLE *HandleBuffer;
// EFI_GUID **ProtocolGuidArray;
EFI_PCI_IO_PROTOCOL *PciIo;
PCI_TYPE00 Pci;
UINTN HandleCount;
// UINTN ArrayCount;
UINTN HandleIndex;
// UINTN ProtocolIndex;
UINT64 qpibusspeed; //units=kHz
UINT32 qpimult = 2;
UINT32 BusSpeed = 0; //units kHz
UINT64 ExternalClock;
UINT64 tmpU;
UINT16 did, vid;
UINTN Segment;
UINTN Bus;
UINTN Device;
UINTN Function;
CHAR8 str[128];
DbgHeader("GetCPUProperties");
//initial values
gCPUStructure.MaxRatio = 10; //keep it as K*10
gCPUStructure.MinRatio = 10; //same
gCPUStructure.SubDivider = 0;
gSettings.CpuFreqMHz = 0;
gCPUStructure.FSBFrequency = MultU64x32(gCPUStructure.ExternalClock, Kilo); //kHz -> Hz
gCPUStructure.ProcessorInterconnectSpeed = 0;
gCPUStructure.Mobile = FALSE; //not same as gMobile
if (!gCPUStructure.CurrentSpeed) {
gCPUStructure.CurrentSpeed = (UINT32)DivU64x32(gCPUStructure.TSCCalibr + (Mega >> 1), Mega);
}
if (!gCPUStructure.MaxSpeed) {
gCPUStructure.MaxSpeed = gCPUStructure.CurrentSpeed;
}
/* get CPUID Values */
DoCpuid(0, gCPUStructure.CPUID[CPUID_0]);
gCPUStructure.Vendor = gCPUStructure.CPUID[CPUID_0][EBX];
/*
* Get processor signature and decode
* and bracket this with the approved procedure for reading the
* the microcode version number a.k.a. signature a.k.a. BIOS ID
*/
if (gCPUStructure.Vendor == CPU_VENDOR_INTEL) {
AsmWriteMsr64(MSR_IA32_BIOS_SIGN_ID, 0);
}
DoCpuid(1, gCPUStructure.CPUID[CPUID_1]);
gCPUStructure.Signature = gCPUStructure.CPUID[CPUID_1][EAX];
DBG("CPU Vendor = %X Model=%X\n", gCPUStructure.Vendor, gCPUStructure.Signature);
if (gCPUStructure.Vendor == CPU_VENDOR_INTEL) {
msr = AsmReadMsr64(MSR_IA32_BIOS_SIGN_ID);
gCPUStructure.MicroCode = RShiftU64(msr, 32);
/* Get "processor flag"; necessary for microcode update matching */
gCPUStructure.ProcessorFlag = (RShiftU64(AsmReadMsr64(MSR_IA32_PLATFORM_ID), 50)) & 3;
}
// DoCpuid(2, gCPUStructure.CPUID[2]);
DoCpuid(0x80000000, gCPUStructure.CPUID[CPUID_80]);
if((gCPUStructure.CPUID[CPUID_80][EAX] & 0x0000000f) >= 1){
DoCpuid(0x80000001, gCPUStructure.CPUID[CPUID_81]);
}
gCPUStructure.Stepping = (UINT8) bitfield(gCPUStructure.Signature, 3, 0);
gCPUStructure.Model = (UINT8) bitfield(gCPUStructure.Signature, 7, 4);
gCPUStructure.Family = (UINT8) bitfield(gCPUStructure.Signature, 11, 8);
gCPUStructure.Type = (UINT8) bitfield(gCPUStructure.Signature, 13, 12);
gCPUStructure.Extmodel = (UINT8) bitfield(gCPUStructure.Signature, 19, 16);
gCPUStructure.Extfamily = (UINT8) bitfield(gCPUStructure.Signature, 27, 20);
gCPUStructure.Features = quad(gCPUStructure.CPUID[CPUID_1][ECX], gCPUStructure.CPUID[CPUID_1][EDX]);
gCPUStructure.ExtFeatures = quad(gCPUStructure.CPUID[CPUID_81][ECX], gCPUStructure.CPUID[CPUID_81][EDX]);
DBG(" The CPU%s supported SSE4.1\n", (gCPUStructure.Features & CPUID_FEATURE_SSE4_1)?"":" not");
/* Pack CPU Family and Model */
if (gCPUStructure.Family == 0x0f) {
gCPUStructure.Family += gCPUStructure.Extfamily;
}
gCPUStructure.Model += (gCPUStructure.Extmodel << 4);
/* get BrandString (if supported) */
if (gCPUStructure.CPUID[CPUID_80][EAX] >= 0x80000004) {
CHAR8 *s;
ZeroMem(str, 128);
/*
* The BrandString 48 bytes (max), guaranteed to
* be NULL terminated.
*/
DoCpuid(0x80000002, reg);
CopyMem(&str[0], (CHAR8 *)reg, 16);
DoCpuid(0x80000003, reg);
CopyMem(&str[16], (CHAR8 *)reg, 16);
DoCpuid(0x80000004, reg);
CopyMem(&str[32], (CHAR8 *)reg, 16);
for (s = str; *s != '\0'; s++){
if (*s != ' ') break; //remove leading spaces
}
AsciiStrnCpyS(gCPUStructure.BrandString, 48, s, 48);
if (!strncmp((const CHAR8*)gCPUStructure.BrandString, CPU_STRING_UNKNOWN, iStrLen((gCPUStructure.BrandString) + 1, 48))) {
gCPUStructure.BrandString[0] = '\0';
}
gCPUStructure.BrandString[47] = '\0';
DBG("BrandString = %s\n", gCPUStructure.BrandString);
}
//Calculate Nr of Cores
if (gCPUStructure.Features & CPUID_FEATURE_HTT) {
gCPUStructure.LogicalPerPackage = (UINT32)bitfield(gCPUStructure.CPUID[CPUID_1][EBX], 23, 16); //Atom330 = 4
} else {
gCPUStructure.LogicalPerPackage = 1;
}
if (gCPUStructure.Vendor == CPU_VENDOR_INTEL) {
DoCpuid(4, gCPUStructure.CPUID[CPUID_4]);
if (gCPUStructure.CPUID[CPUID_4][EAX]) {
gCPUStructure.CoresPerPackage = (UINT32)bitfield(gCPUStructure.CPUID[CPUID_4][EAX], 31, 26) + 1; //Atom330 = 2
DBG("CPUID_4_eax=%X\n", gCPUStructure.CPUID[CPUID_4][EAX]);
DoCpuid(4, gCPUStructure.CPUID[CPUID_4]);
DBG("CPUID_4_eax=%X\n", gCPUStructure.CPUID[CPUID_4][EAX]);
DoCpuid(4, gCPUStructure.CPUID[CPUID_4]);
DBG("CPUID_4_eax=%X\n", gCPUStructure.CPUID[CPUID_4][EAX]);
} else {
gCPUStructure.CoresPerPackage = (UINT32)bitfield(gCPUStructure.CPUID[CPUID_1][EBX], 18, 16);
if (gCPUStructure.CoresPerPackage) {
DBG("got cores from CPUID_1 = %d\n", gCPUStructure.CoresPerPackage);
}
}
} else if (gCPUStructure.Vendor == CPU_VENDOR_AMD) {
post_startup_cpu_fixups();
if(gCPUStructure.CPUID[CPUID_80][EAX] >= 0x80000008){
DoCpuid(0x80000008, gCPUStructure.CPUID[CPUID_88]);
}
if (gCPUStructure.Extfamily < 0x8) {
gCPUStructure.CoresPerPackage = (gCPUStructure.CPUID[CPUID_88][ECX] & 0xFF) + 1;
} else {
// Bronya : test for SMT
INTN Logical = 1;
if(gCPUStructure.CPUID[CPUID_80][EAX] >= 0x8000001E) {
DoCpuid(0x8000001E, gCPUStructure.CPUID[CPUID_81E]);
Logical = (INTN)bitfield(gCPUStructure.CPUID[CPUID_81E][EBX], 15, 8) + 1;
}
gCPUStructure.CoresPerPackage = (UINT32)(((gCPUStructure.CPUID[CPUID_88][ECX] & 0xFF) + 1) / Logical);
}
gCPUStructure.Cores = (UINT8)gCPUStructure.CoresPerPackage;
gCPUStructure.Threads = (UINT8)gCPUStructure.LogicalPerPackage;
if (gCPUStructure.Cores == 0) {
gCPUStructure.Cores = 1;
}
}
if (gCPUStructure.CoresPerPackage == 0) {
gCPUStructure.CoresPerPackage = 1;
}
/* Fold in the Invariant TSC feature bit, if present */
if(gCPUStructure.CPUID[CPUID_80][EAX] >= 0x80000007){
DoCpuid(0x80000007, gCPUStructure.CPUID[CPUID_87]);
gCPUStructure.ExtFeatures |=
gCPUStructure.CPUID[CPUID_87][EDX] & (UINT32)CPUID_EXTFEATURE_TSCI;
}
// if ((bit(9) & gCPUStructure.CPUID[CPUID_1][ECX]) != 0) {
// SSSE3 = TRUE;
// }
gCPUStructure.Turbo = FALSE;
if (gCPUStructure.Vendor == CPU_VENDOR_INTEL) {
// Determine turbo boost support
DoCpuid(6, gCPUStructure.CPUID[CPUID_6]);
gCPUStructure.Turbo = ((gCPUStructure.CPUID[CPUID_6][EAX] & BIT1) != 0);
DBG(" The CPU%s supported turbo\n", gCPUStructure.Turbo?"":" not");
//get cores and threads
BOOLEAN PerfBias = (gCPUStructure.CPUID[CPUID_6][ECX] & BIT3) != 0;
DBG(" Energy PerfBias is %s visible:\n", PerfBias?"":" not");
switch (gCPUStructure.Model)
{
case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)
case CPU_MODEL_FIELDS: // Intel Core i5, i7 LGA1156 (45nm)
case CPU_MODEL_CLARKDALE: // Intel Core i3, i5, i7 LGA1156 (32nm)
case CPU_MODEL_NEHALEM_EX:
case CPU_MODEL_JAKETOWN:
case CPU_MODEL_SANDY_BRIDGE:
case CPU_MODEL_IVY_BRIDGE:
case CPU_MODEL_IVY_BRIDGE_E5:
case CPU_MODEL_HASWELL:
case CPU_MODEL_HASWELL_U5:
case CPU_MODEL_HASWELL_E:
case CPU_MODEL_HASWELL_ULT:
case CPU_MODEL_CRYSTALWELL:
case CPU_MODEL_BROADWELL_HQ:
case CPU_MODEL_AIRMONT:
case CPU_MODEL_AVOTON:
case CPU_MODEL_SKYLAKE_U:
case CPU_MODEL_BROADWELL_DE:
case CPU_MODEL_BROADWELL_E5:
case CPU_MODEL_KNIGHT:
case CPU_MODEL_MOOREFIELD:
case CPU_MODEL_GOLDMONT:
case CPU_MODEL_ATOM_X3:
case CPU_MODEL_SKYLAKE_D:
case CPU_MODEL_SKYLAKE_S:
case CPU_MODEL_KABYLAKE1:
case CPU_MODEL_KABYLAKE2:
case CPU_MODEL_CANNONLAKE:
case CPU_MODEL_ICELAKE_A:
case CPU_MODEL_ICELAKE_C:
case CPU_MODEL_ICELAKE_D:
case CPU_MODEL_ICELAKE:
case CPU_MODEL_COMETLAKE_S:
case CPU_MODEL_COMETLAKE_Y:
case CPU_MODEL_COMETLAKE_U:
case CPU_MODEL_TIGERLAKE_C:
case CPU_MODEL_TIGERLAKE_D:
msr = AsmReadMsr64(MSR_CORE_THREAD_COUNT); //0x35
DBG("MSR 0x35 %16llX\n", msr);
gCPUStructure.Cores = (UINT8)bitfield((UINT32)msr, 31, 16);
gCPUStructure.Threads = (UINT8)bitfield((UINT32)msr, 15, 0);
break;
case CPU_MODEL_DALES:
case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core
case CPU_MODEL_WESTMERE_EX:
msr = AsmReadMsr64(MSR_CORE_THREAD_COUNT);
gCPUStructure.Cores = (UINT8)bitfield((UINT32)msr, 19, 16);
gCPUStructure.Threads = (UINT8)bitfield((UINT32)msr, 15, 0);
break;
case CPU_MODEL_ATOM_3700:
gCPUStructure.Cores = 4;
gCPUStructure.Threads = 4;
break;
case CPU_MODEL_ATOM:
gCPUStructure.Cores = 2;
gCPUStructure.Threads = 2;
break;
default:
gCPUStructure.Cores = 0;
break;
}
}
if (gCPUStructure.Vendor == CPU_VENDOR_INTEL) {
DoCpuid(7, gCPUStructure.CPUID[CPUID_7]);
if ((gCPUStructure.CPUID[CPUID_7][EBX] & BIT1) != 0) {
DBG(" IA32_TSC_ADJUST MSR is supported \n");
msr = AsmReadMsr64(MSR_IA32_TSC_ADJUST); //0x3B
DBG(" value to adjust = %llu\n", msr);
}
}
//workaround for Xeon Harpertown and Yorkfield
if ((gCPUStructure.Model == CPU_MODEL_PENRYN) &&
(gCPUStructure.Cores == 0)) {
if ((AsciiStrStr(gCPUStructure.BrandString, "X54")) ||
(AsciiStrStr(gCPUStructure.BrandString, "E54")) ||
(AsciiStrStr(gCPUStructure.BrandString, "W35")) ||
(AsciiStrStr(gCPUStructure.BrandString, "X34")) ||
(AsciiStrStr(gCPUStructure.BrandString, "X33")) ||
(AsciiStrStr(gCPUStructure.BrandString, "L33")) ||
(AsciiStrStr(gCPUStructure.BrandString, "X32")) ||
(AsciiStrStr(gCPUStructure.BrandString, "L3426")) ||
(AsciiStrStr(gCPUStructure.BrandString, "L54"))) {
gCPUStructure.Cores = 4;
gCPUStructure.Threads = 4;
} else if (AsciiStrStr(gCPUStructure.BrandString, "W36")) {
gCPUStructure.Cores = 6;
gCPUStructure.Threads = 6;
} else { //other Penryn and Wolfdale
gCPUStructure.Cores = 0;
gCPUStructure.Threads = 0;
}
}
if (gCPUStructure.Cores == 0) {
gCPUStructure.Cores = (UINT8)(gCPUStructure.CoresPerPackage & 0xff);
gCPUStructure.Threads = (UINT8)(gCPUStructure.LogicalPerPackage & 0xff);
if (gCPUStructure.Cores > gCPUStructure.Threads) {
gCPUStructure.Threads = gCPUStructure.Cores;
}
}
//workaround for N270. I don't know why it detected wrong
if ((gCPUStructure.Model == CPU_MODEL_ATOM) &&
(AsciiStrStr(gCPUStructure.BrandString, "270"))) {
gCPUStructure.Cores = 1;
gCPUStructure.Threads = 2;
}
//workaround for Quad
if (AsciiStrStr(gCPUStructure.BrandString, "Quad")) {
gCPUStructure.Cores = 4;
gCPUStructure.Threads = 4;
}
//New for SkyLake 0x4E, 0x5E
if(gCPUStructure.CPUID[CPUID_0][EAX] >= 0x15) {
UINT32 Num, Denom;
DoCpuid(0x15, gCPUStructure.CPUID[CPUID_15]);
Num = gCPUStructure.CPUID[CPUID_15][EBX];
Denom = gCPUStructure.CPUID[CPUID_15][EAX];
DBG(" TSC/CCC Information Leaf:\n");
DBG(" numerator : %d\n", Num);
DBG(" denominator : %d\n", Denom);
if (Num && Denom) {
gCPUStructure.ARTFrequency = DivU64x32(MultU64x32(gCPUStructure.TSCCalibr, Denom), Num);
DBG(" Calibrated ARTFrequency: %lld\n", gCPUStructure.ARTFrequency);
UINT64 Stokg = DivU64x32(gCPUStructure.ARTFrequency + 49999, 100000);
gCPUStructure.ARTFrequency = MultU64x32(Stokg, 100000);
DBG(" Rounded ARTFrequency: %lld\n", gCPUStructure.ARTFrequency);
}
}
//get Min and Max Ratio Cpu/Bus
/* if (QEMU) {
0x06170C2D06000C2DULL
} */
if(gCPUStructure.Vendor == CPU_VENDOR_INTEL &&
((gCPUStructure.Family == 0x06 && gCPUStructure.Model >= 0x0c) ||
(gCPUStructure.Family == 0x0f && gCPUStructure.Model >= 0x03))) {
if (gCPUStructure.Family == 0x06) {
// DBG("Get min and max ratio\n");
switch (gCPUStructure.Model) {
case CPU_MODEL_NEHALEM:// Core i7 LGA1366, Xeon 5500, "Bloomfield", "Gainstown", 45nm
case CPU_MODEL_FIELDS:// Core i7, i5 LGA1156, "Clarksfield", "Lynnfield", "Jasper", 45nm
case CPU_MODEL_DALES:// Core i7, i5, Nehalem
case CPU_MODEL_CLARKDALE:// Core i7, i5, i3 LGA1156, "Westmere", "Clarkdale", , 32nm
case CPU_MODEL_WESTMERE:// Core i7 LGA1366, Six-core, "Westmere", "Gulftown", 32nm
case CPU_MODEL_NEHALEM_EX:// Core i7, Nehalem-Ex Xeon, "Beckton"
case CPU_MODEL_WESTMERE_EX:// Core i7, Nehalem-Ex Xeon, "Eagleton"
//since rev 553 bcc9 patch
gCPUStructure.TSCFrequency = MultU64x32(gCPUStructure.CurrentSpeed, Mega); //MHz -> Hz
gCPUStructure.CPUFrequency = gCPUStructure.TSCFrequency;
msr = AsmReadMsr64(MSR_FLEX_RATIO);
if ((RShiftU64(msr, 16) & 0x01) != 0) {
UINT8 flex_ratio = RShiftU64(msr, 8) & 0xff;
MsgLog("non-usable FLEX_RATIO = %llX\n", msr);
if (flex_ratio == 0) {
AsmWriteMsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
gBS->Stall(10);
msr = AsmReadMsr64(MSR_FLEX_RATIO);
MsgLog("corrected FLEX_RATIO = %llX\n", msr);
}
}
//
msr = AsmReadMsr64(MSR_PLATFORM_INFO); //0xCE
gCPUStructure.MinRatio = (UINT8)RShiftU64(msr, 40) & 0xff;
// msr = AsmReadMsr64(MSR_IA32_PERF_STATUS);
gCPUStructure.MaxRatio = (UINT8)(RShiftU64(msr, 8) & 0xff);
TurboMsr = msr + 1;
if(gCPUStructure.MaxRatio) {
gCPUStructure.FSBFrequency = DivU64x32(gCPUStructure.TSCFrequency, gCPUStructure.MaxRatio);
} else {
gCPUStructure.FSBFrequency = 133333333ULL; // 133 MHz
}
// This makes no sense and seems arbitrary - apianti
if (gCPUStructure.Turbo) {
msr = AsmReadMsr64(MSR_TURBO_RATIO_LIMIT);
gCPUStructure.Turbo1 = (UINT8)(RShiftU64(msr, 0) & 0xff);
gCPUStructure.Turbo2 = (UINT8)(RShiftU64(msr, 8) & 0xff);
gCPUStructure.Turbo3 = (UINT8)(RShiftU64(msr, 16) & 0xff);
gCPUStructure.Turbo4 = (UINT8)(RShiftU64(msr, 24) & 0xff); //later
}
gCPUStructure.MaxRatio *= 10;
gCPUStructure.MinRatio *= 10;
gCPUStructure.Turbo1 *= 10;
gCPUStructure.Turbo2 *= 10;
gCPUStructure.Turbo3 *= 10;
gCPUStructure.Turbo4 *= 10;
break;
case CPU_MODEL_SANDY_BRIDGE:// Sandy Bridge, 32nm
case CPU_MODEL_IVY_BRIDGE:
case CPU_MODEL_IVY_BRIDGE_E5:
case CPU_MODEL_JAKETOWN:
case CPU_MODEL_ATOM_3700:
case CPU_MODEL_HASWELL:
case CPU_MODEL_HASWELL_U5:
case CPU_MODEL_HASWELL_E:
case CPU_MODEL_HASWELL_ULT:
case CPU_MODEL_CRYSTALWELL:
case CPU_MODEL_BROADWELL_HQ:
case CPU_MODEL_BROADWELL_E5:
case CPU_MODEL_BROADWELL_DE:
case CPU_MODEL_AIRMONT:
case CPU_MODEL_SKYLAKE_U:
case CPU_MODEL_SKYLAKE_D:
case CPU_MODEL_SKYLAKE_S:
case CPU_MODEL_GOLDMONT:
case CPU_MODEL_KABYLAKE1:
case CPU_MODEL_KABYLAKE2:
case CPU_MODEL_CANNONLAKE:
case CPU_MODEL_ICELAKE_A:
case CPU_MODEL_ICELAKE_C:
case CPU_MODEL_ICELAKE_D:
case CPU_MODEL_ICELAKE:
case CPU_MODEL_COMETLAKE_S:
case CPU_MODEL_COMETLAKE_Y:
case CPU_MODEL_COMETLAKE_U:
case CPU_MODEL_TIGERLAKE_C:
case CPU_MODEL_TIGERLAKE_D:
gCPUStructure.TSCFrequency = MultU64x32(gCPUStructure.CurrentSpeed, Mega); //MHz -> Hz
gCPUStructure.CPUFrequency = gCPUStructure.TSCFrequency;
//----test C3 patch
msr = AsmReadMsr64(MSR_PKG_CST_CONFIG_CONTROL); //0xE2
MsgLog("MSR 0xE2 before patch %08llX\n", msr);
if (msr & 0x8000) {
MsgLog("MSR 0xE2 is locked, PM patches will be turned on\n");
GlobalConfig.NeedPMfix = TRUE;
}
// AsmWriteMsr64(MSR_PKG_CST_CONFIG_CONTROL, (msr & 0x8000000ULL));
// msr = AsmReadMsr64(MSR_PKG_CST_CONFIG_CONTROL);
// MsgLog("MSR 0xE2 after patch %08X\n", msr);
// msr = AsmReadMsr64(MSR_PMG_IO_CAPTURE_BASE);
// MsgLog("MSR 0xE4 %08X\n", msr);
//------------
msr = AsmReadMsr64(MSR_PLATFORM_INFO); //0xCE
MsgLog("MSR 0xCE %08llX_%08llX\n", (msr>>32), msr & 0xFFFFFFFFull);
gCPUStructure.MaxRatio = (UINT8)RShiftU64(msr, 8) & 0xff;
gCPUStructure.MinRatio = (UINT8)MultU64x32(RShiftU64(msr, 40) & 0xff, 10);
//--- Check if EIST locked
msr = AsmReadMsr64(MSR_IA32_MISC_ENABLE); //0x1A0
if (msr & _Bit(20)) {
MsgLog("MSR 0x1A0 %08llX\n", msr);
MsgLog(" EIST is locked and %s\n", (msr & _Bit(16))?"enabled":"disabled");
}
if (gCPUStructure.Model != CPU_MODEL_GOLDMONT && gCPUStructure.Model != CPU_MODEL_AIRMONT &&
gCPUStructure.Model != CPU_MODEL_AVOTON) {
msr = AsmReadMsr64(MSR_FLEX_RATIO); //0x194
if ((RShiftU64(msr, 16) & 0x01) != 0) {
// bcc9 patch
UINT8 flex_ratio = RShiftU64(msr, 8) & 0xff;
// MsgLog("non-usable FLEX_RATIO = %X\n", msr);
if (flex_ratio == 0) {
AsmWriteMsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
gBS->Stall(10);
msr = AsmReadMsr64(MSR_FLEX_RATIO);
MsgLog("corrected FLEX_RATIO = %llX\n", msr);
}
}
}
if ((gCPUStructure.CPUID[CPUID_6][ECX] & (1 << 3)) != 0) {
msr = AsmReadMsr64(IA32_ENERGY_PERF_BIAS); //0x1B0
MsgLog("MSR 0x1B0 %08llX\n", msr);
}
if(gCPUStructure.MaxRatio) {
gCPUStructure.FSBFrequency = DivU64x32(gCPUStructure.TSCFrequency, gCPUStructure.MaxRatio);
} else {
gCPUStructure.FSBFrequency = 100000000ULL; //100*Mega
}
msr = AsmReadMsr64(MSR_TURBO_RATIO_LIMIT); //0x1AD
gCPUStructure.Turbo1 = (UINT8)(RShiftU64(msr, 0) & 0xff);
gCPUStructure.Turbo2 = (UINT8)(RShiftU64(msr, 8) & 0xff);
gCPUStructure.Turbo3 = (UINT8)(RShiftU64(msr, 16) & 0xff);
gCPUStructure.Turbo4 = (UINT8)(RShiftU64(msr, 24) & 0xff);
if (gCPUStructure.Turbo4 == 0) {
gCPUStructure.Turbo4 = gCPUStructure.Turbo1;
if (gCPUStructure.Turbo4 == 0) {
gCPUStructure.Turbo4 = (UINT16)gCPUStructure.MaxRatio;
}
}
//Slice - we found that for some i5-2400 and i7-2600 MSR 1AD reports wrong turbo mult
// another similar bug in i7-3820
//MSR 000001AD  0000-0000-3B3B-3B3B - from AIDA64
// so there is a workaround
if ((gCPUStructure.Turbo4 == 0x3B) || (gCPUStructure.Turbo4 == 0x39)) {
gCPUStructure.Turbo4 = (UINT16)gCPUStructure.MaxRatio + (gCPUStructure.Turbo?1:0);
//this correspond to 2nd-gen-core-desktop-specification-update.pdf
}
gCPUStructure.MaxRatio *= 10;
gCPUStructure.Turbo1 *= 10;
gCPUStructure.Turbo2 *= 10;
gCPUStructure.Turbo3 *= 10;
gCPUStructure.Turbo4 *= 10;
break;
case CPU_MODEL_PENTIUM_M:
case CPU_MODEL_ATOM:// Atom
case CPU_MODEL_DOTHAN:// Pentium M, Dothan, 90nm
case CPU_MODEL_YONAH:// Core Duo/Solo, Pentium M DC
case CPU_MODEL_MEROM:// Core Xeon, Core 2 Duo, 65nm, Mobile
//case CPU_MODEL_CONROE:// Core Xeon, Core 2 Duo, 65nm, Desktop like Merom but not mobile
case CPU_MODEL_CELERON:
case CPU_MODEL_PENRYN:// Core 2 Duo/Extreme, Xeon, 45nm , Mobile
//case CPU_MODEL_WOLFDALE:// Core 2 Duo/Extreme, Xeon, 45nm, Desktop like Penryn but not Mobile
if(AsmReadMsr64(MSR_IA32_PLATFORM_ID) & (1 << 28)){
gCPUStructure.Mobile = TRUE;
}
gCPUStructure.TSCFrequency = MultU64x32(gCPUStructure.MaxSpeed, Mega); //MHz -> Hz
gCPUStructure.CPUFrequency = gCPUStructure.TSCFrequency;
msr = AsmReadMsr64(MSR_IA32_PERF_STATUS);
gCPUStructure.MaxRatio = (UINT32)(RShiftU64(msr, 8)) & 0x1f;
TurboMsr = (UINT32)(RShiftU64(msr, 40)) & 0x1f;
if ((TurboMsr > gCPUStructure.MaxRatio) && (gCPUStructure.Model == CPU_MODEL_MEROM)) {
DBG(" CPU works at low speed, MaxRatio=%llu CurrRatio=%d\n", TurboMsr,
gCPUStructure.MaxRatio);
gCPUStructure.MaxRatio = (UINT32)TurboMsr;
}
gCPUStructure.SubDivider = (UINT32)(RShiftU64(msr, 46)) & 0x1;
gCPUStructure.MinRatio = 60;
if(!gCPUStructure.MaxRatio) gCPUStructure.MaxRatio = 6; // :(
msr = AsmReadMsr64(MSR_FSB_FREQ); //0xCD
gCPUStructure.FSBFrequency = DivU64x32(LShiftU64(gCPUStructure.TSCFrequency, 1),
gCPUStructure.MaxRatio * 2 + gCPUStructure.SubDivider);
if ((msr & 3) == 2 && (gCPUStructure.FSBFrequency < 196 * Mega)) {
DBG("wrong MaxRatio = %d.%d, corrected\n", gCPUStructure.MaxRatio, gCPUStructure.SubDivider * 5);
gCPUStructure.MaxRatio = (UINT32)DivU64x32(gCPUStructure.TSCFrequency, 200 * Mega);
}
gCPUStructure.MaxRatio = gCPUStructure.MaxRatio * 10 + gCPUStructure.SubDivider * 5;
if (AsciiStrStr(gCPUStructure.BrandString, "P8400")) {
gCPUStructure.MaxRatio = 85;
gCPUStructure.FSBFrequency = DivU64x32(MultU64x32(gCPUStructure.TSCFrequency, 10), gCPUStructure.MaxRatio);
DBG("workaround for Code2Duo P8400, MaxRatio=8.5\n");
}
if (TurboMsr == 6) {
TurboMsr = AsmReadMsr64(MSR_PLATFORM_INFO); //0xCE
gCPUStructure.Turbo4 = ((UINT32)(RShiftU64(TurboMsr, 8)) & 0x1f) * 10; //workaround for Harpertown
} else {
gCPUStructure.Turbo4 = (UINT16)(gCPUStructure.MaxRatio + 10);
}
DBG("MSR dumps:\n");
DBG("\t@0x00CD=%llx\n", msr);
DBG("\t@0x0198=%llx\n", AsmReadMsr64(MSR_IA32_PERF_STATUS));
break;
default:
gCPUStructure.TSCFrequency = MultU64x32(gCPUStructure.CurrentSpeed, Mega); //MHz -> Hz
gCPUStructure.CPUFrequency = gCPUStructure.TSCFrequency;
gCPUStructure.MinRatio = 60;
if (!gCPUStructure.FSBFrequency) {
gCPUStructure.FSBFrequency = 100000000ULL; //100*Mega
}
gCPUStructure.MaxRatio = (UINT32)(MultU64x32(DivU64x64Remainder(gCPUStructure.TSCFrequency, gCPUStructure.FSBFrequency, NULL), 10));
gCPUStructure.CPUFrequency = gCPUStructure.TSCFrequency;
break;
}
}
else //Family !=6 i.e. Pentium 4
{
gCPUStructure.TSCFrequency = MultU64x32((gCPUStructure.Model >= 3) ? gCPUStructure.MaxSpeed : gCPUStructure.CurrentSpeed, Mega); //MHz -> Hz
gCPUStructure.CPUFrequency = gCPUStructure.TSCFrequency;
msr = AsmReadMsr64(MSR_IA32_PLATFORM_ID);
TurboMsr = 0;
if (!gCPUStructure.FSBFrequency) {
gCPUStructure.FSBFrequency = 100000000ULL; //100*Mega
}
if ((RShiftU64(msr, 31) & 0x01) != 0) {
gCPUStructure.MaxRatio = (UINT8)MultU64x32((RShiftU64(msr, 8) & 0x1f), 10);
gCPUStructure.MinRatio = gCPUStructure.MaxRatio; //no speedstep
} else {
gCPUStructure.MaxRatio = (UINT32)DivU64x64Remainder(gCPUStructure.TSCFrequency, gCPUStructure.FSBFrequency, 0);
}
gCPUStructure.CPUFrequency = gCPUStructure.TSCFrequency;
}
}
else if(gCPUStructure.Vendor == CPU_VENDOR_AMD ) {
UINT32 cpudid_zen = 0x17;
INTN currcoef = 0;
INTN cpuMultN2 = 0;
INTN currdiv = 0;
UINT64 busFCvtt2n;
UINT64 tscFCvtt2n;
// UINT64 busFCvtn2t = 0;
UINT64 busFrequency = 0;
UINT64 cpuFrequency = 0;
gCPUStructure.TSCFrequency = MultU64x32(gCPUStructure.CurrentSpeed, Mega); //MHz -> Hz
DBG("CurrentSpeed: %llu\n", DivU64x32(gCPUStructure.TSCFrequency, Mega));
switch (gCPUStructure.Family)
{
//if(gCPUStructure.Extfamily == 0x00 /* K8 */)
/*case 0xf:
{
msr = AsmReadMsr64(K8_FIDVID_STATUS);
gCPUStructure.MaxRatio = (UINT32)(RShiftU64((RShiftU64(msr, 16) & 0x3f), 2) + 4);
gCPUStructure.MinRatio = (UINT32)(RShiftU64((RShiftU64(msr, 8) & 0x3f), 2) + 4);
} break;
*/
//if(gCPUStructure.Family >= 0x01 /* K10+ */) {
case 0xF: //// AMD Family 8h ////
{
UINT64 fidvid = 0;
UINT64 cpuMult;
UINT64 fid;
fidvid = AsmReadMsr64(K8_FIDVID_STATUS);
fid = bitfield(fidvid, 5, 0);
cpuMult = (fid + 8);// / 2;
gCPUStructure.MinRatio = (UINT32)(RShiftU64((RShiftU64(fidvid, 8) & 0x3f), 2) + 4);
currcoef = (INTN)cpuMult;
gCPUStructure.MaxRatio = (UINT32)cpuMult;
cpuMultN2 = (fidvid & (UINT64)bit(0));
currdiv = cpuMultN2;
gCPUStructure.MaxRatio = (gCPUStructure.MaxRatio * 5) ;
/////// Addon END ///////
}
break;
case 0x10: //// AMD Family 10h ////
{
UINT64 msr_min, msr_max;
UINT64 cpuMult;
UINT64 CpuDid;
UINT64 CpuFid;
// UINT64 divisor = 0;
msr_min = AsmReadMsr64(K10_COFVID_LIMIT);
cpudid_zen = (UINT32)bitfield(msr_min, 6 , 4);
msr_min = AsmReadMsr64(K10_PSTATE_STATUS + cpudid_zen);
gCPUStructure.MinRatio = 5 * (UINT32)DivU64(((msr_min & 0x3f) + 0x08), LShiftU64(1ULL, ((RShiftU64(msr_min, 6) & 0x7))));
msr_max = AsmReadMsr64(K10_PSTATE_STATUS);
CpuDid = bitfield(msr_max, 8, 6);
CpuFid = bitfield(msr_max, 5, 0);
/* if (CpuDid == 0) divisor = 2;
else if (CpuDid == 1) divisor = 4;
else if (CpuDid == 2) divisor = 8;
else if (CpuDid == 3) divisor = 16;
else if (CpuDid == 4) divisor = 32;
gCPUStructure.CpuDid = divisor;
*/
cpuMult = DivU64((CpuFid + 0x10), LShiftU64(1ULL, (UINTN)CpuDid));
currcoef = (INTN)cpuMult;
gCPUStructure.MaxRatio = (UINT32)cpuMult;
cpuMultN2 = (msr_max & (UINT64)bit(0));
currdiv = cpuMultN2;
/////// Addon END ///////
}
break;
case 0x11: //// AMD Family 11h ////
{
UINT64 cofvid = 0;
UINT64 cpuMult;
// UINT64 divisor = 0;
UINT64 CpuDid;
UINT64 CpuFid;
UINT64 msr_min = 0;
msr_min = AsmReadMsr64(K10_COFVID_LIMIT);
msr_min = AsmReadMsr64(K10_PSTATE_STATUS + (RShiftU64(msr_min, 4) & 0x07));
gCPUStructure.MinRatio = 5 * (UINT32)DivU64(((msr_min & 0x3f) + 0x08), LShiftU64(1ULL, ((RShiftU64(msr_min, 6) & 0x7))));
cofvid = AsmReadMsr64(K10_PSTATE_STATUS);
CpuDid = bitfield(cofvid, 8, 6);
CpuFid = bitfield(cofvid, 5, 0);
//if (CpuDid == 0) divisor = 2;
//else if (CpuDid == 1) divisor = 4;
//else if (CpuDid == 2) divisor = 8;
//else if (CpuDid == 3) divisor = 16;
//else if (did == 4) divisor = 32;
cpuMult = DivU64((CpuFid + 0x8), LShiftU64(1ULL, (UINTN)CpuDid));
currcoef = (INTN)cpuMult;
gCPUStructure.MaxRatio = (UINT32)cpuMult;
cpuMultN2 = (cofvid & (UINT64)bit(0));
currdiv = cpuMultN2;
/////// Addon END ///////
}
break;
case 0x12: //// AMD Family 12h ////
{
// 8:4 CpuFid: current CPU core frequency ID
// 3:0 CpuDid: current CPU core divisor ID
UINT64 prfsts,CpuFid,CpuDid;
UINT64 msr_min = 0;
msr_min = AsmReadMsr64(K10_COFVID_LIMIT);
msr_min = AsmReadMsr64(K10_PSTATE_STATUS + (RShiftU64(msr_min, 4) & 0x07));
gCPUStructure.MinRatio = 5 * (UINT32)DivU64(((msr_min & 0x3f) + 0x08), LShiftU64(1ULL, ((RShiftU64(msr_min, 0) & 0x7))));
prfsts = AsmReadMsr64(K10_PSTATE_STATUS);
CpuDid = bitfield(prfsts, 3, 0) ;
CpuFid = bitfield(prfsts, 8, 4) ;
//uint64_t divisor;
/*switch (CpuDid)
{
case 0: divisor = 1; break;
case 1: divisor = (3/2); break;
case 2: divisor = 2; break;
case 3: divisor = 3; break;
case 4: divisor = 4; break;
case 5: divisor = 6; break;
case 6: divisor = 8; break;
case 7: divisor = 12; break;
case 8: divisor = 16; break;
default: divisor = 1; break;
}*/
currcoef = (INTN)DivU64((CpuFid + 0x10), LShiftU64(1ULL, (UINTN)CpuDid));
gCPUStructure.MaxRatio = (UINT32)currcoef;
cpuMultN2 = (prfsts & (UINT64)bit(0));
currdiv = cpuMultN2;
}
break;
case 0x14: //// AMD Family 14h ////
{
// 8:4: current CPU core divisor ID most significant digit
// 3:0: current CPU core divisor ID least significant digit
UINT64 prfsts;
UINT64 msr_min = 0;
msr_min = AsmReadMsr64(K10_COFVID_LIMIT);
msr_min = AsmReadMsr64(K10_PSTATE_STATUS + (RShiftU64(msr_min, 4) & 0x07));
gCPUStructure.MinRatio = 5 * (UINT32)DivU64(((msr_min & 0x3f) + 0x08), LShiftU64(1ULL, ((RShiftU64(msr_min, 0) & 0x7))));
prfsts = AsmReadMsr64(K10_PSTATE_STATUS);
UINT64 CpuDidMSD,CpuDidLSD;
CpuDidMSD = bitfield(prfsts, 8, 4) ;
CpuDidLSD = bitfield(prfsts, 3, 0) ;
UINT64 frequencyId = DivU64x32(gCPUStructure.CPUFrequency, Mega);
//Bronya : i think that this fixed, need test this ...
currcoef = (INTN)DivU64((DivU64x32((frequencyId + 5), 100) + 0x10), (UINT64)(CpuDidMSD + DivU64x32(CpuDidLSD, 4) + 1));
gCPUStructure.MaxRatio = (UINT32)currcoef;
currdiv = (INTN)(((CpuDidMSD) + 1) << 2);
currdiv += (INTN)bitfield(prfsts, 3, 0);
cpuMultN2 = currdiv;//(prfsts & (UINT64)bit(0));
//currdiv = cpuMultN2;
}
break;
case 0x15: //// AMD Family 15h ////
case 0x06: //// AMD Family 06h ////
{
UINT64 cofvid = 0;
UINT64 cpuMult;
//UINT64 divisor = 0;
UINT64 CpuDid;
UINT64 CpuFid;
UINT64 msr_min = 0;
msr_min = AsmReadMsr64(K10_COFVID_LIMIT);
msr_min = AsmReadMsr64(K10_PSTATE_STATUS + (RShiftU64(msr_min, 4) & 0x07));
gCPUStructure.MinRatio = 5 * (UINT32)DivU64(((msr_min & 0x3f) + 0x08), LShiftU64(1ULL, ((RShiftU64(msr_min, 6) & 0x7))));
cofvid = AsmReadMsr64(K10_PSTATE_STATUS);
CpuDid = bitfield(cofvid, 8, 6);
CpuFid = bitfield(cofvid, 5, 0);
/* if (CpuDid == 0) divisor = 2;
else if (CpuDid == 1) divisor = 4;
else if (CpuDid == 2) divisor = 8;
else if (CpuDid == 3) divisor = 16;
else if (CpuDid == 4) divisor = 32;
*/
cpuMult = DivU64((CpuFid + 0x10), LShiftU64(1ULL, (UINTN)CpuDid));
currcoef = (INTN)cpuMult;
gCPUStructure.MaxRatio = (UINT32)cpuMult;
//printf("cpuMult %d\n",currcoef);
cpuMultN2 = (cofvid & (UINT64)bit(0));
currdiv = cpuMultN2;
}
break;
case 0x16: //// AMD Family 16h kabini ////
{
UINT64 cofvid = 0;
UINT64 cpuMult;
//UINT64 divisor = 0;
UINT64 CpuDid;
UINT64 CpuFid;
UINT64 msr_min = 0;
msr_min = AsmReadMsr64(K10_COFVID_LIMIT);
msr_min = AsmReadMsr64(K10_PSTATE_STATUS + (RShiftU64(msr_min, 4) & 0x07));
gCPUStructure.MinRatio = 5 * (UINT32)DivU64(((msr_min & 0x3f) + 0x08), LShiftU64(1ULL, ((RShiftU64(msr_min, 6) & 0x7))));
cofvid = AsmReadMsr64(K10_PSTATE_STATUS);
CpuDid = bitfield(cofvid, 8, 6);
CpuFid = bitfield(cofvid, 5, 0);
/* if (CpuDid == 0) divisor = 2;
else if (CpuDid == 1) divisor = 4;
else if (CpuDid == 2) divisor = 8;
else if (CpuDid == 3) divisor = 16;
else if (CpuDid == 4) divisor = 32;
*/
cpuMult = DivU64((CpuFid + 0x10), LShiftU64(1ULL, (UINTN)CpuDid));
currcoef = (INTN)cpuMult;
gCPUStructure.MaxRatio = (UINT32)cpuMult;
cpuMultN2 = (cofvid & (UINT64)bit(0));
currdiv = cpuMultN2;
}
break;
case 0x17: //Bronya: For AMD Family 17h Ryzen ! //
case 0x19: // and 19h Ryzen
{
// CoreCOF = (Core::X86::Msr::PStateDef[CpuFid[7:0]]/Core::X86::Msr::PStateDef[CpuDfsId])*200
//gCPUStructure.MaxRatio = gCPUStructure.TSCFrequency / (100 * Mega);//Mhz ;
UINT64 cofvid = 0 , msr_min = 0;
UINT64 cpuMult;
UINT64 CpuDfsId;
UINT64 CpuFid;
msr_min = AsmReadMsr64(K10_COFVID_LIMIT);
msr_min = AsmReadMsr64(K10_PSTATE_STATUS + (RShiftU64(msr_min, 4) & 0x7));
gCPUStructure.MinRatio = ((UINT32)DivU64x32(((msr_min & 0xFF)), (RShiftU64(msr_min, 8) & 0x3f)))*20;
cofvid = AsmReadMsr64(K10_PSTATE_STATUS);
CpuDfsId = bitfield(cofvid, 13, 8);
CpuFid = bitfield(cofvid, 7, 0);
cpuMult = DivU64(CpuFid, CpuDfsId) * 2 * 2 ; //Bronya: This add * 2 <- Interested ))
//cpuMult = (UINT32)DivU64x32(((cofvid & 0xFF)), (RShiftU64(cofvid, 8) & 0x3f))*2;
currcoef = (INTN)cpuMult;
gCPUStructure.MaxRatio = (UINT32)cpuMult;
cpuMultN2 = (cofvid & (UINT64)bit(0));
currdiv = cpuMultN2;
cpudid_zen = (UINT32)(RShiftU64(cofvid, 8) & 0xff); //for mult
/////// Addon END ///////
}
break;
default:
{
gCPUStructure.MaxRatio = (UINT32)DivU64x32(gCPUStructure.TSCFrequency, (200 * Mega));//hz / (200 * Mega);
currcoef = gCPUStructure.MaxRatio;
}
}
if (currcoef) {
if (currdiv) {
busFrequency = DivU64((gCPUStructure.TSCFrequency * 2), ((currcoef * 2) + 1));
busFCvtt2n = DivU64(((1 * Giga) << 32), busFrequency);
// busFCvtn2t = DivU64(0xFFFFFFFFFFFFFFFFULL, busFCvtt2n);
tscFCvtt2n = DivU64(busFCvtt2n * 2, (1 + (2 * currcoef)));
cpuFrequency = DivU64(((1 * Giga) << 32), tscFCvtt2n);
gCPUStructure.FSBFrequency = busFrequency ;
gCPUStructure.CPUFrequency = cpuFrequency ;
//gCPUStructure.MaxRatio = cpuFrequency / busFrequency;
// DBG("maxratio (n/2) %d.%d\n", (gCPUStructure.MaxRatio) / currdiv, (((gCPUStructure.MaxRatio) % currdiv) * 100) / currdiv);
DBG("cpudid_zen(n/2) %d\n", cpudid_zen);
// DBG("busFrequency(N/2): %d \n currcoef(N/2): %hhd \n cpuFrequency(N/2): %lld \n tscFreq(N/2): %lld",(uint32_t)(busFrequency / Mega),currcoef,cpuFrequency /1000,tscFreq/1000);
} else {
//currcoef = tscFreq / (200 * Mega);//hz / (200 * Mega);
busFrequency = DivU64(gCPUStructure.TSCFrequency, currcoef);
busFCvtt2n = DivU64(((1 * Giga) << 32), busFrequency);
// busFCvtn2t = DivU64(0xFFFFFFFFFFFFFFFFULL, busFCvtt2n);
tscFCvtt2n = DivU64(busFCvtt2n, currcoef);
cpuFrequency = DivU64(((1 * Giga) << 32), tscFCvtt2n);
gCPUStructure.FSBFrequency = busFrequency;
gCPUStructure.CPUFrequency = cpuFrequency;
//gCPUStructure.MaxRatio = cpuFrequency / busFrequency;
DBG("maxratio %d\n", gCPUStructure.MaxRatio);
DBG("cpudid_zen %d\n", cpudid_zen);
//DBG("busFrequency: %6d MHz \n, cpuMult: %lld \n, cpuFrequency: %lld \n",(uint32_t)(busFrequency / Mega),currcoef, cpuFrequency);
}
}
// gCPUStructure.MaxRatio >>= 1;
if (!gCPUStructure.MaxRatio) {
gCPUStructure.MaxRatio = 1; //??? to avoid zero division
}
//gCPUStructure.FSBFrequency = DivU64x32(LShiftU64(gCPUStructure.TSCFrequency, 1), gCPUStructure.MaxRatio);
gCPUStructure.MaxRatio = (gCPUStructure.MaxRatio * 5) ;
// gCPUStructure.FSBFrequency = DivU64x32(LShiftU64(gCPUStructure.CPUFrequency, 1), gCPUStructure.MaxRatio);
}
// ExternalClock and QPI were fixed by Sherlocks
// Read original ExternalClock
switch (gCPUStructure.Model)
{
case CPU_MODEL_PENTIUM_M:
case CPU_MODEL_ATOM:// Atom
case CPU_MODEL_DOTHAN:// Pentium M, Dothan, 90nm
case CPU_MODEL_YONAH:// Core Duo/Solo, Pentium M DC
case CPU_MODEL_MEROM:// Core Xeon, Core 2 Duo, 65nm, Mobile
//case CPU_MODEL_CONROE:// Core Xeon, Core 2 Duo, 65nm, Desktop like Merom but not mobile
case CPU_MODEL_CELERON:
case CPU_MODEL_PENRYN:// Core 2 Duo/Extreme, Xeon, 45nm , Mobile
case CPU_MODEL_NEHALEM:// Core i7 LGA1366, Xeon 5500, "Bloomfield", "Gainstown", 45nm
case CPU_MODEL_FIELDS:// Core i7, i5 LGA1156, "Clarksfield", "Lynnfield", "Jasper", 45nm
case CPU_MODEL_DALES:// Core i7, i5, Nehalem
case CPU_MODEL_CLARKDALE:// Core i7, i5, i3 LGA1156, "Westmere", "Clarkdale", , 32nm
case CPU_MODEL_WESTMERE:// Core i7 LGA1366, Six-core, "Westmere", "Gulftown", 32nm
case CPU_MODEL_NEHALEM_EX:// Core i7, Nehalem-Ex Xeon, "Beckton"
case CPU_MODEL_WESTMERE_EX:// Core i7, Nehalem-Ex Xeon, "Eagleton"
ExternalClock = gCPUStructure.ExternalClock;
//DBG("Read original ExternalClock: %d MHz\n", (INT32)(DivU64x32(ExternalClock, Kilo)));
break;
default:
ExternalClock = gCPUStructure.ExternalClock;
//DBG("Read original ExternalClock: %d MHz\n", (INT32)(DivU64x32(ExternalClock, Kilo)));
// for sandy bridge or newer
// to match ExternalClock 25 MHz like real mac, divide ExternalClock by 4
gCPUStructure.ExternalClock = (ExternalClock + 3) / 4;
//DBG("Corrected ExternalClock: %d MHz\n", (INT32)(DivU64x32(gCPUStructure.ExternalClock, Kilo)));
break;
}
// DBG("take FSB\n");
tmpU = gCPUStructure.FSBFrequency;
// DBG("divide by 1000\n");
BusSpeed = (UINT32)DivU64x32(tmpU, Kilo); //Hz -> kHz
DBG("FSBFrequency = %llu MHz, DMI FSBFrequency = %llu MHz, ", DivU64x32 (tmpU + Mega - 1, Mega), DivU64x32 (ExternalClock + 499, Kilo));
//now check if SMBIOS has ExternalClock = 4xBusSpeed
if ((BusSpeed > 50*Kilo) &&
((ExternalClock > BusSpeed * 3) || (ExternalClock < 50*Kilo))) { //khz
gCPUStructure.ExternalClock = BusSpeed;
} else {
tmpU = MultU64x32(ExternalClock, Kilo); //kHz -> Hz
gCPUStructure.FSBFrequency = tmpU;
}
tmpU = gCPUStructure.FSBFrequency;
DBG("Corrected FSBFrequency = %llu MHz\n", DivU64x32(tmpU, Mega));
if ((gCPUStructure.Vendor == CPU_VENDOR_INTEL) && (gCPUStructure.Model == CPU_MODEL_NEHALEM)) {
//Slice - for Nehalem we can do more calculation as in Cham
// but this algo almost always wrong
//
// thanks to dgobe for i3/i5/i7 bus speed detection
// TODO: consider more Nehalem based CPU(?) ex. CPU_MODEL_NEHALEM_EX, CPU_MODEL_WESTMERE, CPU_MODEL_WESTMERE_EX
// info: https://en.wikipedia.org/wiki/List_of_Intel_Xeon_microprocessors#Nehalem-based_Xeons
qpimult = 2; //init
/* Scan PCI BUS For QPI Frequency */
// get all PciIo handles
Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &HandleBuffer);
if (Status == EFI_SUCCESS) {
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
Status = gBS->HandleProtocol(HandleBuffer[HandleIndex], &gEfiPciIoProtocolGuid, (void **) &PciIo);
if (!EFI_ERROR(Status)) {
/* Read PCI BUS */
Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
if ((Bus & 0x3F) != 0x3F) {
continue;
}
Status = PciIo->Pci.Read (
PciIo,
EfiPciIoWidthUint32,
0,
sizeof (Pci) / sizeof (UINT32),
&Pci
);
vid = Pci.Hdr.VendorId & 0xFFFF;
did = Pci.Hdr.DeviceId & 0xFF00;
if ((vid == 0x8086) && (did >= 0x2C00)
//Slice - why 2:1? Intel spec said 3:4 - QCLK_RATIO at offset 0x50
// && (Device == 2) && (Function == 1)) {
&& (Device == 3) && (Function == 4)) {
DBG("Found QCLK_RATIO at bus 0x%02llX dev=%llX funs=%llX\n", Bus, Device, Function);
Status = PciIo->Mem.Read (
PciIo,
EfiPciIoWidthUint32,
EFI_PCI_IO_PASS_THROUGH_BAR,
0x50,
1,
&qpimult
);
DBG("qpi read from PCI %X\n", qpimult & 0x1F);
if (EFI_ERROR(Status)) continue;
qpimult &= 0x1F; //bits 0:4
break;
}
}
}
}
DBG("qpimult %d\n", qpimult);
qpibusspeed = MultU64x32(gCPUStructure.ExternalClock, qpimult * 2); //kHz
DBG("qpibusspeed %llukHz\n", qpibusspeed);
gCPUStructure.ProcessorInterconnectSpeed = DivU64x32(qpibusspeed, Kilo); //kHz->MHz
// set QPI for Nehalem
gSettings.QPI = (UINT16)gCPUStructure.ProcessorInterconnectSpeed;
} else {
gCPUStructure.ProcessorInterconnectSpeed = DivU64x32(LShiftU64(gCPUStructure.ExternalClock, 2), Kilo); //kHz->MHz
}
gCPUStructure.MaxSpeed = (UINT32)(DivU64x32(MultU64x64(gCPUStructure.FSBFrequency, gCPUStructure.MaxRatio), Mega * 10)); //kHz->MHz
// DBG("Vendor/Model/Stepping: 0x%X/0x%X/0x%X\n", gCPUStructure.Vendor, gCPUStructure.Model, gCPUStructure.Stepping);
// DBG("Family/ExtFamily: 0x%X/0x%X\n", gCPUStructure.Family, gCPUStructure.Extfamily);
DBG("MaxDiv/MinDiv: %d.%d/%d\n", gCPUStructure.MaxRatio/10, gCPUStructure.MaxRatio%10 , gCPUStructure.MinRatio/10);
DBG("Turbo: %d/%d/%d/%d\n", gCPUStructure.Turbo4/10, gCPUStructure.Turbo3/10, gCPUStructure.Turbo2/10, gCPUStructure.Turbo1/10);
DBG("Features: 0x%llX\n",gCPUStructure.Features);
DBG("Threads: %d\n",gCPUStructure.Threads);
DBG("Cores: %d\n",gCPUStructure.Cores);
DBG("FSB: %d MHz\n", (INT32)(DivU64x32(gCPUStructure.FSBFrequency, Mega)));
DBG("CPU: %d MHz\n", (INT32)(DivU64x32(gCPUStructure.CPUFrequency, Mega)));
DBG("TSC: %d MHz\n", (INT32)(DivU64x32(gCPUStructure.TSCFrequency, Mega)));
DBG("PIS: %d MHz\n", (INT32)gCPUStructure.ProcessorInterconnectSpeed);
DBG("ExternalClock: %d MHz\n", (INT32)(DivU64x32(gCPUStructure.ExternalClock + 499, Kilo)));
//#if DEBUG_PCI
// WaitForKeyPress("waiting for key press...\n");
//#endif
// return;
}
void SetCPUProperties (void)
{
UINT64 msr = 0;
if ((gCPUStructure.CPUID[CPUID_6][ECX] & (1 << 3)) != 0) {
if (gSettings.SavingMode != 0xFF) {
msr = gSettings.SavingMode;
AsmWriteMsr64(IA32_ENERGY_PERF_BIAS, msr);
msr = AsmReadMsr64(IA32_ENERGY_PERF_BIAS); //0x1B0
MsgLog("MSR 0x1B0 set to %llX\n", msr);
}
}
}
//PCI info
/*
typedef struct {
UINT16 VendorId;
UINT16 DeviceId;
UINT16 Command;
UINT16 Status;
UINT8 RevisionID;
UINT8 ClassCode[3];
UINT8 CacheLineSize;
UINT8 LatencyTimer;
UINT8 HeaderType;
UINT8 BIST;
} PCI_DEVICE_INDEPENDENT_REGION;
///
/// PCI Device header region in PCI Configuration Space
/// Section 6.1, PCI Local Bus Specification, 2.2
///
typedef struct {
UINT32 Bar[6];
UINT32 CISPtr;
UINT16 SubsystemVendorID;
UINT16 SubsystemID;
UINT32 ExpansionRomBar;
UINT8 CapabilityPtr;
UINT8 Reserved1[3];
UINT32 Reserved2;
UINT8 InterruptLine;
UINT8 InterruptPin;
UINT8 MinGnt;
UINT8 MaxLat;
} PCI_DEVICE_HEADER_TYPE_REGION;
///
/// PCI Device Configuration Space
/// Section 6.1, PCI Local Bus Specification, 2.2
///
typedef struct {
PCI_DEVICE_INDEPENDENT_REGION Hdr;
PCI_DEVICE_HEADER_TYPE_REGION Device;
} PCI_TYPE00;
// Definitions of PCI Config Registers
enum {
kIOPCIConfigVendorID = 0x00,
kIOPCIConfigDeviceID = 0x02,
kIOPCIConfigCommand = 0x04,
kIOPCIConfigStatus = 0x06,
kIOPCIConfigRevisionID = 0x08,
kIOPCIConfigClassCode = 0x09,
kIOPCIConfigCacheLineSize = 0x0C,
kIOPCIConfigLatencyTimer = 0x0D,
kIOPCIConfigHeaderType = 0x0E,
kIOPCIConfigBIST = 0x0F,
kIOPCIConfigBaseAddress0 = 0x10,
kIOPCIConfigBaseAddress1 = 0x14,
kIOPCIConfigBaseAddress2 = 0x18,
kIOPCIConfigBaseAddress3 = 0x1C,
kIOPCIConfigBaseAddress4 = 0x20,
kIOPCIConfigBaseAddress5 = 0x24,
kIOPCIConfigCardBusCISPtr = 0x28,
kIOPCIConfigSubSystemVendorID = 0x2C,
kIOPCIConfigSubSystemID = 0x2E,
kIOPCIConfigExpansionROMBase = 0x30,
kIOPCIConfigCapabilitiesPtr = 0x34,
kIOPCIConfigInterruptLine = 0x3C,
kIOPCIConfigInterruptPin = 0x3D,
kIOPCIConfigMinimumGrant = 0x3E,
kIOPCIConfigMaximumLatency = 0x3F
};
*/
UINT16 GetStandardCpuType()
{
if (gCPUStructure.Threads >= 4) {
return 0x402; // Quad-Core Xeon
}
else if (gCPUStructure.Threads == 1) {
return 0x201; // Core Solo
}
return 0x301; // Core 2 Duo
}
UINT16 GetAdvancedCpuType ()
{
if (gCPUStructure.Vendor == CPU_VENDOR_INTEL) {
switch (gCPUStructure.Family) {
case 0x06:
{
switch (gCPUStructure.Model) {
case CPU_MODEL_PENTIUM_M:
case CPU_MODEL_DOTHAN:// Dothan
case CPU_MODEL_YONAH: // Yonah
return 0x201;
case CPU_MODEL_CELERON: //M520
case CPU_MODEL_MEROM: // Merom
case CPU_MODEL_PENRYN:// Penryn
if (AsciiStrStr(gCPUStructure.BrandString, "Xeon"))
return 0x402; // Xeon
case CPU_MODEL_ATOM: // Atom (45nm)
return GetStandardCpuType();
case CPU_MODEL_NEHALEM_EX: //Xeon 5300
return 0x402;
case CPU_MODEL_NEHALEM: // Intel Core i7 LGA1366 (45nm)
if (AsciiStrStr(gCPUStructure.BrandString, "Xeon"))
return 0x501; // Xeon
return 0x701; // Core i7
case CPU_MODEL_FIELDS: // Lynnfield, Clarksfield, Jasper
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i5"))
return 0x601; // Core i5
return 0x701; // Core i7
case CPU_MODEL_DALES: // Intel Core i5, i7 LGA1156 (45nm) (Havendale, Auburndale)
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i3"))
return 0x901; // Core i3 //why not 902? Ask Apple
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i5"))
return 0x602; // Core i5
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i7"))
return 0x702; // Core i7
if (gCPUStructure.Cores <= 2) {
return 0x602;
}
return 0x702; // Core i7
//case CPU_MODEL_ARRANDALE:
case CPU_MODEL_CLARKDALE: // Intel Core i3, i5, i7 LGA1156 (32nm) (Clarkdale, Arrandale)
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i3"))
return 0x901; // Core i3
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i5"))
return 0x601; // Core i5 - (M540 -> 0x0602)
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i7"))
return 0x701; // Core i7
if (gCPUStructure.Cores <= 2) {
return 0x601;
}
return 0x701; // Core i7
case CPU_MODEL_WESTMERE: // Intel Core i7 LGA1366 (32nm) 6 Core (Gulftown, Westmere-EP, Westmere-WS)
case CPU_MODEL_WESTMERE_EX: // Intel Core i7 LGA1366 (45nm) 6 Core ???
if (AsciiStrStr(gCPUStructure.BrandString, "Xeon"))
return 0x501; // Xeon
return 0x701; // Core i7
case CPU_MODEL_SANDY_BRIDGE:
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i3"))
return 0x903; // Core i3
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i5"))
return 0x603; // Core i5
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i7"))
return 0x703; // Core i7
if (gCPUStructure.Cores <= 2) {
return 0x603;
}
return 0x703;
case CPU_MODEL_IVY_BRIDGE:
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i3"))
return 0x903; // Core i3 - Apple doesn't use it
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i5"))
return 0x604; // Core i5
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i7"))
return 0x704; // Core i7
if (gCPUStructure.Cores <= 2) {
return 0x604;
}
return 0x704;
case CPU_MODEL_HASWELL_U5:
// case CPU_MODEL_SKYLAKE_S:
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) M"))
return 0xB06; // Core M
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i3"))
return 0x906; // Core i3 - Apple doesn't use it
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i5"))
return 0x606; // Core i5
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i7"))
return 0x706; // Core i7
if (gCPUStructure.Cores <= 2) {
return 0x606;
}
return 0x706;
case CPU_MODEL_HASWELL_E:
return 0x507;
case CPU_MODEL_IVY_BRIDGE_E5:
return 0xA01;
case CPU_MODEL_BROADWELL_E5:
return 0xA02; //0xA02 or 0xA03
case CPU_MODEL_ATOM_3700:
case CPU_MODEL_HASWELL:
case CPU_MODEL_HASWELL_ULT:
case CPU_MODEL_CRYSTALWELL:
case CPU_MODEL_BROADWELL_HQ:
case CPU_MODEL_SKYLAKE_U:
case CPU_MODEL_SKYLAKE_D:
case CPU_MODEL_SKYLAKE_S:
case CPU_MODEL_KABYLAKE1:
case CPU_MODEL_KABYLAKE2:
case CPU_MODEL_CANNONLAKE:
case CPU_MODEL_ICELAKE_A:
case CPU_MODEL_ICELAKE_C:
case CPU_MODEL_ICELAKE_D:
case CPU_MODEL_ICELAKE:
case CPU_MODEL_COMETLAKE_S:
case CPU_MODEL_COMETLAKE_Y:
case CPU_MODEL_COMETLAKE_U:
case CPU_MODEL_TIGERLAKE_C:
case CPU_MODEL_TIGERLAKE_D:
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i3"))
return 0x905; // Core i3 - Apple doesn't use it
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i5"))
return 0x605; // Core i5
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i7-8"))
return 0x709; // Core i7 CoffeeLake
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i7-9"))
return 0x1005; // Core i7 CoffeeLake
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i7-1"))
return 0x070B; // Core i7 IceLake
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i7"))
return 0x705; // Core i7
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) i9"))
return 0x1009; // Core i7 CoffeeLake
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) m3"))
return 0xC05;
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) m5"))
return 0xD05;
if (AsciiStrStr(gCPUStructure.BrandString, "Core(TM) m7"))
return 0xE05;
if (AsciiStrStr(gCPUStructure.BrandString, "Xeon"))
return 0xF01;
if (gCPUStructure.Cores <= 2) {
return 0x605;
}
return 0x705;
}
}
}
}
return GetStandardCpuType();
}
MACHINE_TYPES GetDefaultModel()
{
MACHINE_TYPES DefaultType = iMac132;
if (gCPUStructure.Vendor != CPU_VENDOR_INTEL) {
return MacPro31;
}
// TODO: Add more CPU models and configure the correct machines per CPU/GFX model
if(gMobile) {
switch (gCPUStructure.Model)
{
case CPU_MODEL_ATOM:
DefaultType = MacBookAir31; //MacBookAir1,1 doesn't support _PSS for speedstep!
break;
case CPU_MODEL_DOTHAN:
DefaultType = MacBook11;
break;
case CPU_MODEL_YONAH:
case CPU_MODEL_PENTIUM_M:
DefaultType = MacBook11;
break;
case CPU_MODEL_CELERON:
case CPU_MODEL_MEROM:
DefaultType = MacBook21;
break;
case CPU_MODEL_PENRYN:
if ((gGraphics[0].Vendor == Nvidia) ||
(gGraphics[1].Vendor == Nvidia)) {
DefaultType = MacBookPro51;
} else
DefaultType = MacBook41;
break;
case CPU_MODEL_CLARKDALE:
DefaultType = MacBookPro62;
break;
case CPU_MODEL_JAKETOWN:
case CPU_MODEL_SANDY_BRIDGE:
if((AsciiStrStr(gCPUStructure.BrandString, "i3")) ||
(AsciiStrStr(gCPUStructure.BrandString, "i5"))) {
DefaultType = MacBookPro81;
break;
}
DefaultType = MacBookPro83;
break;
case CPU_MODEL_IVY_BRIDGE:
case CPU_MODEL_IVY_BRIDGE_E5:
DefaultType = MacBookAir52;
break;
case CPU_MODEL_HASWELL:
case CPU_MODEL_HASWELL_E:
case CPU_MODEL_ATOM_3700:
DefaultType = MacBookAir62;
break;
case CPU_MODEL_HASWELL_ULT:
case CPU_MODEL_CRYSTALWELL:
case CPU_MODEL_BROADWELL_HQ:
DefaultType = MacBookPro111;
break;
case CPU_MODEL_HASWELL_U5: // Broadwell Mobile
if(AsciiStrStr(gCPUStructure.BrandString, "M")) {
DefaultType = MacBook81;
break;
}
DefaultType = MacBookPro121;
break;
case CPU_MODEL_SKYLAKE_U:
if(AsciiStrStr(gCPUStructure.BrandString, "m")) {
DefaultType = MacBook91;
break;
}
DefaultType = MacBookPro131;
break;
case CPU_MODEL_KABYLAKE1:
if(AsciiStrStr(gCPUStructure.BrandString, "Y")) {
DefaultType = MacBook101;
break;
}
DefaultType = MacBookPro141;
break;
case CPU_MODEL_SKYLAKE_D:
DefaultType = MacBookPro133;
break;
case CPU_MODEL_KABYLAKE2:
DefaultType = MacBookPro143;
break;
default:
if ((gGraphics[0].Vendor == Nvidia) ||
(gGraphics[1].Vendor == Nvidia)) {
DefaultType = MacBookPro51;
} else
DefaultType = MacBookPro83;
break;
}
} else {
switch (gCPUStructure.Model) {
case CPU_MODEL_CELERON:
DefaultType = MacMini21;
break;
case CPU_MODEL_LINCROFT:
DefaultType = MacMini21;
break;
case CPU_MODEL_ATOM:
DefaultType = MacMini21;
break;
case CPU_MODEL_CONROE: //Conroe
// DefaultType = iMac81;
// break;
case CPU_MODEL_WOLFDALE: //Wolfdale, Hapertown
DefaultType = iMac101; //MacPro31 - speedstep without patching; but it is Hackintosh
break;
case CPU_MODEL_NEHALEM:
DefaultType = iMac111;
break;
case CPU_MODEL_NEHALEM_EX:
DefaultType = MacPro41;
break;
case CPU_MODEL_FIELDS:
if(AsciiStrStr(gCPUStructure.BrandString, "Xeon")) {
DefaultType = MacPro41;
break;
}
DefaultType = iMac113;
break;
case CPU_MODEL_DALES:
DefaultType = iMac112;
break;
case CPU_MODEL_CLARKDALE:
DefaultType = iMac112;
break;
case CPU_MODEL_WESTMERE:
DefaultType = MacPro51;
break;
case CPU_MODEL_WESTMERE_EX:
DefaultType = MacPro51;
break;
case CPU_MODEL_SANDY_BRIDGE:
if (gGraphics[0].Vendor == Intel) {
DefaultType = MacMini51;
break;
}
if((AsciiStrStr(gCPUStructure.BrandString, "i3")) ||
(AsciiStrStr(gCPUStructure.BrandString, "i5"))) {
DefaultType = iMac121;
break;
}
if(AsciiStrStr(gCPUStructure.BrandString, "i7")) {
DefaultType = iMac122;
break;
}
DefaultType = MacPro51;
break;
case CPU_MODEL_IVY_BRIDGE:
case CPU_MODEL_IVY_BRIDGE_E5:
DefaultType = iMac132;
if (gGraphics[0].Vendor == Intel) {
DefaultType = MacMini62;
break;
}
if (AsciiStrStr(gCPUStructure.BrandString, "i3")) {
DefaultType = iMac131;
break;
}
break;
case CPU_MODEL_JAKETOWN:
DefaultType = MacPro41;
break;
case CPU_MODEL_HASWELL_U5:
DefaultType = iMac151;
break;
case CPU_MODEL_SKYLAKE_D:
case CPU_MODEL_SKYLAKE_S:
DefaultType = iMac171;
break;
case CPU_MODEL_KABYLAKE1:
case CPU_MODEL_KABYLAKE2:
if (AsciiStrStr(gCPUStructure.BrandString, "i5")) {
DefaultType = iMac182;
break;
}
DefaultType = iMac183;
break;
case CPU_MODEL_HASWELL:
case CPU_MODEL_HASWELL_E:
DefaultType = iMac142;
if (AsciiStrStr(gCPUStructure.BrandString, "70S")) {
DefaultType = iMac141;
break;
}
break;
case CPU_MODEL_BROADWELL_E5:
DefaultType = MacPro61;
break;
default:
DefaultType = iMac132;
break;
}
}
return DefaultType;
}