]> git.proxmox.com Git - mirror_edk2.git/commitdiff
DynamicTablesPkg: AML debug logging
authorPierre Gondois <pierre.gondois@arm.com>
Tue, 4 Aug 2020 13:55:03 +0000 (14:55 +0100)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Thu, 13 Aug 2020 18:00:06 +0000 (18:00 +0000)
The AML debug print functions enable logging
of the operations on the AML tree and the data
output. The debug logging functionality is
enabled for debug builds when the DEBUG_INFO
or DEBUG_VERBOSE mask is enabled in the PCD
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel

Signed-off-by: Pierre Gondois <pierre.gondois@arm.com>
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Alexei Fedorov <Alexei.Fedorov@arm.com>
DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c [new file with mode: 0644]
DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h [new file with mode: 0644]

diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c b/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c
new file mode 100644 (file)
index 0000000..7b11cc8
--- /dev/null
@@ -0,0 +1,546 @@
+/** @file\r
+  AML Print Function.\r
+\r
+  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>\r
+  Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#include <AmlNodeDefines.h>\r
+#include <AmlDbgPrint/AmlDbgPrint.h>\r
+\r
+#include <AmlCoreInterface.h>\r
+#include <String/AmlString.h>\r
+#include <Tree/AmlNode.h>\r
+#include <Tree/AmlTreeTraversal.h>\r
+\r
+#if !defined (MDEPKG_NDEBUG)\r
+\r
+/** String table representing AML Data types as defined by EAML_NODE_DATA_TYPE.\r
+*/\r
+CONST CHAR8 * NodeDataTypeStrTbl[] = {\r
+  "EAmlNodeDataTypeNone",\r
+  "EAmlNodeDataTypeReserved1",\r
+  "EAmlNodeDataTypeReserved2",\r
+  "EAmlNodeDataTypeReserved3",\r
+  "EAmlNodeDataTypeReserved4",\r
+  "EAmlNodeDataTypeReserved5",\r
+  "EAmlNodeDataTypeNameString",\r
+  "EAmlNodeDataTypeString",\r
+  "EAmlNodeDataTypeUInt",\r
+  "EAmlNodeDataTypeRaw",\r
+  "EAmlNodeDataTypeResourceData",\r
+  "EAmlNodeDataTypeFieldPkgLen",\r
+  "EAmlNodeDataTypeMax"\r
+};\r
+\r
+/** String table representing AML Node types as defined by EAML_NODE_TYPE.\r
+*/\r
+CONST CHAR8 * NodeTypeStrTbl[] = {\r
+  "EAmlNodeUnknown",\r
+  "EAmlNodeRoot",\r
+  "EAmlNodeObject",\r
+  "EAmlNodeData",\r
+  "EAmlNodeMax"\r
+};\r
+\r
+/** Print Size chars at Buffer address.\r
+\r
+  @param  [in]  ErrorLevel    Error level for the DEBUG macro.\r
+  @param  [in]  Buffer        Buffer containing the chars.\r
+  @param  [in]  Size          Number of chars to print.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintChars (\r
+  IN        UINT32      ErrorLevel,\r
+  IN  CONST CHAR8     * Buffer,\r
+  IN        UINT32      Size\r
+  )\r
+{\r
+  UINT32  i;\r
+\r
+  if (Buffer == NULL) {\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  for (i = 0; i < Size; i++) {\r
+    DEBUG ((ErrorLevel, "%c", Buffer[i]));\r
+  }\r
+}\r
+\r
+/** Print an AML NameSeg.\r
+    Don't print trailing underscores ('_').\r
+\r
+  @param  [in] Buffer   Buffer containing an AML NameSeg.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintNameSeg (\r
+  IN  CONST CHAR8   * Buffer\r
+  )\r
+{\r
+  if (Buffer == NULL) {\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "%c", Buffer[0]));\r
+  if ((Buffer[1] == AML_NAME_CHAR__)  &&\r
+      (Buffer[2] == AML_NAME_CHAR__)  &&\r
+      (Buffer[3] == AML_NAME_CHAR__)) {\r
+    return;\r
+  }\r
+  DEBUG ((DEBUG_INFO, "%c", Buffer[1]));\r
+  if ((Buffer[2] == AML_NAME_CHAR__)  &&\r
+      (Buffer[3] == AML_NAME_CHAR__)) {\r
+    return;\r
+  }\r
+  DEBUG ((DEBUG_INFO, "%c", Buffer[2]));\r
+  if (Buffer[3] == AML_NAME_CHAR__) {\r
+    return;\r
+  }\r
+  DEBUG ((DEBUG_INFO, "%c", Buffer[3]));\r
+  return;\r
+}\r
+\r
+/** Print an AML NameString.\r
+\r
+  @param  [in] Buffer   Buffer containing an AML NameString.\r
+  @param  [in] NewLine  Print a newline char at the end of the NameString.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintNameString (\r
+  IN  CONST CHAR8   * Buffer,\r
+  IN        BOOLEAN   NewLine\r
+  )\r
+{\r
+  UINT8     SegCount;\r
+  UINT8     Index;\r
+\r
+  if (Buffer == NULL) {\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  // Handle Root and Parent(s).\r
+  if (*Buffer == AML_ROOT_CHAR) {\r
+    Buffer++;\r
+    DEBUG ((DEBUG_INFO, "\\"));\r
+  } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {\r
+    do {\r
+      Buffer++;\r
+      DEBUG ((DEBUG_INFO, "^"));\r
+    } while (*Buffer == AML_PARENT_PREFIX_CHAR);\r
+  }\r
+\r
+  // Handle SegCount(s).\r
+  if (*Buffer == AML_DUAL_NAME_PREFIX) {\r
+    Buffer++;\r
+    SegCount = 2;\r
+  } else if (*Buffer == AML_MULTI_NAME_PREFIX) {\r
+    Buffer++;\r
+    // For multi name prefix the seg count is in the second byte.\r
+    SegCount = *Buffer;\r
+    Buffer++;\r
+  } else if (AmlIsLeadNameChar (*Buffer)) {\r
+    // Only check the first char first to avoid overflow.\r
+    // Then the whole NameSeg can be checked.\r
+    if (!AmlIsNameSeg (Buffer)) {\r
+      ASSERT (0);\r
+      return;\r
+    }\r
+    SegCount = 1;\r
+  } else if (*Buffer == AML_ZERO_OP) {\r
+    SegCount = 0;\r
+  } else {\r
+    // Should not be possible.\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  if (SegCount != 0) {\r
+    AmlDbgPrintNameSeg (Buffer);\r
+    Buffer += AML_NAME_SEG_SIZE;\r
+    for (Index = 0; Index < SegCount - 1; Index++) {\r
+      DEBUG ((DEBUG_INFO, "."));\r
+      AmlDbgPrintNameSeg (Buffer);\r
+      Buffer += AML_NAME_SEG_SIZE;\r
+    }\r
+  }\r
+\r
+  if (NewLine) {\r
+    DEBUG ((DEBUG_INFO, "\n"));\r
+  }\r
+\r
+  return;\r
+}\r
+\r
+/** Print the information contained in the header of the Node.\r
+\r
+  @param  [in]  Node    Pointer to a node.\r
+  @param  [in]  Level   Level of the indentation.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintNodeHeader (\r
+  IN  AML_NODE_HEADER  * Node,\r
+  IN  UINT8              Level\r
+  )\r
+{\r
+  if (!IS_AML_NODE_VALID (Node)) {\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "%3d | %-15s | ",\r
+    Level,\r
+    NodeTypeStrTbl[Node->NodeType]\r
+    ));\r
+}\r
+\r
+/** Print fields of a data node.\r
+\r
+  @param  [in]  DataNode  Pointer to a data node.\r
+  @param  [in]  Level     Level of the indentation.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintDataNode (\r
+  IN  AML_DATA_NODE   * DataNode,\r
+  IN  UINT8             Level\r
+  )\r
+{\r
+  UINT32  Idx;\r
+\r
+  if (!IS_AML_DATA_NODE (DataNode)) {\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  AmlDbgPrintNodeHeader ((AML_NODE_HEADER*)DataNode, Level);\r
+\r
+  DEBUG ((DEBUG_INFO, "%-36s | ", NodeDataTypeStrTbl[DataNode->DataType]));\r
+  DEBUG ((DEBUG_INFO, "0x%04x | ", DataNode->Size));\r
+\r
+  if ((DataNode->DataType == EAmlNodeDataTypeNameString) ||\r
+      (DataNode->DataType == EAmlNodeDataTypeString)) {\r
+    AmlDbgPrintChars (\r
+      DEBUG_INFO,\r
+      (CONST CHAR8*)DataNode->Buffer,\r
+      DataNode->Size\r
+      );\r
+  } else if (DataNode->DataType == EAmlNodeDataTypeUInt) {\r
+    switch (DataNode->Size) {\r
+      case 1:\r
+      {\r
+        DEBUG ((DEBUG_INFO, "0x%0x", *((UINT8*)DataNode->Buffer)));\r
+        break;\r
+      }\r
+      case 2:\r
+      {\r
+        DEBUG ((DEBUG_INFO, "0x%0x", *((UINT16*)DataNode->Buffer)));\r
+        break;\r
+      }\r
+      case 4:\r
+      {\r
+        DEBUG ((DEBUG_INFO, "0x%0lx", *((UINT32*)DataNode->Buffer)));\r
+        break;\r
+      }\r
+      case 8:\r
+      {\r
+        DEBUG ((DEBUG_INFO, "0x%0llx", *((UINT64*)DataNode->Buffer)));\r
+        break;\r
+      }\r
+      default:\r
+      {\r
+        ASSERT (0);\r
+        return;\r
+      }\r
+    }\r
+  } else {\r
+    // No specific format.\r
+    for (Idx = 0; Idx < DataNode->Size; Idx++) {\r
+      DEBUG ((DEBUG_INFO, "%02x ", DataNode->Buffer[Idx]));\r
+    }\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "\n"));\r
+}\r
+\r
+/** Print fields of an object node.\r
+\r
+  @param  [in]  ObjectNode  Pointer to an object node.\r
+  @param  [in]  Level       Level of the indentation.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintObjectNode (\r
+  IN  AML_OBJECT_NODE  * ObjectNode,\r
+  IN  UINT8              Level\r
+  )\r
+{\r
+  if (!IS_AML_OBJECT_NODE (ObjectNode)) {\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  AmlDbgPrintNodeHeader ((AML_NODE_HEADER*)ObjectNode, Level);\r
+\r
+  DEBUG ((DEBUG_INFO, "0x%02x | ", ObjectNode->AmlByteEncoding->OpCode));\r
+  DEBUG ((DEBUG_INFO, "0x%02x | ", ObjectNode->AmlByteEncoding->SubOpCode));\r
+\r
+  // Print a string corresponding to the field object OpCode/SubOpCode.\r
+  if (AmlNodeHasAttribute (ObjectNode, AML_IS_FIELD_ELEMENT)) {\r
+    DEBUG ((DEBUG_INFO, "%-15s ", AmlGetFieldOpCodeStr (\r
+                                    ObjectNode->AmlByteEncoding->OpCode,\r
+                                    0\r
+                                    )));\r
+  } else {\r
+    // Print a string corresponding to the object OpCode/SubOpCode.\r
+    DEBUG ((DEBUG_INFO, "%-15s | ", AmlGetOpCodeStr (\r
+                                      ObjectNode->AmlByteEncoding->OpCode,\r
+                                      ObjectNode->AmlByteEncoding->SubOpCode)\r
+                                      ));\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "%3d | ", ObjectNode->AmlByteEncoding->MaxIndex));\r
+  DEBUG ((DEBUG_INFO, "0x%08x | ", ObjectNode->AmlByteEncoding->Attribute));\r
+  DEBUG ((DEBUG_INFO, "0x%04x | ", ObjectNode->PkgLen));\r
+  if (AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE)) {\r
+    AmlDbgPrintNameString (\r
+      AmlNodeGetName ((CONST AML_OBJECT_NODE*)ObjectNode),\r
+      FALSE\r
+      );\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "\n"));\r
+}\r
+\r
+/** Print fields of a root node.\r
+\r
+  @param  [in]  RootNode  Pointer to a root node.\r
+  @param  [in]  Level     Level of the indentation.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintRootNode (\r
+  IN  AML_ROOT_NODE  * RootNode,\r
+  IN  UINT8            Level\r
+  )\r
+{\r
+  if (!IS_AML_ROOT_NODE (RootNode)) {\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  AmlDbgPrintNodeHeader ((AML_NODE_HEADER*)RootNode, Level);\r
+\r
+  DEBUG ((DEBUG_INFO, "%8x | ", RootNode->SdtHeader->Signature));\r
+  DEBUG ((DEBUG_INFO, "0x%08x | ", RootNode->SdtHeader->Length));\r
+  DEBUG ((DEBUG_INFO, "%3d | ", RootNode->SdtHeader->Revision));\r
+  DEBUG ((DEBUG_INFO, "0x%02x | ", RootNode->SdtHeader->Checksum));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "%c%c%c%c%c%c | ",\r
+    RootNode->SdtHeader->OemId[0],\r
+    RootNode->SdtHeader->OemId[1],\r
+    RootNode->SdtHeader->OemId[2],\r
+    RootNode->SdtHeader->OemId[3],\r
+    RootNode->SdtHeader->OemId[4],\r
+    RootNode->SdtHeader->OemId[5]\r
+    ));\r
+  DEBUG ((DEBUG_INFO, "%-16llx | ", RootNode->SdtHeader->OemTableId));\r
+  DEBUG ((DEBUG_INFO, "%8x | ", RootNode->SdtHeader->OemRevision));\r
+  DEBUG ((DEBUG_INFO, "%8x | ", RootNode->SdtHeader->CreatorId));\r
+  DEBUG ((DEBUG_INFO, "%8x", RootNode->SdtHeader->CreatorRevision));\r
+  DEBUG ((DEBUG_INFO, "\n"));\r
+}\r
+\r
+/** Print a header to help interpreting node information.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintTableHeader (\r
+  VOID\r
+  )\r
+{\r
+  DEBUG ((DEBUG_INFO, "Lvl | Node Type       |\n"));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "    | %-15s | Signature| Length     | Rev | CSum | OemId  | "\r
+      "OemTableId       | OemRev   | CreatorId| CreatorRev\n",\r
+    NodeTypeStrTbl[EAmlNodeRoot]\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "    | %-15s | Op   | SubOp| OpName          | MaxI| Attribute  | "\r
+      "PkgLen | NodeName (opt)\n",\r
+    NodeTypeStrTbl[EAmlNodeObject]\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "    | %-15s | Data Type                            | Size   | "\r
+      "Buffer\n",\r
+    NodeTypeStrTbl[EAmlNodeData]\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_INFO,\r
+    "---------------------------------------"\r
+      "---------------------------------------\n"\r
+    ));\r
+}\r
+\r
+/** Recursively print the subtree under the Node.\r
+    This is an internal function.\r
+\r
+  @param  [in]  Node            Pointer to the root of the subtree to print.\r
+                                Can be a root/object/data node.\r
+  @param  [in]  Recurse         If TRUE, recurse.\r
+  @param  [in]  Level           Level in the tree.\r
+**/\r
+STATIC\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintTreeInternal (\r
+  IN  AML_NODE_HEADER   * Node,\r
+  IN  BOOLEAN             Recurse,\r
+  IN  UINT8               Level\r
+  )\r
+{\r
+  AML_NODE_HEADER   * ChildNode;\r
+\r
+  if (!IS_AML_NODE_VALID (Node)) {\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  if (IS_AML_DATA_NODE (Node)) {\r
+    AmlDbgPrintDataNode ((AML_DATA_NODE*)Node, Level);\r
+    return;\r
+  } else if (IS_AML_OBJECT_NODE (Node)) {\r
+    AmlDbgPrintObjectNode ((AML_OBJECT_NODE*)Node, Level);\r
+  } else if (IS_AML_ROOT_NODE (Node)) {\r
+    AmlDbgPrintRootNode ((AML_ROOT_NODE*)Node, Level);\r
+  } else {\r
+    // Should not be possible.\r
+    ASSERT (0);\r
+    return;\r
+  }\r
+\r
+  if (!Recurse) {\r
+    return;\r
+  }\r
+\r
+  // Get the first child node.\r
+  ChildNode = AmlGetNextSibling (Node, NULL);\r
+  while (ChildNode != NULL) {\r
+    ASSERT (Level < MAX_UINT8);\r
+    AmlDbgPrintTreeInternal (ChildNode, Recurse, (UINT8)(Level + 1));\r
+    ChildNode = AmlGetNextSibling (Node, ChildNode);\r
+  }\r
+}\r
+\r
+/** Print Node information.\r
+\r
+  @param  [in]  Node    Pointer to the Node to print.\r
+                        Can be a root/object/data node.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintNode (\r
+  IN  AML_NODE_HEADER   * Node\r
+  )\r
+{\r
+  AmlDbgPrintTableHeader ();\r
+  AmlDbgPrintTreeInternal (Node, FALSE, 0);\r
+}\r
+\r
+/** Recursively print the subtree under the Node.\r
+\r
+  @param  [in]  Node    Pointer to the root of the subtree to print.\r
+                        Can be a root/object/data node.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintTree (\r
+  IN  AML_NODE_HEADER   * Node\r
+  )\r
+{\r
+  AmlDbgPrintTableHeader ();\r
+  AmlDbgPrintTreeInternal (Node, TRUE, 0);\r
+}\r
+\r
+/** This function performs a raw data dump of the ACPI table.\r
+\r
+  @param  [in]  Ptr     Pointer to the start of the table buffer.\r
+  @param  [in]  Length  The length of the buffer.\r
+**/\r
+VOID\r
+EFIAPI\r
+DumpRaw (\r
+  IN  CONST UINT8   * Ptr,\r
+  IN        UINT32    Length\r
+  )\r
+{\r
+  UINT32  ByteCount;\r
+  UINT32  PartLineChars;\r
+  UINT32  AsciiBufferIndex;\r
+  CHAR8   AsciiBuffer[17];\r
+\r
+  ByteCount = 0;\r
+  AsciiBufferIndex = 0;\r
+\r
+  DEBUG ((DEBUG_VERBOSE, "Address  : 0x%p\n", Ptr));\r
+  DEBUG ((DEBUG_VERBOSE, "Length   : %lld", Length));\r
+\r
+  while (ByteCount < Length) {\r
+    if ((ByteCount & 0x0F) == 0) {\r
+      AsciiBuffer[AsciiBufferIndex] = '\0';\r
+      DEBUG ((DEBUG_VERBOSE, "  %a\n%08X : ", AsciiBuffer, ByteCount));\r
+      AsciiBufferIndex = 0;\r
+    } else if ((ByteCount & 0x07) == 0) {\r
+      DEBUG ((DEBUG_VERBOSE, "- "));\r
+    }\r
+\r
+    if ((*Ptr >= ' ') && (*Ptr < 0x7F)) {\r
+      AsciiBuffer[AsciiBufferIndex++] = *Ptr;\r
+    } else {\r
+      AsciiBuffer[AsciiBufferIndex++] = '.';\r
+    }\r
+\r
+    DEBUG ((DEBUG_VERBOSE, "%02X ", *Ptr++));\r
+\r
+    ByteCount++;\r
+  }\r
+\r
+  // Justify the final line using spaces before printing\r
+  // the ASCII data.\r
+  PartLineChars = (Length & 0x0F);\r
+  if (PartLineChars != 0) {\r
+    PartLineChars = 48 - (PartLineChars * 3);\r
+    if ((Length & 0x0F) <= 8) {\r
+      PartLineChars += 2;\r
+    }\r
+    while (PartLineChars > 0) {\r
+      DEBUG ((DEBUG_VERBOSE, " "));\r
+      PartLineChars--;\r
+    }\r
+  }\r
+\r
+  // Print ASCII data for the final line.\r
+  AsciiBuffer[AsciiBufferIndex] = '\0';\r
+  DEBUG ((DEBUG_VERBOSE, "  %a\n\n", AsciiBuffer));\r
+}\r
+\r
+#endif // MDEPKG_NDEBUG\r
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h b/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h
new file mode 100644 (file)
index 0000000..68f4c74
--- /dev/null
@@ -0,0 +1,154 @@
+/** @file\r
+  AML Debug Print.\r
+\r
+  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>\r
+  Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>\r
+\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#ifndef AML_PRINT_H_\r
+#define AML_PRINT_H_\r
+\r
+/* This header file does not include internal Node definition,\r
+   i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions\r
+   must be included by the caller file. The function prototypes must\r
+   only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node\r
+   definitions.\r
+   This allows to keep the functions defined here both internal and\r
+   potentially external. If necessary, any function of this file can\r
+   be exposed externally.\r
+   The Api folder is internal to the AmlLib, but should only use these\r
+   functions. They provide a "safe" way to interact with the AmlLib.\r
+*/\r
+\r
+#if !defined (MDEPKG_NDEBUG)\r
+\r
+#include <AmlInclude.h>\r
+\r
+/**\r
+  @defgroup DbgPrintApis Print APIs for debugging.\r
+  @ingroup AMLLib\r
+  @{\r
+    Print APIs provide a way to print:\r
+     - A buffer;\r
+     - A (root/object/data) node;\r
+     - An AML tree/branch;\r
+     - The AML NameSpace from the root node.\r
+  @}\r
+*/\r
+\r
+/** This function performs a raw data dump of the ACPI table.\r
+\r
+  @param  [in]  Ptr     Pointer to the start of the table buffer.\r
+  @param  [in]  Length  The length of the buffer.\r
+**/\r
+VOID\r
+EFIAPI\r
+DumpRaw (\r
+  IN  CONST UINT8   * Ptr,\r
+  IN        UINT32    Length\r
+  );\r
+\r
+/** Print Size chars at Buffer address.\r
+\r
+  @ingroup DbgPrintApis\r
+\r
+  @param  [in]  ErrorLevel    Error level for the DEBUG macro.\r
+  @param  [in]  Buffer        Buffer containing the chars.\r
+  @param  [in]  Size          Number of chars to print.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintChars (\r
+  IN        UINT32      ErrorLevel,\r
+  IN  CONST CHAR8     * Buffer,\r
+  IN        UINT32      Size\r
+  );\r
+\r
+/** Print an AML NameSeg.\r
+    Don't print trailing underscores ('_').\r
+\r
+  @param  [in] Buffer   Buffer containing an AML NameSeg.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintNameSeg (\r
+  IN  CONST CHAR8   * Buffer\r
+  );\r
+\r
+/** Print an AML NameString.\r
+\r
+  @param  [in] Buffer   Buffer containing an AML NameString.\r
+  @param  [in] NewLine  Print a newline char at the end of the NameString.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintNameString (\r
+  IN  CONST CHAR8   * Buffer,\r
+  IN        BOOLEAN   NewLine\r
+  );\r
+\r
+/** Print Node information.\r
+\r
+  @ingroup DbgPrintApis\r
+\r
+  @param  [in]  Node    Pointer to the Node to print.\r
+                        Can be a root/object/data node.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintNode (\r
+  IN  AML_NODE_HANDLE   Node\r
+  );\r
+\r
+/** Recursively print the subtree under the Node.\r
+\r
+  @ingroup DbgPrintApis\r
+\r
+  @param  [in]  Node    Pointer to the root of the subtree to print.\r
+                        Can be a root/object/data node.\r
+**/\r
+VOID\r
+EFIAPI\r
+AmlDbgPrintTree (\r
+  IN  AML_NODE_HANDLE   Node\r
+  );\r
+\r
+/** Print the absolute pathnames in the AML namespace of\r
+    all the nodes in the tree starting from the Root node.\r
+\r
+  @ingroup DbgPrintApis\r
+\r
+  @param  [in]  RootNode    Pointer to a root node.\r
+\r
+  @retval EFI_SUCCESS             The function completed successfully.\r
+  @retval EFI_BUFFER_TOO_SMALL    No space left in the buffer.\r
+  @retval EFI_INVALID_PARAMETER   Invalid parameter.\r
+  @retval EFI_OUT_OF_RESOURCES    Out of memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AmlDbgPrintNameSpace (\r
+  IN  AML_ROOT_NODE_HANDLE  RootNode\r
+  );\r
+\r
+#else\r
+\r
+#define DumpRaw(Ptr, Length)\r
+\r
+#define AmlDbgPrintChars(ErrorLevel, Buffer, Size)\r
+\r
+#define AmlDbgPrintNameSeg(Buffer)\r
+\r
+#define AmlDbgPrintNameString(Buffer,NewLine)\r
+\r
+#define AmlDbgPrintNode(Node)\r
+\r
+#define AmlDbgPrintTree(Node)\r
+\r
+#define AmlDbgPrintNameSpace(RootNode)\r
+\r
+#endif // MDEPKG_NDEBUG\r
+\r
+#endif // AML_PRINT_H_\r