Date   

[PATCH v2 04/15] DynamicTablesPkg: FdtHwInfoParser: Add Boot Arch parser

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

The Fixed ACPI Description Table (FADT) is a mandatory table
required for booting a standards-based operating system. The
FADT table has an 'ARM Boot Architecture Flags' field that is
used by an OS at boot time to determine the code path during
boot. This field is used to specify if the platform complies
with the PSCI specification. It is also used to describe the
conduit (SMC/HVC) to be used for PSCI.

The PSCI compliance information for a platform is described
in the platform Device Tree, the bindings for which can be
found at:
- linux/Documentation/devicetree/bindings/arm/psci.yaml

The FdtHwInfoParser implements a Boot Arch Parser that parses
the platform Device Tree to create a CM_ARM_BOOT_ARCH_INFO
object. The CM_ARM_BOOT_ARCH_INFO object is encapsulated in
a Configuration Manager descriptor object and added to the
platform information repository.

The platform Configuration Manager can then utilise this
information when generating the FADT table.

Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../BootArch/ArmBootArchParser.c | 159 ++++++++++++++++++
.../BootArch/ArmBootArchParser.h | 45 +++++
2 files changed, 204 insertions(+)
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.h

diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.c
new file mode 100644
index 000000000000..5040e50eb16a
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.c
@@ -0,0 +1,159 @@
+/** @file
+ Arm boot architecture parser.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - linux/Documentation/devicetree/bindings/arm/psci.yaml
+**/
+
+#include "FdtHwInfoParser.h"
+#include "CmObjectDescUtility.h"
+#include "BootArch/ArmBootArchParser.h"
+
+/** List of "compatible" property values for Psci nodes.
+
+ Other "compatible" values are not supported by this module.
+*/
+STATIC CONST COMPATIBILITY_STR PsciCompatibleStr[] = {
+ {"arm,psci-0.2"},
+ {"arm,psci"}
+};
+
+/** COMPATIBILITY_INFO structure for the PsciCompatibleInfo.
+*/
+STATIC CONST COMPATIBILITY_INFO PsciCompatibleInfo = {
+ ARRAY_SIZE (PsciCompatibleStr),
+ PsciCompatibleStr
+};
+
+/** List of PSCI method strings.
+*/
+STATIC CONST CHAR8 *PsciMethod[] = {
+ "smc",
+ "hvc"
+};
+
+/** Parse a Psci node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] PsciNode Offset of a Psci node.
+ @param [in] BootArchInfo The CM_ARM_BOOT_ARCH_INFO to populate.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+PsciNodeParser (
+ IN CONST VOID * Fdt,
+ IN INT32 PsciNode,
+ IN CM_ARM_BOOT_ARCH_INFO * BootArchInfo
+ )
+{
+ CONST VOID * Data;
+ INT32 DataSize;
+
+ if ((Fdt == NULL) ||
+ (BootArchInfo == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Default to parking protocol
+ BootArchInfo->BootArchFlags = 0;
+
+ Data = fdt_getprop (Fdt, PsciNode, "method", &DataSize);
+ if ((Data == NULL) || (DataSize < 0)) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ // Check PSCI conduit.
+ if (AsciiStrnCmp (Data, PsciMethod[0], DataSize) == 0) {
+ BootArchInfo->BootArchFlags = EFI_ACPI_6_3_ARM_PSCI_COMPLIANT;
+
+ } else if (AsciiStrnCmp (Data, PsciMethod[1], DataSize) == 0) {
+ BootArchInfo->BootArchFlags = (EFI_ACPI_6_3_ARM_PSCI_COMPLIANT |
+ EFI_ACPI_6_3_ARM_PSCI_USE_HVC);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** CM_ARM_BOOT_ARCH_INFO parser function.
+
+ The following structure is populated:
+ typedef struct CmArmBootArchInfo {
+ UINT16 BootArchFlags; // {Populated}
+ } CM_ARM_BOOT_ARCH_INFO;
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+ArmBootArchInfoParser (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN INT32 FdtBranch
+ )
+{
+ EFI_STATUS Status;
+ INT32 PsciNode;
+ CM_ARM_BOOT_ARCH_INFO BootArchInfo;
+
+ if (FdtParserHandle == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (&BootArchInfo, sizeof (CM_ARM_BOOT_ARCH_INFO));
+
+ PsciNode = FdtBranch;
+ Status = FdtGetNextCompatNodeInBranch (
+ FdtParserHandle->Fdt,
+ FdtBranch,
+ &PsciCompatibleInfo,
+ &PsciNode
+ );
+ if (EFI_ERROR (Status)) {
+ // Error, or no node found.
+ ASSERT (Status == EFI_NOT_FOUND);
+ return Status;
+ }
+
+ // Parse the psci node.
+ Status = PsciNodeParser (FdtParserHandle->Fdt, PsciNode, &BootArchInfo);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the CmObj to the Configuration Manager.
+ Status = AddSingleCmObj (
+ FdtParserHandle,
+ CREATE_CM_ARM_OBJECT_ID (EArmObjBootArchInfo),
+ &BootArchInfo,
+ sizeof (CM_ARM_BOOT_ARCH_INFO),
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.h
new file mode 100644
index 000000000000..959c65a53fb3
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.h
@@ -0,0 +1,45 @@
+/** @file
+ Arm boot architecture parser.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - linux/Documentation/devicetree/bindings/arm/psci.yaml
+**/
+
+#ifndef ARM_BOOT_ARCH_PARSER_H_
+#define ARM_BOOT_ARCH_PARSER_H_
+
+/** CM_ARM_BOOT_ARCH_INFO parser function.
+
+ The following structure is populated:
+ typedef struct CmArmBootArchInfo {
+ UINT16 BootArchFlags; // {Populated}
+ } CM_ARM_BOOT_ARCH_INFO;
+
+ A parser parses a Device Tree to populate a specific CmObj type. None,
+ one or many CmObj can be created by the parser.
+ The created CmObj are then handed to the parser's caller through the
+ HW_INFO_ADD_OBJECT interface.
+ This can also be a dispatcher. I.e. a function that not parsing a
+ Device Tree but calling other parsers.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] FdtBranch When searching for DT node name, restrict
+ the search to this Device Tree branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Not found.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+ArmBootArchInfoParser (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN INT32 FdtBranch
+ );
+
+#endif // ARM_BOOT_ARCH_PARSER_H_
--
2.17.1


[PATCH v2 03/15] DynamicTablesPkg: FdtHwInfoParser: Add FDT utility functions

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

The FdtHwInfoParser parses a platform Device Tree and populates
the Platform Information repository with Configuration Manager
objects.

Therefore, add a set of helper functions to simplify parsing of
the platform Device Tree.

Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../Library/FdtHwInfoParserLib/FdtUtility.c | 907 ++++++++++++++++++
.../Library/FdtHwInfoParserLib/FdtUtility.h | 458 +++++++++
2 files changed, 1365 insertions(+)
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h

diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
new file mode 100644
index 000000000000..3a88fda46127
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
@@ -0,0 +1,907 @@
+/** @file
+ Flattened device tree utility.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - Device tree Specification - Release v0.3
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
+ - linux//Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
+**/
+
+#include <FdtHwInfoParserInclude.h>
+#include "FdtUtility.h"
+
+/** Get the interrupt Id of an interrupt described in a fdt.
+
+ Data must describe a GIC interrupt. A GIC interrupt is on at least
+ 3 UINT32 cells.
+ This function DOES NOT SUPPORT extended SPI range and extended PPI range.
+
+ @param [in] Data Pointer to the first cell of an "interrupts" property.
+
+ @retval The interrupt id.
+**/
+UINT32
+EFIAPI
+FdtGetInterruptId (
+ UINT32 CONST * Data
+ )
+{
+ UINT32 IrqType;
+ UINT32 IrqId;
+
+ ASSERT (Data != NULL);
+
+ IrqType = fdt32_to_cpu (Data[IRQ_TYPE_OFFSET]);
+ IrqId = fdt32_to_cpu (Data[IRQ_NUMBER_OFFSET]);
+
+ switch (IrqType) {
+ case DT_SPI_IRQ:
+ IrqId += SPI_OFFSET;
+ break;
+
+ case DT_PPI_IRQ:
+ IrqId += PPI_OFFSET;
+ break;
+
+ default:
+ ASSERT (0);
+ IrqId = 0;
+ }
+
+ return IrqId;
+}
+
+/** Get the ACPI interrupt flags of an interrupt described in a fdt.
+
+ Data must describe a GIC interrupt. A GIC interrupt is on at least
+ 3 UINT32 cells.
+
+ PPI interrupt cpu mask on bits [15:8] are ignored.
+
+ @param [in] Data Pointer to the first cell of an "interrupts" property.
+
+ @retval The interrupt flags (for ACPI).
+**/
+UINT32
+EFIAPI
+FdtGetInterruptFlags (
+ UINT32 CONST * Data
+ )
+{
+ UINT32 IrqFlags;
+ UINT32 AcpiIrqFlags;
+
+ ASSERT (Data != NULL);
+
+ IrqFlags = fdt32_to_cpu (Data[IRQ_FLAGS_OFFSET]);
+
+ AcpiIrqFlags = DT_IRQ_IS_EDGE_TRIGGERED (IrqFlags) ? BIT0 : 0;
+ AcpiIrqFlags |= DT_IRQ_IS_ACTIVE_LOW (IrqFlags) ? BIT1 : 0;
+
+ return AcpiIrqFlags;
+}
+
+/** Check whether a node has the input name.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node to check the name.
+ @param [in] SearchName Node name to search.
+ This is a NULL terminated string.
+
+ @retval True The node has the input name.
+ @retval FALSE Otherwise, or error.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+FdtNodeHasName (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ IN CONST VOID * SearchName
+ )
+{
+ CONST CHAR8 * NodeName;
+ UINT32 Length;
+
+ if ((Fdt == NULL) ||
+ (SearchName == NULL)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Always compare the whole string. Don't stop at the "@" char.
+ Length = (UINT32)AsciiStrLen (SearchName);
+
+ // Get the address of the node name.
+ NodeName = fdt_offset_ptr (Fdt, Node + FDT_TAGSIZE, Length + 1);
+ if (NodeName == NULL) {
+ return FALSE;
+ }
+
+ // SearchName must be longer than the node name.
+ if (Length > AsciiStrLen (NodeName)) {
+ return FALSE;
+ }
+
+ if (AsciiStrnCmp (NodeName, SearchName, Length) != 0) {
+ return FALSE;
+ }
+
+ // The name matches perfectly, or
+ // the node name is XXX@addr and the XXX matches.
+ if ((NodeName[Length] == '\0') ||
+ (NodeName[Length] == '@')) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/** Iterate through the list of strings in the Context,
+ and check whether at least one string is matching the
+ "compatible" property of the node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node to operate the check on.
+ @param [in] CompatInfo COMPATIBILITY_INFO containing the list of compatible
+ strings to compare with the "compatible" property
+ of the node.
+
+ @retval TRUE At least one string matched, the node is compatible.
+ @retval FALSE Otherwise, or error.
+**/
+BOOLEAN
+EFIAPI
+FdtNodeIsCompatible (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ IN CONST VOID * CompatInfo
+ )
+{
+ UINT32 Index;
+ CONST COMPATIBILITY_STR * CompatibleTable;
+ UINT32 Count;
+ CONST VOID * Prop;
+ INT32 PropLen;
+
+ if ((Fdt == NULL) ||
+ (CompatInfo == NULL)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ Count = ((COMPATIBILITY_INFO*)CompatInfo)->Count;
+ CompatibleTable = ((COMPATIBILITY_INFO*)CompatInfo)->CompatTable;
+
+ // Get the "compatible" property.
+ Prop = fdt_getprop (Fdt, Node, "compatible", &PropLen);
+ if ((Prop == NULL) || (PropLen < 0)) {
+ return FALSE;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ if (fdt_stringlist_contains (
+ Prop,
+ PropLen,
+ CompatibleTable[Index].CompatStr
+ )) {
+ return TRUE;
+ }
+ } // for
+
+ return FALSE;
+}
+
+/** Check whether a node has a property.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node to operate the check on.
+ @param [in] PropertyName Name of the property to search.
+ This is a NULL terminated string.
+
+ @retval True The node has the property.
+ @retval FALSE Otherwise, or error.
+**/
+BOOLEAN
+EFIAPI
+FdtNodeHasProperty (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ IN CONST VOID * PropertyName
+ )
+{
+ INT32 Size;
+ CONST VOID * Prop;
+
+ if ((Fdt == NULL) ||
+ (PropertyName == NULL)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ Prop = fdt_getprop (Fdt, Node, PropertyName, &Size);
+ if ((Prop == NULL) || (Size < 0)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/** Get the next node in the whole DT fulfilling a condition.
+
+ The condition to fulfill is checked by the NodeChecker function.
+ Context is passed to NodeChecker.
+
+ The Device tree is traversed in a depth-first search, starting from Node.
+ The input Node is skipped.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in, out] Node At entry: Node offset to start the search.
+ This first node is skipped.
+ Write (-1) to search the whole tree.
+ At exit: If success, contains the offset of
+ the next node fulfilling the
+ condition.
+ @param [in, out] Depth Depth is incremented/decremented of the depth
+ difference between the input Node and the
+ output Node.
+ E.g.: If the output Node is a child node
+ of the input Node, contains (+1).
+ @param [in] NodeChecker Function called to check if the condition
+ is fulfilled.
+ @param [in] Context Context for the NodeChecker.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND No matching node found.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FdtGetNextCondNode (
+ IN CONST VOID * Fdt,
+ IN OUT INT32 * Node,
+ IN OUT INT32 * Depth,
+ IN NODE_CHECKER_FUNC NodeChecker,
+ IN CONST VOID * Context
+ )
+{
+ INT32 CurrNode;
+
+ if ((Fdt == NULL) ||
+ (Node == NULL) ||
+ (Depth == NULL) ||
+ (NodeChecker == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CurrNode = *Node;
+ do {
+ CurrNode = fdt_next_node (Fdt, CurrNode, Depth);
+ if ((CurrNode == -FDT_ERR_NOTFOUND) ||
+ (*Depth < 0)) {
+ // End of the tree, no matching node found.
+ return EFI_NOT_FOUND;
+ } else if (CurrNode < 0) {
+ // An error occurred.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+ } while (!NodeChecker (Fdt, CurrNode, Context));
+
+ // Matching node found.
+ *Node = CurrNode;
+ return EFI_SUCCESS;
+}
+
+/** Get the next node in a branch fulfilling a condition.
+
+ The condition to fulfill is checked by the NodeChecker function.
+ Context is passed to NodeChecker.
+
+ The Device tree is traversed in a depth-first search, starting from Node.
+ The input Node is skipped.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this
+ branch.
+ Write (-1) to search the whole tree.
+ @param [in] NodeChecker Function called to check if the condition
+ is fulfilled.
+ @param [in] Context Context for the NodeChecker.
+ @param [in, out] Node At entry: Node offset to start the search.
+ This first node is skipped.
+ Write (-1) to search the whole tree.
+ At exit: If success, contains the offset
+ of the next node in the branch
+ fulfilling the condition.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND No matching node found.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FdtGetNextCondNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN NODE_CHECKER_FUNC NodeChecker,
+ IN CONST VOID * Context,
+ IN OUT INT32 * Node
+ )
+{
+ EFI_STATUS Status;
+ INT32 CurrNode;
+ INT32 Depth;
+
+ if ((Fdt == NULL) ||
+ (Node == NULL) ||
+ (NodeChecker == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CurrNode = FdtBranch;
+ Depth = 0;
+
+ // First, check the Node is in the sub-nodes of the branch.
+ // This allows to find the relative depth of Node in the branch.
+ if (CurrNode != *Node) {
+ for (CurrNode = fdt_next_node (Fdt, CurrNode, &Depth);
+ (CurrNode >= 0) && (Depth > 0);
+ CurrNode = fdt_next_node (Fdt, CurrNode, &Depth)) {
+ if (CurrNode == *Node) {
+ // Node found.
+ break;
+ }
+ } // for
+
+ if ((CurrNode < 0) || (Depth <= 0)) {
+ // Node is not a node in the branch, or an error occurred.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ // Get the next node in the tree fulfilling the condition,
+ // in any branch.
+ Status = FdtGetNextCondNode (
+ Fdt,
+ Node,
+ &Depth,
+ NodeChecker,
+ Context
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (Status == EFI_NOT_FOUND);
+ return Status;
+ }
+
+ if (Depth <= 0) {
+ // The node found is not in the right branch.
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Get the next node in a branch having a matching name.
+
+ The Device tree is traversed in a depth-first search, starting from Node.
+ The input Node is skipped.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] NodeName The node name to search.
+ This is a NULL terminated string.
+ @param [in, out] Node At entry: Node offset to start the search.
+ This first node is skipped.
+ Write (-1) to search the whole tree.
+ At exit: If success, contains the offset of
+ the next node in the branch
+ having a matching name.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextNamedNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST CHAR8 * NodeName,
+ IN OUT INT32 * Node
+ )
+{
+ return FdtGetNextCondNodeInBranch (
+ Fdt,
+ FdtBranch,
+ FdtNodeHasName,
+ NodeName,
+ Node
+ );
+}
+
+/** Get the next node in a branch with at least one compatible property.
+
+ The Device tree is traversed in a depth-first search, starting from Node.
+ The input Node is skipped.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] CompatNamesInfo Table of compatible strings to compare with
+ the compatible property of the node.
+ @param [in, out] Node At entry: Node offset to start the search.
+ This first node is skipped.
+ Write (-1) to search the whole tree.
+ At exit: If success, contains the offset of
+ the next node in the branch
+ being compatible.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextCompatNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST COMPATIBILITY_INFO * CompatNamesInfo,
+ IN OUT INT32 * Node
+ )
+{
+ return FdtGetNextCondNodeInBranch (
+ Fdt,
+ FdtBranch,
+ FdtNodeIsCompatible,
+ (CONST VOID*)CompatNamesInfo,
+ Node
+ );
+}
+
+/** Get the next node in a branch having the PropName property.
+
+ The Device tree is traversed in a depth-first search, starting from Node.
+ The input Node is skipped.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] PropName Name of the property to search.
+ This is a NULL terminated string.
+ @param [in, out] Node At entry: Node offset to start the search.
+ This first node is skipped.
+ Write (-1) to search the whole tree.
+ At exit: If success, contains the offset of
+ the next node in the branch
+ being compatible.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextPropNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST CHAR8 * PropName,
+ IN OUT INT32 * Node
+ )
+{
+ return FdtGetNextCondNodeInBranch (
+ Fdt,
+ FdtBranch,
+ FdtNodeHasProperty,
+ (CONST VOID*)PropName,
+ Node
+ );
+}
+
+/** Count the number of Device Tree nodes fulfilling a condition
+ in a Device Tree branch.
+
+ The condition to fulfill is checked by the NodeChecker function.
+ Context is passed to NodeChecker.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] NodeChecker Function called to check the condition is
+ fulfilled.
+ @param [in] Context Context for the NodeChecker.
+ @param [out] NodeCount If success, contains the count of nodes
+ fulfilling the condition.
+ Can be 0.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FdtCountCondNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN NODE_CHECKER_FUNC NodeChecker,
+ IN CONST VOID * Context,
+ OUT UINT32 * NodeCount
+ )
+{
+ EFI_STATUS Status;
+ INT32 CurrNode;
+
+ if ((Fdt == NULL) ||
+ (NodeChecker == NULL) ||
+ (NodeCount == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *NodeCount = 0;
+ CurrNode = FdtBranch;
+ while (TRUE) {
+ Status = FdtGetNextCondNodeInBranch (
+ Fdt,
+ FdtBranch,
+ NodeChecker,
+ Context,
+ &CurrNode
+ );
+ if (EFI_ERROR (Status) &&
+ (Status != EFI_NOT_FOUND)) {
+ ASSERT (0);
+ return Status;
+ } else if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ (*NodeCount)++;
+ }
+ return EFI_SUCCESS;
+}
+
+/** Count the number of nodes in a branch with the input name.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] NodeName Node name to search.
+ This is a NULL terminated string.
+ @param [out] NodeCount If success, contains the count of nodes
+ fulfilling the condition.
+ Can be 0.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountNamedNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST CHAR8 * NodeName,
+ OUT UINT32 * NodeCount
+ )
+{
+ return FdtCountCondNodeInBranch (
+ Fdt,
+ FdtBranch,
+ FdtNodeHasName,
+ NodeName,
+ NodeCount
+ );
+}
+
+/** Count the number of nodes in a branch with at least
+ one compatible property.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] CompatNamesInfo Table of compatible strings to
+ compare with the compatible property
+ of the node.
+ @param [out] NodeCount If success, contains the count of nodes
+ fulfilling the condition.
+ Can be 0.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountCompatNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST COMPATIBILITY_INFO * CompatNamesInfo,
+ OUT UINT32 * NodeCount
+ )
+{
+ return FdtCountCondNodeInBranch (
+ Fdt,
+ FdtBranch,
+ FdtNodeIsCompatible,
+ CompatNamesInfo,
+ NodeCount
+ );
+}
+
+/** Count the number of nodes in a branch having the PropName property.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] PropName Name of the property to search.
+ This is a NULL terminated string.
+ @param [out] NodeCount If success, contains the count of nodes
+ fulfilling the condition.
+ Can be 0.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountPropNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST CHAR8 * PropName,
+ OUT UINT32 * NodeCount
+ )
+{
+ return FdtCountCondNodeInBranch (
+ Fdt,
+ FdtBranch,
+ FdtNodeHasProperty,
+ PropName,
+ NodeCount
+ );
+}
+
+/** Get the interrupt-controller node handling the interrupts of
+ the input node.
+
+ To do this, recursively search a node with either the "interrupt-controller"
+ or the "interrupt-parent" property in the parents of Node.
+
+ Devicetree Specification, Release v0.3,
+ 2.4.1 "Properties for Interrupt Generating Devices":
+ Because the hierarchy of the nodes in the interrupt tree
+ might not match the devicetree, the interrupt-parent
+ property is available to make the definition of an
+ interrupt parent explicit. The value is the phandle to the
+ interrupt parent. If this property is missing from a
+ device, its interrupt parent is assumed to be its devicetree
+ parent.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node to start the search.
+ @param [out] IntcNode If success, contains the offset of the
+ interrupt-controller node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND No interrupt-controller node found.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetIntcParentNode (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ OUT INT32 * IntcNode
+ )
+{
+ CONST UINT32 * PHandle;
+ INT32 Size;
+ CONST VOID * Prop;
+
+ if ((Fdt == NULL) ||
+ (IntcNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while (TRUE) {
+ // Check whether the node has the "interrupt-controller" property.
+ Prop = fdt_getprop (Fdt, Node, "interrupt-controller", &Size);
+ if ((Prop != NULL) && (Size >= 0)) {
+ // The interrupt-controller has been found.
+ *IntcNode = Node;
+ return EFI_SUCCESS;
+ } else {
+ // Check whether the node has the "interrupt-parent" property.
+ PHandle = fdt_getprop (Fdt, Node, "interrupt-parent", &Size);
+ if ((PHandle != NULL) && (Size == sizeof (UINT32))) {
+ // The phandle of the interrupt-controller has been found.
+ // Search the node having this phandle and return it.
+ Node = fdt_node_offset_by_phandle (Fdt, fdt32_to_cpu (*PHandle));
+ if (Node < 0) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ *IntcNode = Node;
+ return EFI_SUCCESS;
+ } else if (Size != -FDT_ERR_NOTFOUND) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+ }
+
+ if (Node == 0) {
+ // We are at the root of the tree. Not parent available.
+ return EFI_NOT_FOUND;
+ }
+
+ // Get the parent of the node.
+ Node = fdt_parent_offset (Fdt, Node);
+ if (Node < 0) {
+ // An error occurred.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+ } // while
+}
+
+/** Get the "interrupt-cells" property value of the node.
+
+ The "interrupts" property requires to know the number of cells used
+ to encode an interrupt. This information is stored in the
+ interrupt-controller of the input Node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] IntcNode Offset of an interrupt-controller node.
+ @param [out] IntCells If success, contains the "interrupt-cells"
+ property of the IntcNode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetInterruptCellsInfo (
+ IN CONST VOID * Fdt,
+ IN INT32 IntcNode,
+ OUT INT32 * IntCells
+ )
+{
+ CONST UINT32 * Data;
+ INT32 Size;
+
+ if ((Fdt == NULL) ||
+ (IntCells == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Data = fdt_getprop (Fdt, IntcNode, "#interrupt-cells", &Size);
+ if ((Data == NULL) || (Size != sizeof (UINT32))) {
+ // If error or not on one UINT32 cell.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ *IntCells = fdt32_to_cpu (*Data);
+
+ return EFI_SUCCESS;
+}
+
+/** Get the "#address-cells" and/or "#size-cells" property of the node.
+
+ According to the Device Tree specification, s2.3.5 "#address-cells and
+ #size-cells":
+ "If missing, a client program should assume a default value of 2 for
+ #address-cells, and a value of 1 for #size-cells."
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node having to get the
+ "#address-cells" and "#size-cells"
+ properties from.
+ @param [out] AddressCells If success, number of address-cells.
+ If the property is not available,
+ default value is 2.
+ @param [out] SizeCells If success, number of size-cells.
+ If the property is not available,
+ default value is 1.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetAddressInfo (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ OUT INT32 * AddressCells, OPTIONAL
+ OUT INT32 * SizeCells OPTIONAL
+ )
+{
+ if (Fdt == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (AddressCells != NULL) {
+ *AddressCells = fdt_address_cells (Fdt, Node);
+ if (*AddressCells < 0) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+ }
+
+ if (SizeCells != NULL) {
+ *SizeCells = fdt_size_cells (Fdt, Node);
+ if (*SizeCells < 0) {
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Get the "#address-cells" and/or "#size-cells" property of the parent node.
+
+ According to the Device Tree specification, s2.3.5 "#address-cells and
+ #size-cells":
+ "If missing, a client program should assume a default value of 2 for
+ #address-cells, and a value of 1 for #size-cells."
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node having to get the
+ "#address-cells" and "#size-cells"
+ properties from its parent.
+ @param [out] AddressCells If success, number of address-cells.
+ If the property is not available,
+ default value is 2.
+ @param [out] SizeCells If success, number of size-cells.
+ If the property is not available,
+ default value is 1.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetParentAddressInfo (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ OUT INT32 * AddressCells, OPTIONAL
+ OUT INT32 * SizeCells OPTIONAL
+ )
+{
+ if (Fdt == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Node = fdt_parent_offset (Fdt, Node);
+ if (Node < 0) {
+ // End of the tree, or an error occurred.
+ ASSERT (0);
+ return EFI_ABORTED;
+ }
+
+ return FdtGetAddressInfo (Fdt, Node, AddressCells, SizeCells);
+}
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h
new file mode 100644
index 000000000000..0076c5066d4c
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h
@@ -0,0 +1,458 @@
+/** @file
+ Flattened device tree utility.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - Device tree Specification - Release v0.3
+ - linux/Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
+ - linux//Documentation/devicetree/bindings/interrupt-controller/arm%2Cgic.yaml
+**/
+
+#ifndef FDT_UTILITY_H_
+#define FDT_UTILITY_H_
+
+/** Get the offset of an address in a "reg" Device Tree property.
+
+ In a Device Tree, the "reg" property stores address/size couples.
+ They are stored on N 32-bits cells.
+ Based on the value of the #address-cells, the #size-cells and the
+ index in the "reg" property, compute the number of 32-bits cells
+ to skip.
+
+ @param [in] Index Index in the reg property.
+ @param [in] AddrCells Number of cells used to store an address.
+ @param [in] SizeCells Number of cells used to store the size of
+ an address.
+
+ @retval Number of 32-bits cells to skip to access the address.
+*/
+#define GET_DT_REG_ADDRESS_OFFSET(Index, AddrCells, SizeCells) ( \
+ (Index) * ((AddrCells) + (SizeCells)) \
+ )
+
+/** Get the offset of an address size in a "reg" Device Tree property.
+
+ In a Device Tree, the "reg" property stores address/size couples.
+ They are stored on N 32-bits cells.
+ Based on the value of the #address-cells, the #size-cells and the
+ index in the "reg" property, compute the number of 32-bits cells
+ to skip.
+
+ @param [in] Index Index in the reg property.
+ @param [in] AddrCells Number of cells used to store an address.
+ @param [in] SizeCells Number of cells used to store the size of
+ an address.
+
+ @retval Number of 32-bits cells to skip to access the address size.
+*/
+#define GET_DT_REG_SIZE_OFFSET(Index, AddrCells, SizeCells) ( \
+ GET_DT_REG_ADDRESS_OFFSET ((Index), (AddrCells), (SizeCells)) + \
+ (SizeCells) \
+ )
+
+/// Maximum string length for compatible names.
+#define COMPATIBLE_STR_LEN (32U)
+
+/// Interrupt macros
+#define PPI_OFFSET (16U)
+#define SPI_OFFSET (32U)
+#define DT_PPI_IRQ (1U)
+#define DT_SPI_IRQ (0U)
+#define DT_IRQ_IS_EDGE_TRIGGERED(x) ((((x) & (BIT0 | BIT2)) != 0))
+#define DT_IRQ_IS_ACTIVE_LOW(x) ((((x) & (BIT1 | BIT3)) != 0))
+#define IRQ_TYPE_OFFSET (0U)
+#define IRQ_NUMBER_OFFSET (1U)
+#define IRQ_FLAGS_OFFSET (2U)
+
+/** Get the interrupt Id of an interrupt described in a fdt.
+
+ Data must describe a GIC interrupt. A GIC interrupt is on at least
+ 3 UINT32 cells.
+ This function DOES NOT SUPPORT extended SPI range and extended PPI range.
+
+ @param [in] Data Pointer to the first cell of an "interrupts" property.
+
+ @retval The interrupt id.
+**/
+UINT32
+EFIAPI
+FdtGetInterruptId (
+ UINT32 CONST * Data
+ );
+
+/** Get the ACPI interrupt flags of an interrupt described in a fdt.
+
+ Data must describe a GIC interrupt. A GIC interrupt is on at least
+ 3 UINT32 cells.
+
+ @param [in] Data Pointer to the first cell of an "interrupts" property.
+
+ @retval The interrupt flags (for ACPI).
+**/
+UINT32
+EFIAPI
+FdtGetInterruptFlags (
+ UINT32 CONST * Data
+ );
+
+/** A structure describing a compatibility string.
+*/
+typedef struct CompatStr {
+ CONST CHAR8 CompatStr[COMPATIBLE_STR_LEN];
+} COMPATIBILITY_STR;
+
+/** Structure containing a list of compatible names and their count.
+*/
+typedef struct CompatibilityInfo {
+ /// Count of entries in the NAME_TABLE.
+ UINT32 Count;
+
+ /// Pointer to a table storing the names.
+ CONST COMPATIBILITY_STR * CompatTable;
+} COMPATIBILITY_INFO;
+
+/** Operate a check on a Device Tree node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] NodeOffset Offset of the node to compare input string.
+ @param [in] Context Context to operate the check on the node.
+
+ @retval True The check is correct.
+ @retval FALSE Otherwise, or error.
+**/
+typedef
+BOOLEAN
+(EFIAPI *NODE_CHECKER_FUNC) (
+ IN CONST VOID * Fdt,
+ IN INT32 NodeOffset,
+ IN CONST VOID * Context
+ );
+
+/** Iterate through the list of strings in the Context,
+ and check whether at least one string is matching the
+ "compatible" property of the node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node to operate the check on.
+ @param [in] CompatInfo COMPATIBILITY_INFO containing the list of compatible
+ strings to compare with the "compatible" property
+ of the node.
+
+ @retval TRUE At least one string matched, the node is compatible.
+ @retval FALSE Otherwise, or error.
+**/
+BOOLEAN
+EFIAPI
+FdtNodeIsCompatible (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ IN CONST VOID * CompatInfo
+ );
+
+/** Check whether a node has a property.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node to operate the check on.
+ @param [in] PropertyName Name of the property to search.
+ This is a NULL terminated string.
+
+ @retval True The node has the property.
+ @retval FALSE Otherwise, or error.
+**/
+BOOLEAN
+EFIAPI
+FdtNodeHasProperty (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ IN CONST VOID * PropertyName
+ );
+
+/** Get the next node in a branch having a matching name.
+
+ The Device tree is traversed in a depth-first search, starting from Node.
+ The input Node is skipped.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] NodeName The node name to search.
+ This is a NULL terminated string.
+ @param [in, out] Node At entry: Node offset to start the search.
+ This first node is skipped.
+ Write (-1) to search the whole tree.
+ At exit: If success, contains the offset of
+ the next node in the branch
+ having a matching name.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextNamedNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST CHAR8 * NodeName,
+ IN OUT INT32 * Node
+ );
+
+/** Get the next node in a branch with at least one compatible property.
+
+ The Device tree is traversed in a depth-first search, starting from Node.
+ The input Node is skipped.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] CompatNamesInfo Table of compatible strings to compare with
+ the compatible property of the node.
+ @param [in, out] Node At entry: Node offset to start the search.
+ This first node is skipped.
+ Write (-1) to search the whole tree.
+ At exit: If success, contains the offset of
+ the next node in the branch
+ being compatible.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextCompatNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST COMPATIBILITY_INFO * CompatNamesInfo,
+ IN OUT INT32 * Node
+ );
+
+/** Get the next node in a branch having the PropName property.
+
+ The Device tree is traversed in a depth-first search, starting from Node.
+ The input Node is skipped.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] PropName Name of the property to search.
+ This is a NULL terminated string.
+ @param [in, out] Node At entry: Node offset to start the search.
+ This first node is skipped.
+ Write (-1) to search the whole tree.
+ At exit: If success, contains the offset of
+ the next node in the branch
+ being compatible.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND No matching node found.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetNextPropNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST CHAR8 * PropName,
+ IN OUT INT32 * Node
+ );
+
+/** Count the number of nodes in a branch with the input name.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] NodeName Node name to search.
+ This is a NULL terminated string.
+ @param [out] NodeCount If success, contains the count of nodes
+ fulfilling the condition.
+ Can be 0.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountNamedNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST CHAR8 * NodeName,
+ OUT UINT32 * NodeCount
+ );
+
+/** Count the number of nodes in a branch with at least
+ one compatible property.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] CompatibleTable Table of compatible strings to
+ compare with the compatible property
+ of the node.
+ @param [out] NodeCount If success, contains the count of nodes
+ fulfilling the condition.
+ Can be 0.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountCompatNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST COMPATIBILITY_INFO * CompatNamesInfo,
+ OUT UINT32 * NodeCount
+ );
+
+/** Count the number of nodes in a branch having the PropName property.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] FdtBranch Only search in the sub-nodes of this branch.
+ Write (-1) to search the whole tree.
+ @param [in] PropName Name of the property to search.
+ This is a NULL terminated string.
+ @param [out] NodeCount If success, contains the count of nodes
+ fulfilling the condition.
+ Can be 0.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtCountPropNodeInBranch (
+ IN CONST VOID * Fdt,
+ IN INT32 FdtBranch,
+ IN CONST CHAR8 * PropName,
+ OUT UINT32 * NodeCount
+ );
+
+/** Get the interrupt-controller node handling the interrupts of
+ the input node.
+
+ To do this, recursively search a node with either the "interrupt-controller"
+ or the "interrupt-parent" property in the parents of Node.
+
+ Devicetree Specification, Release v0.3,
+ 2.4.1 "Properties for Interrupt Generating Devices":
+ Because the hierarchy of the nodes in the interrupt tree
+ might not match the devicetree, the interrupt-parent
+ property is available to make the definition of an
+ interrupt parent explicit. The value is the phandle to the
+ interrupt parent. If this property is missing from a
+ device, its interrupt parent is assumed to be its devicetree
+ parent.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node to start the search.
+ @param [out] IntcNode If success, contains the offset of the
+ interrupt-controller node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND No interrupt-controller node found.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetIntcParentNode (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ OUT INT32 * IntcNode
+ );
+
+/** Get the "interrupt-cells" property value of the node.
+
+ The "interrupts" property requires to know the number of cells used
+ to encode an interrupt. This information is stored in the
+ interrupt-controller of the input Node.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [in] IntcNode Offset of an interrupt-controller node.
+ @param [out] IntCells If success, contains the "interrupt-cells"
+ property of the IntcNode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetInterruptCellsInfo (
+ IN CONST VOID * Fdt,
+ IN INT32 IntcNode,
+ OUT INT32 * InterruptCells
+ );
+
+/** Get the "#address-cells" and/or "#size-cells" property of the node.
+
+ According to the Device Tree specification, s2.3.5 "#address-cells and
+ #size-cells":
+ "If missing, a client program should assume a default value of 2 for
+ #address-cells, and a value of 1 for #size-cells."
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node having to get the
+ "#address-cells" and "#size-cells"
+ properties from.
+ @param [out] AddressCells If success, number of address-cells.
+ If the property is not available,
+ default value is 2.
+ @param [out] SizeCells If success, number of size-cells.
+ If the property is not available,
+ default value is 1.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetAddressInfo (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ OUT INT32 * AddressCells, OPTIONAL
+ OUT INT32 * SizeCells OPTIONAL
+ );
+
+/** Get the "#address-cells" and/or "#size-cells" property of the parent node.
+
+ According to the Device Tree specification, s2.3.5 "#address-cells and
+ #size-cells":
+ "If missing, a client program should assume a default value of 2 for
+ #address-cells, and a value of 1 for #size-cells."
+
+ @param [in] Fdt Pointer to a Flattened Device Tree.
+ @param [in] Node Offset of the node having to get the
+ "#address-cells" and "#size-cells"
+ properties from its parent.
+ @param [out] AddressCells If success, number of address-cells.
+ If the property is not available,
+ default value is 2.
+ @param [out] SizeCells If success, number of size-cells.
+ If the property is not available,
+ default value is 1.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_ABORTED An error occurred.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FdtGetParentAddressInfo (
+ IN CONST VOID * Fdt,
+ IN INT32 Node,
+ OUT INT32 * AddressCells, OPTIONAL
+ OUT INT32 * SizeCells OPTIONAL
+ );
+
+#endif // FDT_UTILITY_H_
--
2.17.1


[PATCH v2 02/15] DynamicTablesPkg: FdtHwInfoParser: CM Object descriptor helper

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

FdtHwInfoParserLib is an instance of the HwInfoParser. The
FdtHwInfoParser parses a platform Device Tree and populates
the Platform Information repository with Configuration
Manager objects that describe the platform hardware.
These Configuration Manager objects are encapsulated in
Configuration Manager Object Descriptors.

Therefore, add helper functions to create and free the
Configuration Manager Object descriptors.

Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../FdtHwInfoParserLib/CmObjectDescUtility.c | 302 ++++++++++++++++++
.../FdtHwInfoParserLib/CmObjectDescUtility.h | 131 ++++++++
2 files changed, 433 insertions(+)
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.h

diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.c b/DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.c
new file mode 100644
index 000000000000..75a5b1208d0e
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.c
@@ -0,0 +1,302 @@
+/** @file
+ Configuration manager Object Descriptor Utility.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <FdtHwInfoParserInclude.h>
+#include <ConfigurationManagerObject.h>
+
+#include "CmObjectDescUtility.h"
+
+/** Create a CM_OBJ_DESCRIPTOR.
+
+ @param [in] ObjectId CM_OBJECT_ID of the node.
+ @param [in] Count Number of CmObj stored in the
+ data field.
+ @param [in] Data Pointer to one or more CmObj objects.
+ The content of this Data buffer is copied.
+ @param [in] Size Size of the Data buffer.
+ @param [out] NewCmObjDesc The created CM_OBJ_DESCRIPTOR.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+CreateCmObjDesc (
+ IN CM_OBJECT_ID ObjectId,
+ IN UINT32 Count,
+ IN VOID * Data,
+ IN UINT32 Size,
+ OUT CM_OBJ_DESCRIPTOR ** NewCmObjDesc
+ )
+{
+ CM_OBJ_DESCRIPTOR * CmObjDesc;
+ VOID * DataBuffer;
+
+ if ((Count == 0) ||
+ (Data == NULL) ||
+ (Size == 0) ||
+ (NewCmObjDesc == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CmObjDesc = AllocateZeroPool (sizeof (CM_OBJ_DESCRIPTOR));
+ if (CmObjDesc == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DataBuffer = AllocateCopyPool (Size, Data);
+ if (DataBuffer == NULL) {
+ FreePool (CmObjDesc);
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CmObjDesc->ObjectId = ObjectId;
+ CmObjDesc->Count = Count;
+ CmObjDesc->Data = DataBuffer;
+ CmObjDesc->Size = Size;
+
+ *NewCmObjDesc = CmObjDesc;
+
+ return EFI_SUCCESS;
+}
+
+/** Free resources allocated for the CM_OBJ_DESCRIPTOR.
+
+ @param [in] CmObjDesc Pointer to the CM_OBJ_DESCRIPTOR.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FreeCmObjDesc (
+ IN CM_OBJ_DESCRIPTOR * CmObjDesc
+ )
+{
+ if (CmObjDesc == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (CmObjDesc->Data != NULL) {
+ FreePool (CmObjDesc->Data);
+ }
+
+ FreePool (CmObjDesc);
+ return EFI_SUCCESS;
+}
+
+/** Add a single CmObj to the Configuration Manager.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] ObjectId CmObj ObjectId.
+ @param [in] Data CmObj Data.
+ @param [in] Size CmObj Size.
+ @param [out] Token If provided and success,
+ token generated for this CmObj.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AddSingleCmObj (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN CM_OBJECT_ID ObjectId,
+ IN VOID *Data,
+ IN UINT32 Size,
+ OUT CM_OBJECT_TOKEN *Token OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CM_OBJ_DESCRIPTOR CmObjDesc;
+
+ if ((FdtParserHandle == NULL) ||
+ (FdtParserHandle->HwInfoAdd == NULL) ||
+ (Data == NULL) ||
+ (Size == 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CmObjDesc.ObjectId = ObjectId;
+ CmObjDesc.Count = 1;
+ CmObjDesc.Data = Data;
+ CmObjDesc.Size = Size;
+
+ // Add the CmObj.
+ // Don't ask for a token.
+ Status = FdtParserHandle->HwInfoAdd (
+ FdtParserHandle,
+ FdtParserHandle->Context,
+ &CmObjDesc,
+ Token
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/** Add multiple CmObj to the Configuration Manager.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] CmObjDesc CmObjDesc containing multiple CmObj
+ to add.
+ @param [in] TokenCount If provided, count of entries in the
+ TokenTable.
+ @param [out] TokenTable If provided and success,
+ token generated for these CmObj.
+ Address of an array of CM_OBJECT_TOKEN
+ with the same number of elements as the
+ CmObjDesc.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AddMultipleCmObj (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN CONST CM_OBJ_DESCRIPTOR *CmObjDesc,
+ IN UINT32 TokenCount, OPTIONAL
+ OUT CM_OBJECT_TOKEN *TokenTable OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ UINT32 Count;
+ VOID * Data;
+ UINT32 Size;
+ CM_OBJ_DESCRIPTOR SingleCmObjDesc;
+
+ if ((FdtParserHandle == NULL) ||
+ (FdtParserHandle->HwInfoAdd == NULL) ||
+ (CmObjDesc == NULL) ||
+ (CmObjDesc->Count == 0) ||
+ (CmObjDesc->Data == NULL) ||
+ (CmObjDesc->Size == 0)){
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Count = CmObjDesc->Count;
+ Data = CmObjDesc->Data;
+ Size = CmObjDesc->Size / Count;
+
+ SingleCmObjDesc.ObjectId = CmObjDesc->ObjectId;
+ SingleCmObjDesc.Count = 1;
+ SingleCmObjDesc.Size = Size;
+
+ for (Index = 0; Index < Count; Index++) {
+ SingleCmObjDesc.Data = (UINT8*)Data + Index * Size;
+ // Add the CmObj.
+ Status = FdtParserHandle->HwInfoAdd (
+ FdtParserHandle,
+ FdtParserHandle->Context,
+ &SingleCmObjDesc,
+ (TokenTable != NULL) ?
+ &TokenTable[Index] :
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } // for
+
+ return Status;
+}
+
+/** Add multiple CmObj to the Configuration Manager.
+
+ Get one token referencing a EArmObjCmRef CmObj itself referencing
+ the input CmObj. In the table below, RefToken is returned.
+
+ Token referencing an Array of tokens Array of CmObj
+ array of EArmObjCmRef referencing each from the input:
+ CmObj: CmObj from the input:
+
+ RefToken ---> CmObjToken[0] ---> CmObj[0]
+ CmObjToken[1] ---> CmObj[1]
+ CmObjToken[2] ---> CmObj[2]
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] CmObjDesc CmObjDesc containing multiple CmObj
+ to add.
+ @param [out] Token If success, token referencing an array
+ of EArmObjCmRef CmObj, themselves
+ referencing the input CmObjs.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+AddMultipleCmObjWithCmObjRef (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN CM_OBJ_DESCRIPTOR * CmObjDesc,
+ OUT CM_OBJECT_TOKEN * Token
+ )
+{
+ EFI_STATUS Status;
+ CM_OBJ_DESCRIPTOR CmObjRef;
+ CM_OBJECT_TOKEN *TokenTable;
+ INT32 TokenTableSize;
+
+ if ((FdtParserHandle == NULL) ||
+ (FdtParserHandle->HwInfoAdd == NULL) ||
+ (CmObjDesc == NULL) ||
+ (CmObjDesc->Count == 0) ||
+ (CmObjDesc->Data == NULL) ||
+ (CmObjDesc->Size == 0) ||
+ (Token == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate a buffer to store the tokens.
+ TokenTableSize = CmObjDesc->Count * sizeof (CM_OBJECT_TOKEN);
+ TokenTable = AllocateZeroPool (TokenTableSize);
+ if (TokenTable == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Add the input CmObjs.
+ Status = AddMultipleCmObj (
+ FdtParserHandle,
+ CmObjDesc,
+ CmObjDesc->Count,
+ TokenTable
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ CmObjRef.ObjectId = CREATE_CM_ARM_OBJECT_ID (EArmObjCmRef);
+ CmObjRef.Data = TokenTable;
+ CmObjRef.Count = CmObjDesc->Count;
+ CmObjRef.Size = TokenTableSize;
+
+ // Add the array of EArmObjCmRef CmObjs.
+ Status = FdtParserHandle->HwInfoAdd (
+ FdtParserHandle,
+ FdtParserHandle->Context,
+ &CmObjRef,
+ Token
+ );
+ ASSERT_EFI_ERROR (Status);
+
+exit_handler:
+ FreePool (TokenTable);
+ return Status;
+}
diff --git a/DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.h b/DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.h
new file mode 100644
index 000000000000..34439c716fb3
--- /dev/null
+++ b/DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.h
@@ -0,0 +1,131 @@
+/** @file
+ Configuration manager Object Descriptor Utility.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef CM_OBJECT_DESC_UTILITY_H_
+#define CM_OBJECT_DESC_UTILITY_H_
+
+#include <ConfigurationManagerObject.h>
+
+#include "FdtHwInfoParser.h"
+
+/** Create a CM_OBJ_DESCRIPTOR.
+
+ @param [in] ObjectId CM_OBJECT_ID of the node.
+ @param [in] Count Number of CmObj stored in the
+ data field.
+ @param [in] Data Pointer to one or more CmObj objects.
+ The content of this Data buffer is copied.
+ @param [in] Size Size of the Data buffer.
+ @param [out] NewCmObjDesc The created CM_OBJ_DESCRIPTOR.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+CreateCmObjDesc (
+ IN CM_OBJECT_ID ObjectId,
+ IN UINT32 Count,
+ IN VOID * Data,
+ IN UINT32 Size,
+ OUT CM_OBJ_DESCRIPTOR ** NewCmObjDesc
+ );
+
+/** Free resources allocated for the CM_OBJ_DESCRIPTOR.
+
+ @param [in] CmObjDesc Pointer to the CM_OBJ_DESCRIPTOR.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+FreeCmObjDesc (
+ IN CM_OBJ_DESCRIPTOR * CmObjDesc
+ );
+
+/** Add a single CmObj to the Configuration Manager.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] ObjectId CmObj ObjectId.
+ @param [in] Data CmObj Data.
+ @param [in] Size CmObj Size.
+ @param [out] Token If provided and success,
+ token generated for this CmObj.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AddSingleCmObj (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN CM_OBJECT_ID ObjectId,
+ IN VOID *Data,
+ IN UINT32 Size,
+ OUT CM_OBJECT_TOKEN *Token OPTIONAL
+ );
+
+/** Add multiple CmObj to the Configuration Manager.
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] CmObjDesc CmObjDesc containing multiple CmObj
+ to add.
+ @param [in] TokenCount If provided, count of entries in the
+ TokenTable.
+ @param [out] TokenTable If provided and success,
+ token generated for these CmObj.
+ Address of an array of CM_OBJECT_TOKEN
+ with the same number of elements as the
+ CmObjDesc.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AddMultipleCmObj (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN CONST CM_OBJ_DESCRIPTOR *CmObjDesc,
+ IN UINT32 TokenCount, OPTIONAL
+ OUT CM_OBJECT_TOKEN *TokenTable OPTIONAL
+ );
+
+/** Add multiple CmObj to the Configuration Manager.
+
+ Get one token referencing a EArmObjCmRef CmObj itself referencing
+ the input CmObj. In the table below, RefToken is returned.
+
+ Token referencing an Array of tokens Array of CmObj
+ array of EArmObjCmRef referencing each from the input:
+ CmObj: CmObj from the input:
+
+ RefToken ---> CmObjToken[0] ---> CmObj[0]
+ CmObjToken[1] ---> CmObj[1]
+ CmObjToken[2] ---> CmObj[2]
+
+ @param [in] FdtParserHandle A handle to the parser instance.
+ @param [in] CmObjDesc CmObjDesc containing multiple CmObj
+ to add.
+ @param [out] Token If success, token referencing an array
+ of EArmObjCmRef CmObj, themselves
+ referencing the input CmObjs.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+AddMultipleCmObjWithCmObjRef (
+ IN CONST FDT_HW_INFO_PARSER_HANDLE FdtParserHandle,
+ IN CM_OBJ_DESCRIPTOR * CmObjDesc,
+ OUT CM_OBJECT_TOKEN * Token
+ );
+
+#endif // CM_OBJECT_DESC_UTILITY_H_
--
2.17.1


[PATCH v2 01/15] DynamicTablesPkg: Definition for HwInfoParser interface

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

Hardware information parser is an optional module defined
by the Dynamic Tables Framework. It can either parse an
XML, a Device Tree or a Json file containing the platform
hardware information to populate the platform information
repository.

The Configuration Manager can then utilise this information
to generate ACPI tables for the platform.

Therefore, define an interface for the HwInfoParser library
class.

Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
Co-authored-by: Sami Mujawar <sami.mujawar@...>
---
DynamicTablesPkg/DynamicTablesPkg.dec | 3 +
.../Include/Library/HwInfoParserLib.h | 99 +++++++++++++++++++
2 files changed, 102 insertions(+)
create mode 100644 DynamicTablesPkg/Include/Library/HwInfoParserLib.h

diff --git a/DynamicTablesPkg/DynamicTablesPkg.dec b/DynamicTablesPkg/DynamicTablesPkg.dec
index 9996bdf6f520..80a61dd2dbac 100644
--- a/DynamicTablesPkg/DynamicTablesPkg.dec
+++ b/DynamicTablesPkg/DynamicTablesPkg.dec
@@ -24,6 +24,9 @@ [LibraryClasses]
## @libraryclass Defines a set of APIs for Dynamic AML generation.
AmlLib|Include/Library/AmlLib/AmlLib.h

+ ## @libraryclass Defines a set of APIs to a hardware information parser.
+ HwInfoParserLib|Include/Library/HwInfoParserLib.h
+
## @libraryclass Defines a set of methods for fixing up a SSDT Serial Port.
SsdtSerialPortFixupLib|Include/Library/SsdtSerialPortFixupLib.h

diff --git a/DynamicTablesPkg/Include/Library/HwInfoParserLib.h b/DynamicTablesPkg/Include/Library/HwInfoParserLib.h
new file mode 100644
index 000000000000..472fbefcc6b5
--- /dev/null
+++ b/DynamicTablesPkg/Include/Library/HwInfoParserLib.h
@@ -0,0 +1,99 @@
+/** @file
+ Hardware information parser library.
+
+ Copyright (c) 2021, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef HW_INFO_PARSER_LIB_H_
+#define HW_INFO_PARSER_LIB_H_
+
+#include <ConfigurationManagerObject.h>
+
+/** A handle to the HwInfoParser instance.
+*/
+typedef VOID * HW_INFO_PARSER_HANDLE;
+
+/** Function pointer called by the parser to add information.
+
+ Callback function that the parser can use to add new
+ CmObj. This function must copy the CmObj data and not rely on
+ the parser preserving the CmObj memory.
+ This function is responsible of the Token allocation.
+
+ @param [in] ParserHandle A handle to the parser instance.
+ @param [in] Context A pointer to the caller's context provided in
+ HwInfoParserInit ().
+ @param [in] CmObjDesc CM_OBJ_DESCRIPTOR containing the CmObj(s) to add.
+ @param [out] Token If provided and success, contain the token
+ generated for the CmObj.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+typedef
+EFI_STATUS
+(EFIAPI * HW_INFO_ADD_OBJECT) (
+ IN HW_INFO_PARSER_HANDLE ParserHandle,
+ IN VOID * Context,
+ IN CONST CM_OBJ_DESCRIPTOR * CmObjDesc,
+ OUT CM_OBJECT_TOKEN * Token OPTIONAL
+ );
+
+/** Initialise the HwInfoParser.
+
+ The HwInfoParser shall use the information provided by the HwDataSource
+ to initialise the internal state of the parser or to index the data. This
+ internal state shall be linked to the ParserHandle using an implementation
+ defined mechanism.
+
+ @param [in] HwDataSource Pointer to the blob containing the hardware
+ information. It can be a pointer to a Device
+ Tree, an XML file, etc. or any other data
+ structure defined by the HwInfoParser.
+ @param [in] Context A pointer to the caller's context.
+ @param [in] HwInfoAdd Function pointer called by the parser when
+ adding information.
+ @param [out] ParserHandle A handle to the parser instance.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+HwInfoParserInit (
+ IN VOID * HwDataSource,
+ IN VOID * Context,
+ IN HW_INFO_ADD_OBJECT HwInfoAdd,
+ OUT HW_INFO_PARSER_HANDLE * ParserHandle
+ );
+
+/** Parse the data provided by the HwDataSource.
+
+ @param [in] ParserHandle A handle to the parser instance.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES An allocation has failed.
+**/
+EFI_STATUS
+EFIAPI
+HwInfoParse (
+ IN HW_INFO_PARSER_HANDLE ParserHandle
+ );
+
+/** Cleanup any internal state and resources that were allocated
+ by the the HwInfoParser.
+
+ @param [in] ParserHandle A handle to the parser instance.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+HwInfoParserShutdown (
+ IN HW_INFO_PARSER_HANDLE ParserHandle
+ );
+
+#endif // HW_INFO_PARSER_LIB_H_
--
2.17.1


[PATCH v2 00/15] Implement a FdtHwInfoParserLib

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

v2:
- Handle absence of Pci legacy interrupts in Pci parser. [Pierre]
- Handle Affinity3 field in GicC parser. [Sami]
- Add pl011 compatible string in serial port parser. [Sami]
- Use 16550_with_GAS ID when 16550 is detected in serial
port parser. [Sami]
- Use ASSERT_EFI_ERROR when possible. [Sami]
- Fix typos and add comments. [Pierre]

Ref:https://bugzilla.tianocore.org/show_bug.cgi?id=3741

The generic HwInfoParserLib provides an interface to parse hardware
information stored in certain a data type (e.g.: xml, device tree,
...) and generate objects that can be used by the DynamicTablesPkg
framework to generate another hardware description (e.g.:
SMBIOS tables, ACPI tables, ...).

This patch-set also implements a FdtHwInfoParserLib, parsing
hardware information stored in a device tree. The objects
generated by the library have been used ACPI tables.

The changes can be seen at: https://github.com/PierreARM/edk2/tree/1787_Implement_FdtHwInfoParser_v2

Pierre Gondois (15):
DynamicTablesPkg: Definition for HwInfoParser interface
DynamicTablesPkg: FdtHwInfoParser: CM Object descriptor helper
DynamicTablesPkg: FdtHwInfoParser: Add FDT utility functions
DynamicTablesPkg: FdtHwInfoParser: Add Boot Arch parser
DynamicTablesPkg: FdtHwInfoParser: Generic Timer Parser
DynamicTablesPkg: FdtHwInfoParser: Add Serial port parser
DynamicTablesPkg: FdtHwInfoParser: Add GICC parser
DynamicTablesPkg: FdtHwInfoParser: Add GICD parser
DynamicTablesPkg: FdtHwInfoParser: Add MSI Frame parser
DynamicTablesPkg: FdtHwInfoParser: Add ITS parser
DynamicTablesPkg: FdtHwInfoParser: Add GICR parser
DynamicTablesPkg: FdtHwInfoParser: Add GIC dispatcher
DynamicTablesPkg: FdtHwInfoParser: Add PCI config parser
DynamicTablesPkg: Add FdtHwInfoParser library
DynamicTablesPkg: Handle 16550_WITH_GAS id

DynamicTablesPkg/DynamicTablesPkg.dec | 3 +
DynamicTablesPkg/DynamicTablesPkg.dsc | 3 +-
.../Include/Library/HwInfoParserLib.h | 99 ++
.../SsdtSerialPortFixupLib.c | 5 +-
.../BootArch/ArmBootArchParser.c | 159 +++
.../BootArch/ArmBootArchParser.h | 45 +
.../FdtHwInfoParserLib/CmObjectDescUtility.c | 302 ++++++
.../FdtHwInfoParserLib/CmObjectDescUtility.h | 131 +++
.../FdtHwInfoParserLib/FdtHwInfoParser.c | 190 ++++
.../FdtHwInfoParserLib/FdtHwInfoParser.h | 63 ++
.../FdtHwInfoParserInclude.h | 17 +
.../FdtHwInfoParserLib/FdtHwInfoParserLib.inf | 56 ++
.../Library/FdtHwInfoParserLib/FdtUtility.c | 907 ++++++++++++++++++
.../Library/FdtHwInfoParserLib/FdtUtility.h | 458 +++++++++
.../GenericTimer/ArmGenericTimerParser.c | 254 +++++
.../GenericTimer/ArmGenericTimerParser.h | 66 ++
.../FdtHwInfoParserLib/Gic/ArmGicCParser.c | 771 +++++++++++++++
.../FdtHwInfoParserLib/Gic/ArmGicCParser.h | 67 ++
.../FdtHwInfoParserLib/Gic/ArmGicDParser.c | 169 ++++
.../FdtHwInfoParserLib/Gic/ArmGicDParser.h | 50 +
.../FdtHwInfoParserLib/Gic/ArmGicDispatcher.c | 212 ++++
.../FdtHwInfoParserLib/Gic/ArmGicDispatcher.h | 72 ++
.../FdtHwInfoParserLib/Gic/ArmGicItsParser.c | 215 +++++
.../FdtHwInfoParserLib/Gic/ArmGicItsParser.h | 48 +
.../Gic/ArmGicMsiFrameParser.c | 214 +++++
.../Gic/ArmGicMsiFrameParser.h | 50 +
.../FdtHwInfoParserLib/Gic/ArmGicRParser.c | 235 +++++
.../FdtHwInfoParserLib/Gic/ArmGicRParser.h | 47 +
.../Pci/ArmPciConfigSpaceParser.c | 797 +++++++++++++++
.../Pci/ArmPciConfigSpaceParser.h | 142 +++
.../Serial/ArmSerialPortParser.c | 620 ++++++++++++
.../Serial/ArmSerialPortParser.h | 47 +
32 files changed, 6512 insertions(+), 2 deletions(-)
create mode 100644 DynamicTablesPkg/Include/Library/HwInfoParserLib.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/BootArch/ArmBootArchParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/CmObjectDescUtility.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserInclude.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtHwInfoParserLib.inf
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/FdtUtility.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/GenericTimer/ArmGenericTimerParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicCParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicDispatcher.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicItsParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicItsParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicMsiFrameParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicMsiFrameParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicRParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Gic/ArmGicRParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Pci/ArmPciConfigSpaceParser.h
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.c
create mode 100644 DynamicTablesPkg/Library/FdtHwInfoParserLib/Serial/ArmSerialPortParser.h

--
2.17.1


[PATCH v3 8/8] DynamicTablesPkg: Fix multiple objects parsing

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

When a CmObjDesc contains multiple objects, only the first one is
parsed as the buffer doesn't progress. Fix this.
Also check that the whole buffer has been parsed with an asset.

Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../ConfigurationManagerObjectParser.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
index e340ce185256..681137a0e3b2 100644
--- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
+++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
@@ -685,7 +685,7 @@ ParseCmObjDesc (
UINTN NameSpaceId;
UINT32 ObjIndex;
UINT32 ObjectCount;
- INTN RemainingSize;
+ INTN RemainingSize, Offset;
CONST CM_OBJ_PARSER_ARRAY * ParserArray;

if ((CmObjDesc == NULL) || (CmObjDesc->Data == NULL)) {
@@ -718,6 +718,7 @@ ParseCmObjDesc (

ObjectCount = CmObjDesc->Count;
RemainingSize = CmObjDesc->Size;
+ Offset = 0;

for (ObjIndex = 0; ObjIndex < ObjectCount; ObjIndex++) {
DEBUG ((
@@ -729,11 +730,19 @@ ParseCmObjDesc (
ObjectCount
));
PrintCmObjDesc (
- CmObjDesc->Data,
+ (VOID*)((UINTN)CmObjDesc->Data + Offset),
ParserArray->Parser,
ParserArray->ItemCount,
&RemainingSize,
1
);
+ if ((RemainingSize > CmObjDesc->Size) ||
+ (RemainingSize < 0)) {
+ ASSERT (0);
+ return;
+ }
+ Offset = CmObjDesc->Size - RemainingSize;
} // for
+
+ ASSERT (RemainingSize == 0);
}
--
2.17.1


[PATCH v3 7/8] DynamicTablesPkg: SSDT Pci express generator

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

This generator allows to generate a SSDT table describing
a Pci express Bus. It uses the following CmObj:
- EArmObjCmRef
- EArmObjPciConfigSpaceInfo
- EArmObjPciAddressMapInfo
- EArmObjPciInterruptMapInfo

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3682

To: Sami Mujawar <sami.mujawar@...>
To: Alexei Fedorov <Alexei.Fedorov@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
DynamicTablesPkg/DynamicTables.dsc.inc | 2 +
DynamicTablesPkg/Include/AcpiTableGenerator.h | 5 +
.../AcpiSsdtPcieLibArm/SsdtPcieGenerator.c | 1450 +++++++++++++++++
.../AcpiSsdtPcieLibArm/SsdtPcieGenerator.h | 138 ++
.../Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf | 32 +
.../SsdtPcieOscTemplate.asl | 80 +
6 files changed, 1707 insertions(+)
create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl

diff --git a/DynamicTablesPkg/DynamicTables.dsc.inc b/DynamicTablesPkg/DynamicTables.dsc.inc
index 292215c39456..60bcf4b199e8 100644
--- a/DynamicTablesPkg/DynamicTables.dsc.inc
+++ b/DynamicTablesPkg/DynamicTables.dsc.inc
@@ -39,6 +39,7 @@ [Components.common]

# AML Codegen
DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf

#
# Dynamic Table Factory Dxe
@@ -62,6 +63,7 @@ [Components.common]

# AML Codegen
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCpuTopologyLibArm/SsdtCpuTopologyLibArm.inf
+ NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
}

#
diff --git a/DynamicTablesPkg/Include/AcpiTableGenerator.h b/DynamicTablesPkg/Include/AcpiTableGenerator.h
index 45c808ba740d..58ec941f2a35 100644
--- a/DynamicTablesPkg/Include/AcpiTableGenerator.h
+++ b/DynamicTablesPkg/Include/AcpiTableGenerator.h
@@ -67,6 +67,10 @@ The Dynamic Tables Framework implements the following ACPI table generators:
The SSDT Cpu-Topology generator collates the cpu and LPI
information from the Configuration Manager and generates a
SSDT table describing the CPU hierarchy.
+ - SSDT Pci-Express:
+ The SSDT Pci Express generator collates the Pci Express
+ information from the Configuration Manager and generates a
+ SSDT table describing a Pci Express bus.
*/

/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
@@ -93,6 +97,7 @@ typedef enum StdAcpiTableId {
EStdAcpiTableIdSsdtSerialPort, ///< SSDT Serial-Port Generator
EStdAcpiTableIdSsdtCmn600, ///< SSDT Cmn-600 Generator
EStdAcpiTableIdSsdtCpuTopology, ///< SSDT Cpu Topology
+ EStdAcpiTableIdSsdtPciExpress, ///< SSDT Pci Express Generator
EStdAcpiTableIdMax
} ESTD_ACPI_TABLE_ID;

diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
new file mode 100644
index 000000000000..fedb06b28ec1
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
@@ -0,0 +1,1450 @@
+/** @file
+ SSDT Pcie Table Generator.
+
+ Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - PCI Firmware Specification - Revision 3.0
+ - ACPI 6.4 specification:
+ - s6.2.13 "_PRT (PCI Routing Table)"
+ - s6.1.1 "_ADR (Address)"
+ - linux kernel code
+ - Arm Base Boot Requirements v1.0
+**/
+
+#include <Library/AcpiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/AcpiHelperLib.h>
+#include <Library/TableHelperLib.h>
+#include <Library/AmlLib/AmlLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+#include "SsdtPcieGenerator.h"
+
+/** ARM standard SSDT Pcie Table Generator.
+
+Requirements:
+ The following Configuration Manager Object(s) are required by
+ this Generator:
+ - EArmObjCmRef
+ - EArmObjPciConfigSpaceInfo
+ - EArmObjPciAddressMapInfo
+ - EArmObjPciInterruptMapInfo
+*/
+
+/** This macro expands to a function that retrieves the cross-CM-object-
+ reference information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjCmRef,
+ CM_ARM_OBJ_REF
+ );
+
+/** This macro expands to a function that retrieves the Pci
+ Configuration Space Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjPciConfigSpaceInfo,
+ CM_ARM_PCI_CONFIG_SPACE_INFO
+ );
+
+/** This macro expands to a function that retrieves the Pci
+ Address Mapping Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjPciAddressMapInfo,
+ CM_ARM_PCI_ADDRESS_MAP_INFO
+ );
+
+/** This macro expands to a function that retrieves the Pci
+ Interrupt Mapping Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjPciInterruptMapInfo,
+ CM_ARM_PCI_INTERRUPT_MAP_INFO
+ );
+
+/** Initialize the MappingTable.
+
+ @param [in] MappingTable The mapping table structure.
+ @param [in] Count Number of entries to allocate in the
+ MappingTable.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MappingTableInitialize (
+ IN MAPPING_TABLE * MappingTable,
+ IN UINT32 Count
+ )
+{
+ UINT32 * Table;
+
+ if ((MappingTable == NULL) ||
+ (Count == 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Table = AllocateZeroPool (sizeof (*Table) * Count);
+ if (Table == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ MappingTable->Table = Table;
+ MappingTable->LastIndex = 0;
+ MappingTable->MaxIndex = Count;
+
+ return EFI_SUCCESS;
+}
+
+/** Free the MappingTable.
+
+ @param [in, out] MappingTable The mapping table structure.
+**/
+STATIC
+VOID
+EFIAPI
+MappingTableFree (
+ IN OUT MAPPING_TABLE * MappingTable
+ )
+{
+ ASSERT (MappingTable != NULL);
+ ASSERT (MappingTable->Table != NULL);
+
+ if (MappingTable->Table != NULL) {
+ FreePool (MappingTable->Table);
+ }
+}
+
+/** Add a new entry to the MappingTable and return its index.
+
+ If an entry with [Integer] is already available in the table,
+ return its index without adding a new entry.
+
+ @param [in] MappingTable The mapping table structure.
+ @param [in] Integer New Integer entry to add.
+
+ @retval The index of the Integer entry in the MappingTable.
+**/
+STATIC
+UINT32
+EFIAPI
+MappingTableAdd (
+ IN MAPPING_TABLE * MappingTable,
+ IN UINT32 Integer
+ )
+{
+ UINT32 * Table;
+ UINT32 Index;
+ UINT32 LastIndex;
+
+ ASSERT (MappingTable != NULL);
+ ASSERT (MappingTable->Table != NULL);
+
+ Table = MappingTable->Table;
+ LastIndex = MappingTable->LastIndex;
+
+ // Search if there is already an entry with this Integer.
+ for (Index = 0; Index < LastIndex; Index++) {
+ if (Table[Index] == Integer) {
+ return Index;
+ }
+ }
+
+ ASSERT (LastIndex < MappingTable->MaxIndex);
+
+ // If no, create a new entry.
+ Table[LastIndex] = Integer;
+
+ return MappingTable->LastIndex++;
+}
+
+/** Generate required Pci device information.
+
+ ASL code:
+ Name (_UID, <Uid>) // Uid of the Pci device
+ Name (_HID, EISAID ("PNP0A08")) // PCI Express Root Bridge
+ Name (_CID, EISAID ("PNP0A03")) // Compatible PCI Root Bridge
+ Name (_SEG, <Pci segment group>) // PCI Segment Group number
+ Name (_BBN, <Bus number>) // PCI Base Bus Number
+ Name (_CCA, 1) // Initially mark the PCI coherent
+
+ @param [in] PciInfo Pci device information.
+ @param [in] Uid Unique Id of the Pci device.
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePciDeviceInfo (
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * PciInfo,
+ IN UINT32 Uid,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ EFI_STATUS Status;
+ UINT32 EisaId;
+
+ ASSERT (PciInfo != NULL);
+ ASSERT (PciNode != NULL);
+
+ // ASL: Name (_UID, <Uid>)
+ Status = AmlCodeGenNameInteger ("_UID", Uid, PciNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL: Name (_HID, EISAID ("PNP0A08"))
+ Status = AmlGetEisaIdFromString ("PNP0A08", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ Status = AmlCodeGenNameInteger ("_HID", EisaId, PciNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL: Name (_CID, EISAID ("PNP0A03"))
+ Status = AmlGetEisaIdFromString ("PNP0A03", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ Status = AmlCodeGenNameInteger ("_CID", EisaId, PciNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL: Name (_SEG, <Pci segment group>)
+ Status = AmlCodeGenNameInteger (
+ "_SEG",
+ PciInfo->PciSegmentGroupNumber,
+ PciNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL: Name (_BBN, <Bus number>)
+ Status = AmlCodeGenNameInteger (
+ "_BBN",
+ PciInfo->StartBusNumber,
+ PciNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL: Name (_CCA, 1)
+ // Must be aligned with the IORT CCA property in
+ // "Table 14 Memory access properties"
+ Status = AmlCodeGenNameInteger ("_CCA", 1, PciNode, NULL);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/** Generate a Link device.
+
+ The Link device is added at the beginning of the ASL Pci device definition.
+
+ Each Link device represents a Pci legacy interrupt (INTA-...-INTD).
+
+ ASL code:
+ Device (<Link Name>) {
+ Name (_UID, <Uid>])
+ Name (_HID, EISAID ("PNP0C0F"))
+ Name (CRS0, ResourceTemplate () {
+ Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { <Irq>] }
+ })
+ Method (_CRS, 0) {
+ Return CRS0
+ })
+ Method (_DIS) { }
+ }
+
+ The list of objects to define is available at:
+ PCI Firmware Specification - Revision 3.3,
+ s3.5. "Device State at Firmware/Operating System Handoff"
+
+ The _PRS and _SRS are not supported, cf Arm Base Boot Requirements v1.0:
+ "The _PRS (Possible Resource Settings) and _SRS (Set Resource Settings)
+ are not supported."
+
+ @param [in] Irq Interrupt controller interrupt.
+ @param [in] IrqFlags Interrupt flags.
+ @param [in] LinkIndex Legacy Pci interrupt index.
+ Must be between 0-INTA and 3-INTD.
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GenerateLinkDevice (
+ IN UINT32 Irq,
+ IN UINT32 IrqFlags,
+ IN UINT32 LinkIndex,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
+ AML_OBJECT_NODE_HANDLE LinkNode;
+ AML_OBJECT_NODE_HANDLE CrsNode;
+ UINT32 EisaId;
+
+ ASSERT (LinkIndex < 4);
+ ASSERT (PciNode != NULL);
+
+ CopyMem (AslName, "LNKx", AML_NAME_SEG_SIZE + 1);
+ AslName[AML_NAME_SEG_SIZE - 1] = 'A' + LinkIndex;
+
+ // ASL: Device (LNKx) {}
+ Status = AmlCodeGenDevice (AslName, NULL, &LinkNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlAttachNode (PciNode, LinkNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ // Failed to add.
+ AmlDeleteTree ((AML_NODE_HANDLE)LinkNode);
+ return Status;
+ }
+
+ // ASL: Name (_UID, <Uid>)
+ Status = AmlCodeGenNameInteger ("_UID", LinkIndex, LinkNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL: Name (_HID, EISAID ("PNP0C0F"))
+ Status = AmlGetEisaIdFromString ("PNP0C0F", &EisaId);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ Status = AmlCodeGenNameInteger ("_HID", EisaId, LinkNode, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL:
+ // Name (CRS0, ResourceTemplate () {
+ // Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { <Irq> }
+ // })
+ Status = AmlCodeGenNameResourceTemplate ("CRS0", LinkNode, &CrsNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ Status = AmlCodeGenRdInterrupt (
+ FALSE,
+ (IrqFlags & BIT0) != 0,
+ (IrqFlags & BIT1) != 0,
+ FALSE,
+ &Irq,
+ 1,
+ CrsNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL:
+ // Method (_CRS, 0) {
+ // Return (CRS0)
+ // }
+ Status = AmlCodeGenMethodRetNameString (
+ "_CRS",
+ "CRS0",
+ 0,
+ FALSE,
+ 0,
+ LinkNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL:Method (_DIS, 1) {}
+ // Not possible to disable interrupts.
+ Status = AmlCodeGenMethodRetNameString (
+ "_DIS",
+ NULL,
+ 0,
+ FALSE,
+ 0,
+ LinkNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // _STA:
+ // ACPI 6.4, s6.3.7 "_STA (Device Status)":
+ // If a device object describes a device that is not on an enumerable bus
+ // and the device object does not have an _STA object, then OSPM assumes
+ // that the device is present, enabled, shown in the UI, and functioning.
+
+ // _MAT:
+ // Not supported. Mainly used for processors.
+
+ return Status;
+}
+
+/** Generate Pci slots devices.
+
+ PCI Firmware Specification - Revision 3.3,
+ s4.8 "Generic ACPI PCI Slot Description" requests to describe the PCI slot
+ used. It should be possible to enumerate them, but this is additional
+ information.
+
+ @param [in] MappingTable The mapping table structure.
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePciSlots (
+ IN CONST MAPPING_TABLE * MappingTable,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+ UINT32 LastIndex;
+ UINT32 DeviceId;
+ CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
+ AML_OBJECT_NODE_HANDLE DeviceNode;
+
+ ASSERT (MappingTable != NULL);
+ ASSERT (PciNode != NULL);
+
+ // Generic device name is "Dxx".
+ CopyMem (AslName, "Dxx_", AML_NAME_SEG_SIZE + 1);
+
+ LastIndex = MappingTable->LastIndex;
+
+ // There are at most 32 devices on a Pci bus.
+ if (LastIndex >= 32) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < LastIndex; Index++) {
+ DeviceId = MappingTable->Table[Index];
+ AslName[AML_NAME_SEG_SIZE - 3] = AsciiFromHex (DeviceId & 0xF);
+ AslName[AML_NAME_SEG_SIZE - 2] = AsciiFromHex ((DeviceId >> 4) & 0xF);
+
+ // ASL:
+ // Device (Dxx) {
+ // Name (_ADR, <address value>)
+ // }
+ Status = AmlCodeGenDevice (AslName, PciNode, &DeviceNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ /* ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
+ High word-Device #, Low word-Function #. (for example, device 3,
+ function 2 is 0x00030002). To refer to all the functions on a device #,
+ use a function number of FFFF).
+ */
+ Status = AmlCodeGenNameInteger (
+ "_ADR",
+ (DeviceId << 16) | 0xFFFF,
+ DeviceNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // _SUN object is not generated as we don't know which slot will be used.
+ }
+
+ return Status;
+}
+
+/** Generate a _PRT object (Pci Routing Table) for the Pci device.
+
+ Cf. ACPI 6.4 specification, s6.2.13 "_PRT (PCI Routing Table)"
+
+ The first model (defining a _CRS object) is used. This is necessary because
+ PCI legacy interrupts are active low and GICv2 SPI interrupts are active
+ high.
+ Even though PCI interrupts cannot be re-routed, only the first model allows
+ to specify the activation state (low/high).
+
+ @param [in] Generator The SSDT Pci generator.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol interface.
+ @param [in] PciInfo Pci device information.
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePrt (
+ IN ACPI_PCI_GENERATOR * Generator,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * PciInfo,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ EFI_STATUS Status;
+ INT32 Index;
+ UINT32 IrqTableIndex;
+ AML_OBJECT_NODE_HANDLE PrtNode;
+ CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
+ CM_ARM_OBJ_REF * RefInfo;
+ UINT32 RefCount;
+ CM_ARM_PCI_INTERRUPT_MAP_INFO * IrqMapInfo;
+ UINT32 IrqFlags;
+ UINT32 PrevIrqFlags;
+
+ ASSERT (Generator != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (PciInfo != NULL);
+ ASSERT (PciNode != NULL);
+
+ PrtNode = NULL;
+
+ // Get the array of CM_ARM_OBJ_REF referencing the
+ // CM_ARM_PCI_INTERRUPT_MAP_INFO objects.
+ Status = GetEArmObjCmRef (
+ CfgMgrProtocol,
+ PciInfo->InterruptMapToken,
+ &RefInfo,
+ &RefCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Initialized IrqTable.
+ Status = MappingTableInitialize (&Generator->IrqTable, RefCount);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Initialized DeviceTable.
+ Status = MappingTableInitialize (&Generator->DeviceTable, RefCount);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler0;
+ }
+
+ // ASL: Name (_PRT, Package () {})
+ Status = AmlCodeGenNamePackage ("_PRT", NULL, &PrtNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ CopyMem (AslName, "LNKx", AML_NAME_SEG_SIZE + 1);
+
+ for (Index = 0; Index < RefCount; Index++) {
+ // Get CM_ARM_PCI_INTERRUPT_MAP_INFO structures one by one.
+ Status = GetEArmObjPciInterruptMapInfo (
+ CfgMgrProtocol,
+ RefInfo[Index].ReferenceToken,
+ &IrqMapInfo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Add the interrupt in the IrqTable and get the link name.
+ IrqTableIndex = MappingTableAdd (
+ &Generator->IrqTable,
+ IrqMapInfo->IntcInterrupt.Interrupt
+ );
+ if (IrqTableIndex >= MAX_PCI_LEGACY_INTERRUPT) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto exit_handler;
+ }
+
+ AslName[AML_NAME_SEG_SIZE - 1] = 'A' + IrqTableIndex;
+
+ // Check that the interrupts flags are identical for all interrupts.
+ PrevIrqFlags = IrqFlags;
+ IrqFlags = IrqMapInfo->IntcInterrupt.Flags;
+ if ((Index > 0) && (PrevIrqFlags != IrqFlags)) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto exit_handler;
+ }
+
+ // Add the device to the DeviceTable.
+ MappingTableAdd (&Generator->DeviceTable, IrqMapInfo->PciDevice);
+
+ /* Add a _PRT entry.
+ ASL
+ Name (_PRT, Package () {
+ <OldPrtEntries>,
+ <NewPrtEntry>
+ })
+
+ Address is set as:
+ ACPI 6.4 specification, Table 6.2: "ADR Object Address Encodings"
+ High word-Device #, Low word-Function #. (for example, device 3,
+ function 2 is 0x00030002). To refer to all the functions on a device #,
+ use a function number of FFFF).
+ */
+ Status = AmlAddPrtEntry (
+ (IrqMapInfo->PciDevice << 16) | 0xFFFF,
+ IrqMapInfo->PciInterrupt,
+ AslName,
+ 0,
+ PrtNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+ } // for
+
+ // Generate the LNKx devices now that we know all the interrupts used.
+ for (Index = 0; Index < Generator->IrqTable.LastIndex; Index++) {
+ Status = GenerateLinkDevice (
+ Generator->IrqTable.Table[Index],
+ IrqFlags,
+ Index,
+ PciNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+ } // for
+
+ // Attach the _PRT entry now, after the LNKx devices.
+ Status = AmlAttachNode (PciNode, PrtNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+ PrtNode = NULL;
+
+ // Generate the Pci slots once all the device have been added.
+ Status = GeneratePciSlots (&Generator->DeviceTable, PciNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+exit_handler:
+ MappingTableFree (&Generator->DeviceTable);
+exit_handler0:
+ MappingTableFree (&Generator->IrqTable);
+ if (PrtNode != NULL) {
+ AmlDeleteTree (PrtNode);
+ }
+
+ return Status;
+}
+
+/** Generate a _CRS method for the Pci device.
+
+ @param [in] Generator The SSDT Pci generator.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol interface.
+ @param [in] PciInfo Pci device information.
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePciCrs (
+ IN ACPI_PCI_GENERATOR * Generator,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * PciInfo,
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Translation;
+ UINT32 Index;
+ CM_ARM_OBJ_REF * RefInfo;
+ UINT32 RefCount;
+ CM_ARM_PCI_ADDRESS_MAP_INFO * AddrMapInfo;
+ AML_OBJECT_NODE_HANDLE CrsNode;
+
+ ASSERT (Generator != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (PciInfo != NULL);
+ ASSERT (PciNode != NULL);
+
+ // ASL: Name (_CRS, ResourceTemplate () {})
+ Status = AmlCodeGenNameResourceTemplate ("_CRS", PciNode, &CrsNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // ASL:
+ // WordBusNumber ( // Bus numbers assigned to this root
+ // ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ // 0, // AddressGranularity
+ // <Start>, // AddressMinimum - Minimum Bus Number
+ // <End>, // AddressMaximum - Maximum Bus Number
+ // 0, // AddressTranslation - Set to 0
+ // <End> - <Start> + 1 // RangeLength - Number of Busses
+ // )
+ Status = AmlCodeGenRdWordBusNumber (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ 0,
+ PciInfo->StartBusNumber,
+ PciInfo->EndBusNumber,
+ 0,
+ PciInfo->EndBusNumber - PciInfo->StartBusNumber + 1,
+ 0,
+ NULL,
+ CrsNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the array of CM_ARM_OBJ_REF referencing the
+ // CM_ARM_PCI_ADDRESS_MAP_INFO objects.
+ Status = GetEArmObjCmRef (
+ CfgMgrProtocol,
+ PciInfo->AddressMapToken,
+ &RefInfo,
+ &RefCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ for (Index = 0; Index < RefCount; Index++) {
+ // Get CM_ARM_PCI_ADDRESS_MAP_INFO structures one by one.
+ Status = GetEArmObjPciAddressMapInfo (
+ CfgMgrProtocol,
+ RefInfo[Index].ReferenceToken,
+ &AddrMapInfo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Translation = (AddrMapInfo->CpuAddress != AddrMapInfo->PciAddress);
+
+ switch (AddrMapInfo->SpaceCode) {
+ case PCI_SS_IO:
+ Status = AmlCodeGenRdDWordIo (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ 3,
+ 0,
+ AddrMapInfo->PciAddress,
+ AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
+ Translation ? AddrMapInfo->CpuAddress : 0,
+ AddrMapInfo->AddressSize,
+ 0,
+ NULL,
+ TRUE,
+ FALSE,
+ CrsNode,
+ NULL
+ );
+ break;
+
+ case PCI_SS_M32:
+ Status = AmlCodeGenRdDWordMemory (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ TRUE,
+ TRUE,
+ 0,
+ AddrMapInfo->PciAddress,
+ AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
+ Translation ? AddrMapInfo->CpuAddress : 0,
+ AddrMapInfo->AddressSize,
+ 0,
+ NULL,
+ 0,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+ break;
+
+ case PCI_SS_M64:
+ Status = AmlCodeGenRdQWordMemory (
+ FALSE,
+ TRUE,
+ TRUE,
+ TRUE,
+ TRUE,
+ TRUE,
+ 0,
+ AddrMapInfo->PciAddress,
+ AddrMapInfo->PciAddress + AddrMapInfo->AddressSize - 1,
+ Translation ? AddrMapInfo->CpuAddress : 0,
+ AddrMapInfo->AddressSize,
+ 0,
+ NULL,
+ 0,
+ TRUE,
+ CrsNode,
+ NULL
+ );
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ } // switch
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } // for
+ return Status;
+}
+
+/** Add an _OSC template method to the PciNode.
+
+ The _OSC method is provided as an AML blob. The blob is
+ parsed and attached at the end of the PciNode list of variable elements.
+
+ @param [in, out] PciNode Pci node to amend.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AddOscMethod (
+ IN OUT AML_OBJECT_NODE_HANDLE PciNode
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ EFI_ACPI_DESCRIPTION_HEADER * SsdtPcieOscTemplate;
+ AML_ROOT_NODE_HANDLE OscTemplateRoot;
+ AML_OBJECT_NODE_HANDLE OscNode;
+
+ ASSERT (PciNode != NULL);
+
+ // Parse the Ssdt Pci Osc Template.
+ SsdtPcieOscTemplate = (EFI_ACPI_DESCRIPTION_HEADER*)
+ ssdtpcieosctemplate_aml_code;
+
+ OscNode = NULL;
+ OscTemplateRoot = NULL;
+ Status = AmlParseDefinitionBlock (
+ SsdtPcieOscTemplate,
+ &OscTemplateRoot
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI-OSC: Failed to parse SSDT PCI OSC Template."
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ Status = AmlFindNode (OscTemplateRoot, "\\_OSC", &OscNode);
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ Status = AmlDetachNode (OscNode);
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ Status = AmlAttachNode (PciNode, OscNode);
+ if (EFI_ERROR (Status)) {
+ // Free the detached node.
+ AmlDeleteTree (OscNode);
+ goto error_handler;
+ }
+
+error_handler:
+ // Cleanup
+ Status1 = AmlDeleteTree (OscTemplateRoot);
+ if (EFI_ERROR (Status1)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI-OSC: Failed to cleanup AML tree."
+ " Status = %r\n",
+ Status1
+ ));
+ // If Status was success but we failed to delete the AML Tree
+ // return Status1 else return the original error code, i.e. Status.
+ if (!EFI_ERROR (Status)) {
+ return Status1;
+ }
+ }
+
+ return Status;
+}
+
+/** Generate a Pci device.
+
+ @param [in] Generator The SSDT Pci generator.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol interface.
+ @param [in] PciInfo Pci device information.
+ @param [in] Uid Unique Id of the Pci device.
+ @param [in, out] RootNode RootNode of the AML tree to populate.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GeneratePciDevice (
+ IN ACPI_PCI_GENERATOR * Generator,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * PciInfo,
+ IN UINT32 Uid,
+ IN OUT AML_ROOT_NODE_HANDLE * RootNode
+ )
+{
+ EFI_STATUS Status;
+
+ CHAR8 AslName[AML_NAME_SEG_SIZE + 1];
+ AML_OBJECT_NODE_HANDLE ScopeNode;
+ AML_OBJECT_NODE_HANDLE PciNode;
+
+ ASSERT (Generator != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (PciInfo != NULL);
+ ASSERT (RootNode != NULL);
+
+ PciNode = NULL;
+
+ // ASL: Scope (\_SB) {}
+ Status = AmlCodeGenScope (SB_SCOPE, RootNode, &ScopeNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Write the name of the PCI device.
+ CopyMem (AslName, "PCIx", AML_NAME_SEG_SIZE + 1);
+ AslName[AML_NAME_SEG_SIZE - 1] = AsciiFromHex (Uid);
+
+ // ASL: Device (PCIx) {}
+ Status = AmlCodeGenDevice (AslName, ScopeNode, &PciNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Populate the PCIx node with some Id values.
+ Status = GeneratePciDeviceInfo (PciInfo, Uid, PciNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Generate the Pci Routing Table (_PRT).
+ if (PciInfo->InterruptMapToken != CM_NULL_TOKEN) {
+ Status = GeneratePrt (
+ Generator,
+ CfgMgrProtocol,
+ PciInfo,
+ PciNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ // Generate the _CRS method.
+ Status = GeneratePciCrs (Generator, CfgMgrProtocol, PciInfo, PciNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the template _OSC method.
+ Status = AddOscMethod (PciNode);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/** Build an Ssdt table describing a Pci device.
+
+ @param [in] Generator The SSDT Pci generator.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol interface.
+ @param [in] AcpiTableInfo Pointer to the ACPI table information.
+ @param [in] PciInfo Pci device information.
+ @param [in] Uid Unique Id of the Pci device.
+ @param [out] Table If success, contains the created SSDT table.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSsdtPciTable (
+ IN ACPI_PCI_GENERATOR * Generator,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST CM_ARM_PCI_CONFIG_SPACE_INFO * PciInfo,
+ IN UINT32 Uid,
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ AML_ROOT_NODE_HANDLE RootNode;
+
+ ASSERT (Generator != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (PciInfo != NULL);
+ ASSERT (Table != NULL);
+
+ // Create a new Ssdt table.
+ Status = AddSsdtAcpiHeader (
+ CfgMgrProtocol,
+ &Generator->Header,
+ AcpiTableInfo,
+ &RootNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = GeneratePciDevice (
+ Generator,
+ CfgMgrProtocol,
+ PciInfo,
+ Uid,
+ RootNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Serialize the tree.
+ Status = AmlSerializeDefinitionBlock (
+ RootNode,
+ Table
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: Failed to Serialize SSDT Table Data."
+ " Status = %r\n",
+ Status
+ ));
+ }
+
+exit_handler:
+ // Cleanup
+ Status1 = AmlDeleteTree (RootNode);
+ if (EFI_ERROR (Status1)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: Failed to cleanup AML tree."
+ " Status = %r\n",
+ Status1
+ ));
+ // If Status was success but we failed to delete the AML Tree
+ // return Status1 else return the original error code, i.e. Status.
+ if (!EFI_ERROR (Status)) {
+ return Status1;
+ }
+ }
+
+ return Status;
+}
+
+/** Construct SSDT tables describing Pci root complexes.
+
+ This function invokes the Configuration Manager protocol interface
+ to get the required hardware information for generating the ACPI
+ table.
+
+ If this function allocates any resources then they must be freed
+ in the FreeXXXXTableResourcesEx function.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI table information.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol interface.
+ @param [out] Table Pointer to a list of generated ACPI table(s).
+ @param [out] TableCount Number of generated ACPI table(s).
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
+ Manager is less than the Object size for
+ the requested object.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+ @retval EFI_UNSUPPORTED Unsupported configuration.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSsdtPciTableEx (
+ IN CONST ACPI_TABLE_GENERATOR * This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ OUT EFI_ACPI_DESCRIPTION_HEADER *** Table,
+ OUT UINTN * CONST TableCount
+ )
+{
+ EFI_STATUS Status;
+ CM_ARM_PCI_CONFIG_SPACE_INFO * PciInfo;
+ UINT32 PciCount;
+ UINTN Index;
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
+ ACPI_PCI_GENERATOR * Generator;
+
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (Table != NULL);
+ ASSERT (TableCount != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ *TableCount = 0;
+ Generator = (ACPI_PCI_GENERATOR*)This;
+
+ Status = GetEArmObjPciConfigSpaceInfo (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &PciInfo,
+ &PciCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ if (PciCount > MAX_PCI_ROOT_COMPLEXES_SUPPORTED) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: Too many Pci root complexes: %d."
+ " Maximum Pci root complexes supported = %d.\n",
+ PciCount,
+ MAX_PCI_ROOT_COMPLEXES_SUPPORTED
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate a table to store pointers to the SSDT tables.
+ TableList = (EFI_ACPI_DESCRIPTION_HEADER**)
+ AllocateZeroPool (
+ (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * PciCount)
+ );
+ if (TableList == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: Failed to allocate memory for Table List."
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ // Setup the table list early so that appropriate cleanup
+ // can be done in case of failure.
+ *Table = TableList;
+
+ for (Index = 0; Index < PciCount; Index++) {
+ // Build a SSDT table describing the Pci devices.
+ Status = BuildSsdtPciTable (
+ Generator,
+ CfgMgrProtocol,
+ AcpiTableInfo,
+ &PciInfo[Index],
+ Index,
+ &TableList[Index]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: Failed to build associated SSDT table."
+ " Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ *TableCount += 1;
+ } // for
+
+error_handler:
+ // Note: Table list and Table count have been setup. The
+ // error handler does nothing here as the framework will invoke
+ // FreeSsdtPciTableEx () even on failure.
+ return Status;
+}
+
+/** Free any resources allocated for constructing the tables.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in, out] Table Pointer to an array of pointers
+ to ACPI Table(s).
+ @param [in] TableCount Number of ACPI table(s).
+
+ @retval EFI_SUCCESS The resources were freed successfully.
+ @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FreeSsdtPciTableEx (
+ IN CONST ACPI_TABLE_GENERATOR * CONST This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table,
+ IN CONST UINTN TableCount
+ )
+{
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
+ UINTN Index;
+
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ if ((Table == NULL) ||
+ (*Table == NULL) ||
+ (TableCount == 0)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: SSDT-PCI: Invalid Table Pointer\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TableList = *Table;
+ for (Index = 0; Index < TableCount; Index++) {
+ if ((TableList[Index] != NULL) &&
+ (TableList[Index]->Signature ==
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
+ FreePool (TableList[Index]);
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-PCI: Could not free SSDT table at index %d.",
+ Index
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+ } //for
+
+ // Free the table list.
+ FreePool (*Table);
+
+ return EFI_SUCCESS;
+}
+
+/** This macro defines the SSDT Pci Table Generator revision.
+*/
+#define SSDT_PCI_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the SSDT Pci Table Generator.
+*/
+STATIC
+ACPI_PCI_GENERATOR SsdtPcieGenerator = {
+ // ACPI table generator header
+ {
+ // Generator ID
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtPciExpress),
+ // Generator Description
+ L"ACPI.STD.SSDT.PCI.GENERATOR",
+ // ACPI Table Signature
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ // ACPI Table Revision - Unused
+ 0,
+ // Minimum ACPI Table Revision - Unused
+ 0,
+ // Creator ID
+ TABLE_GENERATOR_CREATOR_ID_ARM,
+ // Creator Revision
+ SSDT_PCI_GENERATOR_REVISION,
+ // Build table function. Use the extended version instead.
+ NULL,
+ // Free table function. Use the extended version instead.
+ NULL,
+ // Extended Build table function.
+ BuildSsdtPciTableEx,
+ // Extended free function.
+ FreeSsdtPciTableEx
+ },
+
+ // Private fields are defined from here.
+
+ // IrqTable
+ {
+ // Table
+ NULL,
+ // LastIndex
+ 0,
+ // MaxIndex
+ 0
+ },
+ // DeviceTable
+ {
+ // Table
+ NULL,
+ // LastIndex
+ 0,
+ // MaxIndex
+ 0
+ },
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+ @param [in] ImageHandle The handle to the image.
+ @param [in] SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS The Generator is registered.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_ALREADY_STARTED The Generator for the Table ID
+ is already registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiSsdtPcieLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RegisterAcpiTableGenerator (&SsdtPcieGenerator.Header);
+ DEBUG ((
+ DEBUG_INFO,
+ "SSDT-PCI: Register Generator. Status = %r\n",
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/** Deregister the Generator from the ACPI Table Factory.
+
+ @param [in] ImageHandle The handle to the image.
+ @param [in] SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS The Generator is deregistered.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The Generator is not registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiSsdtPcieLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = DeregisterAcpiTableGenerator (&SsdtPcieGenerator.Header);
+ DEBUG ((
+ DEBUG_INFO,
+ "SSDT-PCI: Deregister Generator. Status = %r\n",
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
new file mode 100644
index 000000000000..784b5274815b
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
@@ -0,0 +1,138 @@
+/** @file
+ SSDT Pcie Table Generator.
+
+ Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - PCI Firmware Specification - Revision 3.0
+ - ACPI 6.4 specification:
+ - s6.2.13 "_PRT (PCI Routing Table)"
+ - s6.1.1 "_ADR (Address)"
+ - linux kernel code
+ - Arm Base Boot Requirements v1.0
+**/
+
+#ifndef SSDT_PCIE_GENERATOR_H_
+#define SSDT_PCIE_GENERATOR_H_
+
+/** Pci address attributes.
+
+ This can also be denoted as space code, address space or ss.
+*/
+#define PCI_SS_CONFIG 0
+#define PCI_SS_IO 1
+#define PCI_SS_M32 2
+#define PCI_SS_M64 3
+
+/** Maximum Pci root complexes supported by this generator.
+
+ Note: This is not a hard limitation and can be extended if needed.
+ Corresponding changes would be needed to support the Name and
+ UID fields describing the Pci root complexes.
+*/
+#define MAX_PCI_ROOT_COMPLEXES_SUPPORTED 16
+
+/** Maximum number of Pci legacy interrupts.
+
+ Currently 4 for INTA-INTB-INTC-INTD.
+*/
+#define MAX_PCI_LEGACY_INTERRUPT 4
+
+// _SB scope of the AML namespace.
+#define SB_SCOPE "\\_SB_"
+
+/** C array containing the compiled AML template.
+ This symbol is defined in the auto generated C file
+ containing the AML bytecode array.
+*/
+extern CHAR8 ssdtpcieosctemplate_aml_code[];
+
+#pragma pack(1)
+
+/** Structure used to map integer to an index.
+*/
+typedef struct MappingTable {
+ /// Mapping table.
+ /// Contains the Index <-> integer mapping
+ UINT32 * Table;
+
+ /// Last used index of the Table.
+ /// Bound by MaxIndex.
+ UINT32 LastIndex;
+
+ /// Number of entries in the Table.
+ UINT32 MaxIndex;
+} MAPPING_TABLE;
+
+/** A structure holding the Pcie generator and additional private data.
+*/
+typedef struct AcpiPcieGenerator {
+ /// ACPI Table generator header
+ ACPI_TABLE_GENERATOR Header;
+
+ // Private fields are defined from here.
+
+ /** A structure used to handle the Address and Interrupt Map referencing.
+
+ A CM_ARM_PCI_CONFIG_SPACE_INFO structure references two CM_ARM_OBJ_REF:
+ - one for the address mapping, referencing
+ CM_ARM_PCI_ADDRESS_MAP_INFO structures.
+ - one for the interrupt mapping, referencing
+ CM_ARM_PCI_INTERRUPT_MAP_INFO structures.
+
+ Example:
+ (Pci0)
+ CM_ARM_PCI_CONFIG_SPACE_INFO
+ |
+ +----------------------------------------
+ | |
+ v v
+ CM_ARM_OBJ_REF CM_ARM_OBJ_REF
+ (List of references to (List of references to
+ address mappings) interrupt mappings)
+ | |
+ v v
+ CM_ARM_PCI_ADDRESS_MAP_INFO[0..N] CM_ARM_PCI_INTERRUPT_MAP_INFO[0..M]
+ (A list of address mappings) (A list of interrupt mappings)
+
+ The CM_ARM_PCI_INTERRUPT_MAP_INFO objects cannot be handled individually.
+ Device's Pci legacy interrupts that are mapped to the same CPU interrupt
+ are grouped under a Link device.
+ For instance, the following mapping:
+ - [INTA of device 0] mapped on [GIC irq 168]
+ - [INTB of device 1] mapped on [GIC irq 168]
+ will be represented in an SSDT table as:
+ - [INTA of device 0] mapped on [Link device A]
+ - [INTB of device 1] mapped on [Link device A]
+ - [Link device A] mapped on [GIC irq 168]
+
+ Counting the number of Cpu interrupts used and grouping them in Link
+ devices is done through this IRQ_TABLE.
+
+ ASL code:
+ Scope (_SB) {
+ Device (LNKA) {
+ [...]
+ Name (_PRS, ResourceTemplate () {
+ Interrupt (ResourceProducer, Level, ActiveHigh, Exclusive) { 168 }
+ })
+ }
+
+ Device (PCI0) {
+ Name (_PRT, Package () {
+ Package (0x0FFFF, 0, LNKA, 0) // INTA of device 0 <-> LNKA
+ Package (0x1FFFF, 1, LNKA, 0) // INTB of device 1 <-> LNKA
+ })
+ }
+ }
+ */
+ MAPPING_TABLE IrqTable;
+
+ /// Table to map: Index <-> Pci device
+ MAPPING_TABLE DeviceTable;
+} ACPI_PCI_GENERATOR;
+
+#pragma pack()
+
+#endif // SSDT_PCIE_GENERATOR_H_
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
new file mode 100644
index 000000000000..283b5648017c
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
@@ -0,0 +1,32 @@
+## @file
+# Ssdt Serial Port Table Generator
+#
+# Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = SsdtPcieLibArm
+ FILE_GUID = E431D7FD-26BF-4E3D-9064-5B13B0439057
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = NULL|DXE_DRIVER
+ CONSTRUCTOR = AcpiSsdtPcieLibConstructor
+ DESTRUCTOR = AcpiSsdtPcieLibDestructor
+
+[Sources]
+ SsdtPcieGenerator.c
+ SsdtPcieGenerator.h
+ SsdtPcieOscTemplate.asl
+
+[Packages]
+ DynamicTablesPkg/DynamicTablesPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ AcpiHelperLib
+ AmlLib
+ BaseLib
diff --git a/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl
new file mode 100644
index 000000000000..feaf56b53384
--- /dev/null
+++ b/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl
@@ -0,0 +1,80 @@
+/** @file
+ SSDT Pci Osc (Operating System Capabilities)
+
+ Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - PCI Firmware Specification - Revision 3.3
+ - ACPI 6.4 specification:
+ - s6.2.13 "_PRT (PCI Routing Table)"
+ - s6.1.1 "_ADR (Address)"
+ - linux kernel code
+**/
+
+DefinitionBlock ("SsdtPciOsc.aml", "SSDT", 2, "ARMLTD", "PCI-OSC", 1) {
+
+ // This table is just a template and is never installed as a table.
+ // Pci devices are dynamically created at runtime as:
+ // ASL:
+ // Device (PCIx) {
+ // ...
+ // }
+ // and the _OSC method available below is appended to the PCIx device as:
+ // ASL:
+ // Device (PCIx) {
+ // ...
+ // Method (_OSC, 4 {
+ // ...
+ // })
+ // }
+ Method (_OSC, 4) {
+ //
+ // OS Control Handoff
+ //
+ Name (SUPP, Zero) // PCI _OSC Support Field value
+ Name (CTRL, Zero) // PCI _OSC Control Field value
+
+ // Create DWord-addressable fields from the Capabilities Buffer
+ CreateDWordField (Arg3, 0, CDW1)
+ CreateDWordField (Arg3, 4, CDW2)
+ CreateDWordField (Arg3, 8, CDW3)
+
+ // Check for proper UUID
+ If (LEqual (Arg0,ToUUID ("33DB4D5B-1FF7-401C-9657-7441C03DD766"))) {
+
+ // Save Capabilities DWord2 & 3
+ Store (CDW2, SUPP)
+ Store (CDW3, CTRL)
+
+ // Only allow native hot plug control if OS supports:
+ // * ASPM
+ // * Clock PM
+ // * MSI/MSI-X
+ If (LNotEqual (And (SUPP, 0x16), 0x16)) {
+ And (CTRL, 0x1E, CTRL) // Mask bit 0 (and undefined bits)
+ }
+
+ // Always allow native PME, AER (no dependencies)
+
+ // Never allow SHPC (no SHPC controller in this system)
+ And (CTRL, 0x1D, CTRL)
+
+ If (LNotEqual (Arg1, One)) { // Unknown revision
+ Or (CDW1, 0x08, CDW1)
+ }
+
+ If (LNotEqual (CDW3, CTRL)) { // Capabilities bits were masked
+ Or (CDW1, 0x10, CDW1)
+ }
+
+ // Update DWORD3 in the buffer
+ Store (CTRL,CDW3)
+ Return (Arg3)
+ } Else {
+ Or (CDW1, 4, CDW1) // Unrecognized UUID
+ Return (Arg3)
+ } // If
+ } // _OSC
+}
--
2.17.1


[PATCH v3 6/8] DynamicTablesPkg: Add Pci related objects

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

Introduce the following CmObj in the ArmNameSpaceObjects:
- CM_ARM_PCI_ADDRESS_MAP_INFO
- CM_ARM_PCI_INTERRUPT_MAP_INFO

These objects allow to describe address range mapping
of Pci busses and interrupt mapping of Pci devices.

To: Sami Mujawar <sami.mujawar@...>
To: Alexei Fedorov <Alexei.Fedorov@...>
Reviewed-by: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../Include/ArmNameSpaceObjects.h | 78 +++++++++++++++++++
.../ConfigurationManagerObjectParser.c | 28 ++++++-
2 files changed, 105 insertions(+), 1 deletion(-)

diff --git a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
index f19c9c706669..ac19fa1f6e6c 100644
--- a/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
+++ b/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
@@ -59,6 +59,8 @@ typedef enum ArmObjectID {
EArmObjSerialPortInfo, ///< 35 - Generic Serial Port Info
EArmObjCmn600Info, ///< 36 - CMN-600 Info
EArmObjLpiInfo, ///< 37 - Lpi Info
+ EArmObjPciAddressMapInfo, ///< 38 - Pci Address Map Info
+ EArmObjPciInterruptMapInfo, ///< 39 - Pci Interrupt Map Info
EArmObjMax
} EARM_OBJECT_ID;

@@ -433,6 +435,14 @@ typedef struct CmArmPciConfigSpaceInfo {

/// The end bus number
UINT8 EndBusNumber;
+
+ /// Optional field: Reference Token for address mapping.
+ /// Token identifying a CM_ARM_OBJ_REF structure.
+ CM_OBJECT_TOKEN AddressMapToken;
+
+ /// Optional field: Reference Token for interrupt mapping.
+ /// Token identifying a CM_ARM_OBJ_REF structure.
+ CM_OBJECT_TOKEN InterruptMapToken;
} CM_ARM_PCI_CONFIG_SPACE_INFO;

/** A structure that describes the
@@ -666,6 +676,10 @@ typedef struct CmArmGenericInterrupt {
UINT32 Interrupt;

/// Flags
+ /// BIT0: 0: Interrupt is Level triggered
+ /// 1: Interrupt is Edge triggered
+ /// BIT1: 0: Interrupt is Active high
+ /// 1: Interrupt is Active low
UINT32 Flags;
} CM_ARM_GENERIC_INTERRUPT;

@@ -946,6 +960,70 @@ typedef struct CmArmLpiInfo {
CHAR8 StateName[16];
} CM_ARM_LPI_INFO;

+/** A structure that describes a PCI Address Map.
+
+ The memory-ranges used by the PCI bus are described by this object.
+
+ ID: EArmObjPciAddressMapInfo
+*/
+typedef struct CmArmPciAddressMapInfo {
+ /** Pci address space code
+
+ Available values are:
+ - 0: Configuration Space
+ - 1: I/O Space
+ - 2: 32-bit-address Memory Space
+ - 3: 64-bit-address Memory Space
+ */
+ UINT8 SpaceCode;
+
+ /// PCI address
+ UINT64 PciAddress;
+
+ /// Cpu address
+ UINT64 CpuAddress;
+
+ /// Address size
+ UINT64 AddressSize;
+} CM_ARM_PCI_ADDRESS_MAP_INFO;
+
+/** A structure that describes a PCI Interrupt Map.
+
+ The legacy PCI interrupts used by PCI devices are described by this object.
+
+ Cf Devicetree Specification - Release v0.3
+ s2.4.3 "Interrupt Nexus Properties"
+
+ ID: EArmObjPciInterruptMapInfo
+*/
+typedef struct CmArmPciInterruptMapInfo {
+ /// Pci Bus.
+ /// Value on 8 bits (max 255).
+ UINT8 PciBus;
+
+ /// Pci Bus.
+ /// Value on 5 bits (max 31).
+ UINT8 PciDevice;
+
+ /** PCI interrupt
+
+ ACPI bindings are used:
+ Cf. ACPI 6.4, s6.2.13 _PRT (PCI Routing Table):
+ "0-INTA, 1-INTB, 2-INTC, 3-INTD"
+
+ Device-tree bindings are shifted by 1:
+ "INTA=1, INTB=2, INTC=3, INTD=4"
+ */
+ UINT8 PciInterrupt;
+
+ /** Interrupt controller interrupt.
+
+ Cf Devicetree Specification - Release v0.3
+ s2.4.3 "Interrupt Nexus Properties": "parent interrupt specifier"
+ */
+ CM_ARM_GENERIC_INTERRUPT IntcInterrupt;
+} CM_ARM_PCI_INTERRUPT_MAP_INFO;
+
#pragma pack()

#endif // ARM_NAMESPACE_OBJECTS_H_
diff --git a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
index 0bdbfbb99c33..e340ce185256 100644
--- a/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
+++ b/DynamicTablesPkg/Library/Common/TableHelperLib/ConfigurationManagerObjectParser.c
@@ -152,7 +152,9 @@ STATIC CONST CM_OBJ_PARSER CmArmPciConfigSpaceInfoParser[] = {
{"BaseAddress", 8, "0x%llx", NULL},
{"PciSegmentGroupNumber", 2, "0x%x", NULL},
{"StartBusNumber", 1, "0x%x", NULL},
- {"EndBusNumber", 1, "0x%x", NULL}
+ {"EndBusNumber", 1, "0x%x", NULL},
+ {"AddressMapToken", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL},
+ {"InterruptMapToken", sizeof (CM_OBJECT_TOKEN), "0x%p", NULL},
};

/** A parser for EArmObjHypervisorVendorIdentity.
@@ -401,6 +403,26 @@ STATIC CONST CM_OBJ_PARSER CmArmLpiInfoParser[] = {
{"StateName", 16, "0x%a", NULL},
};

+/** A parser for EArmObjPciAddressMapInfo.
+*/
+STATIC CONST CM_OBJ_PARSER CmArmPciAddressMapInfoParser[] = {
+ {"SpaceCode", 1, "%d", NULL},
+ {"PciAddress", 8, "0x%llx", NULL},
+ {"CpuAddress", 8, "0x%llx", NULL},
+ {"AddressSize", 8, "0x%llx", NULL},
+};
+
+/** A parser for EArmObjPciInterruptMapInfo.
+*/
+STATIC CONST CM_OBJ_PARSER CmPciInterruptMapInfoParser[] = {
+ {"PciBus", 1, "0x%x", NULL},
+ {"PciDevice", 1, "0x%x", NULL},
+ {"PciInterrupt", 1, "0x%x", NULL},
+ {"IntcInterrupt", sizeof (CM_ARM_GENERIC_INTERRUPT),
+ NULL, NULL, CmArmGenericInterruptParser,
+ ARRAY_SIZE (CmArmGenericInterruptParser)},
+};
+
/** A parser for Arm namespace objects.
*/
STATIC CONST CM_OBJ_PARSER_ARRAY ArmNamespaceObjectParser[] = {
@@ -475,6 +497,10 @@ STATIC CONST CM_OBJ_PARSER_ARRAY ArmNamespaceObjectParser[] = {
ARRAY_SIZE (CmArmCmn600InfoParser)},
{"EArmObjLpiInfo", CmArmLpiInfoParser,
ARRAY_SIZE (CmArmLpiInfoParser)},
+ {"EArmObjPciAddressMapInfo", CmArmPciAddressMapInfoParser,
+ ARRAY_SIZE (CmArmPciAddressMapInfoParser)},
+ {"EArmObjPciInterruptMapInfo", CmPciInterruptMapInfoParser,
+ ARRAY_SIZE (CmPciInterruptMapInfoParser)},
{"EArmObjMax", NULL, 0},
};

--
2.17.1


[PATCH v3 5/8] DynamicTablesPkg: Add AmlAttachNode()

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

This function allows to add a node as the last node of a parent node
in an AML tree. For instance,
ASL code corresponding to NewNode:
Name (_UID, 0)

ASL code corresponding to ParentNode:
Device (PCI0) {
Name(_HID, EISAID("PNP0A08"))
}

"AmlAttachNode (ParentNode, NewNode)" will result in:
ASL code:
Device (PCI0) {
Name(_HID, EISAID("PNP0A08"))
Name (_UID, 0)
}

To: Sami Mujawar <sami.mujawar@...>
To: Alexei Fedorov <Alexei.Fedorov@...>
Reviewed-by: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../Include/Library/AmlLib/AmlLib.h | 33 +++++++++++++++++
.../Library/Common/AmlLib/Api/AmlApi.c | 36 +++++++++++++++++++
2 files changed, 69 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index aef5f55ce319..15517b5efac1 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -166,6 +166,39 @@ AmlDetachNode (
IN AML_NODE_HANDLE Node
);

+/** Attach a node in an AML tree.
+
+ The node will be added as the last statement of the ParentNode.
+ E.g.:
+ ASL code corresponding to NewNode:
+ Name (_UID, 0)
+
+ ASL code corresponding to ParentNode:
+ Device (PCI0) {
+ Name(_HID, EISAID("PNP0A08"))
+ }
+
+ "AmlAttachNode (ParentNode, NewNode)" will result in:
+ ASL code:
+ Device (PCI0) {
+ Name(_HID, EISAID("PNP0A08"))
+ Name (_UID, 0)
+ }
+
+ @param [in] ParentNode Pointer to the parent node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlAttachNode (
+ IN AML_NODE_HANDLE ParentNode,
+ IN AML_NODE_HANDLE NewNode
+ );
+
/** Find a node in the AML namespace, given an ASL path and a reference Node.

- The AslPath can be an absolute path, or a relative path from the
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
index 6f9e3f6f2805..def581299f5c 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
@@ -379,6 +379,42 @@ AmlNameOpGetNextRdNode (
return EFI_SUCCESS;
}

+/** Attach a node in an AML tree.
+
+ The node will be added as the last statement of the ParentNode.
+ E.g.:
+ ASL code corresponding to NewNode:
+ Name (_UID, 0)
+
+ ASL code corresponding to ParentNode:
+ Device (PCI0) {
+ Name(_HID, EISAID("PNP0A08"))
+ }
+
+ "AmlAttachNode (ParentNode, NewNode)" will result in:
+ ASL code:
+ Device (PCI0) {
+ Name(_HID, EISAID("PNP0A08"))
+ Name (_UID, 0)
+ }
+
+ @param [in] ParentNode Pointer to the parent node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlAttachNode (
+ IN AML_NODE_HANDLE ParentNode,
+ IN AML_NODE_HANDLE NewNode
+ )
+{
+ return AmlVarListAddTail (ParentNode, NewNode);
+}
+
// DEPRECATED APIS
#ifndef DISABLE_NEW_DEPRECATED_INTERFACES

--
2.17.1


[PATCH v3 4/8] DynamicTablesPkg: AML Code generation to add _PRT entries

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

_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@...>
To: Alexei Fedorov <Alexei.Fedorov@...>
Reviewed-by: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../Include/Library/AmlLib/AmlLib.h | 52 +++++
.../Common/AmlLib/CodeGen/AmlCodeGen.c | 210 ++++++++++++++++++
2 files changed, 262 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 763e2ce7d268..aef5f55ce319 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -891,6 +891,58 @@ AmlCodeGenNameResourceTemplate (
OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL
);

+/** Add a _PRT entry.
+
+ AmlCodeGenPrtEntry (0x0FFFF, 0, "LNKA", 0, PrtNameNode) is
+ equivalent of the following ASL code:
+ Package (4) {
+ 0x0FFFF, // Address: Device address (([Device Id] << 16) | 0xFFFF).
+ 0, // Pin: PCI pin number of the device (0-INTA, ...).
+ LNKA // Source: Name of the device that allocates the interrupt
+ // to which the above pin is connected.
+ 0 // Source Index: Source is assumed to only describe one
+ // interrupt, so let it to index 0.
+ }
+
+ The package is added at the tail of the list of the input _PRT node
+ name:
+ Name (_PRT, Package () {
+ [Pre-existing _PRT entries],
+ [Newly created _PRT entry]
+ })
+
+ Cf. ACPI 6.4, s6.2.13 "_PRT (PCI Routing Table)"
+
+ @ingroup CodeGenApis
+
+ @param [in] Address Address. Cf ACPI 6.4 specification, Table 6.2:
+ "ADR Object Address Encodings":
+ High word-Device #, Low word-Function #. (for
+ example, device 3, function 2 is 0x00030002).
+ To refer to all the functions on a device #,
+ use a function number of FFFF).
+ @param [in] Pin PCI pin number of the device (0-INTA ... 3-INTD).
+ Must be between 0-3.
+ @param [in] LinkName Link Name, i.e. device in the AML NameSpace
+ describing the interrupt used.
+ The input string is copied.
+ @param [in] SourceIndex Source index or GSIV.
+ @param [in] PrtNameNode Prt Named node to add the object to ....
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlAddPrtEntry (
+ IN UINT32 Address,
+ IN UINT8 Pin,
+ IN CONST CHAR8 * LinkName,
+ IN UINT32 SourceIndex,
+ IN AML_OBJECT_NODE_HANDLE PrtNameNode
+ );
+
/** AML code generation for a Device object node.

AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
index 8f48f214648f..5f2b39305540 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -856,6 +856,216 @@ AmlCodeGenNameResourceTemplate (
return Status;
}

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

AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
--
2.17.1


[PATCH v3 3/8] DynamicTablesPkg: AML Code generation to create a named ResourceTemplate()

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

Add AmlCodeGenNameResourceTemplate() to generate code for a
ResourceTemplate().

AmlCodeGenNameResourceTemplate ("REST", ParentNode, NewObjectNode) is
equivalent of the following ASL code:
Name(REST, ResourceTemplate () {})

To: Sami Mujawar <sami.mujawar@...>
To: Alexei Fedorov <Alexei.Fedorov@...>
Reviewed-by: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../Include/Library/AmlLib/AmlLib.h | 28 ++++++++++
.../Common/AmlLib/CodeGen/AmlCodeGen.c | 55 +++++++++++++++++++
2 files changed, 83 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index d2e9cbe26d75..763e2ce7d268 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -863,6 +863,34 @@ AmlCodeGenNamePackage (
OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL
);

+/** AML code generation for a Name object node, containing a ResourceTemplate.
+
+ AmlCodeGenNameResourceTemplate ("PRS0", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Name(PRS0, ResourceTemplate () {})
+
+ @ingroup CodeGenApis
+
+ @param [in] NameString The new variable name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNameResourceTemplate (
+ IN CONST CHAR8 * NameString,
+ IN AML_NODE_HANDLE ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL
+ );
+
/** AML code generation for a Device object node.

AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
index 1ba75fbd6f12..8f48f214648f 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -801,6 +801,61 @@ AmlCodeGenNamePackage (
return Status;
}

+/** AML code generation for a Name object node, containing a ResourceTemplate.
+
+ AmlCodeGenNameResourceTemplate ("PRS0", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Name(PRS0, ResourceTemplate () {})
+
+ @param [in] NameString The new variable name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNameResourceTemplate (
+ IN CONST CHAR8 * NameString,
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * ResourceTemplateNode;
+
+ if ((NameString == NULL) ||
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlCodeGenResourceTemplate (&ResourceTemplateNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlCodeGenName (
+ NameString,
+ ResourceTemplateNode,
+ ParentNode,
+ NewObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)ResourceTemplateNode);
+ }
+
+ return Status;
+}
+
/** AML code generation for a Device object node.

AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
--
2.17.1


[PATCH v3 2/8] DynamicTablesPkg: AML Code generation to create a named Package()

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

Add AmlCodeGenNamePackage() to generate code for a Package().

AmlCodeGenNamePackage ("PACK", ParentNode, NewObjectNode) is
equivalent of the following ASL code:
Name(PACK, Package () {})

To: Sami Mujawar <sami.mujawar@...>
To: Alexei Fedorov <Alexei.Fedorov@...>
Reviewed-by: Sami Mujawar <sami.mujawar@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../Include/Library/AmlLib/AmlLib.h | 28 ++++++++++
.../Common/AmlLib/CodeGen/AmlCodeGen.c | 55 +++++++++++++++++++
2 files changed, 83 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 59811379c597..d2e9cbe26d75 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -835,6 +835,34 @@ AmlCodeGenNameInteger (
OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL
);

+/** AML code generation for a Name object node, containing a Package.
+
+ AmlCodeGenNamePackage ("PKG0", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Name(PKG0, Package () {})
+
+ @ingroup CodeGenApis
+
+ @param [in] NameString The new variable name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNamePackage (
+ IN CONST CHAR8 * NameString,
+ IN AML_NODE_HANDLE ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL
+ );
+
/** AML code generation for a Device object node.

AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
index 64064018aecb..1ba75fbd6f12 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -746,6 +746,61 @@ AmlCodeGenNameInteger (
return Status;
}

+/** AML code generation for a Name object node, containing a Package.
+
+ AmlCodeGenNamePackage ("PKG0", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Name(PKG0, Package () {})
+
+ @param [in] NameString The new variable name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNamePackage (
+ IN CONST CHAR8 * NameString,
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * PackageNode;
+
+ if ((NameString == NULL) ||
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlCodeGenPackage (&PackageNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlCodeGenName (
+ NameString,
+ PackageNode,
+ ParentNode,
+ NewObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)PackageNode);
+ }
+
+ return Status;
+}
+
/** AML code generation for a Device object node.

AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
--
2.17.1


[PATCH v3 1/8] DynamicTablesPkg: AML Code generation for memory ranges

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

Add helper functions to generate AML Resource Data describing memory
ranges. Memory ranges can be one, double or four words long. They
can be of 'normal', IO or bus number memory type. The following
APIs are exposed:
- AmlCodeGenRdDWordIo ()
- AmlCodeGenRdDWordMemory ()
- AmlCodeGenRdWordBusNumber ()
- AmlCodeGenRdQWordMemory ()

To: Sami Mujawar <sami.mujawar@...>
To: Alexei Fedorov <Alexei.Fedorov@...>
Signed-off-by: Pierre Gondois <Pierre.Gondois@...>
---
.../Include/Library/AmlLib/AmlLib.h | 272 +++++
.../AmlLib/CodeGen/AmlResourceDataCodeGen.c | 943 ++++++++++++++++++
2 files changed, 1215 insertions(+)

diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 4932f6fd9c8b..59811379c597 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -418,6 +418,278 @@ AmlUpdateRdQWord (
IN UINT64 BaseAddressLength
);

+/** Code generation for the "DWordIO ()" ASL function.
+
+ The Resource Data effectively created is a DWord Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.2 "DWord Address Space Descriptor".
+ - s19.6.34 "DWordIO".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.34 for more.
+
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] IsPosDecode Decode parameter
+ @param [in] IsaRanges Possible values are:
+ 0-Reserved
+ 1-NonISAOnly
+ 2-ISAOnly
+ 3-EntireRange
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Not supported. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Not supported. Must be NULL.
+ @param [in] IsDenseTranslation TranslationDensity parameter.
+ @param [in] IsTypeStatic TranslationType parameter.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordIo (
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN BOOLEAN IsPosDecode,
+ IN UINT8 IsaRanges,
+ IN UINT32 AddressGranularity,
+ IN UINT32 AddressMinimum,
+ IN UINT32 AddressMaximum,
+ IN UINT32 AddressTranslation,
+ IN UINT32 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN BOOLEAN IsDenseTranslation,
+ IN BOOLEAN IsTypeStatic,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ );
+
+/** Code generation for the "DWordMemory ()" ASL function.
+
+ The Resource Data effectively created is a DWord Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.2 "DWord Address Space Descriptor".
+ - s19.6.35 "DWordMemory".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.35 for more.
+
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsPosDecode Decode parameter
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] Cacheable Possible values are:
+ 0-The memory is non-cacheable
+ 1-The memory is cacheable
+ 2-The memory is cacheable and supports
+ write combining
+ 3-The memory is cacheable and prefetchable
+ @param [in] IsReadWrite ReadAndWrite parameter.
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Not supported. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Not supported. Must be NULL.
+ @param [in] MemoryRangeType Possible values are:
+ 0-AddressRangeMemory
+ 1-AddressRangeReserved
+ 2-AddressRangeACPI
+ 3-AddressRangeNVS
+ @param [in] IsTypeStatic TranslationType parameter.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordMemory (
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsPosDecode,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN UINT8 Cacheable,
+ IN BOOLEAN IsReadWrite,
+ IN UINT32 AddressGranularity,
+ IN UINT32 AddressMinimum,
+ IN UINT32 AddressMaximum,
+ IN UINT32 AddressTranslation,
+ IN UINT32 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN UINT8 MemoryRangeType,
+ IN BOOLEAN IsTypeStatic,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ );
+
+/** Code generation for the "WordBusNumber ()" ASL function.
+
+ The Resource Data effectively created is a Word Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.3 "Word Address Space Descriptor".
+ - s19.6.149 "WordBusNumber".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.149 for more.
+
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] IsPosDecode Decode parameter
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Not supported. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Not supported. Must be NULL.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdWordBusNumber (
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN BOOLEAN IsPosDecode,
+ IN UINT32 AddressGranularity,
+ IN UINT32 AddressMinimum,
+ IN UINT32 AddressMaximum,
+ IN UINT32 AddressTranslation,
+ IN UINT32 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ );
+
+/** Code generation for the "QWordMemory ()" ASL function.
+
+ The Resource Data effectively created is a QWord Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.1 "QWord Address Space Descriptor".
+ - s19.6.110 "QWordMemory".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.110 for more.
+
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsPosDecode Decode parameter.
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] Cacheable Possible values are:
+ 0-The memory is non-cacheable
+ 1-The memory is cacheable
+ 2-The memory is cacheable and supports
+ write combining
+ 3-The memory is cacheable and prefetchable
+ @param [in] IsReadWrite ReadAndWrite parameter.
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Not supported. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Not supported. Must be NULL.
+ @param [in] MemoryRangeType Possible values are:
+ 0-AddressRangeMemory
+ 1-AddressRangeReserved
+ 2-AddressRangeACPI
+ 3-AddressRangeNVS
+ @param [in] IsTypeStatic TranslationType parameter.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdQWordMemory (
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsPosDecode,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN UINT8 Cacheable,
+ IN BOOLEAN IsReadWrite,
+ IN UINT64 AddressGranularity,
+ IN UINT64 AddressMinimum,
+ IN UINT64 AddressMaximum,
+ IN UINT64 AddressTranslation,
+ IN UINT64 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN UINT8 MemoryRangeType,
+ IN BOOLEAN IsTypeStatic,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ );
+
/** Code generation for the "Interrupt ()" ASL function.

The Resource Data effectively created is an Extended Interrupt Resource
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
index e9e1a85ede63..24763c81805d 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
@@ -100,6 +100,949 @@ error_handler:
return Status;
}

+/** Construct the TypeSpecificFlags field for IO ranges.
+
+ See ACPI 6.4 spec, s19.6.34 for more.
+
+ @param [in] IsaRanges Possible values are:
+ 0-Reserved
+ 1-NonISAOnly
+ 2-ISAOnly
+ 3-EntireRange
+ See ACPI 6.4 spec, s19.6.34 for more.
+ @param [in] IsDenseTranslation TranslationDensity parameter.
+ @param [in] IsTypeStatic TranslationType parameter.
+
+ @return A type specific flags value.
+ MAX_UINT8 if error.
+**/
+STATIC
+UINT8
+EFIAPI
+RdIoRangeSpecificFlags (
+ IN UINT8 IsaRanges,
+ IN BOOLEAN IsDenseTranslation,
+ IN BOOLEAN IsTypeStatic
+ )
+{
+ // Only check type specific parameters.
+ if (IsaRanges > 3) {
+ ASSERT (0);
+ return MAX_UINT8;
+ }
+
+ // Construct TypeSpecificFlags and call the generic function.
+ // Cf ACPI 6.4 specification, Table 6.50:
+ // "Table 6.50: I/O Resource Flag (Resource Type = 1) Definitions"
+ return IsaRanges |
+ (IsTypeStatic ? 0 : BIT4) |
+ (IsDenseTranslation ? 0 : BIT5);
+}
+
+/** Construct the TypeSpecificFlags field for Memory ranges.
+
+ @param [in] Cacheable Possible values are:
+ 0-The memory is non-cacheable
+ 1-The memory is cacheable
+ 2-The memory is cacheable and supports
+ write combining
+ 3-The memory is cacheable and prefetchable
+ @param [in] IsReadWrite ReadAndWrite parameter.
+ @param [in] MemoryRangeType Possible values are:
+ 0-AddressRangeMemory
+ 1-AddressRangeReserved
+ 2-AddressRangeACPI
+ 3-AddressRangeNVS
+ See ACPI 6.4 spec, s19.6.35 for more.
+ @param [in] IsTypeStatic TranslationType parameter.
+
+ @return A type specific flags value.
+ MAX_UINT8 if error.
+**/
+STATIC
+UINT8
+EFIAPI
+MemoryRangeSpecificFlags (
+ IN UINT8 Cacheable,
+ IN BOOLEAN IsReadWrite,
+ IN UINT8 MemoryRangeType,
+ IN BOOLEAN IsTypeStatic
+ )
+{
+ // Only check type specific parameters.
+ if ((Cacheable > 3) ||
+ (MemoryRangeType > 3)) {
+ ASSERT (0);
+ return MAX_UINT8;
+ }
+
+ // Construct TypeSpecificFlags and call the generic function.
+ // Cf ACPI 6.4 specification, Table 6.49:
+ // "Memory Resource Flag (Resource Type = 0) Definitions"
+ return (IsReadWrite ? BIT0 : 0) |
+ (Cacheable << 1) |
+ (MemoryRangeType << 3) |
+ (IsTypeStatic ? 0 : BIT5);
+}
+
+/** Construct the GeneralFlags field of any Address Space Resource Descriptors.
+
+ E.g.:
+ ACPI 6.4 specification, s6.4.3.5.1 "QWord Address Space Descriptor"
+ for QWord
+
+ See ACPI 6.4 spec, s19.6.36 for more.
+
+ @param [in] IsPosDecode Decode parameter
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+
+ @return A type specific flags value.
+**/
+STATIC
+UINT8
+EFIAPI
+AddressSpaceGeneralFlags (
+ IN BOOLEAN IsPosDecode,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed
+ )
+{
+ return (IsPosDecode ? 0 : BIT1) |
+ (IsMinFixed ? BIT2 : 0) |
+ (IsMaxFixed ? BIT3 : 0);
+}
+
+/** Check Address Space Descriptor Fields.
+
+ Cf. ACPI 6.4 Table 6.44:
+ "Valid Combination of Address Space Descriptor Fields"
+
+ See ACPI 6.4 spec, s19.6.36 for more.
+
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CheckAddressSpaceFields (
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN UINT64 AddressGranularity,
+ IN UINT64 AddressMinimum,
+ IN UINT64 AddressMaximum,
+ IN UINT64 AddressTranslation,
+ IN UINT64 RangeLength
+ )
+{
+ if ((AddressMinimum > AddressMaximum) ||
+ (RangeLength > (AddressMaximum - AddressMinimum + 1)) ||
+ ((AddressGranularity != 0) &&
+ ((AddressGranularity + 1) & AddressGranularity) != 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (RangeLength != 0) {
+ if (IsMinFixed ^ IsMaxFixed) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ } else if (IsMinFixed &&
+ IsMaxFixed &&
+ (AddressGranularity != 0) &&
+ ((AddressMaximum - AddressMinimum + 1) != RangeLength)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ if (IsMinFixed && IsMaxFixed) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ } else if (IsMinFixed &&
+ ((AddressMinimum & AddressGranularity) != 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ } else if (IsMaxFixed &&
+ (((AddressMaximum + 1) & AddressGranularity) != 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Code generation for the "DWordSpace ()" ASL function.
+
+ The Resource Data effectively created is a DWord Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.2 "DWord Address Space Descriptor".
+ - s19.6.36 "DWordSpace".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.36 for more.
+
+ @param [in] ResourceType Resource type.
+ Possible values are:
+ 0: Memory range
+ 1: I/O range
+ 2: Bus number range
+ 3-191: Reserved
+ 192-255: Hardware Vendor Defined
+ See ACPI 6.4 spec, s6.4.3.5.2 for more.
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsPosDecode Decode parameter
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] TypeSpecificFlags Type specific flags.
+ See ACPI 6.4 spec, s6.4.3.5.5
+ "Resource Type Specific Flags".
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Unused. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Unused. Must be NULL.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordSpace (
+ IN UINT8 ResourceType,
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsPosDecode,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN UINT8 TypeSpecificFlags,
+ IN UINT32 AddressGranularity,
+ IN UINT32 AddressMinimum,
+ IN UINT32 AddressMaximum,
+ IN UINT32 AddressTranslation,
+ IN UINT32 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_DATA_NODE * RdNode;
+ EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR RdDWord;
+
+ // ResourceSource and ResourceSourceIndex are unused.
+ if ((TypeSpecificFlags == MAX_UINT8) ||
+ (ResourceSourceIndex != 0) ||
+ (ResourceSource != NULL) ||
+ ((NameOpNode == NULL) && (NewRdNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = CheckAddressSpaceFields (
+ IsMinFixed,
+ IsMaxFixed,
+ AddressGranularity,
+ AddressMinimum,
+ AddressMaximum,
+ AddressTranslation,
+ RangeLength
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Header
+ RdDWord.Header.Header.Bits.Name =
+ ACPI_LARGE_DWORD_ADDRESS_SPACE_DESCRIPTOR_NAME;
+ RdDWord.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
+ RdDWord.Header.Length = sizeof (EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR) -
+ sizeof (ACPI_LARGE_RESOURCE_HEADER);
+
+ // Body
+ RdDWord.ResType = ResourceType;
+ RdDWord.GenFlag = AddressSpaceGeneralFlags (
+ IsPosDecode,
+ IsMinFixed,
+ IsMaxFixed
+ );
+ RdDWord.SpecificFlag = TypeSpecificFlags;
+ RdDWord.AddrSpaceGranularity = AddressGranularity;
+ RdDWord.AddrRangeMin = AddressMinimum;
+ RdDWord.AddrRangeMax = AddressMaximum;
+ RdDWord.AddrTranslationOffset = AddressTranslation;
+ RdDWord.AddrLen = RangeLength;
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeResourceData,
+ (UINT8*)&RdDWord,
+ sizeof (EFI_ACPI_DWORD_ADDRESS_SPACE_DESCRIPTOR),
+ &RdNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ return LinkRdNode (RdNode, NameOpNode, NewRdNode);
+}
+
+/** Code generation for the "DWordIO ()" ASL function.
+
+ The Resource Data effectively created is a DWord Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.2 "DWord Address Space Descriptor".
+ - s19.6.34 "DWordIO".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.34 for more.
+
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] IsPosDecode Decode parameter
+ @param [in] IsaRanges Possible values are:
+ 0-Reserved
+ 1-NonISAOnly
+ 2-ISAOnly
+ 3-EntireRange
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Unused. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Unused. Must be NULL.
+ @param [in] IsDenseTranslation TranslationDensity parameter.
+ @param [in] IsTypeStatic TranslationType parameter.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordIo (
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN BOOLEAN IsPosDecode,
+ IN UINT8 IsaRanges,
+ IN UINT32 AddressGranularity,
+ IN UINT32 AddressMinimum,
+ IN UINT32 AddressMaximum,
+ IN UINT32 AddressTranslation,
+ IN UINT32 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN BOOLEAN IsDenseTranslation,
+ IN BOOLEAN IsTypeStatic,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ )
+{
+ return AmlCodeGenRdDWordSpace (
+ ACPI_ADDRESS_SPACE_TYPE_IO,
+ IsResourceConsumer,
+ IsPosDecode,
+ IsMinFixed,
+ IsMaxFixed,
+ RdIoRangeSpecificFlags (
+ IsaRanges,
+ IsDenseTranslation,
+ IsTypeStatic
+ ),
+ AddressGranularity,
+ AddressMinimum,
+ AddressMaximum,
+ AddressTranslation,
+ RangeLength,
+ ResourceSourceIndex,
+ ResourceSource,
+ NameOpNode,
+ NewRdNode
+ );
+}
+
+/** Code generation for the "DWordMemory ()" ASL function.
+
+ The Resource Data effectively created is a DWord Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.2 "DWord Address Space Descriptor".
+ - s19.6.35 "DWordMemory".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.35 for more.
+
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsPosDecode Decode parameter
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] Cacheable Possible values are:
+ 0-The memory is non-cacheable
+ 1-The memory is cacheable
+ 2-The memory is cacheable and supports
+ write combining
+ 3-The memory is cacheable and prefetchable
+ @param [in] IsReadWrite ReadAndWrite parameter.
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Unused. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Unused. Must be NULL.
+ @param [in] MemoryRangeType Possible values are:
+ 0-AddressRangeMemory
+ 1-AddressRangeReserved
+ 2-AddressRangeACPI
+ 3-AddressRangeNVS
+ @param [in] IsTypeStatic TranslationType parameter.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdDWordMemory (
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsPosDecode,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN UINT8 Cacheable,
+ IN BOOLEAN IsReadWrite,
+ IN UINT32 AddressGranularity,
+ IN UINT32 AddressMinimum,
+ IN UINT32 AddressMaximum,
+ IN UINT32 AddressTranslation,
+ IN UINT32 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN UINT8 MemoryRangeType,
+ IN BOOLEAN IsTypeStatic,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ )
+{
+ return AmlCodeGenRdDWordSpace (
+ ACPI_ADDRESS_SPACE_TYPE_MEM,
+ IsResourceConsumer,
+ IsPosDecode,
+ IsMinFixed,
+ IsMaxFixed,
+ MemoryRangeSpecificFlags (
+ Cacheable,
+ IsReadWrite,
+ MemoryRangeType,
+ IsTypeStatic
+ ),
+ AddressGranularity,
+ AddressMinimum,
+ AddressMaximum,
+ AddressTranslation,
+ RangeLength,
+ ResourceSourceIndex,
+ ResourceSource,
+ NameOpNode,
+ NewRdNode
+ );
+}
+
+/** Code generation for the "WordSpace ()" ASL function.
+
+ The Resource Data effectively created is a Word Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.3 "Word Address Space Descriptor".
+ - s19.6.151 "WordSpace".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.151 for more.
+
+ @param [in] ResourceType Resource type.
+ Possible values are:
+ 0: Memory range
+ 1: I/O range
+ 2: Bus number range
+ 3-191: Reserved
+ 192-255: Hardware Vendor Defined
+ See ACPI 6.4 spec, s6.4.3.5.3 for more.
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsPosDecode Decode parameter
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] TypeSpecificFlags Type specific flags.
+ See ACPI 6.4 spec, s6.4.3.5.5
+ "Resource Type Specific Flags".
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Unused. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Unused. Must be NULL.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdWordSpace (
+ IN UINT8 ResourceType,
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsPosDecode,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN UINT8 TypeSpecificFlags,
+ IN UINT16 AddressGranularity,
+ IN UINT16 AddressMinimum,
+ IN UINT16 AddressMaximum,
+ IN UINT16 AddressTranslation,
+ IN UINT16 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_DATA_NODE * RdNode;
+ EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR Rdword;
+
+ // ResourceSource and ResourceSourceIndex are unused.
+ if ((TypeSpecificFlags == MAX_UINT8) ||
+ (ResourceSourceIndex != 0) ||
+ (ResourceSource != NULL) ||
+ ((NameOpNode == NULL) && (NewRdNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = CheckAddressSpaceFields (
+ IsMinFixed,
+ IsMaxFixed,
+ AddressGranularity,
+ AddressMinimum,
+ AddressMaximum,
+ AddressTranslation,
+ RangeLength
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Header
+ Rdword.Header.Header.Bits.Name =
+ ACPI_LARGE_WORD_ADDRESS_SPACE_DESCRIPTOR_NAME;
+ Rdword.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
+ Rdword.Header.Length = sizeof (EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR) -
+ sizeof (ACPI_LARGE_RESOURCE_HEADER);
+
+ // Body
+ Rdword.ResType = ResourceType;
+ Rdword.GenFlag = AddressSpaceGeneralFlags (
+ IsPosDecode,
+ IsMinFixed,
+ IsMaxFixed
+ );
+ Rdword.SpecificFlag = TypeSpecificFlags;
+ Rdword.AddrSpaceGranularity = AddressGranularity;
+ Rdword.AddrRangeMin = AddressMinimum;
+ Rdword.AddrRangeMax = AddressMaximum;
+ Rdword.AddrTranslationOffset = AddressTranslation;
+ Rdword.AddrLen = RangeLength;
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeResourceData,
+ (UINT8*)&Rdword,
+ sizeof (EFI_ACPI_WORD_ADDRESS_SPACE_DESCRIPTOR),
+ &RdNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ return LinkRdNode (RdNode, NameOpNode, NewRdNode);
+}
+
+/** Code generation for the "WordBusNumber ()" ASL function.
+
+ The Resource Data effectively created is a Word Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.3 "Word Address Space Descriptor".
+ - s19.6.149 "WordBusNumber".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.149 for more.
+
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] IsPosDecode Decode parameter
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Unused. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Unused. Must be NULL.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdWordBusNumber (
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN BOOLEAN IsPosDecode,
+ IN UINT32 AddressGranularity,
+ IN UINT32 AddressMinimum,
+ IN UINT32 AddressMaximum,
+ IN UINT32 AddressTranslation,
+ IN UINT32 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ )
+{
+ // There is no Type Specific Flags for buses.
+ return AmlCodeGenRdWordSpace (
+ ACPI_ADDRESS_SPACE_TYPE_BUS,
+ IsResourceConsumer,
+ IsPosDecode,
+ IsMinFixed,
+ IsMaxFixed,
+ 0,
+ AddressGranularity,
+ AddressMinimum,
+ AddressMaximum,
+ AddressTranslation,
+ RangeLength,
+ ResourceSourceIndex,
+ ResourceSource,
+ NameOpNode,
+ NewRdNode
+ );
+}
+
+/** Code generation for the "QWordSpace ()" ASL function.
+
+ The Resource Data effectively created is a QWord Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.1 "QWord Address Space Descriptor".
+ - s19.6.111 "QWordSpace".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.111 for more.
+
+ @param [in] ResourceType Resource type.
+ Possible values are:
+ 0: Memory range
+ 1: I/O range
+ 2: Bus number range
+ 3-191: Reserved
+ 192-255: Hardware Vendor Defined
+ See ACPI 6.4 spec, s6.4.3.5.1 for more.
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsPosDecode Decode parameter
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] TypeSpecificFlags Type specific flags.
+ See ACPI 6.4 spec, s6.4.3.5.5
+ "Resource Type Specific Flags".
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Unused. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Unused. Must be NULL.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdQWordSpace (
+ IN UINT8 ResourceType,
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsPosDecode,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN UINT8 TypeSpecificFlags,
+ IN UINT64 AddressGranularity,
+ IN UINT64 AddressMinimum,
+ IN UINT64 AddressMaximum,
+ IN UINT64 AddressTranslation,
+ IN UINT64 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_DATA_NODE * RdNode;
+ EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR RdQword;
+
+ // ResourceSource and ResourceSourceIndex are unused.
+ if ((TypeSpecificFlags == MAX_UINT8) ||
+ (ResourceSourceIndex != 0) ||
+ (ResourceSource != NULL) ||
+ ((NameOpNode == NULL) && (NewRdNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = CheckAddressSpaceFields (
+ IsMinFixed,
+ IsMaxFixed,
+ AddressGranularity,
+ AddressMinimum,
+ AddressMaximum,
+ AddressTranslation,
+ RangeLength
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Header
+ RdQword.Header.Header.Bits.Name =
+ ACPI_LARGE_QWORD_ADDRESS_SPACE_DESCRIPTOR_NAME;
+ RdQword.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
+ RdQword.Header.Length = sizeof (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) -
+ sizeof (ACPI_LARGE_RESOURCE_HEADER);
+
+ // Body
+ RdQword.ResType = ResourceType;
+ RdQword.GenFlag = AddressSpaceGeneralFlags (
+ IsPosDecode,
+ IsMinFixed,
+ IsMaxFixed
+ );
+ RdQword.SpecificFlag = TypeSpecificFlags;
+ RdQword.AddrSpaceGranularity = AddressGranularity;
+ RdQword.AddrRangeMin = AddressMinimum;
+ RdQword.AddrRangeMax = AddressMaximum;
+ RdQword.AddrTranslationOffset = AddressTranslation;
+ RdQword.AddrLen = RangeLength;
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeResourceData,
+ (UINT8*)&RdQword,
+ sizeof (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR),
+ &RdNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ return LinkRdNode (RdNode, NameOpNode, NewRdNode);
+}
+
+/** Code generation for the "QWordMemory ()" ASL function.
+
+ The Resource Data effectively created is a QWord Address Space Resource
+ Data. Cf ACPI 6.4:
+ - s6.4.3.5.1 "QWord Address Space Descriptor".
+ - s19.6.110 "QWordMemory".
+
+ The created resource data node can be:
+ - appended to the list of resource data elements of the NameOpNode.
+ In such case NameOpNode must be defined by a the "Name ()" ASL statement
+ and initially contain a "ResourceTemplate ()".
+ - returned through the NewRdNode parameter.
+
+ See ACPI 6.4 spec, s19.6.110 for more.
+
+ @param [in] IsResourceConsumer ResourceUsage parameter.
+ @param [in] IsPosDecode Decode parameter.
+ @param [in] IsMinFixed Minimum address is fixed.
+ @param [in] IsMaxFixed Maximum address is fixed.
+ @param [in] Cacheable Possible values are:
+ 0-The memory is non-cacheable
+ 1-The memory is cacheable
+ 2-The memory is cacheable and supports
+ write combining
+ 3-The memory is cacheable and prefetchable
+ @param [in] IsReadWrite ReadAndWrite parameter.
+ @param [in] AddressGranularity Address granularity.
+ @param [in] AddressMinimum Minimum address.
+ @param [in] AddressMaximum Maximum address.
+ @param [in] AddressTranslation Address translation.
+ @param [in] RangeLength Range length.
+ @param [in] ResourceSourceIndex Resource Source index.
+ Unused. Must be 0.
+ @param [in] ResourceSource Resource Source.
+ Unused. Must be NULL.
+ @param [in] MemoryRangeType Possible values are:
+ 0-AddressRangeMemory
+ 1-AddressRangeReserved
+ 2-AddressRangeACPI
+ 3-AddressRangeNVS
+ @param [in] IsTypeStatic TranslationType parameter.
+ @param [in] NameOpNode NameOp object node defining a named object.
+ If provided, append the new resource data
+ node to the list of resource data elements
+ of this node.
+ @param [out] NewRdNode If provided and success,
+ contain the created node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenRdQWordMemory (
+ IN BOOLEAN IsResourceConsumer,
+ IN BOOLEAN IsPosDecode,
+ IN BOOLEAN IsMinFixed,
+ IN BOOLEAN IsMaxFixed,
+ IN UINT8 Cacheable,
+ IN BOOLEAN IsReadWrite,
+ IN UINT64 AddressGranularity,
+ IN UINT64 AddressMinimum,
+ IN UINT64 AddressMaximum,
+ IN UINT64 AddressTranslation,
+ IN UINT64 RangeLength,
+ IN UINT8 ResourceSourceIndex,
+ IN CONST CHAR8 *ResourceSource,
+ IN UINT8 MemoryRangeType,
+ IN BOOLEAN IsTypeStatic,
+ IN AML_OBJECT_NODE_HANDLE NameOpNode, OPTIONAL
+ OUT AML_DATA_NODE_HANDLE *NewRdNode OPTIONAL
+ )
+{
+ return AmlCodeGenRdQWordSpace (
+ ACPI_ADDRESS_SPACE_TYPE_MEM,
+ IsResourceConsumer,
+ IsPosDecode,
+ IsMinFixed,
+ IsMaxFixed,
+ MemoryRangeSpecificFlags (
+ Cacheable,
+ IsReadWrite,
+ MemoryRangeType,
+ IsTypeStatic
+ ),
+ AddressGranularity,
+ AddressMinimum,
+ AddressMaximum,
+ AddressTranslation,
+ RangeLength,
+ ResourceSourceIndex,
+ ResourceSource,
+ NameOpNode,
+ NewRdNode
+ );
+}
+
/** Code generation for the "Interrupt ()" ASL function.

The Resource Data effectively created is an Extended Interrupt Resource
--
2.17.1


[PATCH v3 0/8] Create a SSDT PCIe generator

PierreGondois
 

From: Pierre Gondois <Pierre.Gondois@...>

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3682

As part of the DynamicTablesPkg, add a generator creating a
SSDT table describing a PCIe bus.
This patch-set also adds new functions to generate AML bytecode
in the AmlLib.

The changes can be seen at: https://github.com/PierreARM/edk2/tree/1781_Create_ssdt_pcie_generator_v3

v3:
- Use ASSERT_EFI_ERROR when possible. [Sami]
- Fix typos and add comments. [Pierre]
- Add new patch "DynamicTablesPkg: Fix multiple objects parsing".
[Pierre]
v2:
The following patches were modified:
- DynamicTablesPkg: AML Code generation for memory ranges
- DynamicTablesPkg: SSDT Pci express generator

Pierre Gondois (8):
DynamicTablesPkg: AML Code generation for memory ranges
DynamicTablesPkg: AML Code generation to create a named Package()
DynamicTablesPkg: AML Code generation to create a named
ResourceTemplate()
DynamicTablesPkg: AML Code generation to add _PRT entries
DynamicTablesPkg: Add AmlAttachNode()
DynamicTablesPkg: Add Pci related objects
DynamicTablesPkg: SSDT Pci express generator
DynamicTablesPkg: Fix multiple objects parsing

DynamicTablesPkg/DynamicTables.dsc.inc | 2 +
DynamicTablesPkg/Include/AcpiTableGenerator.h | 5 +
.../Include/ArmNameSpaceObjects.h | 78 +
.../Include/Library/AmlLib/AmlLib.h | 413 +++++
.../AcpiSsdtPcieLibArm/SsdtPcieGenerator.c | 1450 +++++++++++++++++
.../AcpiSsdtPcieLibArm/SsdtPcieGenerator.h | 138 ++
.../Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf | 32 +
.../SsdtPcieOscTemplate.asl | 80 +
.../Library/Common/AmlLib/Api/AmlApi.c | 36 +
.../Common/AmlLib/CodeGen/AmlCodeGen.c | 320 ++++
.../AmlLib/CodeGen/AmlResourceDataCodeGen.c | 943 +++++++++++
.../ConfigurationManagerObjectParser.c | 41 +-
12 files changed, 3535 insertions(+), 3 deletions(-)
create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.c
create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieGenerator.h
create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieLibArm.inf
create mode 100644 DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtPcieLibArm/SsdtPcieOscTemplate.asl

--
2.17.1


[PATCH v3] IntelSiliconPkg/BaseConfigBlockLib: Add function to iterate over Config Blocks

Fedorowicz, Jakub <jakub.fedorowicz@...>
 

In BaseConfigBlockLib add function to get next config block from config blocks table in order to iterate over blocks of the same type.

 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3700

 

Signed-off-by: Jakub Fedorowicz mailto:jakub.fedorowicz@...

 

Cc: Ray Ni mailto:ray.ni@...

Cc: Rangasai V Chaganty mailto:rangasai.v.chaganty@...

---

.../Include/Library/ConfigBlockLib.h          | 20 ++++++++

.../BaseConfigBlockLib/BaseConfigBlockLib.c   | 50 +++++++++++++++++++

2 files changed, 70 insertions(+)

 

diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Library/ConfigBlockLib.h b/Silicon/Intel/IntelSiliconPkg/Include/Library/ConfigBlockLib.h

index 37a39681..77eff21b 100644

--- a/Silicon/Intel/IntelSiliconPkg/Include/Library/ConfigBlockLib.h

+++ b/Silicon/Intel/IntelSiliconPkg/Include/Library/ConfigBlockLib.h

@@ -45,6 +45,7 @@ AddConfigBlock (

 /**

   Retrieve a specific Config Block data by GUID.

+  If there is more than one Config Block with given GUID, return the first found with given GUID.

   @param[in]      ConfigBlockTableAddress      - A pointer to the beginning of Config Block Table Address

   @param[in]      ConfigBlockGuid              - A pointer to the GUID uses to search specific Config Block

@@ -61,4 +62,23 @@ GetConfigBlock (

   OUT    VOID      **ConfigBlockAddress

   );

+/**

+  Search through ConfigBlockTable blocks to find following Config Block of the same GUID.

+  If there is no following Config Block found until the end of the table, return EFI_NOT_FOUND.

+

+  @param[in]      ConfigBlockTableAddress   - A pointer to the beginning of Config Block Table

+  @param[in]      ConfigBlockAddress        - A pointer to the Config Block, against which the search begins

+  @param[out]     NextConfigBlockAddress    - On return, points to a pointer to the found Config Block

+

+  @retval EFI_NOT_FOUND         - Could not find the following Config Block

+  @retval EFI_SUCCESS           - Config Block found and return

+**/

+EFI_STATUS

+EFIAPI

+GetNextConfigBlock (

+  IN     VOID      *ConfigBlockTableAddress,

+  IN     VOID      *ConfigBlockAddress,

+  OUT    VOID      **NextConfigBlockAddress

+  );

+

#endif // _CONFIG_BLOCK_LIB_H_

diff --git a/Silicon/Intel/IntelSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c b/Silicon/Intel/IntelSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c

index c89699ea..f026ac0b 100644

--- a/Silicon/Intel/IntelSiliconPkg/Library/BaseConfigBlockLib/BaseConfigBlockLib.c

+++ b/Silicon/Intel/IntelSiliconPkg/Library/BaseConfigBlockLib/BaseConfi

+++ gBlockLib.c

@@ -95,6 +95,7 @@ AddConfigBlock (

 /**

   Retrieve a specific Config Block data by GUID.

+  If there is more than one Config Block with given GUID, return the first found with given GUID.

   @param[in]      ConfigBlockTableAddress      - A pointer to the beginning of Config Block Table Address

   @param[in]      ConfigBlockGuid              - A pointer to the GUID uses to search specific Config Block

@@ -137,3 +138,52 @@ GetConfigBlock (

   return EFI_NOT_FOUND;

}

+

+/**

+  Search through ConfigBlockTable blocks to find following Config Block of the same GUID.

+  If there is no following Config Block found until the end of the table, return EFI_NOT_FOUND.

+

+  @param[in]      ConfigBlockTableAddress   - A pointer to the beginning of Config Block Table

+  @param[in]      ConfigBlockAddress        - A pointer to the Config Block, against which the search begins

+  @param[out]     NextConfigBlockAddress    - On return, points to a pointer to the found Config Block

+

+  @retval EFI_NOT_FOUND         - Could not find the following Config Block

+  @retval EFI_SUCCESS           - Config Block found and return

+**/

+EFI_STATUS

+EFIAPI

+GetNextConfigBlock (

+  IN     VOID      *ConfigBlockTableAddress,

+  IN     VOID      *ConfigBlockAddress,

+  OUT    VOID      **NextConfigBlockAddress

+  )

+{

+  CONFIG_BLOCK_TABLE_HEADER    *ConfigBlkTblHdrPtr;

+  UINTN                         ConfigBlkTblEndAddr;

+  UINTN                         ConfigBlkOffset;

+  CONFIG_BLOCK                 *TempConfigBlk;

+  EFI_GUID                     *TargetGuid;

+

+  ConfigBlkTblHdrPtr = (CONFIG_BLOCK_TABLE_HEADER *)

+ ConfigBlockTableAddress;  ConfigBlkTblEndAddr = (UINTN)

+ ConfigBlockTableAddress + (UINTN)

+ ConfigBlkTblHdrPtr->Header.GuidHob.Header.HobLength;

+

+  TempConfigBlk = (CONFIG_BLOCK *) ConfigBlockAddress;  TargetGuid =

+ &(TempConfigBlk->Header.GuidHob.Name);

+  ConfigBlkOffset = (UINTN) ConfigBlockAddress + (UINTN)

+ TempConfigBlk->Header.GuidHob.Header.HobLength;

+

+  //

+  // Loop until exceeding ConfigBlockTable range  //  while

+ (ConfigBlkOffset < ConfigBlkTblEndAddr) {

+    TempConfigBlk = (CONFIG_BLOCK *) ConfigBlkOffset;

+

+    if (CompareGuid (TargetGuid, &(TempConfigBlk->Header.GuidHob.Name))) {

+      *NextConfigBlockAddress = (VOID *) TempConfigBlk;

+      return EFI_SUCCESS;

+    }

+

+    ConfigBlkOffset += (UINTN)

+ TempConfigBlk->Header.GuidHob.Header.HobLength;

+  }

+

+  return EFI_NOT_FOUND;

+}

--

2.30.0.windows.2


Intel Technology Poland sp. z o.o.
ul. Słowackiego 173 | 80-298 Gdańsk | Sąd Rejonowy Gdańsk Północ | VII Wydział Gospodarczy Krajowego Rejestru Sądowego - KRS 101882 | NIP 957-07-52-316 | Kapitał zakładowy 200.000 PLN.

Ta wiadomość wraz z załącznikami jest przeznaczona dla określonego adresata i może zawierać informacje poufne. W razie przypadkowego otrzymania tej wiadomości, prosimy o powiadomienie nadawcy oraz trwałe jej usunięcie; jakiekolwiek przeglądanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.


Re: [edk2-platforms][PATCH v6 11/30] AmpereAltraPkg: Add Ac01PcieLib library instance

Leif Lindholm
 

On Thu, Nov 18, 2021 at 20:41:15 +0700, Nhi Pham via groups.io wrote:
From: Vu Nguyen <vunguyen@...>

Provides essential functions to initialize the PCIe Root Complex on
Ampere Altra processor.

Cc: Thang Nguyen <thang@...>
Cc: Chuong Tran <chuong@...>
Cc: Phong Vo <phong@...>
Cc: Leif Lindholm <leif@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Ard Biesheuvel <ardb+tianocore@...>
Cc: Nate DeSimone <nathaniel.l.desimone@...>

Signed-off-by: Nhi Pham <nhi@...>
Reviewed-by: Leif Lindholm <leif@...>

---
Changes since v5:
* Fixed an error with the NOOPT build.
https://edk2.groups.io/g/devel/message/83855

Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 6 +
Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 2 +
Platform/Ampere/JadePkg/Jade.dsc | 5 +
Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf | 42 +
Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf | 25 +
Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h | 49 +
Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h | 45 +
Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h | 372 +++++
Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c | 1416 ++++++++++++++++++++
Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c | 47 +
10 files changed, 2009 insertions(+)

diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
index e19925c68a0e..7bd4d3ac9462 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
@@ -43,6 +43,12 @@ [LibraryClasses]
## @libraryclass Defines a set of methods to access flash memory.
FlashLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h

+ ## @libraryclass Defines a set of platform dependent functions
+ BoardPcieLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h
+
+ ## @libraryclass Defines a set of methods to initialize Pcie
+ Ac01PcieLib|Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h
+
[Guids]
## NVParam MM GUID
gNVParamMmGuid = { 0xE4AC5024, 0x29BE, 0x4ADC, { 0x93, 0x36, 0x87, 0xB5, 0xA0, 0x76, 0x23, 0x2D } }
diff --git a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
index fa9b120b2c2b..5b767ecb024f 100644
--- a/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
+++ b/Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
@@ -81,6 +81,8 @@ [LibraryClasses.common]
NVParamLib|Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLib.inf
MailboxInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/MailboxInterfaceLib/MailboxInterfaceLib.inf
SystemFirmwareInterfaceLib|Silicon/Ampere/AmpereAltraPkg/Library/SystemFirmwareInterfaceLib/SystemFirmwareInterfaceLib.inf
+ PciePhyLib|Silicon/Ampere/AmpereAltraBinPkg/Library/PciePhyLib/PciePhyLib.inf
+ Ac01PcieLib|Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf
AmpereCpuLib|Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.inf
TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
I2cLib|Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.inf
diff --git a/Platform/Ampere/JadePkg/Jade.dsc b/Platform/Ampere/JadePkg/Jade.dsc
index e4b29e36fc8d..23a297d0dbeb 100644
--- a/Platform/Ampere/JadePkg/Jade.dsc
+++ b/Platform/Ampere/JadePkg/Jade.dsc
@@ -82,6 +82,11 @@ [LibraryClasses]
#
AcpiLib|EmbeddedPkg/Library/AcpiLib/AcpiLib.inf

+ #
+ # Pcie Board
+ #
+ BoardPcieLib|Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf
+
################################################################################
#
# Specific Platform Pcds
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf
new file mode 100644
index 000000000000..8c8661265cd5
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf
@@ -0,0 +1,42 @@
+## @file
+#
+# Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = Ac01PcieLib
+ FILE_GUID = 8ABFA0FC-313E-11E8-B467-0ED5F89F718B
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = Ac01PcieLib
+
+[Sources]
+ PcieCore.c
+ PcieCore.h
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraBinPkg/AmpereAltraBinPkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+
+[LibraryClasses]
+ ArmGenericTimerCounterLib
+ BaseLib
+ BoardPcieLib
+ DebugLib
+ HobLib
+ IoLib
+ PciePhyLib
+ SystemFirmwareInterfaceLib
+ TimerLib
+
+[Guids]
+ gPlatformInfoHobGuid
+
+[Depex]
+ TRUE
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf
new file mode 100644
index 000000000000..435092b864ec
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf
@@ -0,0 +1,25 @@
+## @file
+#
+# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = BoardPcieLibNull
+ FILE_GUID = 7820C925-F525-4101-8E64-87838356B7A6
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BoardPcieLib
+
+[Sources.common]
+ BoardPcieLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
+
+[LibraryClasses]
+ BaseLib
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h
new file mode 100644
index 000000000000..692bc2669915
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h
@@ -0,0 +1,49 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AC01_PCIE_LIB_H_
+#define AC01_PCIE_LIB_H_
+
+/**
+ Setup and initialize the AC01 PCIe Root Complex and underneath PCIe controllers
+
+ @param RootComplex Pointer to Root Complex structure
+ @param ReInit Re-init status
+ @param ReInitPcieIndex PCIe controller index
+
+ @retval RETURN_SUCCESS The Root Complex has been initialized successfully.
+ @retval RETURN_DEVICE_ERROR PHY, Memory or PIPE is not ready.
+**/
+RETURN_STATUS
+Ac01PcieCoreSetupRC (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN BOOLEAN ReInit,
+ IN UINT8 ReInitPcieIndex
+ );
+
+/**
+ Verify the link status and retry to initialize the Root Complex if there's any issue.
+
+ @param RootComplexList Pointer to the Root Complex list
+**/
+VOID
+Ac01PcieCorePostSetupRC (
+ IN AC01_ROOT_COMPLEX *RootComplexList
+ );
+
+/**
+ Callback function when the Host Bridge enumeration end.
+
+ @param RootComplex Pointer to the Root Complex structure
+**/
+VOID
+Ac01PcieCoreEndEnumeration (
+ IN AC01_ROOT_COMPLEX *RootComplex
+ );
+
+#endif /* AC01_PCIE_LIB_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h b/Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h
new file mode 100644
index 000000000000..34e7dee702ec
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h
@@ -0,0 +1,45 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BOARD_PCIE_LIB_H_
+#define BOARD_PCIE_LIB_H_
+
+#include <Guid/RootComplexInfoHob.h>
+
+/**
+ Assert PERST of the PCIe controller
+
+ @param[in] RootComplex Root Complex instance.
+ @param[in] PcieIndex PCIe controller index of input Root Complex.
+ @param[in] IsPullToHigh Target status for the PERST.
+
+ @retval RETURN_SUCCESS The operation is successful.
+ @retval Others An error occurred.
+**/
+RETURN_STATUS
+EFIAPI
+BoardPcieAssertPerst (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex,
+ IN BOOLEAN IsPullToHigh
+ );
+
+/**
+ Override the segment number for a root complex with a board specific number.
+
+ @param[in] RootComplex Root Complex instance with properties.
+
+ @retval Segment number corresponding to the input root complex.
+ Default segment number is 0x0F.
+**/
+UINT16
+BoardPcieGetSegmentNumber (
+ IN AC01_ROOT_COMPLEX *RootComplex
+ );
+
+#endif /* BOARD_PCIE_LIB_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h
new file mode 100644
index 000000000000..1db8a68b3df4
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h
@@ -0,0 +1,372 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef AC01_PCIE_CORE_H_
+#define AC01_PCIE_CORE_H_
+
+#define BUS_SHIFT 20
+#define DEV_SHIFT 15
+
+#define GET_LOW_8_BITS(x) ((x) & 0xFF)
+#define GET_HIGH_8_BITS(x) (((x) >> 8) & 0xFF)
+#define GET_LOW_16_BITS(x) ((x) & 0xFFFF)
+#define GET_HIGH_16_BITS(x) (((x) >> 16) & 0xFFFF)
+#define GET_CAPABILITY_PTR(x) (GET_LOW_16_BITS (x) >> 8)
+#define GET_EXT_CAPABILITY_PTR(x) (GET_HIGH_16_BITS (x) >> 4)
+
+#define WORD_ALIGN_MASK 0x3
+
+#define MAX_REINIT 3 // Number of soft reset retry
+
+#define SLOT_POWER_LIMIT_75W 75 // Watt
+
+#define LINK_CHECK_SUCCESS 0
+#define LINK_CHECK_FAILED -1
+#define LINK_CHECK_WRONG_PARAMETER 1
+
+#define AMPERE_PCIE_VENDOR_ID 0x1DEF
+#define AC01_HOST_BRIDGE_DEVICE_ID_RCA 0xE100
+#define AC01_HOST_BRIDGE_DEVICE_ID_RCB 0xE110
+#define AC01_PCIE_BRIDGE_DEVICE_ID_RCA 0xE101
+#define AC01_PCIE_BRIDGE_DEVICE_ID_RCB 0xE111
+
+#define MEMRDY_TIMEOUT 10 // 10 us
+#define PIPE_CLOCK_TIMEOUT 20000 // 20,000 us
+#define LTSSM_TRANSITION_TIMEOUT 100000 // 100 ms in total
+#define EP_LINKUP_TIMEOUT (10 * 1000) // 10ms
+#define LINK_WAIT_INTERVAL_US 50
+
+#define PFA_MODE_ENABLE 0
+#define PFA_MODE_CLEAR 1
+#define PFA_MODE_READ 2
+
+//
+// Host Bridge registers
+//
+#define AC01_HOST_BRIDGE_RCA_DEV_MAP_REG 0x0
+#define AC01_HOST_BRIDGE_RCB_DEV_MAP_REG 0x4
+#define AC01_HOST_BRIDGE_VENDOR_DEVICE_ID_REG 0x10
+
+// AC01_HOST_BRIDGE_RCA_DEV_MAP_REG
+#define RCA_DEV_MAP_SET(dst, src) (((dst) & ~0x7) | (((UINT32) (src)) & 0x7))
+#define RCA_DEV_MAP_GET(val) ((val) & 0x7)
+
+// AC01_HOST_BRIDGE_RCB_DEV_MAP_REG
+#define RCB_DEV_MAP_LOW_SET(dst, src) (((dst) & ~0x7) | (((UINT32) (src)) & 0x7))
+#define RCB_DEV_MAP_LOW_GET(val) ((val) & 0x7)
+
+#define RCB_DEV_MAP_HIGH_SET(dst, src) (((dst) & ~0x70) | (((UINT32) (src) << 4) & 0x70))
+#define RCB_DEV_MAP_HIGH_GET(val) (((val) & 0x7) >> 4)
+
+// AC01_HOST_BRIDGE_VENDOR_DEVICE_ID_REG
+#define VENDOR_ID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF))
+#define VENDOR_ID_GET(val) ((val) & 0xFFFF)
+
+#define DEVICE_ID_SET(dst, src) (((dst) & ~0xFFFF0000) | (((UINT32) (src) << 16) & 0xFFFF0000))
+#define DEVICE_ID_GET(val) (((val) & 0xFFFF0000) >> 16)
+
+//
+// PCIe core registers
+//
+#define AC01_PCIE_CORE_LINK_CTRL_REG 0x0
+#define AC01_PCIE_CORE_LINK_STAT_REG 0x4
+#define AC01_PCIE_CORE_IRQ_SEL_REG 0xC
+#define AC01_PCIE_CORE_HOT_PLUG_STAT_REG 0x28
+#define AC01_PCIE_CORE_IRQ_ENABLE_REG 0x30
+#define AC01_PCIE_CORE_IRQ_EVENT_STAT_REG 0x38
+#define AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG 0x3C
+#define AC01_PCIE_CORE_RESET_REG 0xC000
+#define AC01_PCIE_CORE_CLOCK_REG 0xC004
+#define AC01_PCIE_CORE_MEM_READY_REG 0xC104
+#define AC01_PCIE_CORE_RAM_SHUTDOWN_REG 0xC10C
+
+// AC01_PCIE_CORE_LINK_CTRL_REG
+#define LTSSMENB_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
+#define HOLD_LINK_TRAINING 0
+#define START_LINK_TRAINING 1
+#define DEVICETYPE_SET(dst, src) (((dst) & ~0xF0) | (((UINT32) (src) << 4) & 0xF0))
+#define DEVICETYPE_GET(val) (((val) & 0xF0) >> 4)
+
+// AC01_PCIE_CORE_LINK_STAT_REG
+#define PHY_STATUS_MASK (1 << 2)
+#define SMLH_LTSSM_STATE_MASK 0x3F00
+#define SMLH_LTSSM_STATE_GET(val) ((val & SMLH_LTSSM_STATE_MASK) >> 8)
+#define LTSSM_STATE_L0 0x11
+#define RDLH_SMLH_LINKUP_STATUS_GET(val) (val & 0x3)
+#define PHY_STATUS_MASK_BIT 0x04
+#define SMLH_LINK_UP_MASK_BIT 0x02
+#define RDLH_LINK_UP_MASK_BIT 0x01
+
+// AC01_PCIE_CORE_IRQ_SEL_REG
+#define AER_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
+#define PME_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) & 0x2))
+#define LINKAUTOBW_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) & 0x4))
+#define BWMGMT_SET(dst, src) (((dst) & ~0x8) | (((UINT32) (src) << 3) & 0x8))
+#define EQRQST_SET(dst, src) (((dst) & ~0x10) | (((UINT32) (src) << 4) & 0x10))
+#define INTPIN_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
+#define IRQ_INT_A 0x01
+
+// AC01_PCIE_CORE_HOT_PLUG_STAT_REG
+#define PWR_IND_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
+#define ATTEN_IND_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) & 0x2))
+#define PWR_CTRL_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) & 0x4))
+#define EML_CTRL_SET(dst, src) (((dst) & ~0x8) | (((UINT32) (src) << 3) & 0x8))
+
+// AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG
+#define LINKUP_MASK 0x1
+
+// AC01_PCIE_CORE_RESET_REG
+#define DWC_PCIE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
+#define RESET_MASK 0x1
+#define ASSERT_RESET 0x1
+
+// AC01_PCIE_CORE_CLOCK_REG
+#define AXIPIPE_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
+
+// AC01_PCIE_CORE_MEM_READY_REG
+#define MEMORY_READY 0x1
+
+// AC01_PCIE_CORE_RAM_SHUTDOWN_REG
+#define SD_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
+
+//
+// AC01 PCIe Type 1 configuration registers
+//
+#define TYPE1_DEV_ID_VEND_ID_REG 0
+#define TYPE1_CLASS_CODE_REV_ID_REG 0x8
+#define TYPE1_CAP_PTR_REG 0x34
+#define SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG 0x18
+#define BRIDGE_CTRL_INT_PIN_INT_LINE_REG 0x3C
+#define PCIE_CAPABILITY_BASE 0x70
+#define EXT_CAPABILITY_START_BASE 0x100
+#define AER_CAPABILITY_BASE 0x100
+
+// TYPE1_DEV_ID_VEND_ID_REG
+#define VENDOR_ID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF))
+#define DEVICE_ID_SET(dst, src) (((dst) & ~0xFFFF0000) | (((UINT32) (src) << 16) & 0xFFFF0000))
+
+// TYPE1_CLASS_CODE_REV_ID_REG
+#define BASE_CLASS_CODE_SET(dst, src) (((dst) & ~0xFF000000) | (((UINT32) (src) << 24) & 0xFF000000))
+#define DEFAULT_BASE_CLASS_CODE 6
+#define SUB_CLASS_CODE_SET(dst, src) (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000))
+#define DEFAULT_SUB_CLASS_CODE 4
+#define PROGRAM_INTERFACE_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
+#define REVISION_ID_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
+#define DEFAULT_REVISION_ID 4
+
+// SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG
+#define SUB_BUS_SET(dst, src) (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000))
+#define DEFAULT_SUB_BUS 0xFF
+#define SEC_BUS_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
+#define PRIM_BUS_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
+#define DEFAULT_PRIM_BUS 0x00
+
+// BRIDGE_CTRL_INT_PIN_INT_LINE_REG
+#define INT_PIN_SET(dst, src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
+
+//
+// PCI Express Capability
+//
+#define PCIE_CAPABILITY_ID 0x10
+#define LINK_CAPABILITIES_REG 0xC
+#define LINK_CONTROL_LINK_STATUS_REG 0x10
+#define SLOT_CAPABILITIES_REG 0x14
+#define DEVICE_CONTROL2_DEVICE_STATUS2_REG 0x28
+#define LINK_CAPABILITIES2_REG 0x2C
+#define LINK_CONTROL2_LINK_STATUS2_REG 0x30
+
+// LINK_CAPABILITIES_REG
+#define CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET(dst, src) (((dst) & ~0xC00) | (((UINT32)(src) << 10) & 0xC00))
+#define NO_ASPM_SUPPORTED 0x0
+#define L0S_SUPPORTED 0x1
+#define L1_SUPPORTED 0x2
+#define L0S_L1_SUPPORTED 0x3
+#define CAP_MAX_LINK_WIDTH_GET(val) ((val & 0x3F0) >> 4)
+#define CAP_MAX_LINK_WIDTH_SET(dst, src) (((dst) & ~0x3F0) | (((UINT32) (src) << 4) & 0x3F0))
+#define CAP_MAX_LINK_WIDTH_X1 0x1
+#define CAP_MAX_LINK_WIDTH_X2 0x2
+#define CAP_MAX_LINK_WIDTH_X4 0x4
+#define CAP_MAX_LINK_WIDTH_X8 0x8
+#define CAP_MAX_LINK_WIDTH_X16 0x10
+#define CAP_MAX_LINK_SPEED_GET(val) ((val & 0xF))
+#define CAP_MAX_LINK_SPEED_SET(dst, src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
+#define MAX_LINK_SPEED_25 0x1
+#define MAX_LINK_SPEED_50 0x2
+#define MAX_LINK_SPEED_80 0x3
+#define MAX_LINK_SPEED_160 0x4
+#define MAX_LINK_SPEED_320 0x5
+
+// LINK_CONTROL_LINK_STATUS_REG
+#define CAP_DLL_ACTIVE_GET(val) ((val & 0x20000000) >> 29)
+#define CAP_SLOT_CLK_CONFIG_SET(dst, src) (((dst) & ~0x10000000) | (((UINT32) (src) << 28) & 0x10000000))
+#define CAP_NEGO_LINK_WIDTH_GET(val) ((val & 0x3F00000) >> 20)
+#define CAP_LINK_SPEED_GET(val) ((val & 0xF0000) >> 16)
+#define CAP_LINK_SPEED_SET(dst, src) (((dst) & ~0xF0000) | (((UINT32) (src) << 16) & 0xF0000))
+#define CAP_LINK_SPEED_TO_VECTOR(val) (1 << ((val) - 1))
+#define CAP_EN_CLK_POWER_MAN_GET(val) ((val & 0x100) >> 8)
+#define CAP_EN_CLK_POWER_MAN_SET(dst, src) (((dst) & ~0x100) | (((UINT32) (src) << 8) & 0x100))
+#define CAP_COMMON_CLK_SET(dst, src) (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40))
+#define CAP_RETRAIN_LINK_SET(dst, src) (((dst) & ~0x20) | (((UINT32) (src) << 5) & 0x20))
+#define CAP_LINK_TRAINING_GET(val) ((val & 0x8000000) >> 27)
+#define CAP_LINK_DISABLE_SET(dst, src) (((dst) & ~0x10) | (((UINT32)(src) << 4) & 0x10))
+
+// SLOT_CAPABILITIES_REG
+#define SLOT_HPC_SET(dst, src) (((dst) & ~0x40) | (((UINT32) (src) << 6) & 0x40))
+#define SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET(dst, src) \
+ (((dst) & ~0x7F80) | (((UINT32)(src) << 7) & 0x7F80))
+
+// DEVICE_CONTROL2_DEVICE_STATUS2_REG
+#define CAP_CPL_TIMEOUT_VALUE_SET(dst, src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
+
+// LINK_CONTROL2_LINK_STATUS2_REG
+#define CAP_TARGET_LINK_SPEED_SET(dst, src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
+
+//
+// Advanced Error Reporting Capability
+//
+#define AER_CAPABILITY_ID 0x0001
+#define UNCORR_ERR_STATUS_OFF 0x04
+#define UNCORR_ERR_MASK_OFF 0x08
+
+// UNCORR_ERR_MASK_OFF
+#define CMPLT_TIMEOUT_ERR_MASK_SET(dst, src) (((dst) & ~0x4000) | (((UINT32) (src) << 14) & 0x4000))
+#define SDES_ERR_MASK_SET(dst, src) (((dst) & ~0x20) | (((UINT32)(src) << 5) & 0x20))
+
+//
+// Vendor specific RAS D.E.S Capability
+//
+#define RAS_DES_CAPABILITY_ID 0x000B
+#define EVENT_COUNTER_CONTROL_REG 0x08
+#define EVENT_COUNTER_DATA_REG 0x0C
+
+// EVENT_COUNTER_CONTROL_REG
+#define ECCR_GROUP_EVENT_SEL_SET(dst, src) (((dst) & ~0xFFF0000) | (((UINT32)(src) << 16) & 0xFFF0000))
+#define ECCR_GROUP_SEL_SET(dst, src) (((dst) & ~0xF000000) | (((UINT32)(src) << 24) & 0xF000000))
+#define ECCR_EVENT_SEL_SET(dst, src) (((dst) & ~0xFF0000) | (((UINT32)(src) << 16) & 0xFF0000))
+#define ECCR_LANE_SEL_SET(dst, src) (((dst) & ~0xF00) | (((UINT32)(src) << 8) & 0xF00))
+#define ECCR_EVENT_COUNTER_ENABLE_SET(dst, src) (((dst) & ~0x1C) | (((UINT32)(src) << 2) & 0x1C))
+#define EVENT_COUNTER_ENABLE_NO_CHANGE 0x00
+#define EVENT_COUNTER_ENABLE_ALL_ON 0x07
+#define ECCR_EVENT_COUNTER_CLEAR_SET(dst, src) (((dst) & ~0x3) | (((UINT32)(src)) & 0x3))
+#define EVENT_COUNTER_CLEAR_NO_CHANGE 0x00
+#define EVENT_COUNTER_CLEAR_ALL_CLEAR 0x03
+
+//
+// Secondary PCI Express Capability
+//
+#define SPCIE_CAPABILITY_ID 0x0019
+#define SPCIE_CAP_OFF_0C_REG 0x0C
+
+// SPCIE_CAP_OFF_0C_REG
+#define DSP_TX_PRESET0_SET(dst,src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
+#define DSP_TX_PRESET1_SET(dst,src) (((dst) & ~0xF0000) | (((UINT32) (src) << 16) & 0xF0000))
+#define DEFAULT_GEN3_PRESET 0x05
+
+//
+// Physical Layer 16.0 GT/s Extended Capability
+//
+#define PL16G_CAPABILITY_ID 0x0026
+#define PL16G_STATUS_REG 0x0C
+#define PL16G_CAP_OFF_20H_REG 0x20
+
+// PL16G_STATUS_REG
+#define PL16G_STATUS_EQ_CPL_GET(val) (val & 0x1)
+#define PL16G_STATUS_EQ_CPL_P1_GET(val) ((val & 0x2) >> 1)
+#define PL16G_STATUS_EQ_CPL_P2_GET(val) ((val & 0x4) >> 2)
+#define PL16G_STATUS_EQ_CPL_P3_GET(val) ((val & 0x8) >> 3)
+
+// PL16G_CAP_OFF_20H_REG
+#define DSP_16G_TX_PRESET0_SET(dst,src) (((dst) & ~0xF) | (((UINT32) (src)) & 0xF))
+#define DSP_16G_TX_PRESET1_SET(dst,src) (((dst) & ~0xF00) | (((UINT32) (src) << 8) & 0xF00))
+#define DSP_16G_TX_PRESET2_SET(dst,src) (((dst) & ~0xF0000) | (((UINT32) (src) << 16) & 0xF0000))
+#define DSP_16G_TX_PRESET3_SET(dst,src) (((dst) & ~0xF000000) | (((UINT32) (src) << 24) & 0xF000000))
+#define DSP_16G_RXTX_PRESET0_SET(dst,src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
+#define DSP_16G_RXTX_PRESET1_SET(dst,src) (((dst) & ~0xFF00) | (((UINT32) (src) << 8) & 0xFF00))
+#define DSP_16G_RXTX_PRESET2_SET(dst,src) (((dst) & ~0xFF0000) | (((UINT32) (src) << 16) & 0xFF0000))
+#define DSP_16G_RXTX_PRESET3_SET(dst,src) (((dst) & ~0xFF000000) | (((UINT32) (src) << 24) & 0xFF000000))
+#define DEFAULT_GEN4_PRESET 0x57
+
+//
+// Port Logic
+//
+#define PORT_LINK_CTRL_OFF 0x710
+#define FILTER_MASK_2_OFF 0x720
+#define GEN2_CTRL_OFF 0x80C
+#define GEN3_RELATED_OFF 0x890
+#define GEN3_EQ_CONTROL_OFF 0x8A8
+#define MISC_CONTROL_1_OFF 0x8BC
+#define AMBA_ERROR_RESPONSE_DEFAULT_OFF 0x8D0
+#define AMBA_LINK_TIMEOUT_OFF 0x8D4
+#define AMBA_ORDERING_CTRL_OFF 0x8D8
+#define DTIM_CTRL0_OFF 0xAB0
+#define AUX_CLK_FREQ_OFF 0xB40
+#define CCIX_CTRL_OFF 0xC20
+
+// PORT_LINK_CTRL_OFF
+#define LINK_CAPABLE_SET(dst, src) (((dst) & ~0x3F0000) | (((UINT32) (src) << 16) & 0x3F0000))
+#define LINK_CAPABLE_X1 0x1
+#define LINK_CAPABLE_X2 0x3
+#define LINK_CAPABLE_X4 0x7
+#define LINK_CAPABLE_X8 0xF
+#define LINK_CAPABLE_X16 0x1F
+#define LINK_CAPABLE_X32 0x3F
+#define FAST_LINK_MODE_SET(dst, src) (((dst) & ~0x80) | (((UINT32) (src) << 7) & 0x80))
+
+// FILTER_MASK_2_OFF
+#define CX_FLT_MASK_VENMSG0_DROP_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
+#define CX_FLT_MASK_VENMSG1_DROP_SET(dst, src) (((dst) & ~0x2) | (((UINT32) (src) << 1) & 0x2))
+#define CX_FLT_MASK_DABORT_4UCPL_SET(dst, src) (((dst) & ~0x4) | (((UINT32) (src) << 2) & 0x4))
+
+// GEN2_CTRL_OFF
+#define NUM_OF_LANES_SET(dst, src) (((dst) & ~0x1F00) | (((UINT32) (src) << 8) & 0x1F00))
+#define NUM_OF_LANES_X2 0x2
+#define NUM_OF_LANES_X4 0x4
+#define NUM_OF_LANES_X8 0x8
+#define NUM_OF_LANES_X16 0x10
+
+// GEN3_RELATED_OFF
+#define RATE_SHADOW_SEL_SET(dst, src) (((dst) & ~0x3000000) | (((UINT32) (src) << 24) & 0x3000000))
+#define GEN3_DATA_RATE 0x00
+#define GEN4_DATA_RATE 0x01
+#define EQ_PHASE_2_3_SET(dst, src) (((dst) & ~0x200) | (((UINT32) (src) << 9) & 0x200))
+#define ENABLE_EQ_PHASE_2_3 0x00
+#define DISABLE_EQ_PHASE_2_3 0x01
+#define RXEQ_REGRDLESS_SET(dst, src) (((dst) & ~0x2000) | (((UINT32) (src) << 13) & 0x2000))
+#define ASSERT_RXEQ 0x01
+
+// GEN3_EQ_CONTROL_OFF
+#define GEN3_EQ_FB_MODE(dst, src) (((dst) & ~0xF) | ((UINT32) (src) & 0xF))
+#define FOM_METHOD 0x01
+#define GEN3_EQ_PRESET_VEC(dst, src) (((dst) & 0xFF0000FF) | (((UINT32) (src) << 8) & 0xFFFF00))
+#define EQ_DEFAULT_PRESET_VECTOR 0x370
+#define GEN3_EQ_INIT_EVAL(dst,src) (((dst) & ~0x1000000) | (((UINT32) (src) << 24) & 0x1000000))
+#define INCLUDE_INIT_FOM 0x01
+
+// MISC_CONTROL_1_OFF
+#define DBI_RO_WR_EN_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
+#define ENABLE_WR 0x01
+#define DISABLE_WR 0x00
+
+// AMBA_ERROR_RESPONSE_DEFAULT_OFF
+#define AMBA_ERROR_RESPONSE_CRS_SET(dst, src) (((dst) & ~0x18) | (((UINT32) (src) << 3) & 0x18))
+#define AMBA_ERROR_RESPONSE_GLOBAL_SET(dst, src) (((dst) & ~0x1) | (((UINT32) (src)) & 0x1))
+
+// AMBA_LINK_TIMEOUT_OFF
+#define LINK_TIMEOUT_PERIOD_DEFAULT_SET(dst, src) (((dst) & ~0xFF) | (((UINT32) (src)) & 0xFF))
+
+// AMBA_ORDERING_CTRL_OFF
+#define AX_MSTR_ZEROLREAD_FW_SET(dst, src) (((dst) & ~0x80) | (((UINT32) (src) << 7) & 0x80))
+
+// DTIM_CTRL0_OFF
+#define DTIM_CTRL0_ROOT_PORT_ID_SET(dst, src) (((dst) & ~0xFFFF) | (((UINT32) (src)) & 0xFFFF))
+
+// AUX_CLK_FREQ_OFF
+#define AUX_CLK_FREQ_SET(dst, src) (((dst) & ~0x1FF) | (((UINT32) (src)) & 0x1FF))
+#define AUX_CLK_500MHZ 500
+
+#endif /* AC01_PCIE_CORE_H_ */
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c
new file mode 100644
index 000000000000..ad648b1b9efd
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c
@@ -0,0 +1,1416 @@
+/** @file
+
+ Copyright (c) 2020 - 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Guid/PlatformInfoHob.h>
+#include <Guid/RootComplexInfoHob.h>
+#include <Library/ArmGenericTimerCounterLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BoardPcieLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciePhyLib.h>
+#include <Library/SystemFirmwareInterfaceLib.h>
+#include <Library/TimerLib.h>
+
+#include "PcieCore.h"
+
+/**
+ Return the next extended capability base address
+
+ @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
+ @param PcieIndex PCIe controller index
+ @param IsRootComplex TRUE: Checking RootComplex configuration space
+ FALSE: Checking EP configuration space
+ @param ExtCapabilityId
+**/
+PHYSICAL_ADDRESS
+GetCapabilityBase (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex,
+ IN BOOLEAN IsRootComplex,
+ IN UINT16 ExtCapabilityId
+ )
+{
+ BOOLEAN IsExtCapability = FALSE;
+ PHYSICAL_ADDRESS CfgBase;
+ UINT32 CapabilityId;
+ UINT32 NextCapabilityPtr;
+ UINT32 Val;
+
+ if (IsRootComplex) {
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
+ } else {
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << BUS_SHIFT);
+ }
+
+ Val = MmioRead32 (CfgBase + TYPE1_CAP_PTR_REG);
+ NextCapabilityPtr = GET_LOW_8_BITS (Val);
+
+ // Loop untill desired capability is found else return 0
+ while (1) {
+ if ((NextCapabilityPtr & WORD_ALIGN_MASK) != 0) {
+ // Not alignment, just return
+ return 0;
+ }
+
+ Val = MmioRead32 (CfgBase + NextCapabilityPtr);
+ if (NextCapabilityPtr < EXT_CAPABILITY_START_BASE) {
+ CapabilityId = GET_LOW_8_BITS (Val);
+ } else {
+ CapabilityId = GET_LOW_16_BITS (Val);
+ }
+
+ if (CapabilityId == ExtCapabilityId) {
+ return (CfgBase + NextCapabilityPtr);
+ }
+
+ if (NextCapabilityPtr < EXT_CAPABILITY_START_BASE) {
+ NextCapabilityPtr = GET_CAPABILITY_PTR (Val);
+ } else {
+ NextCapabilityPtr = GET_EXT_CAPABILITY_PTR (Val);
+ }
+
+ if ((NextCapabilityPtr == 0) && !IsExtCapability) {
+ IsExtCapability = TRUE;
+ NextCapabilityPtr = EXT_CAPABILITY_START_BASE;
+ }
+
+ if ((NextCapabilityPtr == 0) && IsExtCapability) {
+ return 0;
+ }
+ }
+}
+
+/**
+ Configure equalization settings for Gen3 and Gen4
+
+ @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
+ @param PcieIndex PCIe controller index
+**/
+STATIC
+VOID
+ConfigureEqualization (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex
+ )
+{
+ PHYSICAL_ADDRESS CfgBase;
+ PHYSICAL_ADDRESS Gen3RelatedAddr;
+ PHYSICAL_ADDRESS Gen3EqControlAddr;
+ UINT32 Val;
+
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
+
+ //
+ // Gen3 and Gen4 EQ process use the same setting registers which are
+ // GEN3_RELATED_OFF and GEN3_EQ_CONTROL_OFF. Both are shadow registers
+ // and controlled by GEN3_RELATED_OFF[25:24].
+ //
+ Gen3RelatedAddr = CfgBase + GEN3_RELATED_OFF;
+ Gen3EqControlAddr = CfgBase + GEN3_EQ_CONTROL_OFF;
+
+ //
+ // Equalization setting for Gen3
+ //
+ Val = MmioRead32 (Gen3RelatedAddr);
+ Val = RATE_SHADOW_SEL_SET (Val, GEN3_DATA_RATE);
+ MmioWrite32 (Gen3RelatedAddr, Val);
+
+ Val = EQ_PHASE_2_3_SET (Val, ENABLE_EQ_PHASE_2_3);
+ Val = RXEQ_REGRDLESS_SET (Val, ASSERT_RXEQ);
+ MmioWrite32 (Gen3RelatedAddr, Val);
+
+ Val = MmioRead32 (Gen3EqControlAddr);
+ Val = GEN3_EQ_FB_MODE (Val, FOM_METHOD);
+ Val = GEN3_EQ_PRESET_VEC (Val, EQ_DEFAULT_PRESET_VECTOR);
+ Val = GEN3_EQ_INIT_EVAL (Val, INCLUDE_INIT_FOM);
+ MmioWrite32 (Gen3EqControlAddr, Val);
+
+ //
+ // Equalization setting for Gen4
+ //
+ Val = MmioRead32 (Gen3RelatedAddr);
+ Val = RATE_SHADOW_SEL_SET (Val, GEN4_DATA_RATE);
+ MmioWrite32 (Gen3RelatedAddr, Val);
+
+ Val = EQ_PHASE_2_3_SET (Val, ENABLE_EQ_PHASE_2_3);
+ Val = RXEQ_REGRDLESS_SET (Val, ASSERT_RXEQ);
+ MmioWrite32 (Gen3RelatedAddr, Val);
+
+ Val = MmioRead32 (Gen3EqControlAddr);
+ Val = GEN3_EQ_FB_MODE (Val, FOM_METHOD);
+ Val = GEN3_EQ_PRESET_VEC (Val, EQ_DEFAULT_PRESET_VECTOR);
+ Val = GEN3_EQ_INIT_EVAL (Val, INCLUDE_INIT_FOM);
+ MmioWrite32 (Gen3EqControlAddr, Val);
+}
+
+/**
+ Configure presets for Gen3 equalization
+
+ @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
+ @param PcieIndex PCIe controller index
+**/
+STATIC
+VOID
+ConfigurePresetGen3 (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex
+ )
+{
+ PHYSICAL_ADDRESS LaneEqControlAddr;
+ PHYSICAL_ADDRESS SpcieCapabilityBase;
+ UINT32 Idx;
+ UINT32 LinkWidth;
+ UINT32 Val;
+
+ // Get the Secondary PCI Express Extended capability base address
+ SpcieCapabilityBase = GetCapabilityBase (RootComplex, PcieIndex, TRUE, SPCIE_CAPABILITY_ID);
+ if (SpcieCapabilityBase == 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "PCIE%d.%d: Cannot get SPCIE capability address\n",
+ RootComplex->ID,
+ PcieIndex
+ ));
+ return;
+ }
+
+ LinkWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
+
+ // Each register holds the Preset for 2 lanes
+ for (Idx = 0; Idx < (LinkWidth / 2); Idx++) {
+ LaneEqControlAddr = SpcieCapabilityBase + SPCIE_CAP_OFF_0C_REG + Idx * sizeof (UINT32);
+ Val = MmioRead32 (LaneEqControlAddr);
+ Val = DSP_TX_PRESET0_SET (Val, DEFAULT_GEN3_PRESET);
+ Val = DSP_TX_PRESET1_SET (Val, DEFAULT_GEN3_PRESET);
+ MmioWrite32 (LaneEqControlAddr, Val);
+ }
+}
+
+/**
+ Configure presets for Gen4 equalization
+
+ @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
+ @param PcieIndex PCIe controller index
+**/
+STATIC
+VOID
+ConfigurePresetGen4 (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex
+ )
+{
+ PHYSICAL_ADDRESS LaneEqControlAddr;
+ PHYSICAL_ADDRESS Pl16gCapabilityBase;
+ UINT32 Idx;
+ UINT32 LinkWidth;
+ UINT32 Val;
+ UINT8 Preset;
+
+ // Get the Physical Layer 16.0 GT/s Extended capability base address
+ Pl16gCapabilityBase = GetCapabilityBase (RootComplex, PcieIndex, TRUE, PL16G_CAPABILITY_ID);
+ if (Pl16gCapabilityBase == 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "PCIE%d.%d: Cannot get PL16G capability address\n",
+ RootComplex->ID,
+ PcieIndex
+ ));
+ return;
+ }
+
+ if (RootComplex->PresetGen4[PcieIndex] == PRESET_INVALID) {
+ Preset = DEFAULT_GEN4_PRESET;
+ } else {
+ Preset = RootComplex->PresetGen4[PcieIndex];
+ }
+
+ LinkWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
+
+ if (LinkWidth == CAP_MAX_LINK_WIDTH_X2) {
+ LaneEqControlAddr = Pl16gCapabilityBase + PL16G_CAP_OFF_20H_REG;
+ Val = MmioRead32 (LaneEqControlAddr);
+ Val = DSP_16G_RXTX_PRESET0_SET (Val, Preset);
+ Val = DSP_16G_RXTX_PRESET1_SET (Val, Preset);
+ MmioWrite32 (LaneEqControlAddr, Val);
+ } else {
+ // Each register holds the Preset for 4 lanes
+ for (Idx = 0; Idx < (LinkWidth / 4); Idx++) {
+ LaneEqControlAddr = Pl16gCapabilityBase + PL16G_CAP_OFF_20H_REG + Idx * sizeof (UINT32);
+ Val = MmioRead32 (LaneEqControlAddr);
+ Val = DSP_16G_RXTX_PRESET0_SET (Val, Preset);
+ Val = DSP_16G_RXTX_PRESET1_SET (Val, Preset);
+ Val = DSP_16G_RXTX_PRESET2_SET (Val, Preset);
+ Val = DSP_16G_RXTX_PRESET3_SET (Val, Preset);
+ MmioWrite32 (LaneEqControlAddr, Val);
+ }
+ }
+}
+
+VOID
+ProgramHostBridgeInfo (
+ AC01_ROOT_COMPLEX *RootComplex
+ )
+{
+ EFI_STATUS Status;
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 Val;
+
+ // Program Root Complex Bifurcation
+ if (RootComplex->Active) {
+ if (RootComplex->Type == RootComplexTypeA) {
+ TargetAddress = RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_RCA_DEV_MAP_REG;
+ Status = MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &Val);
+ if (!RETURN_ERROR (Status)) {
+ Val = RCA_DEV_MAP_SET (Val, RootComplex->DevMapLow);
+ MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val);
+ }
+ } else {
+ TargetAddress = RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_RCB_DEV_MAP_REG;
+ Status = MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &Val);
+ if (!RETURN_ERROR (Status)) {
+ Val = RCB_DEV_MAP_LOW_SET (Val, RootComplex->DevMapLow);
+ Val = RCB_DEV_MAP_HIGH_SET (Val, RootComplex->DevMapHigh);
+ MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val);
+ }
+ }
+ }
+
+ // Program Vendor ID and Device ID
+ TargetAddress = RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_VENDOR_DEVICE_ID_REG;
+ Status = MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &Val);
+ if (!RETURN_ERROR (Status)) {
+ Val = VENDOR_ID_SET (Val, AMPERE_PCIE_VENDOR_ID);
+ if (RootComplexTypeA == RootComplex->Type) {
+ Val = DEVICE_ID_SET (Val, AC01_HOST_BRIDGE_DEVICE_ID_RCA);
+ } else {
+ Val = DEVICE_ID_SET (Val, AC01_HOST_BRIDGE_DEVICE_ID_RCB);
+ }
+ MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val);
+ }
+}
+
+VOID
+ProgramRootPortInfo (
+ AC01_ROOT_COMPLEX *RootComplex,
+ UINT32 PcieIndex
+ )
+{
+ PHYSICAL_ADDRESS CfgBase;
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 Val;
+
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
+
+ // Program Class Code
+ TargetAddress = CfgBase + TYPE1_CLASS_CODE_REV_ID_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = REVISION_ID_SET (Val, DEFAULT_REVISION_ID);
+ Val = SUB_CLASS_CODE_SET (Val, DEFAULT_SUB_CLASS_CODE);
+ Val = BASE_CLASS_CODE_SET (Val, DEFAULT_BASE_CLASS_CODE);
+ MmioWrite32 (TargetAddress, Val);
+
+ // Program Vendor ID and Device ID
+ TargetAddress = CfgBase + TYPE1_DEV_ID_VEND_ID_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = VENDOR_ID_SET (Val, AMPERE_PCIE_VENDOR_ID);
+ if (RootComplexTypeA == RootComplex->Type) {
+ Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICE_ID_RCA + PcieIndex);
+ } else {
+ Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICE_ID_RCB + PcieIndex);
+ }
+ MmioWrite32 (TargetAddress, Val);
+}
+
+VOID
+ProgramLinkCapabilities (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex
+ )
+{
+ PHYSICAL_ADDRESS CfgBase;
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 Val;
+ UINT8 MaxWidth;
+ UINT8 MaxGen;
+
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
+
+ MaxWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
+ MaxGen = RootComplex->Pcie[PcieIndex].MaxGen;
+
+ TargetAddress = CfgBase + PORT_LINK_CTRL_OFF;
+ Val = MmioRead32 (TargetAddress);
+ switch (MaxWidth) {
+ case LINK_WIDTH_X2:
+ Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X2);
+ break;
+
+ case LINK_WIDTH_X4:
+ Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X4);
+ break;
+
+ case LINK_WIDTH_X8:
+ Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X8);
+ break;
+
+ case LINK_WIDTH_X16:
+ default:
+ Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X16);
+ break;
+ }
+ MmioWrite32 (TargetAddress, Val);
+
+ TargetAddress = CfgBase + GEN2_CTRL_OFF;
+ Val = MmioRead32 (TargetAddress);
+ switch (MaxWidth) {
+ case LINK_WIDTH_X2:
+ Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X2);
+ break;
+
+ case LINK_WIDTH_X4:
+ Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X4);
+ break;
+
+ case LINK_WIDTH_X8:
+ Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X8);
+ break;
+
+ case LINK_WIDTH_X16:
+ default:
+ Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X16);
+ break;
+ }
+ MmioWrite32 (TargetAddress, Val);
+
+ TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + LINK_CAPABILITIES_REG;
+ Val = MmioRead32 (TargetAddress);
+ switch (MaxWidth) {
+ case LINK_WIDTH_X2:
+ Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X2);
+ break;
+
+ case LINK_WIDTH_X4:
+ Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X4);
+ break;
+
+ case LINK_WIDTH_X8:
+ Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X8);
+ break;
+
+ case LINK_WIDTH_X16:
+ default:
+ Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X16);
+ break;
+ }
+
+ switch (MaxGen) {
+ case LINK_SPEED_GEN1:
+ Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25);
+ break;
+
+ case LINK_SPEED_GEN2:
+ Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50);
+ break;
+
+ case LINK_SPEED_GEN3:
+ Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80);
+ break;
+
+ default:
+ Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_160);
+ break;
+ }
+ // Enable ASPM Capability
+ Val = CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET (Val, L0S_L1_SUPPORTED);
+ MmioWrite32 (TargetAddress, Val);
+
+ TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL2_LINK_STATUS2_REG;
+ Val = MmioRead32 (TargetAddress);
+ switch (MaxGen) {
+ case LINK_SPEED_GEN1:
+ Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25);
+ break;
+
+ case LINK_SPEED_GEN2:
+ Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50);
+ break;
+
+ case LINK_SPEED_GEN3:
+ Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80);
+ break;
+
+ default:
+ Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_160);
+ break;
+ }
+ MmioWrite32 (TargetAddress, Val);
+}
+
+VOID
+DisableCompletionTimeOut (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex,
+ IN BOOLEAN IsMask
+ )
+{
+ PHYSICAL_ADDRESS CfgBase;
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 Val;
+
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
+
+ TargetAddress = CfgBase + AER_CAPABILITY_BASE + UNCORR_ERR_MASK_OFF;
+ Val = MmioRead32 (TargetAddress);
+ Val = CMPLT_TIMEOUT_ERR_MASK_SET (Val, IsMask ? 1 : 0);
+ MmioWrite32 (TargetAddress, Val);
+}
+
+BOOLEAN
+EnableItsMemory (
+ AC01_ROOT_COMPLEX *RootComplex,
+ UINT32 PcieIndex
+ )
+{
+ PHYSICAL_ADDRESS CsrBase;
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 TimeOut;
+ UINT32 Val;
+
+ CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
+
+ // Clear memory shutdown
+ TargetAddress = CsrBase + AC01_PCIE_CORE_RAM_SHUTDOWN_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = SD_SET (Val, 0);
+ MmioWrite32 (TargetAddress, Val);
+
+ // Poll till ITS Memory is ready
+ TimeOut = MEMRDY_TIMEOUT;
+ do {
+ Val = MmioRead32 (CsrBase + AC01_PCIE_CORE_MEM_READY_REG);
+ if (Val & MEMORY_READY) {
+ return TRUE;
+ }
+
+ TimeOut--;
+ MicroSecondDelay (1);
+ } while (TimeOut > 0);
+
+ return FALSE;
+}
+
+BOOLEAN
+EnableAxiPipeClock (
+ AC01_ROOT_COMPLEX *RootComplex,
+ UINT32 PcieIndex
+ )
+{
+ PHYSICAL_ADDRESS CsrBase;
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 TimeOut;
+ UINT32 Val;
+
+ CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
+
+ // Enable subsystem clock and release reset
+ TargetAddress = CsrBase + AC01_PCIE_CORE_CLOCK_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = AXIPIPE_SET (Val, 1);
+ MmioWrite32 (TargetAddress, Val);
+
+ TargetAddress = CsrBase + AC01_PCIE_CORE_RESET_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = DWC_PCIE_SET (Val, 0);
+ MmioWrite32 (TargetAddress, Val);
+
+ //
+ // Controller does not provide any indicator for reset released.
+ // Must wait at least 1us as per EAS.
+ //
+ MicroSecondDelay (1);
+
+ // Poll till PIPE clock is stable
+ TimeOut = PIPE_CLOCK_TIMEOUT;
+ do {
+ Val = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
+ if (!(Val & PHY_STATUS_MASK)) {
+ return TRUE;
+ }
+
+ TimeOut--;
+ MicroSecondDelay (1);
+ } while (TimeOut > 0);
+
+ return FALSE;
+}
+
+VOID
+SetLinkTimeout (
+ AC01_ROOT_COMPLEX *RootComplex,
+ UINT32 PcieIndex,
+ UINTN Timeout
+ )
+{
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 Val;
+
+ TargetAddress = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT)
+ + AMBA_LINK_TIMEOUT_OFF;
+
+ Val = MmioRead32 (TargetAddress);
+ Val = LINK_TIMEOUT_PERIOD_DEFAULT_SET (Val, Timeout);
+ MmioWrite32 (TargetAddress, Val);
+}
+
+VOID
+StartLinkTraining (
+ AC01_ROOT_COMPLEX *RootComplex,
+ UINT32 PcieIndex,
+ BOOLEAN StartLink
+ )
+{
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 Val;
+
+ TargetAddress = RootComplex->Pcie[PcieIndex].CsrBase + AC01_PCIE_CORE_LINK_CTRL_REG;
+
+ Val = MmioRead32 (TargetAddress);
+ Val = LTSSMENB_SET (Val, StartLink ? START_LINK_TRAINING : HOLD_LINK_TRAINING);
+ MmioWrite32 (TargetAddress, Val);
+}
+
+VOID
+EnableDbiAccess (
+ AC01_ROOT_COMPLEX *RootComplex,
+ UINT32 PcieIndex,
+ BOOLEAN EnableDbi
+ )
+{
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 Val;
+
+ TargetAddress = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT)
+ + MISC_CONTROL_1_OFF;
+
+ Val = MmioRead32 (TargetAddress);
+ Val = DBI_RO_WR_EN_SET (Val, EnableDbi ? ENABLE_WR : DISABLE_WR);
+ MmioWrite32 (TargetAddress, Val);
+}
+
+/**
+ Setup and initialize the AC01 PCIe Root Complex and underneath PCIe controllers
+
+ @param RootComplex Pointer to Root Complex structure
+ @param ReInit Re-init status
+ @param ReInitPcieIndex PCIe controller index
+
+ @retval RETURN_SUCCESS The Root Complex has been initialized successfully.
+ @retval RETURN_DEVICE_ERROR PHY, Memory or PIPE is not ready.
+**/
+RETURN_STATUS
+Ac01PcieCoreSetupRC (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN BOOLEAN ReInit,
+ IN UINT8 ReInitPcieIndex
+ )
+{
+ PHYSICAL_ADDRESS CfgBase;
+ PHYSICAL_ADDRESS CsrBase;
+ PHYSICAL_ADDRESS TargetAddress;
+ RETURN_STATUS Status;
+ UINT32 Val;
+ UINT8 PcieIndex;
+
+ DEBUG ((DEBUG_INFO, "Initializing Socket%d RootComplex%d\n", RootComplex->Socket, RootComplex->ID));
+
+ ProgramHostBridgeInfo (RootComplex);
+
+ if (!ReInit) {
+ Status = PciePhyInit (RootComplex->SerdesBase);
+ if (RETURN_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to initialize the PCIe PHY\n", __FUNCTION__));
+ return RETURN_DEVICE_ERROR;
+ }
+ }
+
+ // Setup each controller
+ for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
+
+ if (ReInit) {
+ PcieIndex = ReInitPcieIndex;
+ }
+
+ if (!RootComplex->Pcie[PcieIndex].Active) {
+ continue;
+ }
+
+ DEBUG ((DEBUG_INFO, "Initializing Controller %d\n", PcieIndex));
+
+ CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
+
+ // Put Controller into reset if not in reset already
+ TargetAddress = CsrBase + AC01_PCIE_CORE_RESET_REG;
+ Val = MmioRead32 (TargetAddress);
+ if (!(Val & RESET_MASK)) {
+ Val = DWC_PCIE_SET (Val, ASSERT_RESET);
+ MmioWrite32 (TargetAddress, Val);
+
+ // Delay 50ms to ensure controller finish its reset
+ MicroSecondDelay (50000);
+ }
+
+ if (!EnableItsMemory (RootComplex, PcieIndex)) {
+ DEBUG ((DEBUG_ERROR, "- Pcie[%d] - ITS Memory is not ready\n", PcieIndex));
+ return RETURN_DEVICE_ERROR;
+ }
+
+ // Hold link training
+ StartLinkTraining (RootComplex, PcieIndex, FALSE);
+
+ if (!EnableAxiPipeClock (RootComplex, PcieIndex)) {
+ DEBUG ((DEBUG_ERROR, "- Pcie[%d] - PIPE clock is not stable\n", PcieIndex));
+ return RETURN_DEVICE_ERROR;
+ }
+
+ // Start PERST pulse
+ BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE);
+
+ // Allow programming to config space
+ EnableDbiAccess (RootComplex, PcieIndex, TRUE);
+
+ // Program the power limit
+ TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + SLOT_CAPABILITIES_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET (Val, SLOT_POWER_LIMIT_75W);
+ MmioWrite32 (TargetAddress, Val);
+
+ // Program DTI for ATS support
+ TargetAddress = CfgBase + DTIM_CTRL0_OFF;
+ Val = MmioRead32 (TargetAddress);
+ Val = DTIM_CTRL0_ROOT_PORT_ID_SET (Val, 0);
+ MmioWrite32 (TargetAddress, Val);
+
+ //
+ // Program number of lanes used
+ // - Reprogram LINK_CAPABLE of PORT_LINK_CTRL_OFF
+ // - Reprogram NUM_OF_LANES of GEN2_CTRL_OFF
+ // - Reprogram CAP_MAX_LINK_WIDTH of LINK_CAPABILITIES_REG
+ //
+ ProgramLinkCapabilities (RootComplex, PcieIndex);
+
+ // Set Zero byte request handling
+ TargetAddress = CfgBase + FILTER_MASK_2_OFF;
+ Val = MmioRead32 (TargetAddress);
+ Val = CX_FLT_MASK_VENMSG0_DROP_SET (Val, 0);
+ Val = CX_FLT_MASK_VENMSG1_DROP_SET (Val, 0);
+ Val = CX_FLT_MASK_DABORT_4UCPL_SET (Val, 0);
+ MmioWrite32 (TargetAddress, Val);
+
+ TargetAddress = CfgBase + AMBA_ORDERING_CTRL_OFF;
+ Val = MmioRead32 (TargetAddress);
+ Val = AX_MSTR_ZEROLREAD_FW_SET (Val, 0);
+ MmioWrite32 (TargetAddress, Val);
+
+ //
+ // Set Completion with CRS handling for CFG Request
+ // Set Completion with CA/UR handling non-CFG Request
+ //
+ TargetAddress = CfgBase + AMBA_ERROR_RESPONSE_DEFAULT_OFF;
+ Val = MmioRead32 (TargetAddress);
+ // 0x2: OKAY with FFFF_0001 and FFFF_FFFF
+ Val = AMBA_ERROR_RESPONSE_CRS_SET (Val, 0x2);
+ MmioWrite32 (TargetAddress, Val);
+
+ // Set Legacy PCIE interrupt map to INTA
+ TargetAddress = CfgBase + BRIDGE_CTRL_INT_PIN_INT_LINE_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = INT_PIN_SET (Val, IRQ_INT_A);
+ MmioWrite32 (TargetAddress, Val);
+
+ TargetAddress = CsrBase + AC01_PCIE_CORE_IRQ_SEL_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = INTPIN_SET (Val, IRQ_INT_A);
+ MmioWrite32 (TargetAddress, Val);
+
+ if (RootComplex->Pcie[PcieIndex].MaxGen >= LINK_SPEED_GEN2) {
+ ConfigureEqualization (RootComplex, PcieIndex);
+ if (RootComplex->Pcie[PcieIndex].MaxGen >= LINK_SPEED_GEN3) {
+ ConfigurePresetGen3 (RootComplex, PcieIndex);
+ if (RootComplex->Pcie[PcieIndex].MaxGen >= LINK_SPEED_GEN4) {
+ ConfigurePresetGen4 (RootComplex, PcieIndex);
+ }
+ }
+ }
+
+ // Link timeout after 1ms
+ SetLinkTimeout (RootComplex, PcieIndex, 1);
+
+ DisableCompletionTimeOut (RootComplex, PcieIndex, TRUE);
+
+ ProgramRootPortInfo (RootComplex, PcieIndex);
+
+ // Enable common clock for downstream
+ TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_STATUS_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1);
+ Val = CAP_COMMON_CLK_SET (Val, 1);
+ MmioWrite32 (TargetAddress, Val);
+
+ // Match aux_clk to system
+ TargetAddress = CfgBase + AUX_CLK_FREQ_OFF;
+ Val = MmioRead32 (TargetAddress);
+ Val = AUX_CLK_FREQ_SET (Val, AUX_CLK_500MHZ);
+ MmioWrite32 (TargetAddress, Val);
+
+ // Assert PERST low to reset endpoint
+ BoardPcieAssertPerst (RootComplex, PcieIndex, FALSE);
+
+ // Start link training
+ StartLinkTraining (RootComplex, PcieIndex, TRUE);
+
+ // Complete the PERST pulse
+ BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE);
+
+ // Lock programming of config space
+ EnableDbiAccess (RootComplex, PcieIndex, FALSE);
+
+ if (ReInit) {
+ return RETURN_SUCCESS;
+ }
+ }
+
+ return RETURN_SUCCESS;
+}
+
+BOOLEAN
+PcieLinkUpCheck (
+ IN AC01_PCIE_CONTROLLER *Pcie
+ )
+{
+ PHYSICAL_ADDRESS CsrBase;
+ UINT32 BlockEvent;
+ UINT32 LinkStat;
+
+ CsrBase = Pcie->CsrBase;
+
+ // Check if card present
+ // smlh_ltssm_state[13:8] = 0
+ // phy_status[2] = 0
+ // smlh_link_up[1] = 0
+ // rdlh_link_up[0] = 0
+ LinkStat = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
+ LinkStat = LinkStat & (SMLH_LTSSM_STATE_MASK | PHY_STATUS_MASK_BIT |
+ SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT);
+ if (LinkStat == 0) {
+ return FALSE;
+ }
+
+ BlockEvent = MmioRead32 (CsrBase + AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG);
+ LinkStat = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
+
+ if (((BlockEvent & LINKUP_MASK) != 0)
+ && (SMLH_LTSSM_STATE_GET(LinkStat) == LTSSM_STATE_L0)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Callback function when the Host Bridge enumeration end.
+
+ @param RootComplex Pointer to the Root Complex structure
+**/
+VOID
+Ac01PcieCoreEndEnumeration (
+ IN AC01_ROOT_COMPLEX *RootComplex
+ )
+{
+
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 PcieIndex;
+ UINT32 Val;
+
+ if (RootComplex == NULL || !RootComplex->Active) {
+ return;
+ }
+
+ // Clear uncorrectable error during enumuration phase. Mainly completion timeout.
+ for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
+ if (!RootComplex->Pcie[PcieIndex].Active) {
+ continue;
+ }
+
+ if (!PcieLinkUpCheck(&RootComplex->Pcie[PcieIndex])) {
+ // If link down/disabled after enumeration, disable completed time out
+ DisableCompletionTimeOut (RootComplex, PcieIndex, TRUE);
+ }
+
+ // Clear all errors
+ TargetAddress = RootComplex->MmcfgBase + ((PcieIndex + 1) << DEV_SHIFT) \
+ + AER_CAPABILITY_BASE + UNCORR_ERR_STATUS_OFF;
+ Val = MmioRead32 (TargetAddress);
+ if (Val != 0) {
+ // Clear error by writting
+ MmioWrite32 (TargetAddress, Val);
+ }
+ }
+}
+
+/**
+ Comparing current link status with the max capabilities of the link
+
+ @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
+ @param PcieIndex PCIe controller index
+ @param EpMaxWidth EP max link width
+ @param EpMaxGen EP max link speed
+
+ @retval -1: Link status do not match with link max capabilities
+ 1: Link capabilites are invalid
+ 0: Link status are correct
+**/
+INT32
+Ac01PcieCoreLinkCheck (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex,
+ IN UINT8 EpMaxWidth,
+ IN UINT8 EpMaxGen
+ )
+{
+ PHYSICAL_ADDRESS CsrBase, CfgBase;
+ UINT32 Val, LinkStat;
+ UINT32 MaxWidth, MaxGen;
+
+ CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
+
+ Val = MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CAPABILITIES_REG);
+ if ((CAP_MAX_LINK_WIDTH_GET (Val) == 0) ||
+ (CAP_MAX_LINK_SPEED_GET (Val) == 0)) {
+ DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong RootComplex capabilities\n", RootComplex->ID, PcieIndex));
+ return LINK_CHECK_WRONG_PARAMETER;
+ }
+
+ if ((EpMaxWidth == 0) || (EpMaxGen == 0)) {
+ DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong EP capabilities\n", RootComplex->ID, PcieIndex));
+ return LINK_CHECK_FAILED;
+ }
+
+ // Compare RootComplex and EP capabilities
+ if (CAP_MAX_LINK_WIDTH_GET (Val) > EpMaxWidth) {
+ MaxWidth = EpMaxWidth;
+ } else {
+ MaxWidth = CAP_MAX_LINK_WIDTH_GET (Val);
+ }
+
+ // Compare RootComplex and EP capabilities
+ if (CAP_MAX_LINK_SPEED_GET (Val) > EpMaxGen) {
+ MaxGen = EpMaxGen;
+ } else {
+ MaxGen = CAP_MAX_LINK_SPEED_GET (Val);
+ }
+
+ LinkStat = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
+ Val = MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_STATUS_REG);
+ DEBUG ((
+ DEBUG_INFO,
+ "PCIE%d.%d: Link MaxWidth %d MaxGen %d, AC01_PCIE_CORE_LINK_STAT_REG 0x%x",
+ RootComplex->ID,
+ PcieIndex,
+ MaxWidth,
+ MaxGen,
+ LinkStat
+ ));
+
+ // Checking all conditions of the link
+ // If one of them is not sastified, return link up fail
+ if ((CAP_NEGO_LINK_WIDTH_GET (Val) != MaxWidth) ||
+ (CAP_LINK_SPEED_GET (Val) != MaxGen) ||
+ (RDLH_SMLH_LINKUP_STATUS_GET (LinkStat) != (SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT)))
+ {
+ DEBUG ((DEBUG_INFO, "\tLinkCheck FAILED\n"));
+ return LINK_CHECK_FAILED;
+ }
+
+ DEBUG ((DEBUG_INFO, "\tLinkCheck SUCCESS\n"));
+ return LINK_CHECK_SUCCESS;
+}
+
+INT32
+PFACounterRead (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex,
+ IN UINT64 RasDesCapabilityBase
+ )
+{
+ INT32 Ret = LINK_CHECK_SUCCESS;
+ UINT32 Val;
+ UINT8 ErrCode, ErrGrpNum;
+
+ UINT32 ErrCtrlCfg[] = {
+ 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00A, // Per Lane
+ 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A,
+ 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207,
+ 0x300, 0x301, 0x302, 0x303, 0x304, 0x305,
+ 0x400, 0x401, // Per Lane
+ 0x500, 0x501, 0x502, 0x503, 0x504, 0x505, 0x506, 0x507, 0x508, 0x509, 0x50A, 0x50B, 0x50C, 0x50D
+ };
+
+ for (ErrCode = 0; ErrCode < ARRAY_SIZE (ErrCtrlCfg); ErrCode++) {
+ ErrGrpNum = GET_HIGH_8_BITS (ErrCtrlCfg[ErrCode]);
+ // Skipping per lane group
+ // Checking common lane group because AER error are included in common group only
+ if ((ErrGrpNum != 0) && (ErrGrpNum != 4)) {
+ Val = MmioRead32 (RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG);
+ if (RootComplex->Type == RootComplexTypeA) {
+ // RootComplexTypeA - 4 PCIe controller per port, 1 controller in charge of 4 lanes
+ Val = ECCR_LANE_SEL_SET (Val, PcieIndex * 4);
+ } else {
+ // RootComplexTypeB - 8 PCIe controller per port, 1 controller in charge of 2 lanes
+ Val = ECCR_LANE_SEL_SET (Val, PcieIndex * 2);
+ }
+ Val = ECCR_GROUP_EVENT_SEL_SET (Val, ErrCtrlCfg[ErrCode]);
+ MmioWrite32 (RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG, Val);
+
+ // After setting Counter Control reg
+ // This delay just to make sure Counter Data reg is update with new value
+ MicroSecondDelay (1);
+ Val = MmioRead32 (RasDesCapabilityBase + EVENT_COUNTER_DATA_REG);
+ if (Val != 0) {
+ Ret = LINK_CHECK_FAILED;
+ DEBUG ((
+ DEBUG_ERROR,
+ "\tSocket%d RootComplex%d RP%d \t%s: %d \tGROUP:%d-EVENT:%d\n",
+ RootComplex->Socket,
+ RootComplex->ID,
+ PcieIndex,
+ Val,
+ ErrGrpNum,
+ GET_LOW_8_BITS (ErrCtrlCfg[ErrCode])
+ ));
+ }
+ }
+ }
+
+ return Ret;
+}
+
+/**
+ Handle Predictive Failure Analysis command
+
+ @param RootComplex Pointer to Root Complex structure
+ @param PcieIndex PCIe controller index
+ @param PFAMode The PFA mode
+
+ @retval The link status
+**/
+INT32
+Ac01PFACommand (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex,
+ IN UINT8 PFAMode
+ )
+{
+ PHYSICAL_ADDRESS RasDesCapabilityBase;
+ PHYSICAL_ADDRESS TargetAddress;
+ INT32 Ret = LINK_CHECK_SUCCESS;
+ UINT32 Val;
+
+ // Allow programming to config space
+ EnableDbiAccess (RootComplex, PcieIndex, TRUE);
+
+ // Get the RAS D.E.S. capability base address
+ RasDesCapabilityBase = GetCapabilityBase (RootComplex, PcieIndex, TRUE, RAS_DES_CAPABILITY_ID);
+ if (RasDesCapabilityBase == 0) {
+ DEBUG ((DEBUG_INFO, "PCIE%d.%d: Cannot get RAS DES capability address\n", RootComplex->ID, PcieIndex));
+ return LINK_CHECK_WRONG_PARAMETER;
+ }
+
+ TargetAddress = RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG;
+
+ switch (PFAMode) {
+ case PFA_MODE_ENABLE:
+ Val = MmioRead32 (TargetAddress);
+ Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, EVENT_COUNTER_ENABLE_ALL_ON);
+ Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, EVENT_COUNTER_CLEAR_NO_CHANGE);
+ MmioWrite32 (TargetAddress, Val);
+ break;
+
+ case PFA_MODE_CLEAR:
+ Val = MmioRead32 (TargetAddress);
+ Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, EVENT_COUNTER_ENABLE_NO_CHANGE);
+ Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, EVENT_COUNTER_CLEAR_ALL_CLEAR);
+ MmioWrite32 (TargetAddress, Val);
+ break;
+
+ case PFA_MODE_READ:
+ Ret = PFACounterRead (RootComplex, PcieIndex, RasDesCapabilityBase);
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: Invalid PFA mode\n"));
+ }
+
+ // Disable programming to config space
+ EnableDbiAccess (RootComplex, PcieIndex, FALSE);
+
+ return Ret;
+}
+
+UINT32
+EndpointCfgReady (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex
+ )
+{
+ PHYSICAL_ADDRESS CfgBase;
+ UINT32 TimeOut;
+ UINT32 Val;
+
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << BUS_SHIFT);
+
+ // Loop read CfgBase value until got valid value or
+ // reach to timeout EP_LINKUP_TIMEOUT (or more depend on card)
+ TimeOut = EP_LINKUP_TIMEOUT;
+ do {
+ Val = MmioRead32 (CfgBase);
+ if (Val != 0xFFFF0001 && Val != 0xFFFFFFFF) {
+ return TRUE;
+ }
+
+ TimeOut -= LINK_WAIT_INTERVAL_US;
+ MicroSecondDelay (LINK_WAIT_INTERVAL_US);
+ } while (TimeOut > 0);
+
+ return FALSE;
+}
+
+/**
+ Get link capabilities link width and speed of endpoint
+
+ @param RootComplex[in] Pointer to AC01_ROOT_COMPLEX structure
+ @param PcieIndex[in] PCIe controller index
+ @param EpMaxWidth[out] EP max link width
+ @param EpMaxGen[out] EP max link speed
+**/
+VOID
+Ac01PcieCoreGetEndpointInfo (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex,
+ OUT UINT8 *EpMaxWidth,
+ OUT UINT8 *EpMaxGen
+ )
+{
+ PHYSICAL_ADDRESS CfgBase;
+ PHYSICAL_ADDRESS PcieCapBase;
+ PHYSICAL_ADDRESS SecLatTimerAddr;
+ PHYSICAL_ADDRESS TargetAddress;
+ UINT32 RestoreVal;
+ UINT32 Val;
+
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
+ SecLatTimerAddr = CfgBase + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG;
+
+ *EpMaxWidth = 0;
+ *EpMaxGen = 0;
+
+ // Allow programming to config space
+ EnableDbiAccess (RootComplex, PcieIndex, TRUE);
+
+ Val = MmioRead32 (SecLatTimerAddr);
+ RestoreVal = Val;
+ Val = SUB_BUS_SET (Val, DEFAULT_SUB_BUS);
+ Val = SEC_BUS_SET (Val, RootComplex->Pcie[PcieIndex].DevNum);
+ Val = PRIM_BUS_SET (Val, DEFAULT_PRIM_BUS);
+ MmioWrite32 (SecLatTimerAddr, Val);
+
+ if (EndpointCfgReady (RootComplex, PcieIndex)) {
+ PcieCapBase = GetCapabilityBase (RootComplex, PcieIndex, FALSE, PCIE_CAPABILITY_ID);
+ if (PcieCapBase == 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "PCIE%d.%d Cannot get PCIe capability base address!\n",
+ RootComplex->ID,
+ PcieIndex
+ ));
+ } else {
+ Val = MmioRead32 (PcieCapBase + LINK_CAPABILITIES_REG);
+ *EpMaxWidth = CAP_MAX_LINK_WIDTH_GET (Val);
+ *EpMaxGen = CAP_MAX_LINK_SPEED_GET (Val);
+ DEBUG ((
+ DEBUG_INFO,
+ "PCIE%d.%d EP MaxWidth %d EP MaxGen %d \n", RootComplex->ID,
+ PcieIndex,
+ *EpMaxWidth,
+ *EpMaxGen
+ ));
+
+ // From EP, enabling common clock for upstream
+ TargetAddress = PcieCapBase + LINK_CONTROL_LINK_STATUS_REG;
+ Val = MmioRead32 (TargetAddress);
+ Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1);
+ Val = CAP_COMMON_CLK_SET (Val, 1);
+ MmioWrite32 (TargetAddress, Val);
+ }
+ }
+
+ // Restore value in order to not affect enumeration process
+ MmioWrite32 (SecLatTimerAddr, RestoreVal);
+
+ // Disable programming to config space
+ EnableDbiAccess (RootComplex, PcieIndex, FALSE);
+}
+
+VOID
+PollLinkUp (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex
+ )
+{
+ UINT32 TimeOut;
+
+ // Poll until link up
+ // This checking for linkup status and
+ // give LTSSM state the time to transit from DECTECT state to L0 state
+ // Total delay are 100ms, smaller number of delay cannot always make sure
+ // the state transition is completed
+ TimeOut = LTSSM_TRANSITION_TIMEOUT;
+ do {
+ if (PcieLinkUpCheck (&RootComplex->Pcie[PcieIndex])) {
+ DEBUG ((
+ DEBUG_INFO,
+ "\tPCIE%d.%d LinkStat is correct after soft reset, transition time: %d\n",
+ RootComplex->ID,
+ PcieIndex,
+ TimeOut
+ ));
+ RootComplex->Pcie[PcieIndex].LinkUp = TRUE;
+ break;
+ }
+
+ MicroSecondDelay (100);
+ TimeOut -= 100;
+ } while (TimeOut > 0);
+
+ if (TimeOut <= 0) {
+ DEBUG ((DEBUG_ERROR, "\tPCIE%d.%d LinkStat TIMEOUT after re-init\n", RootComplex->ID, PcieIndex));
+ } else {
+ DEBUG ((DEBUG_INFO, "PCIE%d.%d Link re-initialization passed!\n", RootComplex->ID, PcieIndex));
+ }
+}
+
+/**
+ Check active PCIe controllers of RootComplex, retrain or soft reset if needed
+
+ @param RootComplex[in] Pointer to AC01_ROOT_COMPLEX structure
+ @param PcieIndex[in] PCIe controller index
+
+ @retval -1: Link recovery had failed
+ 1: Link width and speed are not correct
+ 0: Link recovery succeed
+**/
+INT32
+Ac01PcieCoreQoSLinkCheckRecovery (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex
+ )
+{
+ INT32 LinkStatusCheck, RasdesChecking;
+ INT32 NumberOfReset = MAX_REINIT;
+ UINT8 EpMaxWidth, EpMaxGen;
+
+ // PCIe controller is not active or Link is not up
+ // Nothing to be done
+ if ((!RootComplex->Pcie[PcieIndex].Active) || (!RootComplex->Pcie[PcieIndex].LinkUp)) {
+ return LINK_CHECK_WRONG_PARAMETER;
+ }
+
+ do {
+ if (RootComplex->Pcie[PcieIndex].LinkUp) {
+ // Enable all of RASDES register to detect any training error
+ Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_ENABLE);
+
+ // Accessing Endpoint and checking current link capabilities
+ Ac01PcieCoreGetEndpointInfo (RootComplex, PcieIndex, &EpMaxWidth, &EpMaxGen);
+ LinkStatusCheck = Ac01PcieCoreLinkCheck (RootComplex, PcieIndex, EpMaxWidth, EpMaxGen);
+
+ // Delay to allow the link to perform internal operation and generate
+ // any error status update. This allows detection of any error observed
+ // during initial link training. Possible evaluation time can be
+ // between 100ms to 200ms.
+ MicroSecondDelay (100000);
+
+ // Check for error
+ RasdesChecking = Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_READ);
+
+ // Clear error counter
+ Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_CLEAR);
+
+ // If link check functions return passed, then breaking out
+ // else go to soft reset
+ if (LinkStatusCheck != LINK_CHECK_FAILED &&
+ RasdesChecking != LINK_CHECK_FAILED &&
+ PcieLinkUpCheck (&RootComplex->Pcie[PcieIndex]))
+ {
+ return LINK_CHECK_SUCCESS;
+ }
+
+ RootComplex->Pcie[PcieIndex].LinkUp = FALSE;
+ }
+
+ // Trigger controller soft reset
+ DEBUG ((DEBUG_INFO, "PCIE%d.%d Start link re-initialization..\n", RootComplex->ID, PcieIndex));
+ Ac01PcieCoreSetupRC (RootComplex, TRUE, PcieIndex);
+
+ PollLinkUp (RootComplex, PcieIndex);
+
+ NumberOfReset--;
+ } while (NumberOfReset > 0);
+
+ return LINK_CHECK_SUCCESS;
+}
+
+VOID
+Ac01PcieCoreUpdateLink (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ OUT BOOLEAN *IsNextRoundNeeded,
+ OUT INT8 *FailedPciePtr,
+ OUT INT8 *FailedPcieCount
+ )
+{
+ AC01_PCIE_CONTROLLER *Pcie;
+ PHYSICAL_ADDRESS CfgBase;
+ UINT8 PcieIndex;
+ UINT32 Index;
+ UINT32 Val;
+
+ *IsNextRoundNeeded = FALSE;
+ *FailedPcieCount = 0;
+ for (Index = 0; Index < MaxPcieControllerOfRootComplexB; Index++) {
+ FailedPciePtr[Index] = -1;
+ }
+
+ if (!RootComplex->Active) {
+ return;
+ }
+
+ // Loop for all controllers
+ for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
+ Pcie = &RootComplex->Pcie[PcieIndex];
+ CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
+
+ if (Pcie->Active && !Pcie->LinkUp) {
+ if (PcieLinkUpCheck (Pcie)) {
+ Pcie->LinkUp = TRUE;
+ Val = MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_STATUS_REG);
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a Socket%d RootComplex%d RP%d NEGO_LINK_WIDTH: 0x%x LINK_SPEED: 0x%x\n",
+ __FUNCTION__,
+ RootComplex->Socket,
+ RootComplex->ID,
+ PcieIndex,
+ CAP_NEGO_LINK_WIDTH_GET (Val),
+ CAP_LINK_SPEED_GET (Val)
+ ));
+
+ // Doing link checking and recovery if needed
+ Ac01PcieCoreQoSLinkCheckRecovery (RootComplex, PcieIndex);
+
+ // Link timeout after 32ms
+ SetLinkTimeout (RootComplex, PcieIndex, 32);
+
+ // Un-mask Completion Timeout
+ DisableCompletionTimeOut (RootComplex, PcieIndex, FALSE);
+
+ } else {
+ *IsNextRoundNeeded = FALSE;
+ FailedPciePtr[*FailedPcieCount] = PcieIndex;
+ *FailedPcieCount += 1;
+ }
+ }
+ }
+}
+
+/**
+ Verify the link status and retry to initialize the Root Complex if there's any issue.
+
+ @param RootComplexList Pointer to the Root Complex list
+**/
+VOID
+Ac01PcieCorePostSetupRC (
+ IN AC01_ROOT_COMPLEX *RootComplexList
+ )
+{
+ UINT8 RCIndex, Idx;
+ BOOLEAN IsNextRoundNeeded, NextRoundNeeded;
+ UINT64 PrevTick, CurrTick, ElapsedCycle;
+ UINT64 TimerTicks64;
+ UINT8 ReInit;
+ INT8 FailedPciePtr[MaxPcieControllerOfRootComplexB];
+ INT8 FailedPcieCount;
+
+ ReInit = 0;
+
+_link_polling:
+ NextRoundNeeded = FALSE;
+ //
+ // It is not guaranteed the timer service is ready prior to PCI Dxe.
+ // Calculate system ticks for link training.
+ //
+ TimerTicks64 = ArmGenericTimerGetTimerFreq (); /* 1 Second */
+ PrevTick = ArmGenericTimerGetSystemCount ();
+ ElapsedCycle = 0;
+
+ do {
+ CurrTick = ArmGenericTimerGetSystemCount ();
+ if (CurrTick < PrevTick) {
+ ElapsedCycle += MAX_UINT64 - PrevTick;
+ PrevTick = 0;
+ }
+ ElapsedCycle += (CurrTick - PrevTick);
+ PrevTick = CurrTick;
+ } while (ElapsedCycle < TimerTicks64);
+
+ for (RCIndex = 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) {
+ Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeeded, FailedPciePtr, &FailedPcieCount);
+ if (IsNextRoundNeeded) {
+ NextRoundNeeded = TRUE;
+ }
+ }
+
+ if (NextRoundNeeded && ReInit < MAX_REINIT) {
+ //
+ // Timer is up. Give another chance to re-program controller
+ //
+ ReInit++;
+ for (RCIndex = 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) {
+ Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeeded, FailedPciePtr, &FailedPcieCount);
+ if (IsNextRoundNeeded) {
+ for (Idx = 0; Idx < FailedPcieCount; Idx++) {
+ if (FailedPciePtr[Idx] == -1) {
+ continue;
+ }
+
+ //
+ // Some controller still observes link-down. Re-init controller
+ //
+ Ac01PcieCoreSetupRC (&RootComplexList[RCIndex], TRUE, FailedPciePtr[Idx]);
+ }
+ }
+ }
+
+ goto _link_polling;
+ }
+}
diff --git a/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c
new file mode 100644
index 000000000000..0916adb77539
--- /dev/null
+++ b/Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c
@@ -0,0 +1,47 @@
+/** @file
+
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BoardPcieLib.h>
+
+/**
+ Assert PERST of input PCIe controller
+
+ @param[in] RootComplex RootComplex instance.
+ @param[in] PcieIndex PCIe controller index of input Root Complex.
+ @param[in] Bifurcation Bifurcation mode of input Root Complex.
+ @param[in] IsPullToHigh Target status for the PERST.
+
+ @retval RETURN_SUCCESS The operation is successful.
+ @retval Others An error occurred.
+**/
+RETURN_STATUS
+EFIAPI
+BoardPcieAssertPerst (
+ IN AC01_ROOT_COMPLEX *RootComplex,
+ IN UINT8 PcieIndex,
+ IN BOOLEAN IsPullToHigh
+ )
+{
+ return RETURN_SUCCESS;
+}
+
+/**
+ Override the segment number for a root complex with a board specific number.
+
+ @param[in] RootComplex Root Complex instance with properties.
+
+ @retval Segment number corresponding to the input root complex.
+ Default segment number is 0x0F.
+**/
+UINT16
+BoardPcieGetSegmentNumber (
+ IN AC01_ROOT_COMPLEX *RootComplex
+ )
+{
+ return 0x0F;
+}
--
2.17.1






[edk2platforms][PATCH v3 1/1] IntelSiliconPkg: Add IntelDieInfoProtocol

Maciej Czajkowski
 

Added IntelDieInfo header into IntelSiliconPkg tree.
The purpose is to have generic and unified interface for getting
information about dies installed in the system.
It will be implemented by silicon code.

Cc: Ray Ni <ray.ni@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>
Signed-off-by: Maciej Czajkowski <maciej.czajkowski@...>
---

Notes:
v3:
- added EDKII_ prefix to interface
- removed GUID definitons from .h file
- corrected descriptions
- made PPI/protocol GUIDs unique

v2:
- added interface description
- added die specific GUIDs into .dec file

Silicon/Intel/IntelSiliconPkg/Include/Protocol/IntelDieInfo.h | 96 ++++++++++++++++++++
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 9 ++
2 files changed, 105 insertions(+)

diff --git a/Silicon/Intel/IntelSiliconPkg/Include/Protocol/IntelDieInfo.h b/Silicon/Intel/IntelSiliconPkg/Include/Protocol/IntelDieInfo.h
new file mode 100644
index 000000000000..6fb13ab287b6
--- /dev/null
+++ b/Silicon/Intel/IntelSiliconPkg/Include/Protocol/IntelDieInfo.h
@@ -0,0 +1,96 @@
+/** @file
+ IntelDieInfo definition
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef _DIE_INFO_PROTOCOL_H_
+#define _DIE_INFO_PROTOCOL_H_
+
+typedef struct _EDKII_INTEL_DIE_INFO_PROTOCOL EDKII_INTEL_DIE_INFO_PROTOCOL;
+typedef EDKII_INTEL_DIE_INFO_PROTOCOL EDKII_INTEL_DIE_INFO_PPI;
+
+extern EFI_GUID gIntelDieInfoProtocolGuid;
+extern EFI_GUID gIntelDieInfoPpiGuid;
+
+extern EFI_GUID gIntelDieInfoPchGuid;
+extern EFI_GUID gIntelDieInfoSocGuid;
+extern EFI_GUID gIntelDieInfoIoGuid;
+extern EFI_GUID gIntelDieInfoCpuGuid;
+extern EFI_GUID gIntelDieInfoGfxGuid;
+
+#define DIE_INFO_PROTOCOL_REVISION 1
+#define DIE_INFO_PROTOCOL_SIGNATURE SIGNATURE_32 ('I', 'D', 'I', 'P')
+
+/**
+ Returns pointer to constant string representing die name.
+ Name is specific to die type.
+
+ @param[in] This Pointer to the DieInfoProtocol context structure
+ @retval Pointer to the const string
+**/
+typedef
+CONST CHAR8*
+(EFIAPI *EDKII_INTEL_DIE_INFO_GET_DIE_NAME_STR) (
+ IN EDKII_INTEL_DIE_INFO_PROTOCOL *This
+ );
+
+/**
+ Returns pointer to constant string representing stepping of the die.
+
+ @param[in] This Pointer to the DieInfoProtocol context structure
+ @retval Pointer to the const string
+**/
+typedef
+CONST CHAR8*
+(EFIAPI *EDKII_INTEL_DIE_INFO_GET_STEPPING_STR) (
+ IN EDKII_INTEL_DIE_INFO_PROTOCOL *This
+ );
+
+/**
+ Returns pointer to constant string representing SKU of the die.
+
+ @param[in] This Pointer to the DieInfoProtocol context structure
+ @retval Pointer to the const string
+**/
+typedef
+CONST CHAR8*
+(EFIAPI *EDKII_INTEL_DIE_INFO_GET_SKU_STR) (
+ IN EDKII_INTEL_DIE_INFO_PROTOCOL *This
+ );
+
+/**
+ Protocol/PPI definition.
+ The purpose of this interface is to serve die-specific informations in a unified, generic way.
+ It will be produced by silicon code per die, and can be consumed by any module that needs contained information.
+
+ <b>Revision 1</b>:
+ - Initial version.
+**/
+struct _EDKII_INTEL_DIE_INFO_PROTOCOL {
+ UINT32 Signature; ///< Protocol signature
+ UINT32 Revision; ///< Current protocol revision
+ /**
+ Type of the die that particular instance is reffering to.
+ **/
+ EFI_GUID Type;
+ /**
+ Index of the die in the package.
+ **/
+ UINT32 DieIndex;
+ /**
+ Unique ID specific to the die and the associated generation.
+ **/
+ UINT64 DieId;
+ /**
+ Generation and die specific stepping ID.
+ **/
+ UINT32 SteppingId;
+
+ EDKII_INTEL_DIE_INFO_GET_DIE_NAME_STR GetNameStr;
+ EDKII_INTEL_DIE_INFO_GET_STEPPING_STR GetSteppingStr;
+ EDKII_INTEL_DIE_INFO_GET_SKU_STR GetSkuStr;
+};
+
+#endif // _DIE_INFO_PROTOCOL_H_
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
index 1704f9e02541..ee53f5fb902c 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -92,6 +92,13 @@ [Guids]
gFlashRegionAllGuid = { 0xbabe60dc, 0xf88d, 0x4584, {0x9e, 0x54, 0x57, 0x44, 0x4b, 0xe2, 0x6e, 0xf3 } }
gFlashRegionMaxGuid = { 0x74c2e3c1, 0x8faa, 0x4659, {0xa7, 0xbb, 0x87, 0x1f, 0xbb, 0x61, 0xd3, 0xb4 } }

+ ## Include/Protocol/IntelDieInfo.h
+ gIntelDieInfoPchGuid = { 0x62CB6D68, 0x4771, 0x4569, { 0x81, 0xFA, 0x1E, 0x99, 0x6E, 0xA9, 0x91, 0xC5 }}
+ gIntelDieInfoSocGuid = { 0x63287105, 0x578E, 0x4799, { 0xBE, 0x55, 0x5D, 0xDA, 0xCA, 0x03, 0x74, 0xD0 }}
+ gIntelDieInfoIoGuid = { 0x23DA4C74, 0x54A0, 0x4E01, { 0x83, 0xB1, 0x8C, 0xA7, 0x43, 0x43, 0x1F, 0xF0 }}
+ gIntelDieInfoCpuGuid = { 0x6E5AF2E3, 0x5D84, 0x48F2, { 0x84, 0x28, 0x99, 0xE4, 0x93, 0x4F, 0x51, 0xE4 }}
+ gIntelDieInfoGfxGuid = { 0x1D3D2599, 0x7A1C, 0x4B1E, { 0x8C, 0xC5, 0x0F, 0x88, 0x27, 0xA0, 0x2E, 0xEC }}
+
[Ppis]
## Include/Ppi/Spi.h
gPchSpiPpiGuid = { 0x104c7177, 0xc2e6, 0x44f0, { 0xae, 0xe3, 0x9d, 0x0d, 0x9a, 0x52, 0xca, 0xdf } }
@@ -101,6 +108,7 @@ [Ppis]

gEdkiiVTdInfoPpiGuid = { 0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } }
gEdkiiVTdNullRootEntryTableGuid = { 0x3de0593f, 0x6e3e, 0x4542, { 0xa1, 0xcb, 0xcb, 0xb2, 0xdb, 0xeb, 0xd8, 0xff } }
+ gIntelDieInfoPpiGuid = { 0xF9E45CBF, 0x1E21, 0x434A, { 0x90, 0x88, 0x1D, 0x10, 0x38, 0xF3, 0x68, 0xF2 }}

[Protocols]
## Protocols that provide services for the Intel(R) PCH SPI Host Controller Compatibility Interface
@@ -114,6 +122,7 @@ [Protocols]
gPchSmmSpi2ProtocolGuid = { 0x2d1c0c43, 0x20d3, 0x40ae, { 0x99, 0x07, 0x2d, 0xf0, 0xe7, 0x91, 0x21, 0xa5 } }

gEdkiiPlatformVTdPolicyProtocolGuid = { 0x3d17e448, 0x466, 0x4e20, { 0x99, 0x9f, 0xb2, 0xe1, 0x34, 0x88, 0xee, 0x22 }}
+ gIntelDieInfoProtocolGuid = { 0xAED8A0A1, 0xFDE6, 0x4CF2, { 0xA3, 0x85, 0x08, 0xF1, 0x25, 0xF2, 0x40, 0x37 }}

## Protocol for device security policy.
# Include/Protocol/PlatformDeviceSecurityPolicy.h
--
2.27.0.windows.1

---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.


[edk2platforms][PATCH v3 0/1] IntelSiliconPkg: Add IntelDieInfoProtocol

Maciej Czajkowski
 

This commit will add a protocol/PPI definition which will provide a generic and
unified way to get information about dies installed in the system(PCH, SoC, CPU).
It will be implemented per generation in silicon packages.

v3 changes:
- added EDKII_ prefix to interface
- removed GUID definitons from .h file
- corrected descriptions
- made PPI/protocol GUIDs unique

v2 changes:
- added interface description
- added die specific GUIDs into .dec file

Cc: Ray Ni <ray.ni@...>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@...>


Maciej Czajkowski (1):
IntelSiliconPkg: Add IntelDieInfoProtocol

Silicon/Intel/IntelSiliconPkg/Include/Protocol/IntelDieInfo.h | 96 ++++++++++++++++++++
Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec | 9 ++
2 files changed, 105 insertions(+)
create mode 100644 Silicon/Intel/IntelSiliconPkg/Include/Protocol/IntelDieInfo.h

--
2.27.0.windows.1

---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.


Re: [edk2-platforms][PATCH v5 00/30] Add new Ampere Mt. Jade platform

Leif Lindholm
 

On Thu, Nov 18, 2021 at 20:45:15 +0700, Nhi Pham wrote:
On 18/11/2021 20:02, Leif Lindholm wrote:
Hi Nhi,

9/10 cannot be merged at this point, because that one is dependent on
"EmbeddedPkg/AcpiLib: Add more helper functions" to be merged into
edk2, which is currently in hard freeze.

But if you'd like, I'm happy for 1-8/30 to be merged at this point.
Thanks, Leif. That works for me.
1-8/30 pushed as 60d6b7c751bb..a1a215834fe8.

Thanks!

Best regards,

Nhi


Best Regards,

Leif

On Wed, Nov 17, 2021 at 23:46:57 +0700, Nhi Pham wrote:
This patch series adds the support for the Mt. Jade platform based on Ampere's
Altra Family Processor.

Notes:
+ The current patch series was tested with the edk2-stable202108 tag.
+ Require the added common functions in EmbeddedPkg AcpiLib
https://edk2.groups.io/g/devel/message/80408
+ The IASL compiler version 20201217 is required to build.
+ The edk2-non-osi source is required to build.

You can get code from
https://github.com/AmpereComputing/edk2-platforms/tree/ampere-upstream-wip-v5

Cc: Vu Nguyen <vunguyen@...>
Cc: Nhi Pham <nhi@...>
Cc: Thang Nguyen <thang@...>
Cc: Chuong Tran <chuong@...>
Cc: Phong Vo <phong@...>
Cc: Leif Lindholm <leif@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Ard Biesheuvel <ardb+tianocore@...>
Cc: Nate DeSimone <nathaniel.l.desimone@...>

Signed-off-by: Nhi Pham <nhi@...>

Changes since v4:
+ FlashLib: Fix variable naming.
+ Ac01PcieLib: Fix live-coded integers and variable naming.
+ PciSegmentLib: Fix variable naming.
+ Update the Watchdog timer configuration screen for the removal of
the FailSafe which the implementation is not compliant with PI
specification.

Changes since v3:
We had mainly restructured the PCIe libraries and updated the FlashLib.
+ Ac01PcieLib
* Address all Leif's feedback, especially on variable/macro naming and
enum definitions.
* Update with the new PciePhyLib wrapper for removing the awkward
stuff.
* Move ACPI stuff to AcpiPlatformDxe through new files: AcpiIort.c,
AcpiMcfg.c. And, PCIe patching is moved to AcpiDsdt.c.
* Move functions to access the PCIe configuration space to the PciSegmentLib.
* Ac01PcieLib now maintains the basic functions to initialize the PCIe Root Complex.
+ BoardPcieLib
* Address all Leif's feedback.
* Separate PCIe screen menu from the BoardPcieLib into an independent
module called RootComplexConfigDxe.
* BoardPcieLib take responsibility for providing the segment number and
handling the PERST
+ **NEW** PcieInitPei: To build the Root Complex HOB and initialize all PCIe
Root Complexes.
+ PciHostBridgeLib: Remove the event for fixing up the ACPI table.
+ **NEW** Add RuntimeFlashLib
+ **NEW** Add RuntimeNVParamLib
+ Remove PlatformPeiLib, MemoryInitPei, MmCommunicationDxe -> Leverage modules
from edk2 code.
+ Drop PlatformPcieDeviceConfigDxe as it will be upstreamed later.
+ Merge FailSafeLib into FailSafeDxe
+ Rename NVRAM_UUID to PLATFORM_CONFIG_UUID
+ Other minor improvements based on Leif's feedback.
+ Update sign-off tag to Nhi Pham, but don't change author.

Changes since v2:
+ Addressed all Leif's feedback.

Changes since v1:
+ Addressed all Leif's feedback in the thread
https://edk2.groups.io/g/devel/message/70356.
+ Removed the LinuxBoot image as Leif's feedback in the thread
https://edk2.groups.io/g/devel/message/68717. The image will be
pre-produced by users as the instruction in the README before compiling.
+ Other major code improvements from in-house review:
* Create new AmperePlatformPkg and AmpereSiliconPkg packages for
containing common Platform/Silicon modules.
* Remove SMProLib and PMProLib libraries which are replaced by the
MailboxInterfaceLib and SystemFirmwareInterfaceLib libraries for the
communication interface between UEFI and System Firmware.
* Clean up and fix coding styles to conform to EDK II C Coding
Standards Specification.


Nhi Pham (7):
JadePkg: Implement RealTimeClockLib for PCF85063
AmpereAltraPkg, JadePkg: Add ACPI support
JadePkg: Add ASpeed GOP driver
AmpereAltraPkg: Add Random Number Generator Support
AmpereAltraPkg: Add platform info screen
AmpereAltraPkg: Add configuration screen for CPU
AmpereAltraPkg: Add configuration screen for ACPI

Quan Nguyen (3):
AmpereAltraPkg: Add BootProgress support
JadePkg: Add SMBIOS tables support
AmpereAltraPkg: Add configuration screen for RAS

Vu Nguyen (20):
Ampere: Initial support for Ampere Altra processor and Mt. Jade
platform
AmpereAltraPkg: Add FlashLib library instance
AmpereAltraPkg: Add DwI2cLib library instance
AmpereAltraPkg: Add DwGpioLib library instance
AmpereAltraPkg: Support UEFI non-volatile variable
AmpereSiliconPkg: Add PlatformManagerUiLib library instance
AmpereAltraPkg: Add Root Complex HOB data structures
AmpereAltraPkg: Add Ac01PcieLib library instance
JadePkg: Add BoardPcieLib library instance
AmpereAltraPkg: Add driver to initialize PCIe Root Complex
AmpereAltraPkg: Add PciHostBridgeLib library instance
AmpereAltraPkg: Add PciSegmentLib library instance
JadePkg: Enable PciHostBridgeDxe driver
JadePkg: Add PciPlatformDxe driver
JadePkg: Add ACPI tables to support PCIe
AmpereAltraPkg: Add DebugInfoPei module
AmpereAltraPkg: Add configuration screen for PCIe
Ampere: Utilize the PCIe User setting
AmpereAltraPkg: Add configuration screen for Memory
AmpereAltraPkg: Add configuration screen for Watchdog timer

.../Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 75 +
.../AmpereSiliconPkg/AmpereSiliconPkg.dec | 82 +
.../AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 741 +++
Platform/Ampere/JadePkg/Jade.dsc | 194 +
Platform/Ampere/JadePkg/Jade.fdf | 362 ++
.../Ampere/JadePkg/AcpiTables/AcpiTables.inf | 20 +
.../AcpiPlatformDxe/AcpiPlatformDxe.inf | 83 +
.../Drivers/PciPlatformDxe/PciPlatformDxe.inf | 41 +
.../SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf | 45 +
.../SmbiosPlatformDxe/SmbiosPlatformDxe.inf | 53 +
.../Library/BoardPcieLib/BoardPcieLib.inf | 27 +
.../JadePkg/Library/OemMiscLib/OemMiscLib.inf | 36 +
.../PCF85063RealTimeClockLib.inf | 44 +
.../AcpiCommonTables/AcpiCommonTables.inf | 44 +
.../Drivers/ATFHobPei/ATFHobPeim.inf | 41 +
.../Drivers/AcpiConfigDxe/AcpiConfigDxe.inf | 58 +
.../BootProgressDxe/BootProgressDxe.inf | 51 +
.../BootProgressPeim/BootProgressPeim.inf | 49 +
.../Drivers/CpuConfigDxe/CpuConfigDxe.inf | 58 +
.../Drivers/DebugInfoPei/DebugInfoPei.inf | 40 +
.../Drivers/FlashFvbDxe/FlashFvbDxe.inf | 54 +
.../Drivers/FlashPei/FlashPei.inf | 49 +
.../Drivers/MemInfoDxe/MemInfoDxe.inf | 59 +
.../Drivers/PcieInitPei/PcieInitPei.inf | 45 +
.../PlatformInfoDxe/PlatformInfoDxe.inf | 52 +
.../Drivers/RasConfigDxe/RasConfigDxe.inf | 56 +
.../AmpereAltraPkg/Drivers/RngDxe/RngDxe.inf | 43 +
.../RootComplexConfigDxe.inf | 61 +
.../WatchdogConfigDxe/WatchdogConfigDxe.inf | 50 +
.../Library/Ac01PcieLib/Ac01PcieLib.inf | 42 +
.../Library/AmpereCpuLib/AmpereCpuLib.inf | 45 +
.../AmpereCpuLib/RuntimeAmpereCpuLib.inf | 50 +
.../Library/ArmPlatformLib/ArmPlatformLib.inf | 57 +
.../BoardPcieLibNull/BoardPcieLibNull.inf | 25 +
.../Library/DwGpioLib/DwGpioLib.inf | 33 +
.../Library/DwI2cLib/DwI2cLib.inf | 38 +
.../Library/FlashLib/FlashLib.inf | 35 +
.../Library/FlashLib/RuntimeFlashLib.inf | 37 +
.../MailboxInterfaceLib.inf | 37 +
.../MemoryInitPeiLib/MemoryInitPeiLib.inf | 59 +
.../MmCommunicationLib/MmCommunicationLib.inf | 35 +
.../Library/NVParamLib/NVParamLib.inf | 33 +
.../Library/NVParamLib/RuntimeNVParamLib.inf | 35 +
.../PciHostBridgeLib/PciHostBridgeLib.inf | 39 +
.../PciSegmentLibPci/PciSegmentLibPci.inf | 32 +
.../AmpereAltraPkg/Library/RngLib/RngLib.inf | 29 +
.../SystemFirmwareInterfaceLib.inf | 30 +
.../Library/TrngLib/TrngLib.inf | 29 +
.../PlatformUiLib/PlatformManagerUiLib.inf | 47 +
.../Drivers/AcpiPlatformDxe/AcpiApei.h | 133 +
.../Drivers/AcpiPlatformDxe/AcpiNfit.h | 50 +
.../Drivers/AcpiPlatformDxe/AcpiPlatform.h | 86 +
.../PCF85063RealTimeClockLib/PCF85063.h | 91 +
.../Drivers/AcpiConfigDxe/AcpiConfigDxe.h | 62 +
.../Drivers/CpuConfigDxe/CpuConfigDxe.h | 52 +
.../CpuConfigDxe/CpuConfigNVDataStruc.h | 19 +
.../Drivers/MemInfoDxe/MemInfoScreen.h | 159 +
.../MemInfoDxe/MemInfoScreenNVDataStruct.h | 47 +
.../Drivers/PcieInitPei/RootComplexNVParam.h | 28 +
.../Drivers/PlatformInfoDxe/PlatformInfoHii.h | 22 +
.../Drivers/RasConfigDxe/RasConfigDxe.h | 61 +
.../RasConfigDxe/RasConfigNVDataStruct.h | 46 +
.../RootComplexConfigDxe.h | 114 +
.../RootComplexConfigNVDataStruct.h | 91 +
.../WatchdogConfigDxe/WatchdogConfigDxe.h | 73 +
.../WatchdogConfigNVDataStruct.h | 25 +
.../Include/AcpiConfigNVDataStruct.h | 28 +
.../AmpereAltraPkg/Include/AcpiHeader.h | 37 +
.../Include/Guid/AcpiConfigHii.h | 19 +
.../Include/Guid/CpuConfigHii.h | 19 +
.../Include/Guid/PlatformInfoHob.h | 188 +
.../Include/Guid/RootComplexConfigHii.h | 33 +
.../Include/Guid/RootComplexInfoHob.h | 140 +
.../Include/Guid/WatchdogConfigHii.h | 19 +
.../Include/Library/Ac01PcieLib.h | 49 +
.../Include/Library/AmpereCpuLib.h | 276 +
.../Include/Library/BoardPcieLib.h | 45 +
.../AmpereAltraPkg/Include/Library/FlashLib.h | 118 +
.../AmpereAltraPkg/Include/Library/GpioLib.h | 76 +
.../AmpereAltraPkg/Include/Library/I2cLib.h | 100 +
.../Include/Library/MailboxInterfaceLib.h | 172 +
.../Include/Library/MmCommunicationLib.h | 44 +
.../Include/Library/NVParamLib.h | 134 +
.../Library/SystemFirmwareInterfaceLib.h | 282 +
.../AmpereAltraPkg/Include/Library/TrngLib.h | 31 +
.../AmpereAltraPkg/Include/NVParamDef.h | 534 ++
.../AmpereAltraPkg/Include/Platform/Ac01.h | 342 +
.../Library/Ac01PcieLib/PcieCore.h | 372 ++
.../ArmPlatformLib/PlatformMemoryMap.h | 135 +
.../Library/FlashLib/FlashLibCommon.h | 92 +
.../Library/NVParamLib/NVParamLibCommon.h | 70 +
.../Include/Guid/PlatformManagerHii.h | 31 +
.../Library/PlatformUiLib/PlatformManager.h | 51 +
.../PlatformUiLib/PlatformManagerVfr.h | 28 +
.../Drivers/AcpiConfigDxe/AcpiConfigVfr.vfr | 69 +
.../Drivers/CpuConfigDxe/CpuConfigVfr.vfr | 43 +
.../Drivers/MemInfoDxe/MemInfoScreenVfr.vfr | 62 +
.../PlatformInfoDxe/PlatformInfoVfr.vfr | 112 +
.../Drivers/RasConfigDxe/RasConfigVfr.vfr | 95 +
.../RootComplexConfigVfr.vfr | 219 +
.../WatchdogConfigDxe/WatchdogConfigVfr.vfr | 45 +
.../Drivers/AcpiPlatformDxe/AcpiApei.c | 454 ++
.../Drivers/AcpiPlatformDxe/AcpiDsdt.c | 691 ++
.../Drivers/AcpiPlatformDxe/AcpiIort.c | 367 ++
.../Drivers/AcpiPlatformDxe/AcpiMadt.c | 348 +
.../Drivers/AcpiPlatformDxe/AcpiMcfg.c | 151 +
.../Drivers/AcpiPlatformDxe/AcpiNfit.c | 596 ++
.../Drivers/AcpiPlatformDxe/AcpiPcct.c | 413 ++
.../Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c | 188 +
.../Drivers/AcpiPlatformDxe/AcpiPptt.c | 333 +
.../Drivers/AcpiPlatformDxe/AcpiSlit.c | 187 +
.../Drivers/AcpiPlatformDxe/AcpiSrat.c | 271 +
.../Drivers/PciPlatformDxe/PciPlatformDxe.c | 258 +
.../SmbiosMemInfoDxe/SmbiosMemInfoDxe.c | 704 ++
.../SmbiosPlatformDxe/SmbiosPlatformDxe.c | 1153 ++++
.../Library/BoardPcieLib/BoardPcieLib.c | 117 +
.../JadePkg/Library/OemMiscLib/OemMiscLib.c | 325 +
.../PCF85063RealTimeClockLib/PCF85063.c | 317 +
.../PCF85063RealTimeClockLib.c | 257 +
.../Drivers/ATFHobPei/ATFHobPeim.c | 51 +
.../Drivers/AcpiConfigDxe/AcpiConfigDxe.c | 728 +++
.../BootProgressDxe/BootProgressDxe.c | 212 +
.../BootProgressPeim/BootProgressPeim.c | 211 +
.../Drivers/CpuConfigDxe/CpuConfigDxe.c | 530 ++
.../Drivers/DebugInfoPei/DebugInfoPei.c | 209 +
.../Drivers/FlashFvbDxe/FlashFvbDxe.c | 525 ++
.../Drivers/FlashPei/FlashPei.c | 125 +
.../Drivers/MemInfoDxe/MemInfoNvramLib.c | 394 ++
.../Drivers/MemInfoDxe/MemInfoScreen.c | 1395 ++++
.../Drivers/PcieInitPei/PcieInitPei.c | 191 +
.../Drivers/PcieInitPei/RootComplexNVParam.c | 514 ++
.../Drivers/PlatformInfoDxe/PlatformInfoDxe.c | 390 ++
.../Drivers/RasConfigDxe/RasConfigDxe.c | 821 +++
.../AmpereAltraPkg/Drivers/RngDxe/RngDxe.c | 164 +
.../RootComplexConfigDxe.c | 1226 ++++
.../WatchdogConfigDxe/WatchdogConfigDxe.c | 435 ++
.../Library/Ac01PcieLib/PcieCore.c | 1419 +++++
.../Library/AmpereCpuLib/AmpereCpuLib.c | 42 +
.../Library/AmpereCpuLib/AmpereCpuLibCommon.c | 637 ++
.../AmpereCpuLib/RuntimeAmpereCpuLib.c | 137 +
.../Library/ArmPlatformLib/ArmPlatformLib.c | 168 +
.../ArmPlatformLib/ArmPlatformLibMemory.c | 256 +
.../BoardPcieLibNull/BoardPcieLibNull.c | 47 +
.../Library/DwGpioLib/DwGpioLib.c | 314 +
.../Library/DwI2cLib/DwI2cLib.c | 882 +++
.../Library/FlashLib/FlashLib.c | 83 +
.../Library/FlashLib/FlashLibCommon.c | 372 ++
.../Library/FlashLib/RuntimeFlashLib.c | 137 +
.../MailboxInterfaceLib/MailboxInterfaceLib.c | 281 +
.../MemoryInitPeiLib/MemoryInitPeiLib.c | 93 +
.../MmCommunicationLib/MmCommunicationLib.c | 184 +
.../Library/NVParamLib/NVParamLib.c | 64 +
.../Library/NVParamLib/NVParamLibCommon.c | 235 +
.../Library/NVParamLib/RuntimeNVParamLib.c | 130 +
.../PciHostBridgeLib/PciHostBridgeLib.c | 256 +
.../Library/PciSegmentLibPci/PciSegmentLib.c | 1523 +++++
.../AmpereAltraPkg/Library/RngLib/RngLib.c | 141 +
.../SystemFirmwareInterfaceLib.c | 328 +
.../AmpereAltraPkg/Library/TrngLib/TrngLib.c | 63 +
.../Library/PlatformUiLib/PlatformManager.c | 354 ++
Platform/Ampere/JadePkg/AcpiTables/CPU-S0.asi | 5639 +++++++++++++++++
Platform/Ampere/JadePkg/AcpiTables/CPU-S1.asi | 5639 +++++++++++++++++
Platform/Ampere/JadePkg/AcpiTables/CPU.asi | 127 +
Platform/Ampere/JadePkg/AcpiTables/Dsdt.asl | 531 ++
.../Ampere/JadePkg/AcpiTables/PCI-PDRC.asi | 217 +
.../JadePkg/AcpiTables/PCI-S0.Rca01.asi | 681 ++
Platform/Ampere/JadePkg/AcpiTables/PCI-S0.asi | 2078 ++++++
Platform/Ampere/JadePkg/AcpiTables/PCI-S1.asi | 2087 ++++++
Platform/Ampere/JadePkg/AcpiTables/PMU-S0.asi | 1303 ++++
Platform/Ampere/JadePkg/AcpiTables/PMU-S1.asi | 1303 ++++
Platform/Ampere/JadePkg/AcpiTables/PMU.asi | 10 +
.../AmpereAltraPkg/AcpiCommonTables/Bert.aslc | 33 +
.../AmpereAltraPkg/AcpiCommonTables/Dbg2.aslc | 87 +
.../AmpereAltraPkg/AcpiCommonTables/Einj.asl | 165 +
.../AmpereAltraPkg/AcpiCommonTables/Fadt.aslc | 87 +
.../AmpereAltraPkg/AcpiCommonTables/Gtdt.aslc | 180 +
.../AmpereAltraPkg/AcpiCommonTables/Hest.asl | 330 +
.../AmpereAltraPkg/AcpiCommonTables/Sdei.asl | 17 +
.../AmpereAltraPkg/AcpiCommonTables/Spcr.aslc | 81 +
.../AmpereAltraPkg/AcpiCommonTables/Ssdt.asl | 15 +
.../AcpiConfigDxe/AcpiConfigStrings.uni | 27 +
.../BootProgressDxe/BootProgressDxe.uni | 16 +
.../BootProgressPeim/BootProgressPeim.uni | 18 +
.../Drivers/CpuConfigDxe/CpuConfigStrings.uni | 17 +
.../Drivers/MemInfoDxe/MemInfoDxe.uni | 9 +
.../Drivers/MemInfoDxe/MemInfoDxeExtra.uni | 9 +
.../MemInfoDxe/MemInfoScreenStrings.uni | 64 +
.../PlatformInfoDxe/PlatformInfoStrings.uni | 56 +
.../Drivers/RasConfigDxe/RasConfigStrings.uni | 38 +
.../AmpereAltraPkg/Drivers/RngDxe/RngDxe.uni | 10 +
.../Drivers/RngDxe/RngDxeExtra.uni | 9 +
.../RootComplexConfigDxe.uni | 102 +
.../WatchdogConfigStrings.uni | 22 +
.../ArmPlatformLib/ArmPlatformHelper.S | 45 +
.../AmpereAltraPkg/Library/RngLib/RngLib.uni | 13 +
.../Ampere/AmpereSiliconPkg/FvRules.fdf.inc | 176 +
.../PlatformUiLib/PlatformManagerStrings.uni | 21 +
.../PlatformUiLib/PlatformManagerUiLib.uni | 13 +
.../PlatformUiLib/PlatformManagerVfr.Vfr | 29 +
199 files changed, 53350 insertions(+)
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
create mode 100644 Platform/Ampere/JadePkg/Jade.dsc
create mode 100644 Platform/Ampere/JadePkg/Jade.fdf
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/AcpiTables.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
create mode 100644 Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.inf
create mode 100644 Platform/Ampere/JadePkg/Library/OemMiscLib/OemMiscLib.inf
create mode 100644 Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/AcpiCommonTables.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressDxe/BootProgressDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressPeim/BootProgressPeim.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RngDxe/RngDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/RuntimeAmpereCpuLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MailboxInterfaceLib/MailboxInterfaceLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MmCommunicationLib/MmCommunicationLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/RuntimeNVParamLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/RngLib/RngLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/SystemFirmwareInterfaceLib/SystemFirmwareInterfaceLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/TrngLib/TrngLib.inf
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerUiLib.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.h
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.h
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h
create mode 100644 Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigNVDataStruc.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVParam.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/AcpiConfigNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/AcpiHeader.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/AcpiConfigHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/CpuConfigHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/PlatformInfoHob.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/RootComplexConfigHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/RootComplexInfoHob.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/WatchdogConfigHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/AmpereCpuLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/GpioLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/MailboxInterfaceLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/MmCommunicationLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/NVParamLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/SystemFirmwareInterfaceLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/TrngLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/NVParamDef.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/PlatformMemoryMap.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLibCommon.h
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Include/Guid/PlatformManagerHii.h
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManager.h
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerVfr.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigVfr.vfr
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiIort.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMadt.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMcfg.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPcct.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPptt.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSlit.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSrat.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.c
create mode 100644 Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.c
create mode 100644 Platform/Ampere/JadePkg/Library/OemMiscLib/OemMiscLib.c
create mode 100644 Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c
create mode 100644 Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressDxe/BootProgressDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressPeim/BootProgressPeim.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVParam.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RngDxe/RngDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLibCommon.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/RuntimeAmpereCpuLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/ArmPlatformLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/ArmPlatformLibMemory.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MailboxInterfaceLib/MailboxInterfaceLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MemoryInitPeiLib/MemoryInitPeiLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MmCommunicationLib/MmCommunicationLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLibCommon.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/RuntimeNVParamLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/RngLib/RngLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/SystemFirmwareInterfaceLib/SystemFirmwareInterfaceLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/TrngLib/TrngLib.c
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManager.c
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/CPU-S0.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/CPU-S1.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/CPU.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/Dsdt.asl
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PCI-PDRC.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PCI-S0.Rca01.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PCI-S0.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PCI-S1.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PMU-S0.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PMU-S1.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PMU.asi
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Bert.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Dbg2.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Einj.asl
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Fadt.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Gtdt.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Hest.asl
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Sdei.asl
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Spcr.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Ssdt.asl
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressDxe/BootProgressDxe.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressPeim/BootProgressPeim.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RngDxe/RngDxe.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RngDxe/RngDxeExtra.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/ArmPlatformHelper.S
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/RngLib/RngLib.uni
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/FvRules.fdf.inc
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerStrings.uni
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerUiLib.uni
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerVfr.Vfr

--
2.17.1


Re: [edk2-platforms][PATCH v5 00/30] Add new Ampere Mt. Jade platform

Nhi Pham
 

On 18/11/2021 20:02, Leif Lindholm wrote:
Hi Nhi,

9/10 cannot be merged at this point, because that one is dependent on
"EmbeddedPkg/AcpiLib: Add more helper functions" to be merged into
edk2, which is currently in hard freeze.

But if you'd like, I'm happy for 1-8/30 to be merged at this point.
Thanks, Leif. That works for me.

Best regards,

Nhi


Best Regards,

Leif

On Wed, Nov 17, 2021 at 23:46:57 +0700, Nhi Pham wrote:
This patch series adds the support for the Mt. Jade platform based on Ampere's
Altra Family Processor.

Notes:
+ The current patch series was tested with the edk2-stable202108 tag.
+ Require the added common functions in EmbeddedPkg AcpiLib
https://edk2.groups.io/g/devel/message/80408
+ The IASL compiler version 20201217 is required to build.
+ The edk2-non-osi source is required to build.

You can get code from
https://github.com/AmpereComputing/edk2-platforms/tree/ampere-upstream-wip-v5

Cc: Vu Nguyen <vunguyen@...>
Cc: Nhi Pham <nhi@...>
Cc: Thang Nguyen <thang@...>
Cc: Chuong Tran <chuong@...>
Cc: Phong Vo <phong@...>
Cc: Leif Lindholm <leif@...>
Cc: Michael D Kinney <michael.d.kinney@...>
Cc: Ard Biesheuvel <ardb+tianocore@...>
Cc: Nate DeSimone <nathaniel.l.desimone@...>

Signed-off-by: Nhi Pham <nhi@...>

Changes since v4:
+ FlashLib: Fix variable naming.
+ Ac01PcieLib: Fix live-coded integers and variable naming.
+ PciSegmentLib: Fix variable naming.
+ Update the Watchdog timer configuration screen for the removal of
the FailSafe which the implementation is not compliant with PI
specification.

Changes since v3:
We had mainly restructured the PCIe libraries and updated the FlashLib.
+ Ac01PcieLib
* Address all Leif's feedback, especially on variable/macro naming and
enum definitions.
* Update with the new PciePhyLib wrapper for removing the awkward
stuff.
* Move ACPI stuff to AcpiPlatformDxe through new files: AcpiIort.c,
AcpiMcfg.c. And, PCIe patching is moved to AcpiDsdt.c.
* Move functions to access the PCIe configuration space to the PciSegmentLib.
* Ac01PcieLib now maintains the basic functions to initialize the PCIe Root Complex.
+ BoardPcieLib
* Address all Leif's feedback.
* Separate PCIe screen menu from the BoardPcieLib into an independent
module called RootComplexConfigDxe.
* BoardPcieLib take responsibility for providing the segment number and
handling the PERST
+ **NEW** PcieInitPei: To build the Root Complex HOB and initialize all PCIe
Root Complexes.
+ PciHostBridgeLib: Remove the event for fixing up the ACPI table.
+ **NEW** Add RuntimeFlashLib
+ **NEW** Add RuntimeNVParamLib
+ Remove PlatformPeiLib, MemoryInitPei, MmCommunicationDxe -> Leverage modules
from edk2 code.
+ Drop PlatformPcieDeviceConfigDxe as it will be upstreamed later.
+ Merge FailSafeLib into FailSafeDxe
+ Rename NVRAM_UUID to PLATFORM_CONFIG_UUID
+ Other minor improvements based on Leif's feedback.
+ Update sign-off tag to Nhi Pham, but don't change author.

Changes since v2:
+ Addressed all Leif's feedback.

Changes since v1:
+ Addressed all Leif's feedback in the thread
https://edk2.groups.io/g/devel/message/70356.
+ Removed the LinuxBoot image as Leif's feedback in the thread
https://edk2.groups.io/g/devel/message/68717. The image will be
pre-produced by users as the instruction in the README before compiling.
+ Other major code improvements from in-house review:
* Create new AmperePlatformPkg and AmpereSiliconPkg packages for
containing common Platform/Silicon modules.
* Remove SMProLib and PMProLib libraries which are replaced by the
MailboxInterfaceLib and SystemFirmwareInterfaceLib libraries for the
communication interface between UEFI and System Firmware.
* Clean up and fix coding styles to conform to EDK II C Coding
Standards Specification.


Nhi Pham (7):
JadePkg: Implement RealTimeClockLib for PCF85063
AmpereAltraPkg, JadePkg: Add ACPI support
JadePkg: Add ASpeed GOP driver
AmpereAltraPkg: Add Random Number Generator Support
AmpereAltraPkg: Add platform info screen
AmpereAltraPkg: Add configuration screen for CPU
AmpereAltraPkg: Add configuration screen for ACPI

Quan Nguyen (3):
AmpereAltraPkg: Add BootProgress support
JadePkg: Add SMBIOS tables support
AmpereAltraPkg: Add configuration screen for RAS

Vu Nguyen (20):
Ampere: Initial support for Ampere Altra processor and Mt. Jade
platform
AmpereAltraPkg: Add FlashLib library instance
AmpereAltraPkg: Add DwI2cLib library instance
AmpereAltraPkg: Add DwGpioLib library instance
AmpereAltraPkg: Support UEFI non-volatile variable
AmpereSiliconPkg: Add PlatformManagerUiLib library instance
AmpereAltraPkg: Add Root Complex HOB data structures
AmpereAltraPkg: Add Ac01PcieLib library instance
JadePkg: Add BoardPcieLib library instance
AmpereAltraPkg: Add driver to initialize PCIe Root Complex
AmpereAltraPkg: Add PciHostBridgeLib library instance
AmpereAltraPkg: Add PciSegmentLib library instance
JadePkg: Enable PciHostBridgeDxe driver
JadePkg: Add PciPlatformDxe driver
JadePkg: Add ACPI tables to support PCIe
AmpereAltraPkg: Add DebugInfoPei module
AmpereAltraPkg: Add configuration screen for PCIe
Ampere: Utilize the PCIe User setting
AmpereAltraPkg: Add configuration screen for Memory
AmpereAltraPkg: Add configuration screen for Watchdog timer

.../Ampere/AmpereAltraPkg/AmpereAltraPkg.dec | 75 +
.../AmpereSiliconPkg/AmpereSiliconPkg.dec | 82 +
.../AmpereAltraPkg/AmpereAltraPkg.dsc.inc | 741 +++
Platform/Ampere/JadePkg/Jade.dsc | 194 +
Platform/Ampere/JadePkg/Jade.fdf | 362 ++
.../Ampere/JadePkg/AcpiTables/AcpiTables.inf | 20 +
.../AcpiPlatformDxe/AcpiPlatformDxe.inf | 83 +
.../Drivers/PciPlatformDxe/PciPlatformDxe.inf | 41 +
.../SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf | 45 +
.../SmbiosPlatformDxe/SmbiosPlatformDxe.inf | 53 +
.../Library/BoardPcieLib/BoardPcieLib.inf | 27 +
.../JadePkg/Library/OemMiscLib/OemMiscLib.inf | 36 +
.../PCF85063RealTimeClockLib.inf | 44 +
.../AcpiCommonTables/AcpiCommonTables.inf | 44 +
.../Drivers/ATFHobPei/ATFHobPeim.inf | 41 +
.../Drivers/AcpiConfigDxe/AcpiConfigDxe.inf | 58 +
.../BootProgressDxe/BootProgressDxe.inf | 51 +
.../BootProgressPeim/BootProgressPeim.inf | 49 +
.../Drivers/CpuConfigDxe/CpuConfigDxe.inf | 58 +
.../Drivers/DebugInfoPei/DebugInfoPei.inf | 40 +
.../Drivers/FlashFvbDxe/FlashFvbDxe.inf | 54 +
.../Drivers/FlashPei/FlashPei.inf | 49 +
.../Drivers/MemInfoDxe/MemInfoDxe.inf | 59 +
.../Drivers/PcieInitPei/PcieInitPei.inf | 45 +
.../PlatformInfoDxe/PlatformInfoDxe.inf | 52 +
.../Drivers/RasConfigDxe/RasConfigDxe.inf | 56 +
.../AmpereAltraPkg/Drivers/RngDxe/RngDxe.inf | 43 +
.../RootComplexConfigDxe.inf | 61 +
.../WatchdogConfigDxe/WatchdogConfigDxe.inf | 50 +
.../Library/Ac01PcieLib/Ac01PcieLib.inf | 42 +
.../Library/AmpereCpuLib/AmpereCpuLib.inf | 45 +
.../AmpereCpuLib/RuntimeAmpereCpuLib.inf | 50 +
.../Library/ArmPlatformLib/ArmPlatformLib.inf | 57 +
.../BoardPcieLibNull/BoardPcieLibNull.inf | 25 +
.../Library/DwGpioLib/DwGpioLib.inf | 33 +
.../Library/DwI2cLib/DwI2cLib.inf | 38 +
.../Library/FlashLib/FlashLib.inf | 35 +
.../Library/FlashLib/RuntimeFlashLib.inf | 37 +
.../MailboxInterfaceLib.inf | 37 +
.../MemoryInitPeiLib/MemoryInitPeiLib.inf | 59 +
.../MmCommunicationLib/MmCommunicationLib.inf | 35 +
.../Library/NVParamLib/NVParamLib.inf | 33 +
.../Library/NVParamLib/RuntimeNVParamLib.inf | 35 +
.../PciHostBridgeLib/PciHostBridgeLib.inf | 39 +
.../PciSegmentLibPci/PciSegmentLibPci.inf | 32 +
.../AmpereAltraPkg/Library/RngLib/RngLib.inf | 29 +
.../SystemFirmwareInterfaceLib.inf | 30 +
.../Library/TrngLib/TrngLib.inf | 29 +
.../PlatformUiLib/PlatformManagerUiLib.inf | 47 +
.../Drivers/AcpiPlatformDxe/AcpiApei.h | 133 +
.../Drivers/AcpiPlatformDxe/AcpiNfit.h | 50 +
.../Drivers/AcpiPlatformDxe/AcpiPlatform.h | 86 +
.../PCF85063RealTimeClockLib/PCF85063.h | 91 +
.../Drivers/AcpiConfigDxe/AcpiConfigDxe.h | 62 +
.../Drivers/CpuConfigDxe/CpuConfigDxe.h | 52 +
.../CpuConfigDxe/CpuConfigNVDataStruc.h | 19 +
.../Drivers/MemInfoDxe/MemInfoScreen.h | 159 +
.../MemInfoDxe/MemInfoScreenNVDataStruct.h | 47 +
.../Drivers/PcieInitPei/RootComplexNVParam.h | 28 +
.../Drivers/PlatformInfoDxe/PlatformInfoHii.h | 22 +
.../Drivers/RasConfigDxe/RasConfigDxe.h | 61 +
.../RasConfigDxe/RasConfigNVDataStruct.h | 46 +
.../RootComplexConfigDxe.h | 114 +
.../RootComplexConfigNVDataStruct.h | 91 +
.../WatchdogConfigDxe/WatchdogConfigDxe.h | 73 +
.../WatchdogConfigNVDataStruct.h | 25 +
.../Include/AcpiConfigNVDataStruct.h | 28 +
.../AmpereAltraPkg/Include/AcpiHeader.h | 37 +
.../Include/Guid/AcpiConfigHii.h | 19 +
.../Include/Guid/CpuConfigHii.h | 19 +
.../Include/Guid/PlatformInfoHob.h | 188 +
.../Include/Guid/RootComplexConfigHii.h | 33 +
.../Include/Guid/RootComplexInfoHob.h | 140 +
.../Include/Guid/WatchdogConfigHii.h | 19 +
.../Include/Library/Ac01PcieLib.h | 49 +
.../Include/Library/AmpereCpuLib.h | 276 +
.../Include/Library/BoardPcieLib.h | 45 +
.../AmpereAltraPkg/Include/Library/FlashLib.h | 118 +
.../AmpereAltraPkg/Include/Library/GpioLib.h | 76 +
.../AmpereAltraPkg/Include/Library/I2cLib.h | 100 +
.../Include/Library/MailboxInterfaceLib.h | 172 +
.../Include/Library/MmCommunicationLib.h | 44 +
.../Include/Library/NVParamLib.h | 134 +
.../Library/SystemFirmwareInterfaceLib.h | 282 +
.../AmpereAltraPkg/Include/Library/TrngLib.h | 31 +
.../AmpereAltraPkg/Include/NVParamDef.h | 534 ++
.../AmpereAltraPkg/Include/Platform/Ac01.h | 342 +
.../Library/Ac01PcieLib/PcieCore.h | 372 ++
.../ArmPlatformLib/PlatformMemoryMap.h | 135 +
.../Library/FlashLib/FlashLibCommon.h | 92 +
.../Library/NVParamLib/NVParamLibCommon.h | 70 +
.../Include/Guid/PlatformManagerHii.h | 31 +
.../Library/PlatformUiLib/PlatformManager.h | 51 +
.../PlatformUiLib/PlatformManagerVfr.h | 28 +
.../Drivers/AcpiConfigDxe/AcpiConfigVfr.vfr | 69 +
.../Drivers/CpuConfigDxe/CpuConfigVfr.vfr | 43 +
.../Drivers/MemInfoDxe/MemInfoScreenVfr.vfr | 62 +
.../PlatformInfoDxe/PlatformInfoVfr.vfr | 112 +
.../Drivers/RasConfigDxe/RasConfigVfr.vfr | 95 +
.../RootComplexConfigVfr.vfr | 219 +
.../WatchdogConfigDxe/WatchdogConfigVfr.vfr | 45 +
.../Drivers/AcpiPlatformDxe/AcpiApei.c | 454 ++
.../Drivers/AcpiPlatformDxe/AcpiDsdt.c | 691 ++
.../Drivers/AcpiPlatformDxe/AcpiIort.c | 367 ++
.../Drivers/AcpiPlatformDxe/AcpiMadt.c | 348 +
.../Drivers/AcpiPlatformDxe/AcpiMcfg.c | 151 +
.../Drivers/AcpiPlatformDxe/AcpiNfit.c | 596 ++
.../Drivers/AcpiPlatformDxe/AcpiPcct.c | 413 ++
.../Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c | 188 +
.../Drivers/AcpiPlatformDxe/AcpiPptt.c | 333 +
.../Drivers/AcpiPlatformDxe/AcpiSlit.c | 187 +
.../Drivers/AcpiPlatformDxe/AcpiSrat.c | 271 +
.../Drivers/PciPlatformDxe/PciPlatformDxe.c | 258 +
.../SmbiosMemInfoDxe/SmbiosMemInfoDxe.c | 704 ++
.../SmbiosPlatformDxe/SmbiosPlatformDxe.c | 1153 ++++
.../Library/BoardPcieLib/BoardPcieLib.c | 117 +
.../JadePkg/Library/OemMiscLib/OemMiscLib.c | 325 +
.../PCF85063RealTimeClockLib/PCF85063.c | 317 +
.../PCF85063RealTimeClockLib.c | 257 +
.../Drivers/ATFHobPei/ATFHobPeim.c | 51 +
.../Drivers/AcpiConfigDxe/AcpiConfigDxe.c | 728 +++
.../BootProgressDxe/BootProgressDxe.c | 212 +
.../BootProgressPeim/BootProgressPeim.c | 211 +
.../Drivers/CpuConfigDxe/CpuConfigDxe.c | 530 ++
.../Drivers/DebugInfoPei/DebugInfoPei.c | 209 +
.../Drivers/FlashFvbDxe/FlashFvbDxe.c | 525 ++
.../Drivers/FlashPei/FlashPei.c | 125 +
.../Drivers/MemInfoDxe/MemInfoNvramLib.c | 394 ++
.../Drivers/MemInfoDxe/MemInfoScreen.c | 1395 ++++
.../Drivers/PcieInitPei/PcieInitPei.c | 191 +
.../Drivers/PcieInitPei/RootComplexNVParam.c | 514 ++
.../Drivers/PlatformInfoDxe/PlatformInfoDxe.c | 390 ++
.../Drivers/RasConfigDxe/RasConfigDxe.c | 821 +++
.../AmpereAltraPkg/Drivers/RngDxe/RngDxe.c | 164 +
.../RootComplexConfigDxe.c | 1226 ++++
.../WatchdogConfigDxe/WatchdogConfigDxe.c | 435 ++
.../Library/Ac01PcieLib/PcieCore.c | 1419 +++++
.../Library/AmpereCpuLib/AmpereCpuLib.c | 42 +
.../Library/AmpereCpuLib/AmpereCpuLibCommon.c | 637 ++
.../AmpereCpuLib/RuntimeAmpereCpuLib.c | 137 +
.../Library/ArmPlatformLib/ArmPlatformLib.c | 168 +
.../ArmPlatformLib/ArmPlatformLibMemory.c | 256 +
.../BoardPcieLibNull/BoardPcieLibNull.c | 47 +
.../Library/DwGpioLib/DwGpioLib.c | 314 +
.../Library/DwI2cLib/DwI2cLib.c | 882 +++
.../Library/FlashLib/FlashLib.c | 83 +
.../Library/FlashLib/FlashLibCommon.c | 372 ++
.../Library/FlashLib/RuntimeFlashLib.c | 137 +
.../MailboxInterfaceLib/MailboxInterfaceLib.c | 281 +
.../MemoryInitPeiLib/MemoryInitPeiLib.c | 93 +
.../MmCommunicationLib/MmCommunicationLib.c | 184 +
.../Library/NVParamLib/NVParamLib.c | 64 +
.../Library/NVParamLib/NVParamLibCommon.c | 235 +
.../Library/NVParamLib/RuntimeNVParamLib.c | 130 +
.../PciHostBridgeLib/PciHostBridgeLib.c | 256 +
.../Library/PciSegmentLibPci/PciSegmentLib.c | 1523 +++++
.../AmpereAltraPkg/Library/RngLib/RngLib.c | 141 +
.../SystemFirmwareInterfaceLib.c | 328 +
.../AmpereAltraPkg/Library/TrngLib/TrngLib.c | 63 +
.../Library/PlatformUiLib/PlatformManager.c | 354 ++
Platform/Ampere/JadePkg/AcpiTables/CPU-S0.asi | 5639 +++++++++++++++++
Platform/Ampere/JadePkg/AcpiTables/CPU-S1.asi | 5639 +++++++++++++++++
Platform/Ampere/JadePkg/AcpiTables/CPU.asi | 127 +
Platform/Ampere/JadePkg/AcpiTables/Dsdt.asl | 531 ++
.../Ampere/JadePkg/AcpiTables/PCI-PDRC.asi | 217 +
.../JadePkg/AcpiTables/PCI-S0.Rca01.asi | 681 ++
Platform/Ampere/JadePkg/AcpiTables/PCI-S0.asi | 2078 ++++++
Platform/Ampere/JadePkg/AcpiTables/PCI-S1.asi | 2087 ++++++
Platform/Ampere/JadePkg/AcpiTables/PMU-S0.asi | 1303 ++++
Platform/Ampere/JadePkg/AcpiTables/PMU-S1.asi | 1303 ++++
Platform/Ampere/JadePkg/AcpiTables/PMU.asi | 10 +
.../AmpereAltraPkg/AcpiCommonTables/Bert.aslc | 33 +
.../AmpereAltraPkg/AcpiCommonTables/Dbg2.aslc | 87 +
.../AmpereAltraPkg/AcpiCommonTables/Einj.asl | 165 +
.../AmpereAltraPkg/AcpiCommonTables/Fadt.aslc | 87 +
.../AmpereAltraPkg/AcpiCommonTables/Gtdt.aslc | 180 +
.../AmpereAltraPkg/AcpiCommonTables/Hest.asl | 330 +
.../AmpereAltraPkg/AcpiCommonTables/Sdei.asl | 17 +
.../AmpereAltraPkg/AcpiCommonTables/Spcr.aslc | 81 +
.../AmpereAltraPkg/AcpiCommonTables/Ssdt.asl | 15 +
.../AcpiConfigDxe/AcpiConfigStrings.uni | 27 +
.../BootProgressDxe/BootProgressDxe.uni | 16 +
.../BootProgressPeim/BootProgressPeim.uni | 18 +
.../Drivers/CpuConfigDxe/CpuConfigStrings.uni | 17 +
.../Drivers/MemInfoDxe/MemInfoDxe.uni | 9 +
.../Drivers/MemInfoDxe/MemInfoDxeExtra.uni | 9 +
.../MemInfoDxe/MemInfoScreenStrings.uni | 64 +
.../PlatformInfoDxe/PlatformInfoStrings.uni | 56 +
.../Drivers/RasConfigDxe/RasConfigStrings.uni | 38 +
.../AmpereAltraPkg/Drivers/RngDxe/RngDxe.uni | 10 +
.../Drivers/RngDxe/RngDxeExtra.uni | 9 +
.../RootComplexConfigDxe.uni | 102 +
.../WatchdogConfigStrings.uni | 22 +
.../ArmPlatformLib/ArmPlatformHelper.S | 45 +
.../AmpereAltraPkg/Library/RngLib/RngLib.uni | 13 +
.../Ampere/AmpereSiliconPkg/FvRules.fdf.inc | 176 +
.../PlatformUiLib/PlatformManagerStrings.uni | 21 +
.../PlatformUiLib/PlatformManagerUiLib.uni | 13 +
.../PlatformUiLib/PlatformManagerVfr.Vfr | 29 +
199 files changed, 53350 insertions(+)
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dec
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/AmpereSiliconPkg.dec
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AmpereAltraPkg.dsc.inc
create mode 100644 Platform/Ampere/JadePkg/Jade.dsc
create mode 100644 Platform/Ampere/JadePkg/Jade.fdf
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/AcpiTables.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
create mode 100644 Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.inf
create mode 100644 Platform/Ampere/JadePkg/Library/OemMiscLib/OemMiscLib.inf
create mode 100644 Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/AcpiCommonTables.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressDxe/BootProgressDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressPeim/BootProgressPeim.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RngDxe/RngDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/Ac01PcieLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/RuntimeAmpereCpuLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MailboxInterfaceLib/MailboxInterfaceLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MemoryInitPeiLib/MemoryInitPeiLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MmCommunicationLib/MmCommunicationLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/RuntimeNVParamLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLibPci.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/RngLib/RngLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/SystemFirmwareInterfaceLib/SystemFirmwareInterfaceLib.inf
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/TrngLib/TrngLib.inf
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerUiLib.inf
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.h
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.h
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatform.h
create mode 100644 Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigNVDataStruc.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVParam.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/AcpiConfigNVDataStruct.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/AcpiHeader.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/AcpiConfigHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/CpuConfigHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/PlatformInfoHob.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/RootComplexConfigHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/RootComplexInfoHob.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Guid/WatchdogConfigHii.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/Ac01PcieLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/AmpereCpuLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/BoardPcieLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/FlashLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/GpioLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/I2cLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/MailboxInterfaceLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/MmCommunicationLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/NVParamLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/SystemFirmwareInterfaceLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Library/TrngLib.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/NVParamDef.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Include/Platform/Ac01.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/PlatformMemoryMap.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLibCommon.h
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Include/Guid/PlatformManagerHii.h
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManager.h
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerVfr.h
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigVfr.vfr
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigVfr.vfr
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiApei.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiDsdt.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiIort.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMadt.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiMcfg.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiNfit.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPcct.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPlatformDxe.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiPptt.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSlit.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/AcpiPlatformDxe/AcpiSrat.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/PciPlatformDxe/PciPlatformDxe.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/SmbiosMemInfoDxe/SmbiosMemInfoDxe.c
create mode 100644 Platform/Ampere/JadePkg/Drivers/SmbiosPlatformDxe/SmbiosPlatformDxe.c
create mode 100644 Platform/Ampere/JadePkg/Library/BoardPcieLib/BoardPcieLib.c
create mode 100644 Platform/Ampere/JadePkg/Library/OemMiscLib/OemMiscLib.c
create mode 100644 Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063.c
create mode 100644 Platform/Ampere/JadePkg/Library/PCF85063RealTimeClockLib/PCF85063RealTimeClockLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/ATFHobPei/ATFHobPeim.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressDxe/BootProgressDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressPeim/BootProgressPeim.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/DebugInfoPei/DebugInfoPei.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/FlashFvbDxe/FlashFvbDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/FlashPei/FlashPei.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoNvramLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreen.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/PcieInitPei.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PcieInitPei/RootComplexNVParam.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RngDxe/RngDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigDxe.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/Ac01PcieLib/PcieCore.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/AmpereCpuLibCommon.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/AmpereCpuLib/RuntimeAmpereCpuLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/ArmPlatformLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/ArmPlatformLibMemory.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/BoardPcieLibNull/BoardPcieLibNull.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/DwGpioLib/DwGpioLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/DwI2cLib/DwI2cLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/FlashLibCommon.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/FlashLib/RuntimeFlashLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MailboxInterfaceLib/MailboxInterfaceLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MemoryInitPeiLib/MemoryInitPeiLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/MmCommunicationLib/MmCommunicationLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/NVParamLibCommon.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/NVParamLib/RuntimeNVParamLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/PciSegmentLibPci/PciSegmentLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/RngLib/RngLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/SystemFirmwareInterfaceLib/SystemFirmwareInterfaceLib.c
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/TrngLib/TrngLib.c
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManager.c
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/CPU-S0.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/CPU-S1.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/CPU.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/Dsdt.asl
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PCI-PDRC.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PCI-S0.Rca01.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PCI-S0.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PCI-S1.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PMU-S0.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PMU-S1.asi
create mode 100644 Platform/Ampere/JadePkg/AcpiTables/PMU.asi
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Bert.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Dbg2.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Einj.asl
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Fadt.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Gtdt.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Hest.asl
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Sdei.asl
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Spcr.aslc
create mode 100644 Silicon/Ampere/AmpereAltraPkg/AcpiCommonTables/Ssdt.asl
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/AcpiConfigDxe/AcpiConfigStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressDxe/BootProgressDxe.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/BootProgress/BootProgressPeim/BootProgressPeim.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/CpuConfigDxe/CpuConfigStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxe.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoDxeExtra.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/MemInfoDxe/MemInfoScreenStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/PlatformInfoDxe/PlatformInfoStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RasConfigDxe/RasConfigStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RngDxe/RngDxe.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RngDxe/RngDxeExtra.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/RootComplexConfigDxe/RootComplexConfigDxe.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Drivers/WatchdogConfigDxe/WatchdogConfigStrings.uni
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/ArmPlatformLib/ArmPlatformHelper.S
create mode 100644 Silicon/Ampere/AmpereAltraPkg/Library/RngLib/RngLib.uni
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/FvRules.fdf.inc
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerStrings.uni
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerUiLib.uni
create mode 100644 Silicon/Ampere/AmpereSiliconPkg/Library/PlatformUiLib/PlatformManagerVfr.Vfr

--
2.17.1