]> git.proxmox.com Git - mirror_edk2.git/commitdiff
DynamicTablesPkg: AML Code generation to add _PRT entries
authorPierre Gondois <Pierre.Gondois@arm.com>
Thu, 9 Dec 2021 09:25:01 +0000 (10:25 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 13 Dec 2021 12:48:42 +0000 (12:48 +0000)
_PRT entries can describe interrupt mapping for Pci devices. The
object is described in ACPI 6.4 s6.2.13 "_PRT (PCI Routing Table)".

Add AmlCodeGenPrtEntry() helper function to add _PRT entries
to an existing _PRT object.

To: Sami Mujawar <sami.mujawar@arm.com>
To: Alexei Fedorov <Alexei.Fedorov@arm.com>
Signed-off-by: Pierre Gondois <Pierre.Gondois@arm.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c

index 8949cf4d932a7d036f88bd5484e6289fc1555fb4..9ca34f61ba88c44b27a81fb952794d4f6c0a9408 100644 (file)
@@ -891,6 +891,58 @@ AmlCodeGenNameResourceTemplate (
   OUT       AML_OBJECT_NODE_HANDLE  *NewObjectNode   OPTIONAL\r
   );\r
 \r
+/** Add a _PRT entry.\r
+\r
+  AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is\r
+  equivalent of the following ASL code:\r
+    Package (4) {\r
+      0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).\r
+      0,       // Pin: PCI pin number of the device (0-INTA, ...).\r
+      LNKA     // Source: Name of the device that allocates the interrupt\r
+               // to which the above pin is connected.\r
+      0        // Source Index: Source is assumed to only describe one\r
+               // interrupt, so let it to index 0.\r
+    }\r
+\r
+  The package is added at the tail of the list of the input _PRT node\r
+  name:\r
+    Name (_PRT, Package () {\r
+      [Pre-existing _PRT entries],\r
+      [Newly created _PRT entry]\r
+    })\r
+\r
+  Cf. ACPI 6.4, s6.2.13 "_PRT (PCI Routing Table)"\r
+\r
+  @ingroup CodeGenApis\r
+\r
+  @param [in]  Address        Address. Cf ACPI 6.4 specification, Table 6.2:\r
+                              "ADR Object Address Encodings":\r
+                              High word-Device #, Low word-Function #. (for\r
+                              example, device 3, function 2 is 0x00030002).\r
+                              To refer to all the functions on a device #,\r
+                              use a function number of FFFF).\r
+  @param [in]  Pin            PCI pin number of the device (0-INTA ... 3-INTD).\r
+                              Must be between 0-3.\r
+  @param [in]  LinkName       Link Name, i.e. device in the AML NameSpace\r
+                              describing the interrupt used.\r
+                              The input string is copied.\r
+  @param [in]  SourceIndex    Source index or GSIV.\r
+  @param [in]  PrtNameNode    Prt Named node to add the object to ....\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
+EFI_STATUS\r
+EFIAPI\r
+AmlAddPrtEntry (\r
+  IN        UINT32                  Address,\r
+  IN        UINT8                   Pin,\r
+  IN  CONST CHAR8                   *LinkName,\r
+  IN        UINT32                  SourceIndex,\r
+  IN        AML_OBJECT_NODE_HANDLE  PrtNameNode\r
+  );\r
+\r
 /** AML code generation for a Device object node.\r
 \r
   AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is\r
index 778e3c5ffaf0fe09fe9ad5c3b70f4137e20ef265..d245848ce3fa35f6b58b89210d56e9cf3a8d5d01 100644 (file)
@@ -868,6 +868,220 @@ AmlCodeGenNameResourceTemplate (
   return Status;\r
 }\r
 \r
+/** Add a _PRT entry.\r
+\r
+  AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is\r
+  equivalent of the following ASL code:\r
+    Package (4) {\r
+      0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).\r
+      0,       // Pin: PCI pin number of the device (0-INTA, ...).\r
+      LNKA     // Source: Name of the device that allocates the interrupt\r
+               // to which the above pin is connected.\r
+      0        // Source Index: Source is assumed to only describe one\r
+               // interrupt, so let it to index 0.\r
+    }\r
+\r
+  The package is added at the tail of the list of the input _PRT node\r
+  name:\r
+    Name (_PRT, Package () {\r
+      [Pre-existing _PRT entries],\r
+      [Newly created _PRT entry]\r
+    })\r
+\r
+  Cf. ACPI 6.4 specification:\r
+   - s6.2.13 "_PRT (PCI Routing Table)"\r
+   - s6.1.1 "_ADR (Address)"\r
+\r
+  @param [in]  Address        Address. Cf ACPI 6.4 specification, Table 6.2:\r
+                              "ADR Object Address Encodings":\r
+                              High word-Device #, Low word-Function #. (for\r
+                              example, device 3, function 2 is 0x00030002).\r
+                              To refer to all the functions on a device #,\r
+                              use a function number of FFFF).\r
+  @param [in]  Pin            PCI pin number of the device (0-INTA ... 3-INTD).\r
+                              Must be between 0-3.\r
+  @param [in]  LinkName       Link Name, i.e. device in the AML NameSpace\r
+                              describing the interrupt used.\r
+                              The input string is copied.\r
+  @param [in]  SourceIndex    Source index or GSIV.\r
+  @param [in]  PrtNameNode    Prt Named node to add the object to ....\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
+EFI_STATUS\r
+EFIAPI\r
+AmlAddPrtEntry (\r
+  IN        UINT32                  Address,\r
+  IN        UINT8                   Pin,\r
+  IN  CONST CHAR8                   *LinkName,\r
+  IN        UINT32                  SourceIndex,\r
+  IN        AML_OBJECT_NODE_HANDLE  PrtNameNode\r
+  )\r
+{\r
+  EFI_STATUS       Status;\r
+  AML_OBJECT_NODE  *PrtEntryList;\r
+  AML_OBJECT_NODE  *PackageNode;\r
+  AML_OBJECT_NODE  *NewElementNode;\r
+\r
+  CHAR8          *AmlNameString;\r
+  UINT32         AmlNameStringSize;\r
+  AML_DATA_NODE  *DataNode;\r
+\r
+  if ((Pin > 3)                 ||\r
+      (LinkName == NULL)        ||\r
+      (PrtNameNode == NULL)     ||\r
+      (AmlGetNodeType ((AML_NODE_HANDLE)PrtNameNode) != EAmlNodeObject) ||\r
+      (!AmlNodeHasOpCode (PrtNameNode, AML_NAME_OP, 0))                 ||\r
+      !AmlNameOpCompareName (PrtNameNode, "_PRT"))\r
+  {\r
+    ASSERT (0);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  NewElementNode = NULL;\r
+  AmlNameString  = NULL;\r
+  DataNode       = NULL;\r
+\r
+  // Get the Package object node of the _PRT node,\r
+  // which is the 2nd fixed argument (i.e. index 1).\r
+  PrtEntryList = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (\r
+                                           PrtNameNode,\r
+                                           EAmlParseIndexTerm1\r
+                                           );\r
+  if ((PrtEntryList == NULL)                                              ||\r
+      (AmlGetNodeType ((AML_NODE_HANDLE)PrtEntryList) != EAmlNodeObject)  ||\r
+      (!AmlNodeHasOpCode (PrtEntryList, AML_PACKAGE_OP, 0)))\r
+  {\r
+    ASSERT (0);\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  // The new _PRT entry.\r
+  Status = AmlCodeGenPackage (&PackageNode);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    return Status;\r
+  }\r
+\r
+  Status = AmlCodeGenInteger (Address, &NewElementNode);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  Status = AmlVarListAddTail (\r
+             (AML_NODE_HANDLE)PackageNode,\r
+             (AML_NODE_HANDLE)NewElementNode\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  NewElementNode = NULL;\r
+\r
+  Status = AmlCodeGenInteger (Pin, &NewElementNode);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  Status = AmlVarListAddTail (\r
+             (AML_NODE_HANDLE)PackageNode,\r
+             (AML_NODE_HANDLE)NewElementNode\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  NewElementNode = NULL;\r
+\r
+  Status = ConvertAslNameToAmlName (LinkName, &AmlNameString);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  Status = AmlCreateDataNode (\r
+             EAmlNodeDataTypeNameString,\r
+             (UINT8 *)AmlNameString,\r
+             AmlNameStringSize,\r
+             &DataNode\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  // AmlNameString will be freed before returning.\r
+\r
+  Status = AmlVarListAddTail (\r
+             (AML_NODE_HANDLE)PackageNode,\r
+             (AML_NODE_HANDLE)DataNode\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  DataNode = NULL;\r
+\r
+  Status = AmlCodeGenInteger (SourceIndex, &NewElementNode);\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  Status = AmlVarListAddTail (\r
+             (AML_NODE_HANDLE)PackageNode,\r
+             (AML_NODE_HANDLE)NewElementNode\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  // Append to the the list of _PRT entries.\r
+  Status = AmlVarListAddTail (\r
+             (AML_NODE_HANDLE)PrtEntryList,\r
+             (AML_NODE_HANDLE)PackageNode\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    ASSERT (0);\r
+    goto error_handler;\r
+  }\r
+\r
+  // Free AmlNameString before returning as it is copied\r
+  // in the call to AmlCreateDataNode().\r
+  goto exit_handler;\r
+\r
+error_handler:\r
+  AmlDeleteTree ((AML_NODE_HANDLE)PackageNode);\r
+  if (NewElementNode != NULL) {\r
+    AmlDeleteTree ((AML_NODE_HANDLE)NewElementNode);\r
+  }\r
+\r
+  if (DataNode != NULL) {\r
+    AmlDeleteTree ((AML_NODE_HANDLE)DataNode);\r
+  }\r
+\r
+exit_handler:\r
+  if (AmlNameString != NULL) {\r
+    FreePool (AmlNameString);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
 /** AML code generation for a Device object node.\r
 \r
   AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is\r