📄 hwcpu.c
字号:
/*
* FreeLoader
*
* Copyright (C) 2003 Eric Kohl
* Copyright (C) 2006 Colin Finck <mail@colinfinck.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <freeldr.h>
#define NDEBUG
#include <debug.h>
#define HZ (100)
#define CLOCK_TICK_RATE (1193182)
#define LATCH (CLOCK_TICK_RATE / HZ)
#define CALIBRATE_LATCH (5 * LATCH)
#define CALIBRATE_TIME (5 * 1000020/HZ)
#define MP_FP_SIGNATURE 0x5F504D5F /* "_MP_" */
#define MP_CT_SIGNATURE 0x504D4350 /* "PCMP" */
typedef struct _MP_FLOATING_POINT_TABLE
{
ULONG Signature; /* "_MP_" */
ULONG PhysicalAddressPointer;
UCHAR Length;
UCHAR SpecRev;
UCHAR Checksum;
UCHAR FeatureByte[5];
} PACKED MP_FLOATING_POINT_TABLE, *PMP_FLOATING_POINT_TABLE;
typedef struct _MPS_CONFIG_TABLE_HEADER
{
ULONG Signature; /* "PCMP" */
USHORT BaseTableLength;
UCHAR SpecRev;
UCHAR Checksum;
UCHAR OemIdString[8];
UCHAR ProductIdString[12];
ULONG OemTablePointer;
USHORT OemTableLength;
USHORT EntryCount;
ULONG AddressOfLocalAPIC;
USHORT ExtendedTableLength;
UCHAR ExtendedTableChecksum;
UCHAR Reserved;
} PACKED MP_CONFIGURATION_TABLE, *PMP_CONFIGURATION_TABLE;
typedef struct _MP_PROCESSOR_ENTRY
{
UCHAR EntryType;
UCHAR LocalApicId;
UCHAR LocalApicVersion;
UCHAR CpuFlags;
ULONG CpuSignature;
ULONG FeatureFlags;
ULONG Reserved1;
ULONG Reserved2;
} PACKED MP_PROCESSOR_ENTRY, *PMP_PROCESSOR_ENTRY;
/* FUNCTIONS ****************************************************************/
static ULONG
GetCpuSpeed(BOOLEAN DualCoreSpeedMesure)
{
ULONGLONG Timestamp1;
ULONGLONG Timestamp2;
ULONGLONG Diff;
ULONG Count = 0;
/*
FIXME
if the DualCoreSpeedMesure is true we need
use the wrmsr and rdmsr to mesure the speed
The rdtc are outdate to use if cpu support
the wrmsr and rdmsr, see intel doc AP-485
for more informations and how to use it.
Follow code is good on cpu that does not
support dual core or have a mmx unit or
more.
*/
/* Initialise timer channel 2 */
/* Set the Gate high, disable speaker */
WRITE_PORT_UCHAR((PUCHAR)0x61, (READ_PORT_UCHAR((PUCHAR)0x61) & ~0x02) | 0x01);
WRITE_PORT_UCHAR((PUCHAR)0x43, 0xB0); /* binary, mode 0, LSB/MSB, ch 2 */
WRITE_PORT_UCHAR((PUCHAR)0x42, CALIBRATE_LATCH & 0xff); /* LSB */
WRITE_PORT_UCHAR((PUCHAR)0x42, CALIBRATE_LATCH >> 8); /* MSB */
/* Read TSC (Time Stamp Counter) */
Timestamp1 = RDTSC();
/* Wait */
do
{
Count++;
}
while ((READ_PORT_UCHAR((PUCHAR)0x61) & 0x20) == 0);
/* Read TSC (Time Stamp Counter) again */
Timestamp2 = RDTSC();
/* Calculate elapsed time (check for counter overrun) */
if (Timestamp2 > Timestamp1)
{
Diff = Timestamp2 - Timestamp1;
}
else
{
Diff = Timestamp2 + (((ULONGLONG)-1) - Timestamp1);
}
return (ULONG)(Diff / CALIBRATE_TIME);
}
static VOID
DetectCPU(FRLDRHKEY CpuKey,
FRLDRHKEY FpuKey)
{
WCHAR VendorIdentifier[13];
WCHAR ProcessorNameString[49];
CHAR tmpVendorIdentifier[13];
CHAR tmpProcessorNameString[49];
WCHAR Identifier[64];
ULONG FeatureSet;
FRLDRHKEY CpuInstKey;
FRLDRHKEY FpuInstKey;
ULONG eax = 0;
ULONG ebx = 0;
ULONG ecx = 0;
ULONG edx = 0;
ULONG i;
ULONG *Ptr;
LONG Error;
BOOLEAN SupportTSC = FALSE;
ULONG CpuSpeed;
BOOLEAN DualCoreSpeedMesure = FALSE;
/* Create the CPU instance key */
Error = RegCreateKey(CpuKey,
L"0",
&CpuInstKey);
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
return;
}
/* Create the FPU instance key */
Error = RegCreateKey(FpuKey,
L"0",
&FpuInstKey);
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
return;
}
eax = CpuidSupported();
if (eax & 1)
{
DbgPrint((DPRINT_HWDETECT, "CPUID supported\n"));
/* Get vendor identifier */
GetCpuid(0, &eax, &ebx, &ecx, &edx);
tmpVendorIdentifier[12] = 0;
Ptr = (ULONG*)&tmpVendorIdentifier[0];
*Ptr = ebx;
Ptr++;
*Ptr = edx;
Ptr++;
*Ptr = ecx;
swprintf(VendorIdentifier, L"%S", tmpVendorIdentifier);
/* Get Identifier */
GetCpuid(1, &eax, &ebx, &ecx, &edx);
swprintf(Identifier,
L"x86 Family %u Model %u Stepping %u",
(unsigned int)((eax >> 8) & 0x0F),
(unsigned int)((eax >> 4) & 0x0F),
(unsigned int)(eax & 0x0F));
FeatureSet = edx;
if ((FeatureSet & 0x10) == 0x10)
SupportTSC = TRUE;
if ((FeatureSet & 0x20) == 0x20)
DualCoreSpeedMesure = TRUE;
/* Check if Extended CPUID information is supported */
GetCpuid(0x80000000, &eax, &ebx, &ecx, &edx);
if(eax >= 0x80000004)
{
/* Get Processor Name String */
tmpProcessorNameString[48] = 0;
Ptr = (ULONG*)&tmpProcessorNameString[0];
for (i = 0x80000002; i <= 0x80000004; i++)
{
GetCpuid(i, &eax, &ebx, &ecx, &edx);
*Ptr = eax;
Ptr++;
*Ptr = ebx;
Ptr++;
*Ptr = ecx;
Ptr++;
*Ptr = edx;
Ptr++;
}
swprintf(ProcessorNameString, L"%S", tmpProcessorNameString);
/* Set 'ProcessorNameString' value (CPU only) */
DbgPrint((DPRINT_HWDETECT, "Processor Name String: %S\n", ProcessorNameString));
Error = RegSetValue(CpuInstKey,
L"ProcessorNameString",
REG_SZ,
(PCHAR)ProcessorNameString,
(wcslen(ProcessorNameString) + 1) * sizeof(WCHAR));
if (Error != ERROR_SUCCESS)
DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
}
}
else
{
DbgPrint((DPRINT_HWDETECT, "CPUID not supported\n"));
wcscpy(VendorIdentifier, L"Unknown");
swprintf(Identifier,
L"x86 Family %u Model %u Stepping %u",
(unsigned int)((eax >> 8) & 0x0F),
(unsigned int)((eax >> 4) & 0x0F),
(unsigned int)(eax & 0x0F));
FeatureSet = 0;
}
/* Set 'Conmponent Information' value (CPU and FPU) */
SetComponentInformation(CpuInstKey, 0, 0, 1);
SetComponentInformation(FpuInstKey, 0, 0, 1);
/* Set 'FeatureSet' value (CPU only) */
DbgPrint((DPRINT_HWDETECT, "FeatureSet: %x\n", FeatureSet));
Error = RegSetValue(CpuInstKey,
L"FeatureSet",
REG_DWORD,
(PCHAR)&FeatureSet,
sizeof(ULONG));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
}
/* Set 'Identifier' value (CPU and FPU) */
DbgPrint((DPRINT_HWDETECT, "Identifier: %S\n", Identifier));
Error = RegSetValue(CpuInstKey,
L"Identifier",
REG_SZ,
(PCHAR)Identifier,
(wcslen(Identifier) + 1) * sizeof(WCHAR));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
}
Error = RegSetValue(FpuInstKey,
L"Identifier",
REG_SZ,
(PCHAR)Identifier,
(wcslen(Identifier) + 1) * sizeof(WCHAR));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
}
/* Set 'VendorIdentifier' value (CPU only) */
DbgPrint((DPRINT_HWDETECT, "Vendor Identifier: %S\n", VendorIdentifier));
Error = RegSetValue(CpuInstKey,
L"VendorIdentifier",
REG_SZ,
(PCHAR)VendorIdentifier,
(wcslen(VendorIdentifier) + 1) * sizeof(WCHAR));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
}
/* FIXME: Set 'Update Signature' value (CPU only) */
/* FIXME: Set 'Update Status' value (CPU only) */
/* Set '~MHz' value (CPU only) */
if (SupportTSC)
{
CpuSpeed = GetCpuSpeed(DualCoreSpeedMesure);
Error = RegSetValue(CpuInstKey,
L"~MHz",
REG_DWORD,
(PCHAR)&CpuSpeed,
sizeof(ULONG));
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
}
}
}
static VOID
SetMpsProcessor(FRLDRHKEY CpuKey,
FRLDRHKEY FpuKey,
PMP_PROCESSOR_ENTRY CpuEntry)
{
WCHAR ProcessorNameString[49];
WCHAR VendorIdentifier[13];
CHAR tmpProcessorNameString[49];
CHAR tmpVendorIdentifier[13];
WCHAR Identifier[64];
WCHAR Buffer[8];
ULONG FeatureSet;
FRLDRHKEY CpuInstKey;
FRLDRHKEY FpuInstKey;
ULONG eax = 0;
ULONG ebx = 0;
ULONG ecx = 0;
ULONG edx = 0;
ULONG i;
ULONG *Ptr;
LONG Error;
ULONG CpuSpeed;
/* Get processor instance number */
swprintf(Buffer, L"%u", CpuEntry->LocalApicId);
/* Create the CPU instance key */
Error = RegCreateKey(CpuKey,
Buffer,
&CpuInstKey);
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
return;
}
/* Create the FPU instance key */
Error = RegCreateKey(FpuKey,
Buffer,
&FpuInstKey);
if (Error != ERROR_SUCCESS)
{
DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -