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 + -
显示快捷键?