https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b82bf8ce167ae96dff2868461e82136b90b8c45f

commit b82bf8ce167ae96dff2868461e82136b90b8c45f
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Sun Jan 28 23:44:28 2018 +0100
Commit:     Victor Perevertkin <[email protected]>
CommitDate: Fri Apr 24 13:58:09 2020 +0300

    [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
---
 drivers/bus/pci/CMakeLists.txt          |  3 ++
 drivers/bus/pci/pci.h                   |  1 +
 drivers/bus/pci/pdo.c                   |  7 ++--
 drivers/bus/pcix/CMakeLists.txt         |  4 +-
 drivers/bus/pcix/debug.c                |  5 ++-
 drivers/bus/pcix/enum.c                 |  2 +-
 drivers/bus/pcix/pci.h                  | 15 +++-----
 drivers/bus/pcix/utils.c                | 21 -----------
 ntoskrnl/include/internal/cm.h          |  1 +
 ntoskrnl/io/pnpmgr/pnpres.c             | 60 +++++++++++++++++++++++++-----
 sdk/include/reactos/drivers/cmreslist.h | 66 +++++++++++++++++++++++++++++++++
 win32ss/drivers/videoprt/resource.c     |  9 ++++-
 12 files changed, 146 insertions(+), 48 deletions(-)

diff --git a/drivers/bus/pci/CMakeLists.txt b/drivers/bus/pci/CMakeLists.txt
index 5bd36b7bb7c..3e8fe17c8e6 100644
--- a/drivers/bus/pci/CMakeLists.txt
+++ b/drivers/bus/pci/CMakeLists.txt
@@ -1,4 +1,7 @@
 
+include_directories(
+    ${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers)
+
 list(APPEND SOURCE
     fdo.c
     pci.c
diff --git a/drivers/bus/pci/pci.h b/drivers/bus/pci/pci.h
index f3394c7ca44..3cd2204bf30 100644
--- a/drivers/bus/pci/pci.h
+++ b/drivers/bus/pci/pci.h
@@ -2,6 +2,7 @@
 #define _PCI_PCH_
 
 #include <ntifs.h>
+#include <cmreslist.h>
 
 #define TAG_PCI '0ICP'
 
diff --git a/drivers/bus/pci/pdo.c b/drivers/bus/pci/pdo.c
index bedaac36fc0..1d6b8c54ecf 100644
--- a/drivers/bus/pci/pdo.c
+++ b/drivers/bus/pci/pdo.c
@@ -1335,12 +1335,13 @@ PdoStartDevice(
 
     /* TODO: Assign the other resources we get to the card */
 
-    for (i = 0; i < RawResList->Count; i++)
+    RawFullDesc = &RawResList->List[0];
+    for (i = 0; i < RawResList->Count; i++, RawFullDesc = 
CmiGetNextResourceDescriptor(RawFullDesc))
     {
-        RawFullDesc = &RawResList->List[i];
-
         for (ii = 0; ii < RawFullDesc->PartialResourceList.Count; ii++)
         {
+            /* Partial resource descriptors can be of variable size 
(CmResourceTypeDeviceSpecific),
+               but only one is allowed and it must be the last one in the 
list! */
             RawPartialDesc = 
&RawFullDesc->PartialResourceList.PartialDescriptors[ii];
 
             if (RawPartialDesc->Type == CmResourceTypeInterrupt)
diff --git a/drivers/bus/pcix/CMakeLists.txt b/drivers/bus/pcix/CMakeLists.txt
index 9389bde01eb..cdbcf5f8514 100644
--- a/drivers/bus/pcix/CMakeLists.txt
+++ b/drivers/bus/pcix/CMakeLists.txt
@@ -1,5 +1,7 @@
+
 include_directories(
-    ${REACTOS_SOURCE_DIR}/sdk/lib/drivers/arbiter)
+    ${REACTOS_SOURCE_DIR}/sdk/lib/drivers/arbiter
+    ${REACTOS_SOURCE_DIR}/sdk/include/reactos/drivers)
 
 list(APPEND SOURCE
     arb/ar_busno.c
diff --git a/drivers/bus/pcix/debug.c b/drivers/bus/pcix/debug.c
index 971cdadf498..4b7e0154f3c 100644
--- a/drivers/bus/pcix/debug.c
+++ b/drivers/bus/pcix/debug.c
@@ -386,12 +386,15 @@ PciDebugPrintCmResList(IN PCM_RESOURCE_LIST PartialList)
         Count = FullDescriptor->PartialResourceList.Count;
         for (PartialDescriptor = 
FullDescriptor->PartialResourceList.PartialDescriptors;
              Count;
-             PartialDescriptor = PciNextPartialDescriptor(PartialDescriptor))
+             PartialDescriptor = 
CmiGetNextPartialDescriptor(PartialDescriptor))
         {
             /* Print each partial */
             PciDebugPrintPartialResource(PartialDescriptor);
             Count--;
         }
+
+        /* Go to the next full descriptor */
+        FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)PartialDescriptor;
     }
 
     /* Done printing data */
diff --git a/drivers/bus/pcix/enum.c b/drivers/bus/pcix/enum.c
index edb8a261d97..fc3563d2c21 100644
--- a/drivers/bus/pcix/enum.c
+++ b/drivers/bus/pcix/enum.c
@@ -168,7 +168,7 @@ PciComputeNewCurrentSettings(IN PPCI_PDO_EXTENSION 
PdoExtension,
             }
 
             /* Move to the next descriptor */
-            Partial = PciNextPartialDescriptor(Partial);
+            Partial = CmiGetNextPartialDescriptor(Partial);
         }
 
         /* We should be starting a new list now */
diff --git a/drivers/bus/pcix/pci.h b/drivers/bus/pcix/pci.h
index fc6b578c24d..eb7f517d48b 100644
--- a/drivers/bus/pcix/pci.h
+++ b/drivers/bus/pcix/pci.h
@@ -19,6 +19,7 @@
 #include <ndk/rtlfuncs.h>
 #include <ndk/vffuncs.h>
 #include <arbiter.h>
+#include <cmreslist.h>
 
 //
 // Tag used in all pool allocations (Pci Bus)
@@ -1173,12 +1174,6 @@ PciQueryCapabilities(
     IN OUT PDEVICE_CAPABILITIES DeviceCapability
 );
 
-PCM_PARTIAL_RESOURCE_DESCRIPTOR
-NTAPI
-PciNextPartialDescriptor(
-    PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
-);
-
 //
 // Configuration Routines
 //
@@ -1787,10 +1782,10 @@ PciCacheLegacyDeviceRouting(
     IN PDEVICE_OBJECT DeviceObject,
     IN ULONG BusNumber,
     IN ULONG SlotNumber,
-    IN UCHAR InterruptLine, 
-    IN UCHAR InterruptPin, 
-    IN UCHAR BaseClass, 
-    IN UCHAR SubClass, 
+    IN UCHAR InterruptLine,
+    IN UCHAR InterruptPin,
+    IN UCHAR BaseClass,
+    IN UCHAR SubClass,
     IN PDEVICE_OBJECT PhysicalDeviceObject,
     IN PPCI_PDO_EXTENSION PdoExtension,
     OUT PDEVICE_OBJECT *pFoundDeviceObject
diff --git a/drivers/bus/pcix/utils.c b/drivers/bus/pcix/utils.c
index 32a03339e63..fe231559264 100644
--- a/drivers/bus/pcix/utils.c
+++ b/drivers/bus/pcix/utils.c
@@ -1764,25 +1764,4 @@ PciQueryCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
     return Status;
 }
 
-PCM_PARTIAL_RESOURCE_DESCRIPTOR
-NTAPI
-PciNextPartialDescriptor(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor)
-{
-    PCM_PARTIAL_RESOURCE_DESCRIPTOR NextDescriptor;
-
-    /* Assume the descriptors are the fixed size ones */
-    NextDescriptor = CmDescriptor + 1;
-
-    /* But check if this is actually a variable-sized descriptor */
-    if (CmDescriptor->Type == CmResourceTypeDeviceSpecific)
-    {
-        /* Add the size of the variable section as well */
-        NextDescriptor = (PVOID)((ULONG_PTR)NextDescriptor +
-                                 CmDescriptor->u.DeviceSpecificData.DataSize);
-    }
-
-    /* Now the correct pointer has been computed, return it */
-    return NextDescriptor;
-}
-
 /* EOF */
diff --git a/ntoskrnl/include/internal/cm.h b/ntoskrnl/include/internal/cm.h
index a65e5e8ba2a..19f70265585 100644
--- a/ntoskrnl/include/internal/cm.h
+++ b/ntoskrnl/include/internal/cm.h
@@ -7,6 +7,7 @@
  */
 #define _CM_
 #include "cmlib.h"
+#include <cmreslist.h>
 
 //
 // Define this if you want debugging support
diff --git a/ntoskrnl/io/pnpmgr/pnpres.c b/ntoskrnl/io/pnpmgr/pnpres.c
index 2711e1a1dac..b417072b087 100644
--- a/ntoskrnl/io/pnpmgr/pnpres.c
+++ b/ntoskrnl/io/pnpmgr/pnpres.c
@@ -12,6 +12,16 @@
 #define NDEBUG
 #include <debug.h>
 
+FORCEINLINE
+PIO_RESOURCE_LIST
+IopGetNextResourceList(
+    _In_ const IO_RESOURCE_LIST *ResourceList)
+{
+    ASSERT((ResourceList->Count > 0) && (ResourceList->Count < 1000));
+    return (PIO_RESOURCE_LIST)(
+        &ResourceList->Descriptors[ResourceList->Count]);
+}
+
 static
 BOOLEAN
 IopCheckDescriptorForConflict(
@@ -199,6 +209,9 @@ IopFindInterruptResource(
         }
     }
 
+    DPRINT1("Failed to satisfy interrupt requirement with IRQ 0x%x-0x%x\n",
+            IoDesc->u.Interrupt.MinimumVector,
+            IoDesc->u.Interrupt.MaximumVector);
     return FALSE;
 }
 
@@ -209,6 +222,7 @@ IopFixupResourceListWithRequirements(
 {
     ULONG i, OldCount;
     BOOLEAN AlternateRequired = FALSE;
+    PIO_RESOURCE_LIST ResList;
 
     /* Save the initial resource count when we got here so we can restore if 
an alternate fails */
     if (*ResourceList != NULL)
@@ -216,10 +230,10 @@ IopFixupResourceListWithRequirements(
     else
         OldCount = 0;
 
-    for (i = 0; i < RequirementsList->AlternativeLists; i++)
+    ResList = &RequirementsList->List[0];
+    for (i = 0; i < RequirementsList->AlternativeLists; i++, ResList = 
IopGetNextResourceList(ResList))
     {
         ULONG ii;
-        PIO_RESOURCE_LIST ResList = &RequirementsList->List[i];
 
         /* We need to get back to where we were before processing the last 
alternative list */
         if (OldCount == 0 && *ResourceList != NULL)
@@ -275,6 +289,8 @@ IopFixupResourceListWithRequirements(
 
             for (iii = 0; PartialList && iii < PartialList->Count && !Matched; 
iii++)
             {
+                /* Partial resource descriptors can be of variable size 
(CmResourceTypeDeviceSpecific),
+                   but only one is allowed and it must be the last one in the 
list! */
                 PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc = 
&PartialList->PartialDescriptors[iii];
 
                 /* First check types */
@@ -548,12 +564,18 @@ IopCheckResourceDescriptor(
 {
     ULONG i, ii;
     BOOLEAN Result = FALSE;
+    PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
 
+    FullDescriptor = &ResourceList->List[0];
     for (i = 0; i < ResourceList->Count; i++)
     {
-        PCM_PARTIAL_RESOURCE_LIST ResList = 
&ResourceList->List[i].PartialResourceList;
+        PCM_PARTIAL_RESOURCE_LIST ResList = 
&FullDescriptor->PartialResourceList;
+        FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor);
+
         for (ii = 0; ii < ResList->Count; ii++)
         {
+            /* Partial resource descriptors can be of variable size 
(CmResourceTypeDeviceSpecific),
+               but only one is allowed and it must be the last one in the 
list! */
             PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2 = 
&ResList->PartialDescriptors[ii];
 
             /* We don't care about shared resources */
@@ -674,7 +696,9 @@ ByeBye:
                       sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
     }
 
-    return Result;
+    // Hacked, because after fixing resource list parsing
+    // we actually detect resource conflicts
+    return Silent ? Result : FALSE; // Result; 
 }
 
 static
@@ -937,6 +961,7 @@ IopTranslateDeviceResources(
 {
    PCM_PARTIAL_RESOURCE_LIST pPartialResourceList;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw, DescriptorTranslated;
+   PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
    ULONG i, j, ListSize;
    NTSTATUS Status;
 
@@ -959,13 +984,23 @@ IopTranslateDeviceResources(
    }
    RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, 
ListSize);
 
+   FullDescriptor = &DeviceNode->ResourceList->List[0];
    for (i = 0; i < DeviceNode->ResourceList->Count; i++)
    {
-      pPartialResourceList = 
&DeviceNode->ResourceList->List[i].PartialResourceList;
+      pPartialResourceList = &FullDescriptor->PartialResourceList;
+      FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor);
+
       for (j = 0; j < pPartialResourceList->Count; j++)
       {
+        /* Partial resource descriptors can be of variable size 
(CmResourceTypeDeviceSpecific),
+           but only one is allowed and it must be the last one in the list! */
          DescriptorRaw = &pPartialResourceList->PartialDescriptors[j];
-         DescriptorTranslated = 
&DeviceNode->ResourceListTranslated->List[i].PartialResourceList.PartialDescriptors[j];
+
+         /* Calculate the location of the translated resource descriptor */
+         DescriptorTranslated = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)(
+             (PUCHAR)DeviceNode->ResourceListTranslated +
+             ((PUCHAR)DescriptorRaw - (PUCHAR)DeviceNode->ResourceList));
+
          switch (DescriptorRaw->Type)
          {
             case CmResourceTypePort:
@@ -996,14 +1031,15 @@ IopTranslateDeviceResources(
             }
             case CmResourceTypeInterrupt:
             {
+               KIRQL Irql;
                DescriptorTranslated->u.Interrupt.Vector = 
HalGetInterruptVector(
                   DeviceNode->ResourceList->List[i].InterfaceType,
                   DeviceNode->ResourceList->List[i].BusNumber,
                   DescriptorRaw->u.Interrupt.Level,
                   DescriptorRaw->u.Interrupt.Vector,
-                  (PKIRQL)&DescriptorTranslated->u.Interrupt.Level,
+                  &Irql,
                   &DescriptorTranslated->u.Interrupt.Affinity);
-
+               DescriptorTranslated->u.Interrupt.Level = Irql;
                if (!DescriptorTranslated->u.Interrupt.Vector)
                {
                    Status = STATUS_UNSUCCESSFUL;
@@ -1184,12 +1220,18 @@ IopCheckForResourceConflict(
 {
    ULONG i, ii;
    BOOLEAN Result = FALSE;
+   PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
 
+   FullDescriptor = &ResourceList1->List[0];
    for (i = 0; i < ResourceList1->Count; i++)
    {
-      PCM_PARTIAL_RESOURCE_LIST ResList = 
&ResourceList1->List[i].PartialResourceList;
+      PCM_PARTIAL_RESOURCE_LIST ResList = &FullDescriptor->PartialResourceList;
+      FullDescriptor = CmiGetNextResourceDescriptor(FullDescriptor);
+
       for (ii = 0; ii < ResList->Count; ii++)
       {
+        /* Partial resource descriptors can be of variable size 
(CmResourceTypeDeviceSpecific),
+           but only one is allowed and it must be the last one in the list! */
          PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc = 
&ResList->PartialDescriptors[ii];
 
          Result = IopCheckResourceDescriptor(ResDesc,
diff --git a/sdk/include/reactos/drivers/cmreslist.h 
b/sdk/include/reactos/drivers/cmreslist.h
new file mode 100644
index 00000000000..5b52b8b6656
--- /dev/null
+++ b/sdk/include/reactos/drivers/cmreslist.h
@@ -0,0 +1,66 @@
+/*
+ * PROJECT:     ReactOS Kernel
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
+ * PURPOSE:     Helper functions to parse CM_RESOURCE_LISTs
+ * COPYRIGHT:   Copyright 2020 Timo Kreuzer ([email protected])
+ */
+
+#include <wdm.h>
+
+//
+// Resource list helpers
+//
+
+/* Usage note:
+ * As there can be only one variable-sized CM_PARTIAL_RESOURCE_DESCRIPTOR in 
the list (and it must be the last one),
+ * a right looping through resources can look like this:
+ *
+ * PCM_FULL_RESOURCE_DESCRIPTOR FullDesc = &ResourceList->List[0];
+ * for (ULONG i = 0; i < ResourceList->Count; i++, FullDesc = 
CmiGetNextResourceDescriptor(FullDesc))
+ * {
+ *    for (ULONG j = 0; j < FullDesc->PartialResourceList.Count; j++)
+ *    {
+ *        PartialDesc = &FullDesc->PartialResourceList.PartialDescriptors[j];
+ *        // work with PartialDesc
+ *    }
+ * }
+ */
+
+FORCEINLINE
+PCM_PARTIAL_RESOURCE_DESCRIPTOR
+CmiGetNextPartialDescriptor(
+    _In_ const CM_PARTIAL_RESOURCE_DESCRIPTOR *PartialDescriptor)
+{
+    const CM_PARTIAL_RESOURCE_DESCRIPTOR *NextDescriptor;
+
+    /* Assume the descriptors are the fixed size ones */
+    NextDescriptor = PartialDescriptor + 1;
+
+    /* But check if this is actually a variable-sized descriptor */
+    if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
+    {
+        /* Add the size of the variable section as well */
+        NextDescriptor = (PVOID)((ULONG_PTR)NextDescriptor +
+                                 
PartialDescriptor->u.DeviceSpecificData.DataSize);
+        ASSERT(NextDescriptor >= PartialDescriptor + 1);
+    }
+
+    /* Now the correct pointer has been computed, return it */
+    return (PCM_PARTIAL_RESOURCE_DESCRIPTOR)NextDescriptor;
+}
+
+FORCEINLINE
+PCM_FULL_RESOURCE_DESCRIPTOR
+CmiGetNextResourceDescriptor(
+    _In_ const CM_FULL_RESOURCE_DESCRIPTOR *ResourceDescriptor)
+{
+    const CM_PARTIAL_RESOURCE_DESCRIPTOR *LastPartialDescriptor;
+
+    /* Calculate the location of the last partial descriptor, which can have a
+       variable size! */
+    LastPartialDescriptor = 
&ResourceDescriptor->PartialResourceList.PartialDescriptors[
+            ResourceDescriptor->PartialResourceList.Count - 1];
+
+    /* Next full resource descriptor follows the last partial descriptor */
+    return 
(PCM_FULL_RESOURCE_DESCRIPTOR)CmiGetNextPartialDescriptor(LastPartialDescriptor);
+}
diff --git a/win32ss/drivers/videoprt/resource.c 
b/win32ss/drivers/videoprt/resource.c
index 4a44392a0f3..f6ac53c6842 100644
--- a/win32ss/drivers/videoprt/resource.c
+++ b/win32ss/drivers/videoprt/resource.c
@@ -765,7 +765,7 @@ VideoPortGetAccessRanges(
             ERR_(VIDEOPRT, "Too many access ranges found\n");
             return ERROR_NOT_ENOUGH_MEMORY;
         }
-        if (Descriptor->Type == CmResourceTypeMemory)
+        else if (Descriptor->Type == CmResourceTypeMemory)
         {
             INFO_(VIDEOPRT, "Memory range starting at 0x%08x length 0x%08x\n",
                   Descriptor->u.Memory.Start.u.LowPart, 
Descriptor->u.Memory.Length);
@@ -804,6 +804,11 @@ VideoPortGetAccessRanges(
             else
                 DeviceExtension->InterruptShared = FALSE;
         }
+        else
+        {
+            ASSERT(FALSE);
+            return ERROR_INVALID_PARAMETER;
+        }
     }
 
     return NO_ERROR;
@@ -838,7 +843,7 @@ VideoPortVerifyAccessRanges(
    if (!ResourceList)
    {
       WARN_(VIDEOPRT, "ExAllocatePool() failed\n");
-      return ERROR_INVALID_PARAMETER;
+      return ERROR_NOT_ENOUGH_MEMORY;
    }
 
    /* Fill resource list */

Reply via email to