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.
1121 lines
32 KiB
1121 lines
32 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;
|
|
extern ULONG HalDisableFirmwareMapper;
|
|
|
|
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
|
|
);
|
|
|
|
VOID
|
|
HalpMarkAcpiHal(
|
|
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)
|
|
#pragma alloc_text(PAGE, HalpMarkAcpiHal)
|
|
|
|
#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(§ionName, HalpSzSystem);
|
|
InitializeObjectAttributes( &objectAttributes,
|
|
§ionName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
(HANDLE)NULL,
|
|
NULL);
|
|
status = ZwOpenKey( ®istryHandle,
|
|
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;
|
|
}
|
|
|
|
HalpMarkAcpiHal();
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
HalpMarkAcpiHal(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
UNICODE_STRING unicodeString;
|
|
HANDLE hCurrentControlSet, handle;
|
|
NTSTATUS status;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Open/create System\CurrentControlSet key.
|
|
//
|
|
|
|
RtlInitUnicodeString(&unicodeString, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
|
|
status = HalpOpenRegistryKey (
|
|
&hCurrentControlSet,
|
|
NULL,
|
|
&unicodeString,
|
|
KEY_ALL_ACCESS,
|
|
FALSE
|
|
);
|
|
if (!NT_SUCCESS(status)) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Open HKLM\System\CurrentControlSet\Control\Pnp
|
|
//
|
|
|
|
RtlInitUnicodeString(&unicodeString, L"Control\\Pnp");
|
|
status = HalpOpenRegistryKey (
|
|
&handle,
|
|
hCurrentControlSet,
|
|
&unicodeString,
|
|
KEY_ALL_ACCESS,
|
|
TRUE
|
|
);
|
|
ZwClose(hCurrentControlSet);
|
|
if (!NT_SUCCESS(status)) {
|
|
return;
|
|
}
|
|
|
|
RtlInitUnicodeString(&unicodeString, L"DisableFirmwareMapper");
|
|
ZwSetValueKey(handle,
|
|
&unicodeString,
|
|
0,
|
|
REG_DWORD,
|
|
&HalDisableFirmwareMapper,
|
|
sizeof(HalDisableFirmwareMapper)
|
|
);
|
|
ZwClose(handle);
|
|
}
|