⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hwcpu.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *  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 + -