hwcpu.c
来自「一个类似windows」· C语言 代码 · 共 634 行 · 第 1/2 页
C
634 行
/*
* FreeLoader
*
* Copyright (C) 2003 Eric Kohl
*
* 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 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(VOID)
{
ULONGLONG Timestamp1;
ULONGLONG Timestamp2;
ULONGLONG Diff;
/* Read TSC (Time Stamp Counter) */
Timestamp1 = RDTSC();
/* Wait for 0.1 seconds (= 100 milliseconds = 100000 microseconds)*/
StallExecutionProcessor(100000);
/* 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 / 100000);
}
static VOID
DetectCPU(FRLDRHKEY CpuKey,
FRLDRHKEY FpuKey)
{
WCHAR VendorIdentifier[13];
CHAR tmpVendorIdentifier[13];
WCHAR Identifier[64];
ULONG FeatureSet;
FRLDRHKEY CpuInstKey;
FRLDRHKEY FpuInstKey;
ULONG eax = 0;
ULONG ebx = 0;
ULONG ecx = 0;
ULONG edx = 0;
ULONG *Ptr;
LONG Error;
BOOL SupportTSC = FALSE;
ULONG CpuSpeed;
/* 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 (((eax >> 8) & 0x0F) >= 5)
SupportTSC = TRUE;
}
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();
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 VendorIdentifier[13];
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 *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;
}
/* Get 'VendorIdentifier' */
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' */
swprintf(Identifier,
L"x86 Family %u Model %u Stepping %u",
(ULONG)((CpuEntry->CpuSignature >> 8) & 0x0F),
(ULONG)((CpuEntry->CpuSignature >> 4) & 0x0F),
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?