Reactos

[NTOS:IO] Fix parsing of resource lists

Also add a hack to avoid failing on now occurring resource conflict detection and try to fix at least one resource in ACPI hal.

CORE-10146
CORE-12892

authored by

Timo Kreuzer and committed by
Victor Perevertkin
b82bf8ce c42e1246

+146 -48
+3
drivers/bus/pci/CMakeLists.txt
··· 1 + 2 + include_directories( 3 + ${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers) 1 4 2 5 list(APPEND SOURCE 3 6 fdo.c
+1
drivers/bus/pci/pci.h
··· 2 2 #define _PCI_PCH_ 3 3 4 4 #include <ntifs.h> 5 + #include <cmreslist.h> 5 6 6 7 #define TAG_PCI '0ICP' 7 8
+4 -3
drivers/bus/pci/pdo.c
··· 1335 1335 1336 1336 /* TODO: Assign the other resources we get to the card */ 1337 1337 1338 - for (i = 0; i < RawResList->Count; i++) 1338 + RawFullDesc = &RawResList->List[0]; 1339 + for (i = 0; i < RawResList->Count; i++, RawFullDesc = CmiGetNextResourceDescriptor(RawFullDesc)) 1339 1340 { 1340 - RawFullDesc = &RawResList->List[i]; 1341 - 1342 1341 for (ii = 0; ii < RawFullDesc->PartialResourceList.Count; ii++) 1343 1342 { 1343 + /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific), 1344 + but only one is allowed and it must be the last one in the list! */ 1344 1345 RawPartialDesc = &RawFullDesc->PartialResourceList.PartialDescriptors[ii]; 1345 1346 1346 1347 if (RawPartialDesc->Type == CmResourceTypeInterrupt)
+3 -1
drivers/bus/pcix/CMakeLists.txt
··· 1 + 1 2 include_directories( 2 - ${REACTOS_SOURCE_DIR}/sdk/lib/drivers/arbiter) 3 + ${REACTOS_SOURCE_DIR}/sdk/lib/drivers/arbiter 4 + ${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers) 3 5 4 6 list(APPEND SOURCE 5 7 arb/ar_busno.c
+4 -1
drivers/bus/pcix/debug.c
··· 386 386 Count = FullDescriptor->PartialResourceList.Count; 387 387 for (PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors; 388 388 Count; 389 - PartialDescriptor = PciNextPartialDescriptor(PartialDescriptor)) 389 + PartialDescriptor = CmiGetNextPartialDescriptor(PartialDescriptor)) 390 390 { 391 391 /* Print each partial */ 392 392 PciDebugPrintPartialResource(PartialDescriptor); 393 393 Count--; 394 394 } 395 + 396 + /* Go to the next full descriptor */ 397 + FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)PartialDescriptor; 395 398 } 396 399 397 400 /* Done printing data */
+1 -1
drivers/bus/pcix/enum.c
··· 168 168 } 169 169 170 170 /* Move to the next descriptor */ 171 - Partial = PciNextPartialDescriptor(Partial); 171 + Partial = CmiGetNextPartialDescriptor(Partial); 172 172 } 173 173 174 174 /* We should be starting a new list now */
+5 -10
drivers/bus/pcix/pci.h
··· 19 19 #include <ndk/rtlfuncs.h> 20 20 #include <ndk/vffuncs.h> 21 21 #include <arbiter.h> 22 + #include <cmreslist.h> 22 23 23 24 // 24 25 // Tag used in all pool allocations (Pci Bus) ··· 1173 1174 IN OUT PDEVICE_CAPABILITIES DeviceCapability 1174 1175 ); 1175 1176 1176 - PCM_PARTIAL_RESOURCE_DESCRIPTOR 1177 - NTAPI 1178 - PciNextPartialDescriptor( 1179 - PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor 1180 - ); 1181 - 1182 1177 // 1183 1178 // Configuration Routines 1184 1179 // ··· 1787 1782 IN PDEVICE_OBJECT DeviceObject, 1788 1783 IN ULONG BusNumber, 1789 1784 IN ULONG SlotNumber, 1790 - IN UCHAR InterruptLine, 1791 - IN UCHAR InterruptPin, 1792 - IN UCHAR BaseClass, 1793 - IN UCHAR SubClass, 1785 + IN UCHAR InterruptLine, 1786 + IN UCHAR InterruptPin, 1787 + IN UCHAR BaseClass, 1788 + IN UCHAR SubClass, 1794 1789 IN PDEVICE_OBJECT PhysicalDeviceObject, 1795 1790 IN PPCI_PDO_EXTENSION PdoExtension, 1796 1791 OUT PDEVICE_OBJECT *pFoundDeviceObject
-21
drivers/bus/pcix/utils.c
··· 1764 1764 return Status; 1765 1765 } 1766 1766 1767 - PCM_PARTIAL_RESOURCE_DESCRIPTOR 1768 - NTAPI 1769 - PciNextPartialDescriptor(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor) 1770 - { 1771 - PCM_PARTIAL_RESOURCE_DESCRIPTOR NextDescriptor; 1772 - 1773 - /* Assume the descriptors are the fixed size ones */ 1774 - NextDescriptor = CmDescriptor + 1; 1775 - 1776 - /* But check if this is actually a variable-sized descriptor */ 1777 - if (CmDescriptor->Type == CmResourceTypeDeviceSpecific) 1778 - { 1779 - /* Add the size of the variable section as well */ 1780 - NextDescriptor = (PVOID)((ULONG_PTR)NextDescriptor + 1781 - CmDescriptor->u.DeviceSpecificData.DataSize); 1782 - } 1783 - 1784 - /* Now the correct pointer has been computed, return it */ 1785 - return NextDescriptor; 1786 - } 1787 - 1788 1767 /* EOF */
+1
ntoskrnl/include/internal/cm.h
··· 7 7 */ 8 8 #define _CM_ 9 9 #include "cmlib.h" 10 + #include <cmreslist.h> 10 11 11 12 // 12 13 // Define this if you want debugging support
+51 -9
ntoskrnl/io/pnpmgr/pnpres.c
··· 12 12 #define NDEBUG 13 13 #include <debug.h> 14 14 15 + FORCEINLINE 16 + PIO_RESOURCE_LIST 17 + IopGetNextResourceList( 18 + _In_ const IO_RESOURCE_LIST *ResourceList) 19 + { 20 + ASSERT((ResourceList->Count > 0) && (ResourceList->Count < 1000)); 21 + return (PIO_RESOURCE_LIST)( 22 + &ResourceList->Descriptors[ResourceList->Count]); 23 + } 24 + 15 25 static 16 26 BOOLEAN 17 27 IopCheckDescriptorForConflict( ··· 199 209 } 200 210 } 201 211 212 + DPRINT1("Failed to satisfy interrupt requirement with IRQ 0x%x-0x%x\n", 213 + IoDesc->u.Interrupt.MinimumVector, 214 + IoDesc->u.Interrupt.MaximumVector); 202 215 return FALSE; 203 216 } 204 217 ··· 209 222 { 210 223 ULONG i, OldCount; 211 224 BOOLEAN AlternateRequired = FALSE; 225 + PIO_RESOURCE_LIST ResList; 212 226 213 227 /* Save the initial resource count when we got here so we can restore if an alternate fails */ 214 228 if (*ResourceList != NULL) ··· 216 230 else 217 231 OldCount = 0; 218 232 219 - for (i = 0; i < RequirementsList->AlternativeLists; i++) 233 + ResList = &RequirementsList->List[0]; 234 + for (i = 0; i < RequirementsList->AlternativeLists; i++, ResList = IopGetNextResourceList(ResList)) 220 235 { 221 236 ULONG ii; 222 - PIO_RESOURCE_LIST ResList = &RequirementsList->List[i]; 223 237 224 238 /* We need to get back to where we were before processing the last alternative list */ 225 239 if (OldCount == 0 && *ResourceList != NULL) ··· 275 289 276 290 for (iii = 0; PartialList && iii < PartialList->Count && !Matched; iii++) 277 291 { 292 + /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific), 293 + but only one is allowed and it must be the last one in the list! */ 278 294 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc = &PartialList->PartialDescriptors[iii]; 279 295 280 296 /* First check types */ ··· 548 564 { 549 565 ULONG i, ii; 550 566 BOOLEAN Result = FALSE; 567 + PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 551 568 569 + FullDescriptor = &ResourceList->List[0]; 552 570 for (i = 0; i < ResourceList->Count; i++) 553 571 { 554 - PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList->List[i].PartialResourceList; 572 + PCM_PARTIAL_RESOURCE_LIST ResList = &FullDescriptor->PartialResourceList; 573 + FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor); 574 + 555 575 for (ii = 0; ii < ResList->Count; ii++) 556 576 { 577 + /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific), 578 + but only one is allowed and it must be the last one in the list! */ 557 579 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2 = &ResList->PartialDescriptors[ii]; 558 580 559 581 /* We don't care about shared resources */ ··· 674 696 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); 675 697 } 676 698 677 - return Result; 699 + // Hacked, because after fixing resource list parsing 700 + // we actually detect resource conflicts 701 + return Silent ? Result : FALSE; // Result; 678 702 } 679 703 680 704 static ··· 937 961 { 938 962 PCM_PARTIAL_RESOURCE_LIST pPartialResourceList; 939 963 PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated; 964 + PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 940 965 ULONG i, j, ListSize; 941 966 NTSTATUS Status; 942 967 ··· 959 984 } 960 985 RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, ListSize); 961 986 987 + FullDescriptor = &DeviceNode->ResourceList->List[0]; 962 988 for (i = 0; i < DeviceNode->ResourceList->Count; i++) 963 989 { 964 - pPartialResourceList = &DeviceNode->ResourceList->List[i].PartialResourceList; 990 + pPartialResourceList = &FullDescriptor->PartialResourceList; 991 + FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor); 992 + 965 993 for (j = 0; j < pPartialResourceList->Count; j++) 966 994 { 995 + /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific), 996 + but only one is allowed and it must be the last one in the list! */ 967 997 DescriptorRaw = &pPartialResourceList->PartialDescriptors[j]; 968 - DescriptorTranslated = &DeviceNode->ResourceListTranslated->List[i].PartialResourceList.PartialDescriptors[j]; 998 + 999 + /* Calculate the location of the translated resource descriptor */ 1000 + DescriptorTranslated = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)( 1001 + (PUCHAR)DeviceNode->ResourceListTranslated + 1002 + ((PUCHAR)DescriptorRaw - (PUCHAR)DeviceNode->ResourceList)); 1003 + 969 1004 switch (DescriptorRaw->Type) 970 1005 { 971 1006 case CmResourceTypePort: ··· 996 1031 } 997 1032 case CmResourceTypeInterrupt: 998 1033 { 1034 + KIRQL Irql; 999 1035 DescriptorTranslated->u.Interrupt.Vector = HalGetInterruptVector( 1000 1036 DeviceNode->ResourceList->List[i].InterfaceType, 1001 1037 DeviceNode->ResourceList->List[i].BusNumber, 1002 1038 DescriptorRaw->u.Interrupt.Level, 1003 1039 DescriptorRaw->u.Interrupt.Vector, 1004 - (PKIRQL)&DescriptorTranslated->u.Interrupt.Level, 1040 + &Irql, 1005 1041 &DescriptorTranslated->u.Interrupt.Affinity); 1006 - 1042 + DescriptorTranslated->u.Interrupt.Level = Irql; 1007 1043 if (!DescriptorTranslated->u.Interrupt.Vector) 1008 1044 { 1009 1045 Status = STATUS_UNSUCCESSFUL; ··· 1184 1220 { 1185 1221 ULONG i, ii; 1186 1222 BOOLEAN Result = FALSE; 1223 + PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; 1187 1224 1225 + FullDescriptor = &ResourceList1->List[0]; 1188 1226 for (i = 0; i < ResourceList1->Count; i++) 1189 1227 { 1190 - PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList1->List[i].PartialResourceList; 1228 + PCM_PARTIAL_RESOURCE_LIST ResList = &FullDescriptor->PartialResourceList; 1229 + FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor); 1230 + 1191 1231 for (ii = 0; ii < ResList->Count; ii++) 1192 1232 { 1233 + /* Partial resource descriptors can be of variable size (CmResourceTypeDeviceSpecific), 1234 + but only one is allowed and it must be the last one in the list! */ 1193 1235 PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc = &ResList->PartialDescriptors[ii]; 1194 1236 1195 1237 Result = IopCheckResourceDescriptor(ResDesc,
+66
sdk/include/reactos/drivers/cmreslist.h
··· 1 + /* 2 + * PROJECT: ReactOS Kernel 3 + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 + * PURPOSE: Helper functions to parse CM_RESOURCE_LISTs 5 + * COPYRIGHT: Copyright 2020 Timo Kreuzer (timo.kreuzer@reactos.org) 6 + */ 7 + 8 + #include <wdm.h> 9 + 10 + // 11 + // Resource list helpers 12 + // 13 + 14 + /* Usage note: 15 + * As there can be only one variable-sized CM_PARTIAL_RESOURCE_DESCRIPTOR in the list (and it must be the last one), 16 + * a right looping through resources can look like this: 17 + * 18 + * PCM_FULL_RESOURCE_DESCRIPTOR FullDesc = &ResourceList->List[0]; 19 + * for (ULONG i = 0; i < ResourceList->Count; i++, FullDesc = CmiGetNextResourceDescriptor(FullDesc)) 20 + * { 21 + * for (ULONG j = 0; j < FullDesc->PartialResourceList.Count; j++) 22 + * { 23 + * PartialDesc = &FullDesc->PartialResourceList.PartialDescriptors[j]; 24 + * // work with PartialDesc 25 + * } 26 + * } 27 + */ 28 + 29 + FORCEINLINE 30 + PCM_PARTIAL_RESOURCE_DESCRIPTOR 31 + CmiGetNextPartialDescriptor( 32 + _In_ const CM_PARTIAL_RESOURCE_DESCRIPTOR *PartialDescriptor) 33 + { 34 + const CM_PARTIAL_RESOURCE_DESCRIPTOR *NextDescriptor; 35 + 36 + /* Assume the descriptors are the fixed size ones */ 37 + NextDescriptor = PartialDescriptor + 1; 38 + 39 + /* But check if this is actually a variable-sized descriptor */ 40 + if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific) 41 + { 42 + /* Add the size of the variable section as well */ 43 + NextDescriptor = (PVOID)((ULONG_PTR)NextDescriptor + 44 + PartialDescriptor->u.DeviceSpecificData.DataSize); 45 + ASSERT(NextDescriptor >= PartialDescriptor + 1); 46 + } 47 + 48 + /* Now the correct pointer has been computed, return it */ 49 + return (PCM_PARTIAL_RESOURCE_DESCRIPTOR)NextDescriptor; 50 + } 51 + 52 + FORCEINLINE 53 + PCM_FULL_RESOURCE_DESCRIPTOR 54 + CmiGetNextResourceDescriptor( 55 + _In_ const CM_FULL_RESOURCE_DESCRIPTOR *ResourceDescriptor) 56 + { 57 + const CM_PARTIAL_RESOURCE_DESCRIPTOR *LastPartialDescriptor; 58 + 59 + /* Calculate the location of the last partial descriptor, which can have a 60 + variable size! */ 61 + LastPartialDescriptor = &ResourceDescriptor->PartialResourceList.PartialDescriptors[ 62 + ResourceDescriptor->PartialResourceList.Count - 1]; 63 + 64 + /* Next full resource descriptor follows the last partial descriptor */ 65 + return (PCM_FULL_RESOURCE_DESCRIPTOR)CmiGetNextPartialDescriptor(LastPartialDescriptor); 66 + }
+7 -2
win32ss/drivers/videoprt/resource.c
··· 765 765 ERR_(VIDEOPRT, "Too many access ranges found\n"); 766 766 return ERROR_NOT_ENOUGH_MEMORY; 767 767 } 768 - if (Descriptor->Type == CmResourceTypeMemory) 768 + else if (Descriptor->Type == CmResourceTypeMemory) 769 769 { 770 770 INFO_(VIDEOPRT, "Memory range starting at 0x%08x length 0x%08x\n", 771 771 Descriptor->u.Memory.Start.u.LowPart, Descriptor->u.Memory.Length); ··· 804 804 else 805 805 DeviceExtension->InterruptShared = FALSE; 806 806 } 807 + else 808 + { 809 + ASSERT(FALSE); 810 + return ERROR_INVALID_PARAMETER; 811 + } 807 812 } 808 813 809 814 return NO_ERROR; ··· 838 843 if (!ResourceList) 839 844 { 840 845 WARN_(VIDEOPRT, "ExAllocatePool() failed\n"); 841 - return ERROR_INVALID_PARAMETER; 846 + return ERROR_NOT_ENOUGH_MEMORY; 842 847 } 843 848 844 849 /* Fill resource list */