Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

809 lines
25 KiB

/*++
Copyright (c) 1990, 1991 Microsoft Corporation
Module Name:
initia64.c
Abstract:
This module is responsible for building any IA64 specific entries in
the hardware tree of the registry.
Author:
Ken Reneris (kenr) 04-Aug-1992
Environment:
Kernel mode.
Revision History:
shielint - add BIOS date and version detection.
--*/
#include "cmp.h"
#include "stdio.h"
#include "smbios.h"
//
// Title Index is set to 0.
// (from ..\cmconfig.c)
//
#define TITLE_INDEX_VALUE 0
extern PCHAR SearchStrings[];
extern PCHAR BiosBegin;
extern PCHAR Start;
extern PCHAR End;
extern CHAR CmpID[];
extern WCHAR CmpVendorID[];
extern WCHAR CmpProcessorNameString[];
extern WCHAR CmpFeatureBits[];
extern WCHAR CmpMHz[];
extern WCHAR CmpUpdateSignature[];
extern CHAR CmpIntelID[];
extern CHAR CmpItanium[];
extern CHAR CmpItanium2[];
//
// Bios date and version definitions
//
#define BIOS_DATE_LENGTH 64
#define MAXIMUM_BIOS_VERSION_LENGTH 128
WCHAR SystemBIOSDateString[BIOS_DATE_LENGTH];
WCHAR SystemBIOSVersionString[MAXIMUM_BIOS_VERSION_LENGTH];
WCHAR VideoBIOSDateString[BIOS_DATE_LENGTH];
WCHAR VideoBIOSVersionString[MAXIMUM_BIOS_VERSION_LENGTH];
//
// Extended CPUID function definitions
//
#define CPUID_PROCESSOR_NAME_STRING_SZ 65
#define CPUID_EXTFN_BASE 0x80000000
#define CPUID_EXTFN_PROCESSOR_NAME 0x80000002
extern ULONG CmpConfigurationAreaSize;
extern PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData;
BOOLEAN
CmpGetBiosVersion (
PCHAR SearchArea,
ULONG SearchLength,
PCHAR VersionString
);
BOOLEAN
CmpGetBiosDate (
PCHAR SearchArea,
ULONG SearchLength,
PCHAR DateString
);
ULONG
Ke386CyrixId (
VOID
);
VOID
InitializeProcessorInformationFromSMBIOS(
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,CmpInitializeMachineDependentConfiguration)
#pragma alloc_text(INIT,InitializeProcessorInformationFromSMBIOS)
#endif
NTSTATUS
CmpInitializeMachineDependentConfiguration(
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This routine creates IA64 specific entries in the registry.
Arguments:
LoaderBlock - supplies a pointer to the LoaderBlock passed in from the
OS Loader.
Returns:
NTSTATUS code for sucess or reason of failure.
--*/
{
NTSTATUS Status;
UNICODE_STRING KeyName;
UNICODE_STRING ValueName;
UNICODE_STRING ValueData;
ANSI_STRING AnsiString;
OBJECT_ATTRIBUTES ObjectAttributes;
ULONG Disposition;
HANDLE ParentHandle;
HANDLE BaseHandle, NpxHandle;
CONFIGURATION_COMPONENT_DATA CurrentEntry;
PCHAR VendorID;
CHAR Buffer[MAXIMUM_BIOS_VERSION_LENGTH];
PKPRCB Prcb;
ULONG i;
USHORT DeviceIndexTable[NUMBER_TYPES];
for (i = 0; i < NUMBER_TYPES; i++) {
DeviceIndexTable[i] = 0;
}
//
// Go get a bunch of information out of SMBIOS
//
InitializeProcessorInformationFromSMBIOS(LoaderBlock);
InitializeObjectAttributes( &ObjectAttributes,
&CmRegistryMachineHardwareDescriptionSystemName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
Status = NtOpenKey( &ParentHandle,
KEY_READ,
&ObjectAttributes
);
if (!NT_SUCCESS(Status)) {
// Something is really wrong...
return Status;
}
//
// On an ARC machine the processor(s) are included in the hardware
// configuration passed in from bootup. Since there's no standard
// way to get all the ARC information for each processor in an MP
// machine via pc-ROMs the information will be added here (if it's
// not already present).
//
RtlInitUnicodeString( &KeyName,
L"CentralProcessor"
);
InitializeObjectAttributes(
&ObjectAttributes,
&KeyName,
0,
ParentHandle,
NULL
);
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
Status = NtCreateKey(
&BaseHandle,
KEY_READ | KEY_WRITE,
&ObjectAttributes,
TITLE_INDEX_VALUE,
&CmClassName[ProcessorClass],
0,
&Disposition
);
NtClose (BaseHandle);
if (Disposition == REG_CREATED_NEW_KEY) {
//
// The ARC rom didn't add the processor(s) into the registry.
// Do it now.
//
CmpConfigurationData = (PCM_FULL_RESOURCE_DESCRIPTOR)ExAllocatePool(
PagedPool,
CmpConfigurationAreaSize
);
if (CmpConfigurationData == NULL) {
// bail out
NtClose (ParentHandle);
return(STATUS_INSUFFICIENT_RESOURCES);
}
for (i=0; i < (ULONG)KeNumberProcessors; i++) {
Prcb = KiProcessorBlock[i];
RtlZeroMemory (&CurrentEntry, sizeof CurrentEntry);
CurrentEntry.ComponentEntry.Class = ProcessorClass;
CurrentEntry.ComponentEntry.Type = CentralProcessor;
CurrentEntry.ComponentEntry.Key = i;
CurrentEntry.ComponentEntry.AffinityMask = (ULONG)AFFINITY_MASK(i);
CurrentEntry.ComponentEntry.Identifier = Buffer;
sprintf( Buffer, CmpID,
Prcb->ProcessorFamily,
Prcb->ProcessorModel,
Prcb->ProcessorRevision
);
CurrentEntry.ComponentEntry.IdentifierLength =
(ULONG)(strlen (Buffer) + 1);
Status = CmpInitializeRegistryNode(
&CurrentEntry,
ParentHandle,
&BaseHandle,
-1,
(ULONG)-1,
DeviceIndexTable
);
if (!NT_SUCCESS(Status)) {
return(Status);
}
VendorID = (PCHAR) Prcb->ProcessorVendorString;
if ( *VendorID == '\0' ) {
VendorID = NULL;
}
if (VendorID) {
//
// Add Vendor Indentifier to the registry
//
RtlInitUnicodeString(
&ValueName,
CmpVendorID
);
RtlInitAnsiString(
&AnsiString,
VendorID
);
Status = RtlAnsiStringToUnicodeString(
&ValueData,
&AnsiString,
TRUE
);
if( NT_SUCCESS(Status) ) {
Status = NtSetValueKey(
BaseHandle,
&ValueName,
TITLE_INDEX_VALUE,
REG_SZ,
ValueData.Buffer,
ValueData.Length + sizeof( UNICODE_NULL )
);
RtlFreeUnicodeString(&ValueData);
}
}
if ( VendorID && !strcmp( VendorID, CmpIntelID ) ) {
PCHAR processorNameString;
//
// Add Processor Name String to the registry
//
RtlInitUnicodeString(
&ValueName,
CmpProcessorNameString
);
switch( Prcb->ProcessorFamily ) {
case 0x07:
processorNameString = CmpItanium;
break;
case 0x1F:
default:
//
// Default to the most recent known family
//
processorNameString = CmpItanium2;
break;
}
RtlInitAnsiString(
&AnsiString,
processorNameString
);
Status = RtlAnsiStringToUnicodeString(
&ValueData,
&AnsiString,
TRUE
);
if( NT_SUCCESS(Status) ) {
Status = NtSetValueKey(
BaseHandle,
&ValueName,
TITLE_INDEX_VALUE,
REG_SZ,
ValueData.Buffer,
ValueData.Length + sizeof( UNICODE_NULL )
);
RtlFreeUnicodeString(&ValueData);
}
}
//
// If more processor IDs have to be restored or initialized,
// check non-IA64 implementations of this function.
//
if ( Prcb->ProcessorFeatureBits ) {
//
// Add processor feature bits to the registry
//
RtlInitUnicodeString(
&ValueName,
CmpFeatureBits
);
Status = NtSetValueKey(
BaseHandle,
&ValueName,
TITLE_INDEX_VALUE,
REG_QWORD,
&Prcb->ProcessorFeatureBits,
sizeof( Prcb->ProcessorFeatureBits )
);
}
if (Prcb->MHz) {
//
// Add processor MHz to the registry
//
RtlInitUnicodeString(
&ValueName,
CmpMHz
);
Status = NtSetValueKey(
BaseHandle,
&ValueName,
TITLE_INDEX_VALUE,
REG_DWORD,
&Prcb->MHz,
sizeof (Prcb->MHz)
);
}
//
// Add ia32 floating point enties for iVE.
//
RtlZeroMemory (&CurrentEntry, sizeof CurrentEntry);
CurrentEntry.ComponentEntry.Class = ProcessorClass;
CurrentEntry.ComponentEntry.Type = FloatingPointProcessor;
CurrentEntry.ComponentEntry.Key = i;
CurrentEntry.ComponentEntry.AffinityMask = (ULONG)AFFINITY_MASK(i);
CurrentEntry.ComponentEntry.Identifier = Buffer;
//
// The iVE is defined to look like the Pentium III FP
// This is the value returned by the ia32 CPUID instruction
// on Merced (Itanium)
//
strcpy (Buffer, "x86 Family 7 Model 0 Stepping 0");
CurrentEntry.ComponentEntry.IdentifierLength =
(ULONG)(strlen (Buffer) + 1);
Status = CmpInitializeRegistryNode(
&CurrentEntry,
ParentHandle,
&NpxHandle,
-1,
(ULONG)-1,
DeviceIndexTable
);
//
// How odd. Some calls check the status return value
// and others don't. Is this based on required vs. optional
// keys? For the moment, since it was checked on the i386
// then do the check here too...
//
if (!NT_SUCCESS(Status)) {
NtClose(BaseHandle);
return(Status);
}
//
// Only need to close the handle if we succeeded
//
NtClose(NpxHandle);
NtClose(BaseHandle);
}
ExFreePool((PVOID)CmpConfigurationData);
}
//
// Next we try to collect System BIOS date and version strings.
//
if( SystemBIOSDateString[0] != 0 ) {
RtlInitUnicodeString(
&ValueName,
L"SystemBiosDate"
);
Status = NtSetValueKey(
ParentHandle,
&ValueName,
TITLE_INDEX_VALUE,
REG_SZ,
SystemBIOSDateString,
(ULONG)((wcslen(SystemBIOSDateString)+1) * sizeof( WCHAR ))
);
}
if( SystemBIOSVersionString[0] != 0 ) {
RtlInitUnicodeString(
&ValueName,
L"SystemBiosVersion"
);
Status = NtSetValueKey(
ParentHandle,
&ValueName,
TITLE_INDEX_VALUE,
REG_SZ,
SystemBIOSVersionString,
(ULONG)((wcslen(SystemBIOSVersionString)+1) * sizeof( WCHAR ))
);
}
//
// Next we try to collect Video BIOS date and version strings.
//
if( VideoBIOSDateString[0] != 0 ) {
RtlInitUnicodeString(
&ValueName,
L"VideoBiosDate"
);
Status = NtSetValueKey(
ParentHandle,
&ValueName,
TITLE_INDEX_VALUE,
REG_SZ,
VideoBIOSDateString,
(ULONG)((wcslen(VideoBIOSDateString)+1) * sizeof( WCHAR ))
);
}
if( VideoBIOSVersionString[0] != 0 ) {
RtlInitUnicodeString(
&ValueName,
L"VideoBiosVersion"
);
Status = NtSetValueKey(
ParentHandle,
&ValueName,
TITLE_INDEX_VALUE,
REG_SZ,
VideoBIOSVersionString,
(ULONG)((wcslen(VideoBIOSVersionString)+1) * sizeof( WCHAR ))
);
}
NtClose (ParentHandle);
//
// Add any other x86 specific code here...
//
return STATUS_SUCCESS;
}
VOID
InitializeProcessorInformationFromSMBIOS(
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
This function attempts to load processor-specific information
out of the SMBIOS table. If present, that information will be
used to initialize specific global variables.
Arguments:
LoaderBlock : Pointer to the loaderblock as sent in from the loader.
Return Value:
NONE.
--*/
{
PLOADER_PARAMETER_EXTENSION LoaderExtension;
PSMBIOS_EPS_HEADER SMBiosEPSHeader;
PDMIBIOS_EPS_HEADER DMIBiosEPSHeader;
BOOLEAN Found = FALSE;
PHYSICAL_ADDRESS SMBiosTablePhysicalAddress = {0};
PUCHAR StartPtr = NULL;
PUCHAR EndPtr = NULL;
PUCHAR SMBiosDataVirtualAddress = NULL;
PSMBIOS_STRUCT_HEADER Header = NULL;
ULONG i = 0;
UCHAR Checksum;
PAGED_CODE();
LoaderExtension = LoaderBlock->Extension;
if (LoaderExtension->Size >= sizeof(LOADER_PARAMETER_EXTENSION)) {
if (LoaderExtension->SMBiosEPSHeader != NULL) {
//
// Load the SMBIOS table address and checksum it just to make sure.
//
SMBiosEPSHeader = (PSMBIOS_EPS_HEADER)LoaderExtension->SMBiosEPSHeader;
DMIBiosEPSHeader = (PDMIBIOS_EPS_HEADER)&SMBiosEPSHeader->Signature2[0];
SMBiosTablePhysicalAddress.HighPart = 0;
SMBiosTablePhysicalAddress.LowPart = DMIBiosEPSHeader->StructureTableAddress;
StartPtr = (PUCHAR)SMBiosEPSHeader;
Checksum = 0;
for( i = 0; i < SMBiosEPSHeader->Length; i++ ) {
Checksum = (UCHAR)(Checksum + StartPtr[i]);
}
if( Checksum != 0 ) {
CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"InitializeProcessorInformationFromSMBIOS: _SM_ table has an incorrect checksum.\n"));
return;
}
//
// Map the table into a virtual address and search it.
//
SMBiosDataVirtualAddress = MmMapIoSpace( SMBiosTablePhysicalAddress,
DMIBiosEPSHeader->StructureTableLength,
MmCached );
if( SMBiosDataVirtualAddress != NULL ) {
//
// Search...
//
StartPtr = SMBiosDataVirtualAddress;
EndPtr = StartPtr + DMIBiosEPSHeader->StructureTableLength;
Found = FALSE;
while( (StartPtr < EndPtr) ) {
if (StartPtr + sizeof(SMBIOS_STRUCT_HEADER) > EndPtr) {
break;
}
Header = (PSMBIOS_STRUCT_HEADER)StartPtr;
if( Header->Type == SMBIOS_BIOS_INFORMATION_TYPE ) {
PSMBIOS_BIOS_INFORMATION_STRUCT InfoHeader = (PSMBIOS_BIOS_INFORMATION_STRUCT)StartPtr;
PUCHAR StringPtr = NULL;
PUCHAR StringEndPtr = NULL;
if (StartPtr + sizeof(SMBIOS_BIOS_INFORMATION_STRUCT) > EndPtr) {
break;
}
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: SMBIOS_BIOS_INFORMATION\n"));
//
// Load the System BIOS Version information.
//
// Now jump to the BiosInfoHeader->BIOSVersion-th string which
// is appended onto the end of the formatted section of the table.
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the version string is at offset: %d\n", (ULONG)InfoHeader->Version));
if( (ULONG)InfoHeader->Version > 0 ) {
// Jump to the end of the formatted portion of the SMBIOS table.
StringPtr = StartPtr + Header->Length;
// Jump over some number of strings to get to our string.
for( i = 0; i < ((ULONG)InfoHeader->Version-1); i++ ) {
while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
StringPtr++;
}
StringPtr++;
}
//
// Make sure the end string is null terminated in the buffer.
//
StringEndPtr = StringPtr;
while (StringEndPtr < EndPtr && *(StringEndPtr) != 0) {
StringEndPtr++;
}
// StringPtr should be sitting at the BIOSVersion string. Convert him to
// Unicode and save it off.
if( StringEndPtr < EndPtr ) {
UNICODE_STRING UnicodeString;
ANSI_STRING AnsiString;
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I'm about to load the Version string %s\n", StringPtr));
UnicodeString.Buffer = SystemBIOSVersionString;
UnicodeString.MaximumLength = MAXIMUM_BIOS_VERSION_LENGTH;
RtlInitAnsiString(
&AnsiString,
(PCSZ) StringPtr
);
RtlAnsiStringToUnicodeString(
&UnicodeString,
&AnsiString,
FALSE
);
}
}
//
// Load the System BIOS Date information
//
// Now jump to the BiosInfoHeader->BIOSDate-th string which
// is appended onto the end of the formatted section of the table.
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I think the ReleaseDate string is at offset: %d\n", (ULONG)InfoHeader->ReleaseDate));
if( (ULONG)InfoHeader->ReleaseDate > 0 ) {
// Jump to the end of the formatted portion of the SMBIOS table.
StringPtr = StartPtr + Header->Length;
// Jump over some number of strings to get to our string.
for( i = 0; i < ((ULONG)InfoHeader->ReleaseDate-1); i++ ) {
while( (*StringPtr != 0) && (StringPtr < EndPtr) ) {
StringPtr++;
}
StringPtr++;
}
//
// Make sure the end string is null terminated in the buffer.
//
StringEndPtr = StringPtr;
while (StringEndPtr < EndPtr && *(StringEndPtr) != 0) {
StringEndPtr++;
}
// StringPtr should be sitting at the BIOSDate string. Convert him to
// Unicode and save it off.
if( StringEndPtr < EndPtr ) {
UNICODE_STRING UnicodeString;
ANSI_STRING AnsiString;
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL," I'm about to load the Date string %s\n", StringPtr));
UnicodeString.Buffer = SystemBIOSDateString;
UnicodeString.MaximumLength = BIOS_DATE_LENGTH;
RtlInitAnsiString(
&AnsiString,
(PCSZ) StringPtr
);
RtlAnsiStringToUnicodeString(
&UnicodeString,
&AnsiString,
FALSE
);
}
}
} else if( Header->Type == SMBIOS_BASE_BOARD_INFORMATION_TYPE ) {
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: SMBIOS_BASE_BOARD_INFORMATION\n"));
} else if( Header->Type == SMBIOS_SYSTEM_CHASIS_INFORMATION_TYPE ) {
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: SMBIOS_SYSTEM_CHASIS_INFORMATION\n"));
}
//
// Go to the next table.
//
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: Haven't found the ProcessorInformation block yet. Just looked at a block of type: %d.\n", Header->Type));
StartPtr += Header->Length;
// jump over any trailing string-list too.
while ( (*((USHORT UNALIGNED *)StartPtr) != 0) &&
(StartPtr < EndPtr) )
{
StartPtr++;
}
StartPtr += 2;
}
MmUnmapIoSpace(SMBiosDataVirtualAddress, DMIBiosEPSHeader->StructureTableLength);
} else {
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: Failed to map the SMBIOS physical address.\n"));
}
} else {
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: The SMBiosEPSHeader is NULL in the extension block.\n"));
}
} else {
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_INFO_LEVEL,"InitializeProcessorInformationFromSMBIOS: LoaderBlock extension is out of sync with the kernel.\n"));
}
}