/*++ 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(§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; } // // 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); } }