]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ShellPkg/AcpiView: Adds ACPI_PARSER bitfield parser
authorAbdul Lateef Attar <abdattar@amd.com>
Fri, 18 Mar 2022 12:58:59 +0000 (20:58 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Mon, 28 Mar 2022 09:38:30 +0000 (09:38 +0000)
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3839

Adds ParseAcpiBitFields() which is based on
ParseAcpi() and capable of parsing the bit fields.
Supports parsing of UINT8, UINT16, UINT32 and UINT64 byte data.

Cc: Ray Ni <ray.ni@intel.com>
Cc: Zhichao Gao <zhichao.gao@intel.com>
Cc: Sami Mujawar <sami.mujawar@arm.com>
Signed-off-by: Abdul Lateef Attar <abdattar@amd.com>
Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
Reviewed-by: Zhichao Gao <zhichao.gao@intel.com>
ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c
ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h

index cb193a5ea449007159c6ef1a828bea9b5dce3537..fcc56c189d65289883690f24c0c5403296d31fb9 100644 (file)
@@ -2,12 +2,14 @@
   ACPI parser\r
 \r
   Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.\r
+  Copyright (c) 2022, AMD Incorporated. All rights reserved.\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 **/\r
 \r
 #include <Uefi.h>\r
 #include <Library/UefiLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
 #include "AcpiParser.h"\r
 #include "AcpiView.h"\r
 #include "AcpiViewConfig.h"\r
@@ -752,3 +754,189 @@ ParseAcpiHeader (
 \r
   return BytesParsed;\r
 }\r
+\r
+/**\r
+  This function is used to parse an ACPI table bitfield buffer.\r
+\r
+  The ACPI table buffer is parsed using the ACPI table parser information\r
+  specified by a pointer to an array of ACPI_PARSER elements. This parser\r
+  function iterates through each item on the ACPI_PARSER array and logs the ACPI table bitfields.\r
+\r
+  This function can optionally be used to parse ACPI tables and fetch specific\r
+  field values. The ItemPtr member of the ACPI_PARSER structure (where used)\r
+  is updated by this parser function to point to the selected field data\r
+  (e.g. useful for variable length nested fields).\r
+\r
+  ItemPtr member of ACPI_PARSER is not supported with this function.\r
+\r
+  @param [in] Trace        Trace the ACPI fields TRUE else only parse the\r
+                           table.\r
+  @param [in] Indent       Number of spaces to indent the output.\r
+  @param [in] AsciiName    Optional pointer to an ASCII string that describes\r
+                           the table being parsed.\r
+  @param [in] Ptr          Pointer to the start of the buffer.\r
+  @param [in] Length       Length in bytes of the buffer pointed by Ptr.\r
+  @param [in] Parser       Pointer to an array of ACPI_PARSER structure that\r
+                           describes the table being parsed.\r
+  @param [in] ParserItems  Number of items in the ACPI_PARSER array.\r
+\r
+  @retval Number of bits parsed.\r
+**/\r
+UINT32\r
+EFIAPI\r
+ParseAcpiBitFields (\r
+  IN BOOLEAN            Trace,\r
+  IN UINT32             Indent,\r
+  IN CONST CHAR8        *AsciiName OPTIONAL,\r
+  IN UINT8              *Ptr,\r
+  IN UINT32             Length,\r
+  IN CONST ACPI_PARSER  *Parser,\r
+  IN UINT32             ParserItems\r
+  )\r
+{\r
+  UINT32   Index;\r
+  UINT32   Offset;\r
+  BOOLEAN  HighLight;\r
+  UINTN    OriginalAttribute;\r
+\r
+  UINT64  Data;\r
+  UINT64  BitsData;\r
+\r
+  if ((Length == 0) || (Length > 8)) {\r
+    IncrementErrorCount ();\r
+    Print (\r
+      L"\nERROR: Bitfield Length(%d) is zero or exceeding the 64 bit limit.\n",\r
+      Length\r
+      );\r
+    return 0;\r
+  }\r
+\r
+  //\r
+  // set local variables to suppress incorrect compiler/analyzer warnings\r
+  //\r
+  OriginalAttribute = 0;\r
+  Offset            = 0;\r
+\r
+  // Increment the Indent\r
+  gIndent += Indent;\r
+\r
+  CopyMem ((VOID *)&BitsData, (VOID *)Ptr, Length);\r
+  if (Trace && (AsciiName != NULL)) {\r
+    HighLight = GetColourHighlighting ();\r
+\r
+    if (HighLight) {\r
+      OriginalAttribute = gST->ConOut->Mode->Attribute;\r
+      gST->ConOut->SetAttribute (\r
+                     gST->ConOut,\r
+                     EFI_TEXT_ATTR (\r
+                       EFI_YELLOW,\r
+                       ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
+                       )\r
+                     );\r
+    }\r
+\r
+    Print (\r
+      L"%*a%-*a :\n",\r
+      gIndent,\r
+      "",\r
+      (OUTPUT_FIELD_COLUMN_WIDTH - gIndent),\r
+      AsciiName\r
+      );\r
+    if (HighLight) {\r
+      gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);\r
+    }\r
+  }\r
+\r
+  for (Index = 0; Index < ParserItems; Index++) {\r
+    if ((Offset + Parser[Index].Length) > (Length * 8)) {\r
+      // For fields outside the buffer length provided, reset any pointers\r
+      // which were supposed to be updated by this function call\r
+      if (Parser[Index].ItemPtr != NULL) {\r
+        *Parser[Index].ItemPtr = NULL;\r
+      }\r
+\r
+      // We don't parse past the end of the max length specified\r
+      continue;\r
+    }\r
+\r
+    if (Parser[Index].Length == 0) {\r
+      IncrementErrorCount ();\r
+      // don't parse the bitfield whose length is zero\r
+      Print (\r
+        L"\nERROR: %a: Cannot parse this field, Field Length = %d\n",\r
+        Parser[Index].Length\r
+        );\r
+      continue;\r
+    }\r
+\r
+    if (GetConsistencyChecking () &&\r
+        (Offset != Parser[Index].Offset))\r
+    {\r
+      IncrementErrorCount ();\r
+      Print (\r
+        L"\nERROR: %a: Offset Mismatch for %s\n"\r
+        L"CurrentOffset = %d FieldOffset = %d\n",\r
+        AsciiName,\r
+        Parser[Index].NameStr,\r
+        Offset,\r
+        Parser[Index].Offset\r
+        );\r
+    }\r
+\r
+    // extract Bitfield data for the current item\r
+    Data = (BitsData >> Parser[Index].Offset) & ~(~0ULL << Parser[Index].Length);\r
+\r
+    if (Trace) {\r
+      // if there is a Formatter function let the function handle\r
+      // the printing else if a Format is specified in the table use\r
+      // the Format for printing\r
+      PrintFieldName (2, Parser[Index].NameStr);\r
+      if (Parser[Index].PrintFormatter != NULL) {\r
+        Parser[Index].PrintFormatter (Parser[Index].Format, (UINT8 *)&Data);\r
+      } else if (Parser[Index].Format != NULL) {\r
+        // convert bit length to byte length\r
+        switch ((Parser[Index].Length + 7) >> 3) {\r
+          // print the data depends on byte size\r
+          case 1:\r
+            DumpUint8 (Parser[Index].Format, (UINT8 *)&Data);\r
+            break;\r
+          case 2:\r
+            DumpUint16 (Parser[Index].Format, (UINT8 *)&Data);\r
+            break;\r
+          case 3:\r
+          case 4:\r
+            DumpUint32 (Parser[Index].Format, (UINT8 *)&Data);\r
+            break;\r
+          case 5:\r
+          case 6:\r
+          case 7:\r
+          case 8:\r
+            DumpUint64 (Parser[Index].Format, (UINT8 *)&Data);\r
+            break;\r
+          default:\r
+            Print (\r
+              L"\nERROR: %a: CANNOT PARSE THIS FIELD, Field Length = %d\n",\r
+              AsciiName,\r
+              Parser[Index].Length\r
+              );\r
+        } // switch\r
+      }\r
+\r
+      // Validating only makes sense if we are tracing\r
+      // the parsed table entries, to report by table name.\r
+      if (GetConsistencyChecking () &&\r
+          (Parser[Index].FieldValidator != NULL))\r
+      {\r
+        Parser[Index].FieldValidator ((UINT8 *)&Data, Parser[Index].Context);\r
+      }\r
+\r
+      Print (L"\n");\r
+    } // if (Trace)\r
+\r
+    Offset += Parser[Index].Length;\r
+  } // for\r
+\r
+  // Decrement the Indent\r
+  gIndent -= Indent;\r
+  return Offset;\r
+}\r
index 5c916a4720b84eb0445d6e60fa59158fe9b6764e..db8c88f6dfa435bb0a929c1e6fc4311a8c5e4c2b 100644 (file)
@@ -2,6 +2,7 @@
   Header file for ACPI parser\r
 \r
   Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.\r
+  Copyright (c) 2022, AMD Incorporated. All rights reserved.\r
   SPDX-License-Identifier: BSD-2-Clause-Patent\r
 **/\r
 \r
@@ -251,6 +252,11 @@ typedef VOID (EFIAPI *FNPTR_FIELD_VALIDATOR)(UINT8 *Ptr, VOID *Context);
   the field data. If the field is more complex and requires additional\r
   processing for formatting and representation a print formatter function\r
   can be specified in 'PrintFormatter'.\r
+\r
+  ParseAcpiBitFields() uses AcpiParser structure to parse the bit fields.\r
+  It considers Length as a number of bits that need to be parsed.\r
+  Also, the Offset field will be considered as starting offset of the bitfield.\r
+\r
   The PrintFormatter function may choose to use the format string\r
   specified by 'Format' or use its own internal format string.\r
 \r
@@ -264,10 +270,12 @@ typedef struct AcpiParser {
 \r
   /// The length of the field.\r
   /// (Byte Length column from ACPI table spec)\r
+  /// Length(in bits) of the bitfield if used with ParseAcpiBitFields().\r
   UINT32                   Length;\r
 \r
   /// The offset of the field from the start of the table.\r
   /// (Byte Offset column from ACPI table spec)\r
+  /// The Bit offset of the field if used with ParseAcpiBitFields().\r
   UINT32                   Offset;\r
 \r
   /// Optional Print() style format string for tracing the data. If not\r
@@ -285,6 +293,7 @@ typedef struct AcpiParser {
   /// a pointer to the field data. This value is set after the FieldValidator\r
   /// has been called and therefore should not be used by the FieldValidator.\r
   /// If unused this must be set to NULL.\r
+  /// ItemPtr is not supported with ParseAcpiBitFields().\r
   VOID                     **ItemPtr;\r
 \r
   /// Optional pointer to a field validator function.\r
@@ -364,6 +373,45 @@ ParseAcpi (
   IN UINT32             ParserItems\r
   );\r
 \r
+/**\r
+  This function is used to parse an ACPI table bitfield buffer.\r
+\r
+  The ACPI table buffer is parsed using the ACPI table parser information\r
+  specified by a pointer to an array of ACPI_PARSER elements. This parser\r
+  function iterates through each item on the ACPI_PARSER array and logs the ACPI table bitfields.\r
+\r
+  This function can optionally be used to parse ACPI tables and fetch specific\r
+  field values. The ItemPtr member of the ACPI_PARSER structure (where used)\r
+  is updated by this parser function to point to the selected field data\r
+  (e.g. useful for variable length nested fields).\r
+\r
+  ItemPtr member of ACPI_PARSER is not supported with this function.\r
+\r
+  @param [in] Trace        Trace the ACPI fields TRUE else only parse the\r
+                           table.\r
+  @param [in] Indent       Number of spaces to indent the output.\r
+  @param [in] AsciiName    Optional pointer to an ASCII string that describes\r
+                           the table being parsed.\r
+  @param [in] Ptr          Pointer to the start of the buffer.\r
+  @param [in] Length       Length of the buffer pointed by Ptr.\r
+  @param [in] Parser       Pointer to an array of ACPI_PARSER structure that\r
+                           describes the table being parsed.\r
+  @param [in] ParserItems  Number of items in the ACPI_PARSER array.\r
+\r
+  @retval Number of bits parsed.\r
+**/\r
+UINT32\r
+EFIAPI\r
+ParseAcpiBitFields (\r
+  IN BOOLEAN            Trace,\r
+  IN UINT32             Indent,\r
+  IN CONST CHAR8        *AsciiName OPTIONAL,\r
+  IN UINT8              *Ptr,\r
+  IN UINT32             Length,\r
+  IN CONST ACPI_PARSER  *Parser,\r
+  IN UINT32             ParserItems\r
+  );\r
+\r
 /**\r
    This is a helper macro to pass parameters to the Parser functions.\r
 \r