Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1043 lines
29 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
ixusage.c
Abstract:
Author:
Ken Reneris (kenr)
Environment:
Kernel mode only.
Revision History:
--*/
#include "halp.h"
#include "kdcom.h"
#include "acpitabl.h"
#define KEY_VALUE_BUFFER_SIZE 1024
//
// Array to remember hal's IDT usage
//
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg("INITCONST") //Yes, this says INITCONST, but that is fine.
#endif
//
// IDT vector usage info
//
IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR+1] = {0};
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg()
#endif
//
// IDT vector usage info
//
IDTUsageFlags HalpIDTUsageFlags[MAXIMUM_IDTVECTOR+1] = {0};
extern WCHAR HalpSzSystem[];
extern WCHAR HalpSzSerialNumber[];
extern ADDRESS_USAGE HalpDetectedROM;
KAFFINITY HalpActiveProcessors;
PUCHAR KdComPortInUse = NULL;
ADDRESS_USAGE HalpComIoSpace = {
NULL, CmResourceTypePort, DeviceUsage,
{
0x2F8, 0x8, // Default is 2F8 for COM2. This will be changed.
0, 0
}
};
BOOLEAN HalpGetInfoFromACPI = FALSE;
USHORT HalpComPortIrqMapping[5][2] = {
{COM1_PORT, 4},
{COM2_PORT, 3},
{COM3_PORT, 4},
{COM4_PORT, 3},
{0,0}
};
VOID
HalpGetResourceSortValue (
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
OUT PULONG sortscale,
OUT PLARGE_INTEGER sortvalue
);
VOID
HalpReportSerialNumber (
VOID
);
#ifndef ACPI_HAL
VOID
HalpInheritROMBlocks (
VOID
);
VOID
HalpAddROMRanges (
VOID
);
#endif
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,HalpEnableInterruptHandler)
#pragma alloc_text(INIT,HalpRegisterVector)
#pragma alloc_text(INIT,HalpGetResourceSortValue)
#pragma alloc_text(INIT,HalpReportResourceUsage)
#pragma alloc_text(INIT,HalpReportSerialNumber)
#ifndef ACPI_HAL
#pragma alloc_text(INIT,HalpInheritROMBlocks)
#pragma alloc_text(INIT,HalpAddROMRanges)
#endif
#endif
#if !defined(_WIN64)
NTSTATUS
HalpEnableInterruptHandler (
IN UCHAR ReportFlags,
IN ULONG BusInterruptVector,
IN ULONG SystemInterruptVector,
IN KIRQL SystemIrql,
IN PHAL_INTERRUPT_SERVICE_ROUTINE HalInterruptServiceRoutine,
IN KINTERRUPT_MODE InterruptMode
)
/*++
Routine Description:
This function connects & registers an IDT vectors usage by the HAL.
Arguments:
Return Value:
--*/
{
#ifndef ACPI_HAL
//
// Remember which vector the hal is connecting so it can be reported
// later on
//
// If this is an ACPI HAL, the vectors will be claimed by the BIOS.
// This is done for Win98 compatibility.
//
HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
#endif
//
// Connect the IDT and enable the vector now
//
KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
return STATUS_SUCCESS;
}
#endif
VOID
HalpRegisterVector (
IN UCHAR ReportFlags,
IN ULONG BusInterruptVector,
IN ULONG SystemInterruptVector,
IN KIRQL SystemIrql
)
/*++
Routine Description:
This registers an IDT vectors usage by the HAL.
Arguments:
Return Value:
--*/
{
#if DBG
// There are only 0ff IDT entries...
ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
BusInterruptVector <= MAXIMUM_IDTVECTOR);
#endif
//
// Remember which vector the hal is connecting so it can be reported
// later on
//
HalpIDTUsageFlags[SystemInterruptVector].Flags = ReportFlags;
HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
}
VOID
HalpGetResourceSortValue (
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
OUT PULONG sortscale,
OUT PLARGE_INTEGER sortvalue
)
/*++
Routine Description:
Used by HalpReportResourceUsage in order to properly sort
partial_resource_descriptors.
Arguments:
pRCurLoc - resource descriptor
Return Value:
sortscale - scaling of resource descriptor for sorting
sortvalue - value to sort on
--*/
{
switch (pRCurLoc->Type) {
case CmResourceTypeInterrupt:
*sortscale = 0;
*sortvalue = RtlConvertUlongToLargeInteger(
pRCurLoc->u.Interrupt.Level );
break;
case CmResourceTypePort:
*sortscale = 1;
*sortvalue = pRCurLoc->u.Port.Start;
break;
case CmResourceTypeMemory:
*sortscale = 2;
*sortvalue = pRCurLoc->u.Memory.Start;
break;
default:
*sortscale = 4;
*sortvalue = RtlConvertUlongToLargeInteger (0);
break;
}
}
#ifndef ACPI_HAL
VOID
HalpInheritROMBlocks (void)
{
PBUS_HANDLER Bus;
PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResourceDescriptor;
PKEY_VALUE_FULL_INFORMATION KeyValueBuffer;
PCM_ROM_BLOCK BiosBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING SectionName;
UNICODE_STRING WorkString;
HANDLE RegistryHandle;
NTSTATUS Status;
LARGE_INTEGER ViewBase;
PVOID BaseAddress;
PVOID destination;
ULONG ViewSize;
ULONG ResultLength;
ULONG Index;
ULONG LastMappedAddress;
Bus = HaliHandlerForBus (PCIBus, 0);
if (!Bus) {
//
//No root bus????
//
return;
}
//
// Set up and open KeyPath
//
RtlInitUnicodeString(&SectionName,HalpSzSystem);
InitializeObjectAttributes(
&ObjectAttributes,
&SectionName,
OBJ_CASE_INSENSITIVE,
(HANDLE)NULL,
NULL
);
Status = ZwOpenKey(
&RegistryHandle,
KEY_READ,
&ObjectAttributes
);
if (!NT_SUCCESS(Status)) {
return;
}
//
// Allocate space for the data
//
KeyValueBuffer = ExAllocatePoolWithTag(
PagedPool,
KEY_VALUE_BUFFER_SIZE,
' MDV'
);
if (KeyValueBuffer == NULL) {
ZwClose(RegistryHandle);
return ;
}
//
// Get the data for the rom information
//
RtlInitUnicodeString(
&WorkString,
L"Configuration Data"
);
Status = ZwQueryValueKey(
RegistryHandle,
&WorkString,
KeyValueFullInformation,
KeyValueBuffer,
KEY_VALUE_BUFFER_SIZE,
&ResultLength
);
if (!NT_SUCCESS(Status)) {
ZwClose(RegistryHandle);
ExFreePool(KeyValueBuffer);
return ;
}
//
//At this point, we have the data, so go ahead and
//add in all of the range, except VGA, we can
//assume we're not going to want to drop another card there
//
HalpAddRange( &Bus->BusAddresses->Memory,
0,
0,
0xC0000,
0xFFFFF
);
ResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
((PUCHAR) KeyValueBuffer + KeyValueBuffer->DataOffset);
if ((KeyValueBuffer->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) ||
(ResourceDescriptor->PartialResourceList.Count < 2)
) {
ZwClose(RegistryHandle);
ExFreePool(KeyValueBuffer);
// No rom blocks.
return;
}
PartialResourceDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
((PUCHAR)ResourceDescriptor +
sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
ResourceDescriptor->PartialResourceList.PartialDescriptors[0]
.u.DeviceSpecificData.DataSize);
if (KeyValueBuffer->DataLength < ((PUCHAR)PartialResourceDescriptor -
(PUCHAR)ResourceDescriptor + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
+ sizeof(CM_ROM_BLOCK))
) {
ZwClose(RegistryHandle);
ExFreePool(KeyValueBuffer);
return;// STATUS_ILL_FORMED_SERVICE_ENTRY;
}
BiosBlock = (PCM_ROM_BLOCK)((PUCHAR)PartialResourceDescriptor +
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
Index = PartialResourceDescriptor->u.DeviceSpecificData.DataSize /
sizeof(CM_ROM_BLOCK);
//
// N.B. Rom blocks begin on 2K (not necessarily page) boundaries
// They end on 512 byte boundaries. This means that we have
// to keep track of the last page mapped, and round the next
// Rom block up to the next page boundary if necessary.
//
LastMappedAddress = 0xC0000;
while (Index) {
#if 0
DbgPrint(
"Bios Block, PhysAddr = %lx, size = %lx\n",
BiosBlock->Address,
BiosBlock->Size
);
#endif
if ((Index > 1) &&
((BiosBlock->Address + BiosBlock->Size) == BiosBlock[1].Address)
) {
//
// Coalesce adjacent blocks
//
BiosBlock[1].Address = BiosBlock[0].Address;
BiosBlock[1].Size += BiosBlock[0].Size;
Index--;
BiosBlock++;
continue;
}
BaseAddress = (PVOID)(BiosBlock->Address);
ViewSize = BiosBlock->Size;
if ((ULONG)BaseAddress < LastMappedAddress) {
if (ViewSize > (LastMappedAddress - (ULONG)BaseAddress)) {
ViewSize = ViewSize - (LastMappedAddress - (ULONG)BaseAddress);
BaseAddress = (PVOID)LastMappedAddress;
} else {
ViewSize = 0;
}
}
ViewBase.LowPart = (ULONG)BaseAddress;
if (ViewSize > 0) {
HalpRemoveRange ( &Bus->BusAddresses->Memory,
ViewBase.LowPart,
ViewSize);
LastMappedAddress = (ULONG)BaseAddress + ViewSize;
}
Index--;
BiosBlock++;
}
//
// Free up the handles
//
ZwClose(RegistryHandle);
ExFreePool(KeyValueBuffer);
}
VOID
HalpAddROMRanges (
VOID
)
{
PCM_FULL_RESOURCE_DESCRIPTOR resourceDescriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialResourceDescriptor;
PKEY_VALUE_FULL_INFORMATION keyValueBuffer;
PCM_ROM_BLOCK biosBlock;
ULONG resultLength;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING sectionName;
UNICODE_STRING workString;
HANDLE registryHandle;
NTSTATUS status;
LARGE_INTEGER viewBase;
PVOID baseAddress;
ULONG viewSize;
ULONG index;
ULONG element;
ULONG lastMappedAddress;
ADDRESS_USAGE *addrUsage;
RtlInitUnicodeString(&sectionName, HalpSzSystem);
InitializeObjectAttributes( &objectAttributes,
&sectionName,
OBJ_CASE_INSENSITIVE,
(HANDLE)NULL,
NULL);
status = ZwOpenKey( &registryHandle,
KEY_READ,
&objectAttributes);
if (NT_SUCCESS(status)) {
//
// Allocate space for the data
//
keyValueBuffer = ExAllocatePoolWithTag( PagedPool,
KEY_VALUE_BUFFER_SIZE,
' MDV');
if (keyValueBuffer) {
//
// Get the data for the rom information
//
RtlInitUnicodeString( &workString,
L"Configuration Data");
status = ZwQueryValueKey( registryHandle,
&workString,
KeyValueFullInformation,
keyValueBuffer,
KEY_VALUE_BUFFER_SIZE,
&resultLength);
if (NT_SUCCESS(status)) {
resourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)keyValueBuffer + keyValueBuffer->DataOffset);
if ( keyValueBuffer->DataLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR) &&
resourceDescriptor->PartialResourceList.Count >= 2) {
partialResourceDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)((PUCHAR)resourceDescriptor +
sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
resourceDescriptor->PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize);
if ( keyValueBuffer->DataLength >=
((PUCHAR)partialResourceDescriptor - (PUCHAR)resourceDescriptor + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + sizeof(CM_ROM_BLOCK))) {
addrUsage = &HalpDetectedROM;
//
// N.B. Rom blocks begin on 2K (not necessarily page) boundaries
// They end on 512 byte boundaries. This means that we have
// to keep track of the last page mapped, and round the next
// Rom block up to the next page boundary if necessary.
//
biosBlock = (PCM_ROM_BLOCK)((PUCHAR)partialResourceDescriptor + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
lastMappedAddress = 0xC0000;
for ( index = partialResourceDescriptor->u.DeviceSpecificData.DataSize / sizeof(CM_ROM_BLOCK), element = 0;
index;
index--, biosBlock++) {
//
// Coalesce adjacent blocks
//
if ( index > 1 && (biosBlock->Address + biosBlock->Size) == biosBlock[1].Address) {
biosBlock[1].Address = biosBlock[0].Address;
biosBlock[1].Size += biosBlock[0].Size;
continue;
}
baseAddress = (PVOID)(biosBlock->Address);
viewSize = biosBlock->Size;
if ((ULONG)baseAddress < lastMappedAddress) {
if (viewSize > (lastMappedAddress - (ULONG)baseAddress)) {
viewSize = viewSize - (lastMappedAddress - (ULONG)baseAddress);
baseAddress = (PVOID)lastMappedAddress;
} else {
viewSize = 0;
}
}
viewBase.LowPart = (ULONG)baseAddress;
if (viewSize > 0) {
addrUsage->Element[element].Start = viewBase.LowPart;
addrUsage->Element[element].Length = viewSize;
element++;
lastMappedAddress = (ULONG)baseAddress + viewSize;
}
}
//
// Register address usage if we found at least one ROM block.
//
if (element) {
addrUsage->Element[element].Start = 0;
addrUsage->Element[element].Length = 0;
HalpRegisterAddressUsage(addrUsage);
}
}
}
}
ExFreePool(keyValueBuffer);
}
ZwClose(registryHandle);
}
}
#endif
VOID
HalpReportResourceUsage (
IN PUNICODE_STRING HalName,
IN INTERFACE_TYPE DeviceInterfaceToUse
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
ULONG i, j, k, ListSize, Count;
ULONG curscale, sortscale;
UCHAR pass, reporton;
INTERFACE_TYPE interfacetype;
ULONG CurrentIDT, CurrentElement;
ADDRESS_USAGE *CurrentAddress;
LARGE_INTEGER curvalue, sortvalue;
#ifdef ACPI_HAL
extern PDEBUG_PORT_TABLE HalpDebugPortTable;
#endif
//
// Claim the debugger com port resource if it is in use
//
if (KdComPortInUse != NULL) {
HalpComIoSpace.Element[0].Start = (ULONG)(ULONG_PTR)KdComPortInUse;
HalpRegisterAddressUsage(&HalpComIoSpace);
#ifdef ACPI_HAL
if (HalpDebugPortTable) {
if (HalpDebugPortTable->BaseAddress.AddressSpaceID == 1) {
HalpGetInfoFromACPI = TRUE;
}
}
#endif
//
// The debugger does not use any interrupts. However for consistent
// behaviour between a machine with and without a debugger, we claim
// an interrupt for the debugger if the debugger port address is one
// for COM1-4.
//
if (!HalpGetInfoFromACPI) {
for (i = 0; HalpComPortIrqMapping[i][0]; i++) {
if ((PUCHAR)HalpComPortIrqMapping[i][0] == KdComPortInUse) {
HalpRegisterVector( DeviceUsage | InterruptLatched,
HalpComPortIrqMapping[i][1],
HalpComPortIrqMapping[i][1] +
PRIMARY_VECTOR_BASE,
HIGH_LEVEL);
break;
}
}
}
}
#ifndef ACPI_HAL // ACPI HALs don't deal with address maps
HalpInheritROMBlocks();
HalpAddROMRanges();
#endif
//
// Allocate some space to build the resource structure
//
RawResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(
NonPagedPool,
PAGE_SIZE*2,
HAL_POOL_TAG);
TranslatedResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(
NonPagedPool,
PAGE_SIZE*2,
HAL_POOL_TAG);
if (!RawResourceList || !TranslatedResourceList) {
//
// These allocations were critical.
//
KeBugCheckEx(HAL_MEMORY_ALLOCATION,
PAGE_SIZE*4,
1,
(ULONG_PTR)__FILE__,
__LINE__
);
}
// This functions assumes unset fields are zero
RtlZeroMemory(RawResourceList, PAGE_SIZE*2);
RtlZeroMemory(TranslatedResourceList, PAGE_SIZE*2);
//
// Initialize the lists
//
RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
pRFullDesc = RawResourceList->List;
pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
//
// Make sure all vectors 00-2f are reserved
// 00-1E reserved by Intel
// 1F reserved by Intel for APIC (apc priority level)
// 20-2e reserved by Microsoft
// 2f reserved by Microsoft for APIC (dpc priority level)
//
for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
if (!(HalpIDTUsageFlags[i].Flags & IDTOwned)) {
HalpIDTUsageFlags[i].Flags = InternalUsage;
HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
}
}
for(pass=0; pass < 2; pass++) {
if (pass == 0) {
//
// First pass - build resource lists for resources reported
// reported against device usage.
//
reporton = DeviceUsage & ~IDTOwned;
interfacetype = DeviceInterfaceToUse;
} else {
//
// Second pass = build reousce lists for resources reported
// as internal usage.
//
reporton = InternalUsage & ~IDTOwned;
interfacetype = Internal;
}
CurrentIDT = 0;
CurrentElement = 0;
CurrentAddress = HalpAddressUsageList;
for (; ;) {
if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
//
// Check to see if CurrentIDT needs to be reported
//
if (!(HalpIDTUsageFlags[CurrentIDT].Flags & reporton)) {
// Don't report on this one
CurrentIDT++;
continue;
}
//
// Report CurrentIDT resource
//
RPartialDesc.Type = CmResourceTypeInterrupt;
RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
RPartialDesc.Flags =
HalpIDTUsageFlags[CurrentIDT].Flags & InterruptLatched ?
CM_RESOURCE_INTERRUPT_LATCHED :
CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
TPartialDesc.u.Interrupt.Vector = CurrentIDT;
TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
CurrentIDT++;
} else {
//
// Check to see if CurrentAddress needs to be reported
//
if (!CurrentAddress) {
break; // No addresses left
}
if (!(CurrentAddress->Flags & reporton)) {
// Don't report on this list
CurrentElement = 0;
CurrentAddress = CurrentAddress->Next;
continue;
}
if (!CurrentAddress->Element[CurrentElement].Length) {
// End of current list, go to next list
CurrentElement = 0;
CurrentAddress = CurrentAddress->Next;
continue;
}
//
// Report CurrentAddress
//
RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
if (RPartialDesc.Type == CmResourceTypePort) {
i = 1; // address space port
RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
if (HalpBusType == MACHINE_TYPE_EISA) {
RPartialDesc.Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
}
#ifdef ACPI_HAL
RPartialDesc.Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
#endif
} else {
i = 0; // address space memory
if (CurrentAddress->Flags & RomResource) {
RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_ONLY;
} else {
RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
}
}
// Notice: assuming u.Memory and u.Port have the same layout
RPartialDesc.u.Memory.Start.HighPart = 0;
RPartialDesc.u.Memory.Start.LowPart =
CurrentAddress->Element[CurrentElement].Start;
RPartialDesc.u.Memory.Length =
CurrentAddress->Element[CurrentElement].Length;
// translated address = Raw address
RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
HalTranslateBusAddress (
interfacetype, // device bus or internal
0, // bus number
RPartialDesc.u.Memory.Start, // source address
&i, // address space
&TPartialDesc.u.Memory.Start ); // translated address
if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
}
CurrentElement++;
}
//
// Include the current resource in the HALs list
//
if (pRFullDesc->InterfaceType != interfacetype) {
//
// Interface type changed, add another full section
//
RawResourceList->Count++;
TranslatedResourceList->Count++;
pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
pRFullDesc->InterfaceType = interfacetype;
pTFullDesc->InterfaceType = interfacetype;
pRPartList = &pRFullDesc->PartialResourceList;
pTPartList = &pTFullDesc->PartialResourceList;
//
// Bump current location pointers up
//
pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
}
pRPartList->Count++;
pTPartList->Count++;
RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
pRCurLoc++;
pTCurLoc++;
}
}
ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
//
// The HAL's resource usage structures have been built
// Sort the partial lists based on the Raw resource values
//
pRFullDesc = RawResourceList->List;
pTFullDesc = TranslatedResourceList->List;
for (i=0; i < RawResourceList->Count; i++) {
pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
Count = pRFullDesc->PartialResourceList.Count;
for (j=0; j < Count; j++) {
HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
pRSortLoc = pRCurLoc;
pTSortLoc = pTCurLoc;
for (k=j; k < Count; k++) {
HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
if (sortscale < curscale ||
(sortscale == curscale &&
RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
//
// Swap the elements..
//
RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
// swap translated descriptor as well
RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
// get new curscale & curvalue
HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
}
pRSortLoc++;
pTSortLoc++;
}
pRCurLoc++;
pTCurLoc++;
}
pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
}
//
// Inform the IO system of our resources..
//
IoReportHalResourceUsage (
HalName,
RawResourceList,
TranslatedResourceList,
ListSize
);
ExFreePool (RawResourceList);
ExFreePool (TranslatedResourceList);
//
// Add system's serial number
//
HalpReportSerialNumber ();
}
VOID
HalpReportSerialNumber (
VOID
)
{
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING unicodeString;
HANDLE hSystem;
NTSTATUS status;
if (!HalpSerialLen) {
return ;
}
//
// Open HKEY_LOCAL_MACHINE\Hardware\Description\System
//
RtlInitUnicodeString (&unicodeString, HalpSzSystem);
InitializeObjectAttributes (
&objectAttributes,
&unicodeString,
OBJ_CASE_INSENSITIVE,
NULL, // handle
NULL
);
status = ZwOpenKey (&hSystem, KEY_READ | KEY_WRITE, &objectAttributes);
if (NT_SUCCESS(status)) {
//
// Add "Serial Number" as REG_BINARY
//
RtlInitUnicodeString (&unicodeString, HalpSzSerialNumber);
ZwSetValueKey (
hSystem,
&unicodeString,
0L,
REG_BINARY,
HalpSerialNumber,
HalpSerialLen
);
ZwClose (hSystem);
}
}