]> git.proxmox.com Git - mirror_edk2.git/blobdiff - DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
DynamicTablesPkg: AcpiSsdtPcieLibArm: Allow use of segment number as UID
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiSsdtPcieLibArm / SsdtPcieGenerator.c
index 3c20d928ce8cad3ed545bda4e3804410a53cb8ac..85098752c614f6556ee768fd79a11ea316c0b5d4 100644 (file)
 #include <Library/AcpiHelperLib.h>\r
 #include <Library/TableHelperLib.h>\r
 #include <Library/AmlLib/AmlLib.h>\r
+#include <Library/SsdtPcieSupportLib.h>\r
 #include <Protocol/ConfigurationManagerProtocol.h>\r
 \r
 #include "SsdtPcieGenerator.h"\r
 \r
+#define PCI_MAX_DEVICE_COUNT_PER_BUS       32\r
+#define PCI_MAX_FUNCTION_COUNT_PER_DEVICE  8\r
+\r
 /** ARM standard SSDT Pcie Table Generator.\r
 \r
 Requirements:\r
@@ -280,86 +284,6 @@ GeneratePciDeviceInfo (
   return Status;\r
 }\r
 \r
-/** Generate Pci slots devices.\r
-\r
-  PCI Firmware Specification - Revision 3.3,\r
-  s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot\r
-  used. It should be possible to enumerate them, but this is additional\r
-  information.\r
-\r
-  @param [in]  MappingTable  The mapping table structure.\r
-  @param [in, out]  PciNode     Pci node to amend.\r
-\r
-  @retval EFI_SUCCESS            Success.\r
-  @retval EFI_INVALID_PARAMETER  Invalid parameter.\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-GeneratePciSlots (\r
-  IN      CONST MAPPING_TABLE           *MappingTable,\r
-  IN  OUT       AML_OBJECT_NODE_HANDLE  PciNode\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  UINT32                  Index;\r
-  UINT32                  LastIndex;\r
-  UINT32                  DeviceId;\r
-  CHAR8                   AslName[AML_NAME_SEG_SIZE + 1];\r
-  AML_OBJECT_NODE_HANDLE  DeviceNode;\r
-\r
-  ASSERT (MappingTable != NULL);\r
-  ASSERT (PciNode != NULL);\r
-\r
-  // Generic device name is "Dxx".\r
-  CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1);\r
-\r
-  LastIndex = MappingTable->LastIndex;\r
-\r
-  // There are at most 32 devices on a Pci bus.\r
-  if (LastIndex >= 32) {\r
-    ASSERT (0);\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  for (Index = 0; Index < LastIndex; Index++) {\r
-    DeviceId                       = MappingTable->Table[Index];\r
-    AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF);\r
-    AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF);\r
-\r
-    // ASL:\r
-    // Device (Dxx) {\r
-    //   Name (_ADR, <address value>)\r
-    // }\r
-    Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode);\r
-    if (EFI_ERROR (Status)) {\r
-      ASSERT (0);\r
-      return Status;\r
-    }\r
-\r
-    /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"\r
-       High word-Device #, Low word-Function #. (for example, device 3,\r
-       function 2 is 0x00030002). To refer to all the functions on a device #,\r
-       use a function number of FFFF).\r
-    */\r
-    Status = AmlCodeGenNameInteger (\r
-               "_ADR",\r
-               (DeviceId << 16) | 0xFFFF,\r
-               DeviceNode,\r
-               NULL\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      ASSERT (0);\r
-      return Status;\r
-    }\r
-\r
-    // _SUN object is not generated as we don't know which slot will be used.\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
 /** Generate a _PRT object (Pci Routing Table) for the Pci device.\r
 \r
   Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)"\r
@@ -374,6 +298,7 @@ GeneratePciSlots (
   @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager\r
                                     Protocol interface.\r
   @param [in]       PciInfo         Pci device information.\r
+  @param [in]       Uid             Unique Id of the Pci device.\r
   @param [in, out]  PciNode         Pci node to amend.\r
 \r
   @retval EFI_SUCCESS             The function completed successfully.\r
@@ -387,6 +312,7 @@ GeneratePrt (
   IN            ACPI_PCI_GENERATOR                            *Generator,\r
   IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,\r
   IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO                  *PciInfo,\r
+  IN            UINT32                                        Uid,\r
   IN  OUT       AML_OBJECT_NODE_HANDLE                        PciNode\r
   )\r
 {\r
@@ -495,7 +421,7 @@ GeneratePrt (
   PrtNode = NULL;\r
 \r
   // Generate the Pci slots once all the device have been added.\r
-  Status = GeneratePciSlots (&Generator->DeviceTable, PciNode);\r
+  Status = GeneratePciSlots (PciInfo, &Generator->DeviceTable, Uid, PciNode);\r
   if (EFI_ERROR (Status)) {\r
     ASSERT (0);\r
     goto exit_handler;\r
@@ -695,84 +621,125 @@ GeneratePciCrs (
   return Status;\r
 }\r
 \r
-/** Add an _OSC template method to the PciNode.\r
-\r
-  The _OSC method is provided as an AML blob. The blob is\r
-  parsed and attached at the end of the PciNode list of variable elements.\r
+/** Generate a RES0 device node to reserve PNP motherboard resources\r
+  for a given PCI node.\r
 \r
-  @param [in, out]  PciNode     Pci node to amend.\r
+  @param [in]   PciNode       Parent PCI node handle of the generated\r
+                              resource object.\r
+  @param [out]  CrsNode       CRS node of the AML tree to populate.\r
 \r
   @retval EFI_SUCCESS             The function completed successfully.\r
-  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+  @retval EFI_INVALID_PARAMETER   Invalid input parameter.\r
   @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.\r
 **/\r
 STATIC\r
 EFI_STATUS\r
 EFIAPI\r
-AddOscMethod (\r
-  IN  OUT   AML_OBJECT_NODE_HANDLE  PciNode\r
+GenerateMotherboardDevice (\r
+  IN  AML_OBJECT_NODE_HANDLE  PciNode,\r
+  OUT AML_OBJECT_NODE_HANDLE  *CrsNode\r
   )\r
 {\r
-  EFI_STATUS                   Status;\r
-  EFI_STATUS                   Status1;\r
-  EFI_ACPI_DESCRIPTION_HEADER  *SsdtPcieOscTemplate;\r
-  AML_ROOT_NODE_HANDLE         OscTemplateRoot;\r
-  AML_OBJECT_NODE_HANDLE       OscNode;\r
+  EFI_STATUS              Status;\r
+  UINT32                  EisaId;\r
+  AML_OBJECT_NODE_HANDLE  ResNode;\r
 \r
-  ASSERT (PciNode != NULL);\r
+  if (CrsNode == NULL) {\r
+    ASSERT (0);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-  // Parse the Ssdt Pci Osc Template.\r
-  SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER *)\r
-                        ssdtpcieosctemplate_aml_code;\r
+  // ASL: Device (RES0) {}\r
+  Status = AmlCodeGenDevice ("RES0", PciNode, &ResNode);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    return Status;\r
+  }\r
 \r
-  OscNode         = NULL;\r
-  OscTemplateRoot = NULL;\r
-  Status          = AmlParseDefinitionBlock (\r
-                      SsdtPcieOscTemplate,\r
-                      &OscTemplateRoot\r
-                      );\r
+  // ASL: Name (_HID, EISAID ("PNP0C02"))\r
+  Status = AmlGetEisaIdFromString ("PNP0C02", &EisaId); /* PNP Motherboard Resources */\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."\r
-      " Status = %r\n",\r
-      Status\r
-      ));\r
+    ASSERT (0);\r
     return Status;\r
   }\r
 \r
-  Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode);\r
+  Status = AmlCodeGenNameInteger ("_HID", EisaId, ResNode, NULL);\r
   if (EFI_ERROR (Status)) {\r
-    goto error_handler;\r
+    ASSERT (0);\r
+    return Status;\r
   }\r
 \r
-  Status = AmlDetachNode (OscNode);\r
+  // ASL: Name (_CRS, ResourceTemplate () {})\r
+  Status = AmlCodeGenNameResourceTemplate ("_CRS", ResNode, CrsNode);\r
   if (EFI_ERROR (Status)) {\r
-    goto error_handler;\r
+    ASSERT (0);\r
+    return Status;\r
   }\r
 \r
-  Status = AmlAttachNode (PciNode, OscNode);\r
+  return Status;\r
+}\r
+\r
+/** Reserves ECAM space for PCI config space\r
+\r
+  @param [in]       Generator       The SSDT Pci generator.\r
+  @param [in]       CfgMgrProtocol  Pointer to the Configuration Manager\r
+                                    Protocol interface.\r
+  @param [in]       PciInfo         Pci device information.\r
+  @param [in, out]  PciNode         RootNode of the AML tree to populate.\r
+\r
+  @retval EFI_SUCCESS             The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate memory.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+ReserveEcamSpace (\r
+  IN            ACPI_PCI_GENERATOR                            *Generator,\r
+  IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,\r
+  IN      CONST CM_ARM_PCI_CONFIG_SPACE_INFO                  *PciInfo,\r
+  IN  OUT       AML_OBJECT_NODE_HANDLE                        PciNode\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  AML_OBJECT_NODE_HANDLE  CrsNode;\r
+  UINT64                  AddressMinimum;\r
+  UINT64                  AddressMaximum;\r
+\r
+  Status = GenerateMotherboardDevice (PciNode, &CrsNode);\r
   if (EFI_ERROR (Status)) {\r
-    // Free the detached node.\r
-    AmlDeleteTree (OscNode);\r
-    goto error_handler;\r
+    ASSERT (0);\r
+    return Status;\r
   }\r
 \r
-error_handler:\r
-  // Cleanup\r
-  Status1 = AmlDeleteTree (OscTemplateRoot);\r
-  if (EFI_ERROR (Status1)) {\r
-    DEBUG ((\r
-      DEBUG_ERROR,\r
-      "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree."\r
-      " Status = %r\n",\r
-      Status1\r
-      ));\r
-    // If Status was success but we failed to delete the AML Tree\r
-    // return Status1 else return the original error code, i.e. Status.\r
-    if (!EFI_ERROR (Status)) {\r
-      return Status1;\r
-    }\r
+  AddressMinimum = PciInfo->BaseAddress + (PciInfo->StartBusNumber *\r
+                                           PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB);\r
+  AddressMaximum = PciInfo->BaseAddress + ((PciInfo->EndBusNumber + 1) *\r
+                                           PCI_MAX_DEVICE_COUNT_PER_BUS * PCI_MAX_FUNCTION_COUNT_PER_DEVICE * SIZE_4KB) - 1;\r
+\r
+  Status = AmlCodeGenRdQWordMemory (\r
+             FALSE,\r
+             TRUE,\r
+             TRUE,\r
+             TRUE,\r
+             FALSE,  // non-cacheable\r
+             TRUE,\r
+             0,\r
+             AddressMinimum,\r
+             AddressMaximum,\r
+             0,  // no translation\r
+             AddressMaximum - AddressMinimum + 1,\r
+             0,\r
+             NULL,\r
+             0,\r
+             TRUE,\r
+             CrsNode,\r
+             NULL\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    return Status;\r
   }\r
 \r
   return Status;\r
@@ -824,7 +791,10 @@ GeneratePciDevice (
 \r
   // Write the name of the PCI device.\r
   CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);\r
-  AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid);\r
+  AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid & 0xF);\r
+  if (Uid > 0xF) {\r
+    AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((Uid >> 4) & 0xF);\r
+  }\r
 \r
   // ASL: Device (PCIx) {}\r
   Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode);\r
@@ -846,6 +816,7 @@ GeneratePciDevice (
                Generator,\r
                CfgMgrProtocol,\r
                PciInfo,\r
+               Uid,\r
                PciNode\r
                );\r
     if (EFI_ERROR (Status)) {\r
@@ -861,9 +832,17 @@ GeneratePciDevice (
     return Status;\r
   }\r
 \r
+  // Add the PNP Motherboard Resources Device to reserve ECAM space\r
+  Status = ReserveEcamSpace (Generator, CfgMgrProtocol, PciInfo, PciNode);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    return Status;\r
+  }\r
+\r
   // Add the template _OSC method.\r
-  Status = AddOscMethod (PciNode);\r
+  Status = AddOscMethod (PciInfo, PciNode);\r
   ASSERT_EFI_ERROR (Status);\r
+\r
   return Status;\r
 }\r
 \r
@@ -1002,6 +981,7 @@ BuildSsdtPciTableEx (
   UINTN                         Index;\r
   EFI_ACPI_DESCRIPTION_HEADER   **TableList;\r
   ACPI_PCI_GENERATOR            *Generator;\r
+  UINT32                        Uid;\r
 \r
   ASSERT (This != NULL);\r
   ASSERT (AcpiTableInfo != NULL);\r
@@ -1057,13 +1037,29 @@ BuildSsdtPciTableEx (
   *Table = TableList;\r
 \r
   for (Index = 0; Index < PciCount; Index++) {\r
+    if (PcdGetBool (PcdPciUseSegmentAsUid)) {\r
+      Uid = PciInfo[Index].PciSegmentGroupNumber;\r
+      if (Uid > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) {\r
+        DEBUG ((\r
+          DEBUG_ERROR,\r
+          "ERROR: SSDT-PCI: Pci root complexes segment number: %d."\r
+          " Greater than maximum number of Pci root complexes supported = %d.\n",\r
+          Uid,\r
+          MAX_PCI_ROOT_COMPLEXES_SUPPORTED\r
+          ));\r
+        return EFI_INVALID_PARAMETER;\r
+      }\r
+    } else {\r
+      Uid = Index;\r
+    }\r
+\r
     // Build a SSDT table describing the Pci devices.\r
     Status = BuildSsdtPciTable (\r
                Generator,\r
                CfgMgrProtocol,\r
                AcpiTableInfo,\r
                &PciInfo[Index],\r
-               Index,\r
+               Uid,\r
                &TableList[Index]\r
                );\r
     if (EFI_ERROR (Status)) {\r