aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers')
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c65
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c302
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c42
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Facs/FacsParser.c71
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c319
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c364
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c764
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c374
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.h40
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c90
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c478
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.h38
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c164
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c188
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c144
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c542
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c42
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c140
18 files changed, 4167 insertions, 0 deletions
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c
new file mode 100644
index 000000000..1a180271a
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c
@@ -0,0 +1,65 @@
+/** @file
+ BGRT table parser
+
+ Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.2 Specification - Errata A, September 2017
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+// Local variables
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ An ACPI_PARSER array describing the ACPI BDRT Table.
+**/
+STATIC CONST ACPI_PARSER BgrtParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"Version", 2, 36, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Status", 1, 38, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Image Type", 1, 39, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Image Address", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Image Offset X", 4, 48, L"%d", NULL, NULL, NULL, NULL},
+ {L"Image Offset Y", 4, 52, L"%d", NULL, NULL, NULL, NULL}
+};
+
+/**
+ This function parses the ACPI BGRT table.
+ When trace is enabled this function parses the BGRT table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiBgrt (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ if (!Trace) {
+ return;
+ }
+
+ ParseAcpi (
+ Trace,
+ 0,
+ "BGRT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (BgrtParser)
+ );
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c
new file mode 100644
index 000000000..9df111eca
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c
@@ -0,0 +1,302 @@
+/** @file
+ DBG2 table parser
+
+ Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015.
+**/
+
+#include <IndustryStandard/DebugPort2Table.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+// Local variables pointing to the table fields
+STATIC CONST UINT32* OffsetDbgDeviceInfo;
+STATIC CONST UINT32* NumberDbgDeviceInfo;
+STATIC CONST UINT16* DbgDevInfoLen;
+STATIC CONST UINT8* GasCount;
+STATIC CONST UINT16* NameSpaceStringLength;
+STATIC CONST UINT16* NameSpaceStringOffset;
+STATIC CONST UINT16* OEMDataLength;
+STATIC CONST UINT16* OEMDataOffset;
+STATIC CONST UINT16* BaseAddrRegOffset;
+STATIC CONST UINT16* AddrSizeOffset;
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ This function validates the NameSpace string length.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateNameSpaceStrLen (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT16 NameSpaceStrLen;
+
+ NameSpaceStrLen = *(UINT16*)Ptr;
+
+ if (NameSpaceStrLen < 2) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: NamespaceString Length = %d. If no Namespace device exists, " \
+ L"NamespaceString[] must contain a period '.'",
+ NameSpaceStrLen
+ );
+ }
+}
+
+/// An ACPI_PARSER array describing the ACPI DBG2 table.
+STATIC CONST ACPI_PARSER Dbg2Parser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"OffsetDbgDeviceInfo", 4, 36, L"0x%x", NULL,
+ (VOID**)&OffsetDbgDeviceInfo, NULL, NULL},
+ {L"NumberDbgDeviceInfo", 4, 40, L"%d", NULL,
+ (VOID**)&NumberDbgDeviceInfo, NULL, NULL}
+};
+
+/// An ACPI_PARSER array describing the debug device information structure
+/// header.
+STATIC CONST ACPI_PARSER DbgDevInfoHeaderParser[] = {
+ {L"Revision", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 2, 1, L"%d", NULL, (VOID**)&DbgDevInfoLen, NULL, NULL}
+};
+
+/// An ACPI_PARSER array describing the debug device information.
+STATIC CONST ACPI_PARSER DbgDevInfoParser[] = {
+ {L"Revision", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL},
+
+ {L"Generic Address Registers Count", 1, 3, L"0x%x", NULL,
+ (VOID**)&GasCount, NULL, NULL},
+ {L"NameSpace String Length", 2, 4, L"%d", NULL,
+ (VOID**)&NameSpaceStringLength, ValidateNameSpaceStrLen, NULL},
+ {L"NameSpace String Offset", 2, 6, L"0x%x", NULL,
+ (VOID**)&NameSpaceStringOffset, NULL, NULL},
+ {L"OEM Data Length", 2, 8, L"%d", NULL, (VOID**)&OEMDataLength,
+ NULL, NULL},
+ {L"OEM Data Offset", 2, 10, L"0x%x", NULL, (VOID**)&OEMDataOffset,
+ NULL, NULL},
+
+ {L"Port Type", 2, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Port SubType", 2, 14, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 16, L"%x", NULL, NULL, NULL, NULL},
+
+ {L"Base Address Register Offset", 2, 18, L"0x%x", NULL,
+ (VOID**)&BaseAddrRegOffset, NULL, NULL},
+ {L"Address Size Offset", 2, 20, L"0x%x", NULL,
+ (VOID**)&AddrSizeOffset, NULL, NULL}
+};
+
+/**
+ This function parses the debug device information structure.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the debug device information structure.
+**/
+STATIC
+VOID
+EFIAPI
+DumpDbgDeviceInfo (
+ IN UINT8* Ptr,
+ IN UINT16 Length
+ )
+{
+ UINT16 Index;
+ UINT16 Offset;
+
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Debug Device Info",
+ Ptr,
+ Length,
+ PARSER_PARAMS (DbgDevInfoParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((GasCount == NULL) ||
+ (NameSpaceStringLength == NULL) ||
+ (NameSpaceStringOffset == NULL) ||
+ (OEMDataLength == NULL) ||
+ (OEMDataOffset == NULL) ||
+ (BaseAddrRegOffset == NULL) ||
+ (AddrSizeOffset == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient Debug Device Information Structure length. " \
+ L"Length = %d.\n",
+ Length
+ );
+ return;
+ }
+
+ // GAS
+ Index = 0;
+ Offset = *BaseAddrRegOffset;
+ while ((Index++ < *GasCount) &&
+ (Offset < Length)) {
+ PrintFieldName (4, L"BaseAddressRegister");
+ Offset += (UINT16)DumpGasStruct (
+ Ptr + Offset,
+ 4,
+ Length - Offset
+ );
+ }
+
+ // Make sure the array of address sizes corresponding to each GAS fit in the
+ // Debug Device Information structure
+ if ((*AddrSizeOffset + (*GasCount * sizeof (UINT32))) > Length) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid GAS count. GasCount = %d. RemainingBufferLength = %d. " \
+ L"Parsing of the Debug Device Information structure aborted.\n",
+ *GasCount,
+ Length - *AddrSizeOffset
+ );
+ return;
+ }
+
+ // Address Size
+ Index = 0;
+ Offset = *AddrSizeOffset;
+ while ((Index++ < *GasCount) &&
+ (Offset < Length)) {
+ PrintFieldName (4, L"Address Size");
+ Print (L"0x%x\n", *((UINT32*)(Ptr + Offset)));
+ Offset += sizeof (UINT32);
+ }
+
+ // NameSpace String
+ Index = 0;
+ Offset = *NameSpaceStringOffset;
+ PrintFieldName (4, L"NameSpace String");
+ while ((Index++ < *NameSpaceStringLength) &&
+ (Offset < Length)) {
+ Print (L"%c", *(Ptr + Offset));
+ Offset++;
+ }
+ Print (L"\n");
+
+ // OEM Data
+ if (*OEMDataOffset != 0) {
+ Index = 0;
+ Offset = *OEMDataOffset;
+ PrintFieldName (4, L"OEM Data");
+ while ((Index++ < *OEMDataLength) &&
+ (Offset < Length)) {
+ Print (L"%x ", *(Ptr + Offset));
+ if ((Index & 7) == 0) {
+ Print (L"\n%-*s ", OUTPUT_FIELD_COLUMN_WIDTH, L"");
+ }
+ Offset++;
+ }
+ Print (L"\n");
+ }
+}
+
+/**
+ This function parses the ACPI DBG2 table.
+ When trace is enabled this function parses the DBG2 table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiDbg2 (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT32 Index;
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "DBG2",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (Dbg2Parser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((OffsetDbgDeviceInfo == NULL) ||
+ (NumberDbgDeviceInfo == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient table length. AcpiTableLength = %d\n",
+ AcpiTableLength
+ );
+ return;
+ }
+
+ Offset = *OffsetDbgDeviceInfo;
+ Index = 0;
+
+ while (Index++ < *NumberDbgDeviceInfo) {
+
+ // Parse the Debug Device Information Structure header to obtain Length
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ Ptr + Offset,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (DbgDevInfoHeaderParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if (DbgDevInfoLen == NULL) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"Debug Device Information structure's 'Length' field. " \
+ L"RemainingTableBufferLength = %d.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate Debug Device Information Structure length
+ if ((*DbgDevInfoLen == 0) ||
+ ((Offset + (*DbgDevInfoLen)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Debug Device Information Structure length. " \
+ L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
+ *DbgDevInfoLen,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ DumpDbgDeviceInfo (Ptr + Offset, (*DbgDevInfoLen));
+ Offset += (*DbgDevInfoLen);
+ }
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c
new file mode 100644
index 000000000..6d43974f5
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c
@@ -0,0 +1,42 @@
+/** @file
+ DSDT table parser
+
+ Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.2 Specification - Errata A, September 2017
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+/**
+ This function parses the ACPI DSDT table.
+ When trace is enabled this function parses the DSDT table and
+ traces the ACPI table fields.
+ For the DSDT table only the ACPI header fields are parsed and
+ traced.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiDsdt (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ if (!Trace) {
+ return;
+ }
+
+ DumpAcpiHeader (Ptr);
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Facs/FacsParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Facs/FacsParser.c
new file mode 100644
index 000000000..d6bea86bd
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Facs/FacsParser.c
@@ -0,0 +1,71 @@
+/** @file
+ FACS table parser
+
+ Copyright (c) 2019, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification - January 2019
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+/**
+ An ACPI_PARSER array describing the ACPI FACS Table.
+**/
+STATIC CONST ACPI_PARSER FacsParser[] = {
+ {L"Signature", 4, 0, L"%c%c%c%c", Dump4Chars, NULL, NULL, NULL},
+ {L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL},
+ {L"Hardware Signature", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Firmware Waking Vector", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Global Lock", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"X Firmware Walking Vector", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Version", 1, 32, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 3, 33, L"%x %x %x", Dump3Chars, NULL, NULL, NULL},
+ {L"OSPM Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 8, 40, L"%x %x %x %x %x %x %x %x", Dump8Chars, NULL, NULL,
+ NULL},
+ {L"Reserved", 8, 48, L"%x %x %x %x %x %x %x %x", Dump8Chars, NULL, NULL,
+ NULL},
+ {L"Reserved", 8, 56, L"%x %x %x %x %x %x %x %x", Dump8Chars, NULL, NULL,
+ NULL}
+};
+
+/**
+ This function parses the ACPI FACS table.
+ When trace is enabled this function parses the FACS table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiFacs (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ if (!Trace) {
+ return;
+ }
+
+ ParseAcpi (
+ Trace,
+ 0,
+ "FACS",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (FacsParser)
+ );
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c
new file mode 100644
index 000000000..d86718bab
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c
@@ -0,0 +1,319 @@
+/** @file
+ FADT table parser
+
+ Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification - January 2019
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+#include "AcpiView.h"
+
+// Local variables
+STATIC CONST UINT32* DsdtAddress;
+STATIC CONST UINT64* X_DsdtAddress;
+STATIC CONST UINT32* Flags;
+STATIC CONST UINT32* FirmwareCtrl;
+STATIC CONST UINT64* X_FirmwareCtrl;
+STATIC CONST UINT8* FadtMinorRevision;
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ A macro defining the Hardware reduced ACPI flag
+**/
+#define HW_REDUCED_ACPI BIT20
+
+/**
+ Offset to the FACS signature from the start of the FACS.
+**/
+#define FACS_SIGNATURE_OFFSET 0
+
+/**
+ Offset to the FACS revision from the start of the FACS.
+**/
+#define FACS_VERSION_OFFSET 32
+
+/**
+ Offset to the FACS length from the start of the FACS.
+**/
+#define FACS_LENGTH_OFFSET 4
+
+/**
+ Get the ACPI XSDT header info.
+**/
+CONST ACPI_DESCRIPTION_HEADER_INFO *
+EFIAPI
+GetAcpiXsdtHeaderInfo (
+ VOID
+ );
+
+/**
+ This function validates the Firmware Control Field.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateFirmwareCtrl (
+ IN UINT8* Ptr,
+ IN VOID* Context
+)
+{
+#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ if (*(UINT32*)Ptr != 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Firmware Control must be zero for ARM platforms."
+ );
+ }
+#endif
+}
+
+/**
+ This function validates the X_Firmware Control Field.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateXFirmwareCtrl (
+ IN UINT8* Ptr,
+ IN VOID* Context
+)
+{
+#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ if (*(UINT64*)Ptr != 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: X Firmware Control must be zero for ARM platforms."
+ );
+ }
+#endif
+}
+
+/**
+ This function validates the flags.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateFlags (
+ IN UINT8* Ptr,
+ IN VOID* Context
+)
+{
+#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ if (((*(UINT32*)Ptr) & HW_REDUCED_ACPI) == 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms."
+ );
+ }
+#endif
+}
+
+/**
+ An ACPI_PARSER array describing the ACPI FADT Table.
+**/
+STATIC CONST ACPI_PARSER FadtParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"FIRMWARE_CTRL", 4, 36, L"0x%x", NULL, (VOID**)&FirmwareCtrl,
+ ValidateFirmwareCtrl, NULL},
+ {L"DSDT", 4, 40, L"0x%x", NULL, (VOID**)&DsdtAddress, NULL, NULL},
+ {L"Reserved", 1, 44, L"%x", NULL, NULL, NULL, NULL},
+ {L"Preferred_PM_Profile", 1, 45, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SCI_INT", 2, 46, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SMI_CMD", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"ACPI_ENABLE", 1, 52, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"ACPI_DISABLE", 1, 53, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"S4BIOS_REQ", 1, 54, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PSTATE_CNT", 1, 55, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM1a_EVT_BLK", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM1b_EVT_BLK", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM1a_CNT_BLK", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM1b_CNT_BLK", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM2_CNT_BLK", 4, 72, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM_TMR_BLK", 4, 76, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"GPE0_BLK", 4, 80, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"GPE1_BLK", 4, 84, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM1_EVT_LEN", 1, 88, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM1_CNT_LEN", 1, 89, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM2_CNT_LEN", 1, 90, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PM_TMR_LEN", 1, 91, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"GPE0_BLK_LEN", 1, 92, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"GPE1_BLK_LEN", 1, 93, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"GPE1_BASE", 1, 94, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"CST_CNT", 1, 95, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"P_LVL2_LAT", 2, 96, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"P_LVL3_LAT", 2, 98, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"FLUSH_SIZE", 2, 100, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"FLUSH_STRIDE", 2, 102, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"DUTY_OFFSET", 1, 104, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"DUTY_WIDTH", 1, 105, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"DAY_ALRM", 1, 106, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"MON_ALRM", 1, 107, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"CENTURY", 1, 108, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"IAPC_BOOT_ARCH", 2, 109, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 1, 111, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 112, L"0x%x", NULL, (VOID**)&Flags, ValidateFlags, NULL},
+ {L"RESET_REG", 12, 116, NULL, DumpGas, NULL, NULL, NULL},
+ {L"RESET_VALUE", 1, 128, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"ARM_BOOT_ARCH", 2, 129, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"FADT Minor Version", 1, 131, L"0x%x", NULL, (VOID**)&FadtMinorRevision,
+ NULL, NULL},
+ {L"X_FIRMWARE_CTRL", 8, 132, L"0x%lx", NULL, (VOID**)&X_FirmwareCtrl,
+ ValidateXFirmwareCtrl, NULL},
+ {L"X_DSDT", 8, 140, L"0x%lx", NULL, (VOID**)&X_DsdtAddress, NULL, NULL},
+ {L"X_PM1a_EVT_BLK", 12, 148, NULL, DumpGas, NULL, NULL, NULL},
+ {L"X_PM1b_EVT_BLK", 12, 160, NULL, DumpGas, NULL, NULL, NULL},
+ {L"X_PM1a_CNT_BLK", 12, 172, NULL, DumpGas, NULL, NULL, NULL},
+ {L"X_PM1b_CNT_BLK", 12, 184, NULL, DumpGas, NULL, NULL, NULL},
+ {L"X_PM2_CNT_BLK", 12, 196, NULL, DumpGas, NULL, NULL, NULL},
+ {L"X_PM_TMR_BLK", 12, 208, NULL, DumpGas, NULL, NULL, NULL},
+ {L"X_GPE0_BLK", 12, 220, NULL, DumpGas, NULL, NULL, NULL},
+ {L"X_GPE1_BLK", 12, 232, NULL, DumpGas, NULL, NULL, NULL},
+ {L"SLEEP_CONTROL_REG", 12, 244, NULL, DumpGas, NULL, NULL, NULL},
+ {L"SLEEP_STATUS_REG", 12, 256, NULL, DumpGas, NULL, NULL, NULL},
+ {L"Hypervisor VendorIdentity", 8, 268, L"%lx", NULL, NULL, NULL, NULL}
+};
+
+/**
+ This function parses the ACPI FADT table.
+ This function parses the FADT table and optionally traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiFadt (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ EFI_STATUS Status;
+ UINT8* DsdtPtr;
+ UINT8* FirmwareCtrlPtr;
+ UINT32 FacsSignature;
+ UINT32 FacsLength;
+ UINT8 FacsRevision;
+ PARSE_ACPI_TABLE_PROC FacsParserProc;
+
+ ParseAcpi (
+ Trace,
+ 0,
+ "FADT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (FadtParser)
+ );
+
+ if (Trace) {
+ if (FadtMinorRevision != NULL) {
+ Print (L"\nSummary:\n");
+ PrintFieldName (2, L"FADT Version");
+ Print (L"%d.%d\n", *AcpiHdrInfo.Revision, *FadtMinorRevision);
+ }
+
+ if (*GetAcpiXsdtHeaderInfo ()->OemTableId != *AcpiHdrInfo.OemTableId) {
+ IncrementErrorCount ();
+ Print (L"ERROR: OEM Table Id does not match with RSDT/XSDT.\n");
+ }
+ }
+
+ // If X_FIRMWARE_CTRL is not zero then use X_FIRMWARE_CTRL and ignore
+ // FIRMWARE_CTRL, else use FIRMWARE_CTRL.
+ if ((X_FirmwareCtrl != NULL) && (*X_FirmwareCtrl != 0)) {
+ FirmwareCtrlPtr = (UINT8*)(UINTN)(*X_FirmwareCtrl);
+ } else if ((FirmwareCtrl != NULL) && (*FirmwareCtrl != 0)) {
+ FirmwareCtrlPtr = (UINT8*)(UINTN)(*FirmwareCtrl);
+ } else {
+ FirmwareCtrlPtr = NULL;
+ // if HW_REDUCED_ACPI flag is not set, both FIRMWARE_CTRL and
+ // X_FIRMWARE_CTRL cannot be zero, and the FACS Table must be
+ // present.
+ if ((Trace) &&
+ (Flags != NULL) &&
+ ((*Flags & EFI_ACPI_6_3_HW_REDUCED_ACPI) != EFI_ACPI_6_3_HW_REDUCED_ACPI)) {
+ IncrementErrorCount ();
+ Print (L"ERROR: No FACS table found, "
+ L"both X_FIRMWARE_CTRL and FIRMWARE_CTRL are zero.\n");
+ }
+ }
+
+ if (FirmwareCtrlPtr != NULL) {
+ // The FACS table does not have a standard ACPI table header. Therefore,
+ // the signature, length and version needs to be initially parsed.
+ // The FACS signature is 4 bytes starting at offset 0.
+ FacsSignature = *(UINT32*)(FirmwareCtrlPtr + FACS_SIGNATURE_OFFSET);
+
+ // The FACS length is 4 bytes starting at offset 4.
+ FacsLength = *(UINT32*)(FirmwareCtrlPtr + FACS_LENGTH_OFFSET);
+
+ // The FACS version is 1 byte starting at offset 32.
+ FacsRevision = *(UINT8*)(FirmwareCtrlPtr + FACS_VERSION_OFFSET);
+
+ Trace = ProcessTableReportOptions (
+ FacsSignature,
+ FirmwareCtrlPtr,
+ FacsLength
+ );
+
+ Status = GetParser (FacsSignature, &FacsParserProc);
+ if (EFI_ERROR (Status)) {
+ Print (
+ L"ERROR: No registered parser found for FACS.\n"
+ );
+ return;
+ }
+
+ FacsParserProc (
+ Trace,
+ FirmwareCtrlPtr,
+ FacsLength,
+ FacsRevision
+ );
+ }
+
+ // If X_DSDT is valid then use X_DSDT and ignore DSDT, else use DSDT.
+ if ((X_DsdtAddress != NULL) && (*X_DsdtAddress != 0)) {
+ DsdtPtr = (UINT8*)(UINTN)(*X_DsdtAddress);
+ } else if ((DsdtAddress != NULL) && (*DsdtAddress != 0)) {
+ DsdtPtr = (UINT8*)(UINTN)(*DsdtAddress);
+ } else {
+ // Both DSDT and X_DSDT cannot be invalid.
+#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ if (Trace) {
+ // The DSDT Table is mandatory for ARM systems
+ // as the CPU information MUST be presented in
+ // the DSDT.
+ IncrementErrorCount ();
+ Print (L"ERROR: Both X_DSDT and DSDT are invalid.\n");
+ }
+#endif
+ return;
+ }
+
+ ProcessAcpiTable (DsdtPtr);
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
new file mode 100644
index 000000000..d02fc4929
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
@@ -0,0 +1,364 @@
+/** @file
+ GTDT table parser
+
+ Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification - January 2019
+ **/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+#include "AcpiViewConfig.h"
+
+// "The number of GT Block Timers must be less than or equal to 8"
+#define GT_BLOCK_TIMER_COUNT_MAX 8
+
+// Local variables
+STATIC CONST UINT32* GtdtPlatformTimerCount;
+STATIC CONST UINT32* GtdtPlatformTimerOffset;
+STATIC CONST UINT8* PlatformTimerType;
+STATIC CONST UINT16* PlatformTimerLength;
+STATIC CONST UINT32* GtBlockTimerCount;
+STATIC CONST UINT32* GtBlockTimerOffset;
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ This function validates the GT Block timer count.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateGtBlockTimerCount (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT32 BlockTimerCount;
+
+ BlockTimerCount = *(UINT32*)Ptr;
+
+ if (BlockTimerCount > GT_BLOCK_TIMER_COUNT_MAX) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Timer Count = %d. Max Timer Count is %d.",
+ BlockTimerCount,
+ GT_BLOCK_TIMER_COUNT_MAX
+ );
+ }
+}
+
+/**
+ This function validates the GT Frame Number.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateGtFrameNumber (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT8 FrameNumber;
+
+ FrameNumber = *(UINT8*)Ptr;
+
+ if (FrameNumber >= GT_BLOCK_TIMER_COUNT_MAX) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: GT Frame Number = %d. GT Frame Number must be in range 0-%d.",
+ FrameNumber,
+ GT_BLOCK_TIMER_COUNT_MAX - 1
+ );
+ }
+}
+
+/**
+ An ACPI_PARSER array describing the ACPI GTDT Table.
+**/
+STATIC CONST ACPI_PARSER GtdtParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"CntControlBase Physical Address", 8, 36, L"0x%lx", NULL, NULL,
+ NULL, NULL},
+ {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Secure EL1 timer GSIV", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Secure EL1 timer FLAGS", 4, 52, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Non-Secure EL1 timer GSIV", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Non-Secure EL1 timer FLAGS", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Virtual timer GSIV", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Virtual timer FLAGS", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Non-Secure EL2 timer GSIV", 4, 72, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Non-Secure EL2 timer FLAGS", 4, 76, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"CntReadBase Physical address", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Platform Timer Count", 4, 88, L"%d", NULL,
+ (VOID**)&GtdtPlatformTimerCount, NULL, NULL},
+ {L"Platform Timer Offset", 4, 92, L"0x%x", NULL,
+ (VOID**)&GtdtPlatformTimerOffset, NULL, NULL},
+ {L"Virtual EL2 Timer GSIV", 4, 96, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Virtual EL2 Timer Flags", 4, 100, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Platform timer header.
+**/
+STATIC CONST ACPI_PARSER GtPlatformTimerHeaderParser[] = {
+ {L"Type", 1, 0, NULL, NULL, (VOID**)&PlatformTimerType, NULL, NULL},
+ {L"Length", 2, 1, NULL, NULL, (VOID**)&PlatformTimerLength, NULL, NULL},
+ {L"Reserved", 1, 3, NULL, NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Platform GT Block.
+**/
+STATIC CONST ACPI_PARSER GtBlockParser[] = {
+ {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL},
+ {L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL},
+ {L"Physical address (CntCtlBase)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Timer Count", 4, 12, L"%d", NULL, (VOID**)&GtBlockTimerCount,
+ ValidateGtBlockTimerCount, NULL},
+ {L"Timer Offset", 4, 16, L"%d", NULL, (VOID**)&GtBlockTimerOffset, NULL,
+ NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the GT Block timer.
+**/
+STATIC CONST ACPI_PARSER GtBlockTimerParser[] = {
+ {L"Frame Number", 1, 0, L"%d", NULL, NULL, ValidateGtFrameNumber, NULL},
+ {L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL},
+ {L"Physical address (CntBaseX)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Physical address (CntEL0BaseX)", 8, 12, L"0x%lx", NULL, NULL, NULL,
+ NULL},
+ {L"Physical Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Physical Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Virtual Timer GSIV", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Virtual Timer Flags", 4, 32, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Common Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Platform Watchdog.
+**/
+STATIC CONST ACPI_PARSER SBSAGenericWatchdogParser[] = {
+ {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL},
+ {L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL},
+ {L"RefreshFrame Physical address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"ControlFrame Physical address", 8, 12, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Watchdog Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Watchdog Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ This function parses the Platform GT Block.
+
+ @param [in] Ptr Pointer to the start of the GT Block data.
+ @param [in] Length Length of the GT Block structure.
+**/
+STATIC
+VOID
+DumpGTBlock (
+ IN UINT8* Ptr,
+ IN UINT16 Length
+ )
+{
+ UINT32 Index;
+ UINT32 Offset;
+
+ ParseAcpi (
+ TRUE,
+ 2,
+ "GT Block",
+ Ptr,
+ Length,
+ PARSER_PARAMS (GtBlockParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((GtBlockTimerCount == NULL) ||
+ (GtBlockTimerOffset == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient GT Block Structure length. Length = %d.\n",
+ Length
+ );
+ return;
+ }
+
+ Offset = *GtBlockTimerOffset;
+ Index = 0;
+
+ // Parse the specified number of GT Block Timer Structures or the GT Block
+ // Structure buffer length. Whichever is minimum.
+ while ((Index++ < *GtBlockTimerCount) &&
+ (Offset < Length)) {
+ Offset += ParseAcpi (
+ TRUE,
+ 2,
+ "GT Block Timer",
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (GtBlockTimerParser)
+ );
+ }
+}
+
+/**
+ This function parses the Platform Watchdog timer.
+
+ @param [in] Ptr Pointer to the start of the watchdog timer data.
+ @param [in] Length Length of the watchdog timer structure.
+**/
+STATIC
+VOID
+DumpWatchdogTimer (
+ IN UINT8* Ptr,
+ IN UINT16 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "SBSA Generic Watchdog",
+ Ptr,
+ Length,
+ PARSER_PARAMS (SBSAGenericWatchdogParser)
+ );
+}
+
+/**
+ This function parses the ACPI GTDT table.
+ When trace is enabled this function parses the GTDT table and
+ traces the ACPI table fields.
+
+ This function also parses the following platform timer structures:
+ - GT Block timer
+ - Watchdog timer
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiGtdt (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Index;
+ UINT32 Offset;
+ UINT8* TimerPtr;
+
+ if (!Trace) {
+ return;
+ }
+
+ ParseAcpi (
+ TRUE,
+ 0,
+ "GTDT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (GtdtParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((GtdtPlatformTimerCount == NULL) ||
+ (GtdtPlatformTimerOffset == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient table length. AcpiTableLength = %d.\n",
+ AcpiTableLength
+ );
+ return;
+ }
+
+ TimerPtr = Ptr + *GtdtPlatformTimerOffset;
+ Offset = *GtdtPlatformTimerOffset;
+ Index = 0;
+
+ // Parse the specified number of Platform Timer Structures or the GTDT
+ // buffer length. Whichever is minimum.
+ while ((Index++ < *GtdtPlatformTimerCount) &&
+ (Offset < AcpiTableLength)) {
+ // Parse the Platform Timer Header to obtain Length and Type
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ TimerPtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (GtPlatformTimerHeaderParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((PlatformTimerType == NULL) ||
+ (PlatformTimerLength == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"Platform Timer Structure header. Length = %d.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate Platform Timer Structure length
+ if ((*PlatformTimerLength == 0) ||
+ ((Offset + (*PlatformTimerLength)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Platform Timer Structure length. " \
+ L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
+ *PlatformTimerLength,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ switch (*PlatformTimerType) {
+ case EFI_ACPI_6_3_GTDT_GT_BLOCK:
+ DumpGTBlock (TimerPtr, *PlatformTimerLength);
+ break;
+ case EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG:
+ DumpWatchdogTimer (TimerPtr, *PlatformTimerLength);
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Platform Timer Type = %d\n",
+ *PlatformTimerType
+ );
+ break;
+ } // switch
+
+ TimerPtr += *PlatformTimerLength;
+ Offset += *PlatformTimerLength;
+ } // while
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
new file mode 100644
index 000000000..f7447947b
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
@@ -0,0 +1,764 @@
+/** @file
+ IORT table parser
+
+ Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - IO Remapping Table, Platform Design Document, Revision D, March 2018
+**/
+
+#include <IndustryStandard/IoRemappingTable.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+#include "AcpiViewConfig.h"
+
+// Local variables
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+STATIC CONST UINT32* IortNodeCount;
+STATIC CONST UINT32* IortNodeOffset;
+
+STATIC CONST UINT8* IortNodeType;
+STATIC CONST UINT16* IortNodeLength;
+STATIC CONST UINT32* IortIdMappingCount;
+STATIC CONST UINT32* IortIdMappingOffset;
+
+STATIC CONST UINT32* InterruptContextCount;
+STATIC CONST UINT32* InterruptContextOffset;
+STATIC CONST UINT32* PmuInterruptCount;
+STATIC CONST UINT32* PmuInterruptOffset;
+
+STATIC CONST UINT32* ItsCount;
+
+/**
+ This function validates the ID Mapping array count for the ITS node.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateItsIdMappingCount (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT32*)Ptr != 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: IORT ID Mapping count must be zero.");
+ }
+}
+
+/**
+ This function validates the ID Mapping array count for the Performance
+ Monitoring Counter Group (PMCG) node.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidatePmcgIdMappingCount (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT32*)Ptr > 1) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: IORT ID Mapping count must not be greater than 1.");
+ }
+}
+
+/**
+ This function validates the ID Mapping array offset for the ITS node.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateItsIdArrayReference (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT32*)Ptr != 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: IORT ID Mapping offset must be zero.");
+ }
+}
+
+/**
+ Helper Macro for populating the IORT Node header in the ACPI_PARSER array.
+
+ @param [out] ValidateIdMappingCount Optional pointer to a function for
+ validating the ID Mapping count.
+ @param [out] ValidateIdArrayReference Optional pointer to a function for
+ validating the ID Array reference.
+**/
+#define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount, \
+ ValidateIdArrayReference) \
+ { L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \
+ { L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \
+ { L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \
+ { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
+ { L"Number of ID mappings", 4, 8, L"%d", NULL, \
+ (VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \
+ { L"Reference to ID Array", 4, 12, L"0x%x", NULL, \
+ (VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL }
+
+/**
+ An ACPI_PARSER array describing the ACPI IORT Table
+**/
+STATIC CONST ACPI_PARSER IortParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"Number of IORT Nodes", 4, 36, L"%d", NULL,
+ (VOID**)&IortNodeCount, NULL, NULL},
+ {L"Offset to Array of IORT Nodes", 4, 40, L"0x%x", NULL,
+ (VOID**)&IortNodeOffset, NULL, NULL},
+ {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the IORT node header structure.
+**/
+STATIC CONST ACPI_PARSER IortNodeHeaderParser[] = {
+ PARSE_IORT_NODE_HEADER (NULL, NULL)
+};
+
+/**
+ An ACPI_PARSER array describing the IORT SMMUv1/2 node.
+**/
+STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser[] = {
+ PARSE_IORT_NODE_HEADER (NULL, NULL),
+ {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Span", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Model", 4, 32, L"%d", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reference to Global Interrupt Array", 4, 40, L"0x%x", NULL, NULL, NULL,
+ NULL},
+ {L"Number of context interrupts", 4, 44, L"%d", NULL,
+ (VOID**)&InterruptContextCount, NULL, NULL},
+ {L"Reference to Context Interrupt Array", 4, 48, L"0x%x", NULL,
+ (VOID**)&InterruptContextOffset, NULL, NULL},
+ {L"Number of PMU Interrupts", 4, 52, L"%d", NULL,
+ (VOID**)&PmuInterruptCount, NULL, NULL},
+ {L"Reference to PMU Interrupt Array", 4, 56, L"0x%x", NULL,
+ (VOID**)&PmuInterruptOffset, NULL, NULL},
+
+ // Interrupt Array
+ {L"SMMU_NSgIrpt", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SMMU_NSgIrpt interrupt flags", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SMMU_NSgCfgIrpt", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SMMU_NSgCfgIrpt interrupt flags", 4, 72, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array.
+**/
+STATIC CONST ACPI_PARSER InterruptArrayParser[] = {
+ {L"Interrupt GSIV", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the IORT ID Mapping.
+**/
+STATIC CONST ACPI_PARSER IortNodeIdMappingParser[] = {
+ {L"Input base", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Number of IDs", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Output base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Output reference", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the IORT SMMUv3 node.
+**/
+STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser[] = {
+ PARSE_IORT_NODE_HEADER (NULL, NULL),
+ {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"VATOS Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Model", 4, 40, L"%d", NULL, NULL, NULL, NULL},
+ {L"Event", 4, 44, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PRI", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"GERR", 4, 52, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Sync", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Proximity domain", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Device ID mapping index", 4, 64, L"%d", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the IORT ITS node.
+**/
+STATIC CONST ACPI_PARSER IortNodeItsParser[] = {
+ PARSE_IORT_NODE_HEADER (
+ ValidateItsIdMappingCount,
+ ValidateItsIdArrayReference
+ ),
+ {L"Number of ITSs", 4, 16, L"%d", NULL, (VOID**)&ItsCount, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the ITS ID.
+**/
+STATIC CONST ACPI_PARSER ItsIdParser[] = {
+ { L"GIC ITS Identifier", 4, 0, L"%d", NULL, NULL, NULL }
+};
+
+/**
+ An ACPI_PARSER array describing the IORT Names Component node.
+**/
+STATIC CONST ACPI_PARSER IortNodeNamedComponentParser[] = {
+ PARSE_IORT_NODE_HEADER (NULL, NULL),
+ {L"Node Flags", 4, 16, L"%d", NULL, NULL, NULL, NULL},
+ {L"Memory access properties", 8, 20, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Device memory address size limit", 1, 28, L"%d", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the IORT Root Complex node.
+**/
+STATIC CONST ACPI_PARSER IortNodeRootComplexParser[] = {
+ PARSE_IORT_NODE_HEADER (NULL, NULL),
+ {L"Memory access properties", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"ATS Attribute", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PCI Segment number", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Memory access size limit", 1, 32, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 3, 33, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the IORT PMCG node.
+**/
+STATIC CONST ACPI_PARSER IortNodePmcgParser[] = {
+ PARSE_IORT_NODE_HEADER (ValidatePmcgIdMappingCount, NULL),
+ {L"Page 0 Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Overflow interrupt GSIV", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Node reference", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Page 1 Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}
+};
+
+/**
+ This function parses the IORT Node Id Mapping array.
+
+ @param [in] Ptr Pointer to the start of the ID mapping array.
+ @param [in] Length Length of the buffer.
+ @param [in] MappingCount The ID Mapping count.
+**/
+STATIC
+VOID
+DumpIortNodeIdMappings (
+ IN UINT8* Ptr,
+ IN UINT32 Length,
+ IN UINT32 MappingCount
+ )
+{
+ UINT32 Index;
+ UINT32 Offset;
+ CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi
+
+ Index = 0;
+ Offset = 0;
+
+ while ((Index < MappingCount) &&
+ (Offset < Length)) {
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "ID Mapping [%d]",
+ Index
+ );
+ Offset += ParseAcpi (
+ TRUE,
+ 4,
+ Buffer,
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (IortNodeIdMappingParser)
+ );
+ Index++;
+ }
+}
+
+/**
+ This function parses the IORT SMMUv1/2 node.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the buffer.
+ @param [in] MappingCount The ID Mapping count.
+ @param [in] MappingOffset The offset of the ID Mapping array
+ from the start of the IORT table.
+**/
+STATIC
+VOID
+DumpIortNodeSmmuV1V2 (
+ IN UINT8* Ptr,
+ IN UINT16 Length,
+ IN UINT32 MappingCount,
+ IN UINT32 MappingOffset
+ )
+{
+ UINT32 Index;
+ UINT32 Offset;
+ CHAR8 Buffer[50]; // Used for AsciiName param of ParseAcpi
+
+ ParseAcpi (
+ TRUE,
+ 2,
+ "SMMUv1 or SMMUv2 Node",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IortNodeSmmuV1V2Parser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((InterruptContextCount == NULL) ||
+ (InterruptContextOffset == NULL) ||
+ (PmuInterruptCount == NULL) ||
+ (PmuInterruptOffset == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient SMMUv1/2 node length. Length = %d\n",
+ Length
+ );
+ return;
+ }
+
+ Offset = *InterruptContextOffset;
+ Index = 0;
+
+ while ((Index < *InterruptContextCount) &&
+ (Offset < Length)) {
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "Context Interrupts Array [%d]",
+ Index
+ );
+ Offset += ParseAcpi (
+ TRUE,
+ 4,
+ Buffer,
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (InterruptArrayParser)
+ );
+ Index++;
+ }
+
+ Offset = *PmuInterruptOffset;
+ Index = 0;
+
+ while ((Index < *PmuInterruptCount) &&
+ (Offset < Length)) {
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "PMU Interrupts Array [%d]",
+ Index
+ );
+ Offset += ParseAcpi (
+ TRUE,
+ 4,
+ Buffer,
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (InterruptArrayParser)
+ );
+ Index++;
+ }
+
+ DumpIortNodeIdMappings (
+ Ptr + MappingOffset,
+ Length - MappingOffset,
+ MappingCount
+ );
+}
+
+/**
+ This function parses the IORT SMMUv3 node.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the buffer.
+ @param [in] MappingCount The ID Mapping count.
+ @param [in] MappingOffset The offset of the ID Mapping array
+ from the start of the IORT table.
+**/
+STATIC
+VOID
+DumpIortNodeSmmuV3 (
+ IN UINT8* Ptr,
+ IN UINT16 Length,
+ IN UINT32 MappingCount,
+ IN UINT32 MappingOffset
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "SMMUV3 Node",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IortNodeSmmuV3Parser)
+ );
+
+ DumpIortNodeIdMappings (
+ Ptr + MappingOffset,
+ Length - MappingOffset,
+ MappingCount
+ );
+}
+
+/**
+ This function parses the IORT ITS node.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the buffer.
+**/
+STATIC
+VOID
+DumpIortNodeIts (
+ IN UINT8* Ptr,
+ IN UINT16 Length
+ )
+{
+ UINT32 Offset;
+ UINT32 Index;
+ CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi
+
+ Offset = ParseAcpi (
+ TRUE,
+ 2,
+ "ITS Node",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IortNodeItsParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if (ItsCount == NULL) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient ITS group length. Length = %d.\n",
+ Length
+ );
+ return;
+ }
+
+ Index = 0;
+
+ while ((Index < *ItsCount) &&
+ (Offset < Length)) {
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "GIC ITS Identifier Array [%d]",
+ Index
+ );
+ Offset += ParseAcpi (
+ TRUE,
+ 4,
+ Buffer,
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (ItsIdParser)
+ );
+ Index++;
+ }
+
+ // Note: ITS does not have the ID Mappings Array
+
+}
+
+/**
+ This function parses the IORT Named Component node.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the buffer.
+ @param [in] MappingCount The ID Mapping count.
+ @param [in] MappingOffset The offset of the ID Mapping array
+ from the start of the IORT table.
+**/
+STATIC
+VOID
+DumpIortNodeNamedComponent (
+ IN UINT8* Ptr,
+ IN UINT16 Length,
+ IN UINT32 MappingCount,
+ IN UINT32 MappingOffset
+ )
+{
+ UINT32 Offset;
+
+ Offset = ParseAcpi (
+ TRUE,
+ 2,
+ "Named Component Node",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IortNodeNamedComponentParser)
+ );
+
+ // Estimate the Device Name length
+ PrintFieldName (2, L"Device Object Name");
+
+ while ((*(Ptr + Offset) != 0) &&
+ (Offset < Length)) {
+ Print (L"%c", *(Ptr + Offset));
+ Offset++;
+ }
+ Print (L"\n");
+
+ DumpIortNodeIdMappings (
+ Ptr + MappingOffset,
+ Length - MappingOffset,
+ MappingCount
+ );
+}
+
+/**
+ This function parses the IORT Root Complex node.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the buffer.
+ @param [in] MappingCount The ID Mapping count.
+ @param [in] MappingOffset The offset of the ID Mapping array
+ from the start of the IORT table.
+**/
+STATIC
+VOID
+DumpIortNodeRootComplex (
+ IN UINT8* Ptr,
+ IN UINT16 Length,
+ IN UINT32 MappingCount,
+ IN UINT32 MappingOffset
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Root Complex Node",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IortNodeRootComplexParser)
+ );
+
+ DumpIortNodeIdMappings (
+ Ptr + MappingOffset,
+ Length - MappingOffset,
+ MappingCount
+ );
+}
+
+/**
+ This function parses the IORT PMCG node.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the buffer.
+ @param [in] MappingCount The ID Mapping count.
+ @param [in] MappingOffset The offset of the ID Mapping array
+ from the start of the IORT table.
+**/
+STATIC
+VOID
+DumpIortNodePmcg (
+ IN UINT8* Ptr,
+ IN UINT16 Length,
+ IN UINT32 MappingCount,
+ IN UINT32 MappingOffset
+)
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "PMCG Node",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IortNodePmcgParser)
+ );
+
+ DumpIortNodeIdMappings (
+ Ptr + MappingOffset,
+ Length - MappingOffset,
+ MappingCount
+ );
+}
+
+/**
+ This function parses the ACPI IORT table.
+ When trace is enabled this function parses the IORT table and traces the ACPI fields.
+
+ This function also parses the following nodes:
+ - ITS Group
+ - Named Component
+ - Root Complex
+ - SMMUv1/2
+ - SMMUv3
+ - PMCG
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiIort (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT32 Index;
+ UINT8* NodePtr;
+
+ if (!Trace) {
+ return;
+ }
+
+ ParseAcpi (
+ TRUE,
+ 0,
+ "IORT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (IortParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((IortNodeCount == NULL) ||
+ (IortNodeOffset == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient table length. AcpiTableLength = %d.\n",
+ AcpiTableLength
+ );
+ return;
+ }
+
+ Offset = *IortNodeOffset;
+ NodePtr = Ptr + Offset;
+ Index = 0;
+
+ // Parse the specified number of IORT nodes or the IORT table buffer length.
+ // Whichever is minimum.
+ while ((Index++ < *IortNodeCount) &&
+ (Offset < AcpiTableLength)) {
+ // Parse the IORT Node Header
+ ParseAcpi (
+ FALSE,
+ 0,
+ "IORT Node Header",
+ NodePtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (IortNodeHeaderParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((IortNodeType == NULL) ||
+ (IortNodeLength == NULL) ||
+ (IortIdMappingCount == NULL) ||
+ (IortIdMappingOffset == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"IORT node header. Length = %d.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate IORT Node length
+ if ((*IortNodeLength == 0) ||
+ ((Offset + (*IortNodeLength)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid IORT Node length. " \
+ L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
+ *IortNodeLength,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ PrintFieldName (2, L"* Node Offset *");
+ Print (L"0x%x\n", Offset);
+
+ switch (*IortNodeType) {
+ case EFI_ACPI_IORT_TYPE_ITS_GROUP:
+ DumpIortNodeIts (
+ NodePtr,
+ *IortNodeLength
+ );
+ break;
+ case EFI_ACPI_IORT_TYPE_NAMED_COMP:
+ DumpIortNodeNamedComponent (
+ NodePtr,
+ *IortNodeLength,
+ *IortIdMappingCount,
+ *IortIdMappingOffset
+ );
+ break;
+ case EFI_ACPI_IORT_TYPE_ROOT_COMPLEX:
+ DumpIortNodeRootComplex (
+ NodePtr,
+ *IortNodeLength,
+ *IortIdMappingCount,
+ *IortIdMappingOffset
+ );
+ break;
+ case EFI_ACPI_IORT_TYPE_SMMUv1v2:
+ DumpIortNodeSmmuV1V2 (
+ NodePtr,
+ *IortNodeLength,
+ *IortIdMappingCount,
+ *IortIdMappingOffset
+ );
+ break;
+ case EFI_ACPI_IORT_TYPE_SMMUv3:
+ DumpIortNodeSmmuV3 (
+ NodePtr,
+ *IortNodeLength,
+ *IortIdMappingCount,
+ *IortIdMappingOffset
+ );
+ break;
+ case EFI_ACPI_IORT_TYPE_PMCG:
+ DumpIortNodePmcg (
+ NodePtr,
+ *IortNodeLength,
+ *IortIdMappingCount,
+ *IortIdMappingOffset
+ );
+ break;
+
+ default:
+ IncrementErrorCount ();
+ Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);
+ } // switch
+
+ NodePtr += (*IortNodeLength);
+ Offset += (*IortNodeLength);
+ } // while
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c
new file mode 100644
index 000000000..15aa2392b
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c
@@ -0,0 +1,374 @@
+/** @file
+ MADT table parser
+
+ Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification - January 2019
+ - Arm Generic Interrupt Controller Architecture Specification,
+ GIC architecture version 3 and version 4, issue E
+ - Arm Server Base System Architecture 5.0
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+#include "AcpiViewConfig.h"
+#include "MadtParser.h"
+
+// Local Variables
+STATIC CONST UINT8* MadtInterruptControllerType;
+STATIC CONST UINT8* MadtInterruptControllerLength;
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ This function validates the System Vector Base in the GICD.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateGICDSystemVectorBase (
+ IN UINT8* Ptr,
+ IN VOID* Context
+)
+{
+ if (*(UINT32*)Ptr != 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: System Vector Base must be zero."
+ );
+ }
+}
+
+/**
+ This function validates the SPE Overflow Interrupt in the GICC.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateSpeOverflowInterrupt (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT16 SpeOverflowInterrupt;
+
+ SpeOverflowInterrupt = *(UINT16*)Ptr;
+
+ // SPE not supported by this processor
+ if (SpeOverflowInterrupt == 0) {
+ return;
+ }
+
+ if ((SpeOverflowInterrupt < ARM_PPI_ID_MIN) ||
+ ((SpeOverflowInterrupt > ARM_PPI_ID_MAX) &&
+ (SpeOverflowInterrupt < ARM_PPI_ID_EXTENDED_MIN)) ||
+ (SpeOverflowInterrupt > ARM_PPI_ID_EXTENDED_MAX)) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: SPE Overflow Interrupt ID of %d is not in the allowed PPI ID "
+ L"ranges of %d-%d or %d-%d (for GICv3.1 or later).",
+ SpeOverflowInterrupt,
+ ARM_PPI_ID_MIN,
+ ARM_PPI_ID_MAX,
+ ARM_PPI_ID_EXTENDED_MIN,
+ ARM_PPI_ID_EXTENDED_MAX
+ );
+ } else if (SpeOverflowInterrupt != ARM_PPI_ID_PMBIRQ) {
+ IncrementWarningCount();
+ Print (
+ L"\nWARNING: SPE Overflow Interrupt ID of %d is not compliant with SBSA "
+ L"Level 3 PPI ID assignment: %d.",
+ SpeOverflowInterrupt,
+ ARM_PPI_ID_PMBIRQ
+ );
+ }
+}
+
+/**
+ An ACPI_PARSER array describing the GICC Interrupt Controller Structure.
+**/
+STATIC CONST ACPI_PARSER GicCParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"CPU Interface Number", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"ACPI Processor UID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Parking Protocol Version", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Performance Interrupt GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Parked Address", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Physical Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"GICV", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"GICH", 8, 48, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"VGIC Maintenance interrupt", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"GICR Base Address", 8, 60, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"MPIDR", 8, 68, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Processor Power Efficiency Class", 1, 76, L"0x%x", NULL, NULL, NULL,
+ NULL},
+ {L"Reserved", 1, 77, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SPE overflow Interrupt", 2, 78, L"0x%x", NULL, NULL,
+ ValidateSpeOverflowInterrupt, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the GICD Interrupt Controller Structure.
+**/
+STATIC CONST ACPI_PARSER GicDParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"GIC ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"System Vector Base", 4, 16, L"0x%x", NULL, NULL,
+ ValidateGICDSystemVectorBase, NULL},
+ {L"GIC Version", 1, 20, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 3, 21, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the MSI Frame Interrupt Controller Structure.
+**/
+STATIC CONST ACPI_PARSER GicMSIFrameParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"MSI Frame ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"SPI Count", 2, 20, L"%d", NULL, NULL, NULL, NULL},
+ {L"SPI Base", 2, 22, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the GICR Interrupt Controller Structure.
+**/
+STATIC CONST ACPI_PARSER GicRParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Discovery Range Base Address", 8, 4, L"0x%lx", NULL, NULL, NULL,
+ NULL},
+ {L"Discovery Range Length", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the GIC ITS Interrupt Controller Structure.
+**/
+STATIC CONST ACPI_PARSER GicITSParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"GIC ITS ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the ACPI MADT Table.
+**/
+STATIC CONST ACPI_PARSER MadtParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"Local Interrupt Controller Address", 4, 36, L"0x%x", NULL, NULL, NULL,
+ NULL},
+ {L"Flags", 4, 40, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the MADT Interrupt Controller Structure Header Structure.
+**/
+STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser[] = {
+ {NULL, 1, 0, NULL, NULL, (VOID**)&MadtInterruptControllerType, NULL, NULL},
+ {L"Length", 1, 1, NULL, NULL, (VOID**)&MadtInterruptControllerLength, NULL,
+ NULL},
+ {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL}
+};
+
+/**
+ This function parses the ACPI MADT table.
+ When trace is enabled this function parses the MADT table and
+ traces the ACPI table fields.
+
+ This function currently parses the following Interrupt Controller
+ Structures:
+ - GICC
+ - GICD
+ - GIC MSI Frame
+ - GICR
+ - GIC ITS
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiMadt (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT8* InterruptContollerPtr;
+ UINT32 GICDCount;
+
+ GICDCount = 0;
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "MADT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (MadtParser)
+ );
+ InterruptContollerPtr = Ptr + Offset;
+
+ while (Offset < AcpiTableLength) {
+ // Parse Interrupt Controller Structure to obtain Length.
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ InterruptContollerPtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (MadtInterruptControllerHeaderParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((MadtInterruptControllerType == NULL) ||
+ (MadtInterruptControllerLength == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"Interrupt Controller Structure header. Length = %d.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate Interrupt Controller Structure length
+ if ((*MadtInterruptControllerLength == 0) ||
+ ((Offset + (*MadtInterruptControllerLength)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Interrupt Controller Structure length. " \
+ L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
+ *MadtInterruptControllerLength,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ switch (*MadtInterruptControllerType) {
+ case EFI_ACPI_6_3_GIC: {
+ ParseAcpi (
+ TRUE,
+ 2,
+ "GICC",
+ InterruptContollerPtr,
+ *MadtInterruptControllerLength,
+ PARSER_PARAMS (GicCParser)
+ );
+ break;
+ }
+
+ case EFI_ACPI_6_3_GICD: {
+ if (++GICDCount > 1) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Only one GICD must be present,"
+ L" GICDCount = %d\n",
+ GICDCount
+ );
+ }
+ ParseAcpi (
+ TRUE,
+ 2,
+ "GICD",
+ InterruptContollerPtr,
+ *MadtInterruptControllerLength,
+ PARSER_PARAMS (GicDParser)
+ );
+ break;
+ }
+
+ case EFI_ACPI_6_3_GIC_MSI_FRAME: {
+ ParseAcpi (
+ TRUE,
+ 2,
+ "GIC MSI Frame",
+ InterruptContollerPtr,
+ *MadtInterruptControllerLength,
+ PARSER_PARAMS (GicMSIFrameParser)
+ );
+ break;
+ }
+
+ case EFI_ACPI_6_3_GICR: {
+ ParseAcpi (
+ TRUE,
+ 2,
+ "GICR",
+ InterruptContollerPtr,
+ *MadtInterruptControllerLength,
+ PARSER_PARAMS (GicRParser)
+ );
+ break;
+ }
+
+ case EFI_ACPI_6_3_GIC_ITS: {
+ ParseAcpi (
+ TRUE,
+ 2,
+ "GIC ITS",
+ InterruptContollerPtr,
+ *MadtInterruptControllerLength,
+ PARSER_PARAMS (GicITSParser)
+ );
+ break;
+ }
+
+ default: {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Unknown Interrupt Controller Structure,"
+ L" Type = %d, Length = %d\n",
+ *MadtInterruptControllerType,
+ *MadtInterruptControllerLength
+ );
+ }
+ } // switch
+
+ InterruptContollerPtr += *MadtInterruptControllerLength;
+ Offset += *MadtInterruptControllerLength;
+ } // while
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.h b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.h
new file mode 100644
index 000000000..fbbc43e09
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.h
@@ -0,0 +1,40 @@
+/** @file
+ Header file for MADT table parser
+
+ Copyright (c) 2019, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - Arm Generic Interrupt Controller Architecture Specification,
+ GIC architecture version 3 and version 4, issue E
+ - Arm Server Base System Architecture 5.0
+**/
+
+#ifndef MADT_PARSER_H_
+#define MADT_PARSER_H_
+
+///
+/// Level 3 base server system Private Peripheral Inerrupt (PPI) ID assignments
+///
+#define ARM_PPI_ID_OVERFLOW_INTERRUPT_FROM_CNTP 30
+#define ARM_PPI_ID_OVERFLOW_INTERRUPT_FROM_CNTPS 29
+#define ARM_PPI_ID_OVERFLOW_INTERRUPT_FROM_CNTHV 28
+#define ARM_PPI_ID_OVERFLOW_INTERRUPT_FROM_CNTV 27
+#define ARM_PPI_ID_OVERFLOW_INTERRUPT_FROM_CNTHP 26
+#define ARM_PPI_ID_GIC_MAINTENANCE_INTERRUPT 25
+#define ARM_PPI_ID_CTIIRQ 24
+#define ARM_PPI_ID_PERFORMANCE_MONITORS_INTERRUPT 23
+#define ARM_PPI_ID_COMMIRQ 22
+#define ARM_PPI_ID_PMBIRQ 21
+#define ARM_PPI_ID_CNTHPS 20
+#define ARM_PPI_ID_CNTHVS 19
+
+///
+/// PPI ID allowed ranges
+///
+#define ARM_PPI_ID_MAX 31
+#define ARM_PPI_ID_MIN 16
+#define ARM_PPI_ID_EXTENDED_MAX 1119
+#define ARM_PPI_ID_EXTENDED_MIN 1056
+
+#endif // MADT_PARSER_H_
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c
new file mode 100644
index 000000000..9da4d60e8
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c
@@ -0,0 +1,90 @@
+/** @file
+ MCFG table parser
+
+ Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - PCI Firmware Specification - Revision 3.2, January 26, 2015.
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+// Local variables
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ An ACPI_PARSER array describing the ACPI MCFG Table.
+**/
+STATIC CONST ACPI_PARSER McfgParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"Reserved", 8, 36, L"0x%lx", NULL, NULL, NULL, NULL},
+};
+
+/**
+ An ACPI_PARSER array describing the PCI configuration Space Base Address structure.
+**/
+STATIC CONST ACPI_PARSER PciCfgSpaceBaseAddrParser[] = {
+ {L"Base Address", 8, 0, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"PCI Segment Group No.", 2, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Start Bus No.", 1, 10, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"End Bus No.", 1, 11, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ This function parses the ACPI MCFG table.
+ When trace is enabled this function parses the MCFG table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiMcfg (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT32 PciCfgOffset;
+ UINT8* PciCfgSpacePtr;
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "MCFG",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (McfgParser)
+ );
+
+ PciCfgSpacePtr = Ptr + Offset;
+
+ while (Offset < AcpiTableLength) {
+ PciCfgOffset = ParseAcpi (
+ TRUE,
+ 2,
+ "PCI Configuration Space",
+ PciCfgSpacePtr,
+ (AcpiTableLength - Offset),
+ PARSER_PARAMS (PciCfgSpaceBaseAddrParser)
+ );
+ PciCfgSpacePtr += PciCfgOffset;
+ Offset += PciCfgOffset;
+ }
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c
new file mode 100644
index 000000000..acd2b81bb
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c
@@ -0,0 +1,478 @@
+/** @file
+ PPTT table parser
+
+ Copyright (c) 2019 - 2020, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification - January 2019
+ - ARM Architecture Reference Manual ARMv8 (D.a)
+**/
+
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiView.h"
+#include "AcpiViewConfig.h"
+#include "PpttParser.h"
+
+// Local variables
+STATIC CONST UINT8* ProcessorTopologyStructureType;
+STATIC CONST UINT8* ProcessorTopologyStructureLength;
+STATIC CONST UINT32* NumberOfPrivateResources;
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ This function validates the Cache Type Structure (Type 1) 'Number of sets'
+ field.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateCacheNumberOfSets (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT32 NumberOfSets;
+ NumberOfSets = *(UINT32*)Ptr;
+
+ if (NumberOfSets == 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Cache number of sets must be greater than 0");
+ return;
+ }
+
+#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ if (NumberOfSets > PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: When ARMv8.3-CCIDX is implemented the maximum cache number of "
+ L"sets must be less than or equal to %d",
+ PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX
+ );
+ return;
+ }
+
+ if (NumberOfSets > PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX) {
+ IncrementWarningCount ();
+ Print (
+ L"\nWARNING: Without ARMv8.3-CCIDX, the maximum cache number of sets "
+ L"must be less than or equal to %d. Ignore this message if "
+ L"ARMv8.3-CCIDX is implemented",
+ PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX
+ );
+ return;
+ }
+#endif
+
+}
+
+/**
+ This function validates the Cache Type Structure (Type 1) 'Associativity'
+ field.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateCacheAssociativity (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT8 Associativity;
+ Associativity = *(UINT8*)Ptr;
+
+ if (Associativity == 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Cache associativity must be greater than 0");
+ return;
+ }
+}
+
+/**
+ This function validates the Cache Type Structure (Type 1) Line size field.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateCacheLineSize (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ // Reference: ARM Architecture Reference Manual ARMv8 (D.a)
+ // Section D12.2.25: CCSIDR_EL1, Current Cache Size ID Register
+ // LineSize, bits [2:0]
+ // (Log2(Number of bytes in cache line)) - 4.
+
+ UINT16 LineSize;
+ LineSize = *(UINT16*)Ptr;
+
+ if ((LineSize < PPTT_ARM_CACHE_LINE_SIZE_MIN) ||
+ (LineSize > PPTT_ARM_CACHE_LINE_SIZE_MAX)) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: The cache line size must be between %d and %d bytes"
+ L" on ARM Platforms.",
+ PPTT_ARM_CACHE_LINE_SIZE_MIN,
+ PPTT_ARM_CACHE_LINE_SIZE_MAX
+ );
+ return;
+ }
+
+ if ((LineSize & (LineSize - 1)) != 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: The cache line size is not a power of 2.");
+ }
+#endif
+}
+
+/**
+ This function validates the Cache Type Structure (Type 1) Attributes field.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateCacheAttributes (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ // Reference: Advanced Configuration and Power Interface (ACPI) Specification
+ // Version 6.2 Errata A, September 2017
+ // Table 5-153: Cache Type Structure
+ UINT8 Attributes;
+ Attributes = *(UINT8*)Ptr;
+
+ if ((Attributes & 0xE0) != 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Attributes bits [7:5] are reserved and must be zero.",
+ Attributes
+ );
+ return;
+ }
+}
+
+/**
+ An ACPI_PARSER array describing the ACPI PPTT Table.
+**/
+STATIC CONST ACPI_PARSER PpttParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo)
+};
+
+/**
+ An ACPI_PARSER array describing the processor topology structure header.
+**/
+STATIC CONST ACPI_PARSER ProcessorTopologyStructureHeaderParser[] = {
+ {L"Type", 1, 0, NULL, NULL, (VOID**)&ProcessorTopologyStructureType,
+ NULL, NULL},
+ {L"Length", 1, 1, NULL, NULL, (VOID**)&ProcessorTopologyStructureLength,
+ NULL, NULL},
+ {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Processor Hierarchy Node Structure - Type 0.
+**/
+STATIC CONST ACPI_PARSER ProcessorHierarchyNodeStructureParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Parent", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"ACPI Processor ID", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Number of private resources", 4, 16, L"%d", NULL,
+ (VOID**)&NumberOfPrivateResources, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Cache Type Structure - Type 1.
+**/
+STATIC CONST ACPI_PARSER CacheTypeStructureParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Next Level of Cache", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Size", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Number of sets", 4, 16, L"%d", NULL, NULL, ValidateCacheNumberOfSets, NULL},
+ {L"Associativity", 1, 20, L"%d", NULL, NULL, ValidateCacheAssociativity, NULL},
+ {L"Attributes", 1, 21, L"0x%x", NULL, NULL, ValidateCacheAttributes, NULL},
+ {L"Line size", 2, 22, L"%d", NULL, NULL, ValidateCacheLineSize, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the ID Type Structure - Type 2.
+**/
+STATIC CONST ACPI_PARSER IdStructureParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"VENDOR_ID", 4, 4, NULL, Dump4Chars, NULL, NULL, NULL},
+ {L"LEVEL_1_ID", 8, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"LEVEL_2_ID", 8, 16, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"MAJOR_REV", 2, 24, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"MINOR_REV", 2, 26, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SPIN_REV", 2, 28, L"0x%x", NULL, NULL, NULL, NULL},
+};
+
+/**
+ This function parses the Processor Hierarchy Node Structure (Type 0).
+
+ @param [in] Ptr Pointer to the start of the Processor Hierarchy Node
+ Structure data.
+ @param [in] Length Length of the Processor Hierarchy Node Structure.
+**/
+STATIC
+VOID
+DumpProcessorHierarchyNodeStructure (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ UINT32 Offset;
+ UINT32 Index;
+ CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];
+
+ Offset = ParseAcpi (
+ TRUE,
+ 2,
+ "Processor Hierarchy Node Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (ProcessorHierarchyNodeStructureParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if (NumberOfPrivateResources == NULL) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient Processor Hierarchy Node length. Length = %d.\n",
+ Length
+ );
+ return;
+ }
+
+ // Make sure the Private Resource array lies inside this structure
+ if (Offset + (*NumberOfPrivateResources * sizeof (UINT32)) > Length) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Number of Private Resources. " \
+ L"PrivateResourceCount = %d. RemainingBufferLength = %d. " \
+ L"Parsing of this structure aborted.\n",
+ *NumberOfPrivateResources,
+ Length - Offset
+ );
+ return;
+ }
+
+ Index = 0;
+
+ // Parse the specified number of private resource references or the Processor
+ // Hierarchy Node length. Whichever is minimum.
+ while (Index < *NumberOfPrivateResources) {
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"Private resources [%d]",
+ Index
+ );
+
+ PrintFieldName (4, Buffer);
+ Print (
+ L"0x%x\n",
+ *((UINT32*)(Ptr + Offset))
+ );
+
+ Offset += sizeof (UINT32);
+ Index++;
+ }
+}
+
+/**
+ This function parses the Cache Type Structure (Type 1).
+
+ @param [in] Ptr Pointer to the start of the Cache Type Structure data.
+ @param [in] Length Length of the Cache Type Structure.
+**/
+STATIC
+VOID
+DumpCacheTypeStructure (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Cache Type Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (CacheTypeStructureParser)
+ );
+}
+
+/**
+ This function parses the ID Structure (Type 2).
+
+ @param [in] Ptr Pointer to the start of the ID Structure data.
+ @param [in] Length Length of the ID Structure.
+**/
+STATIC
+VOID
+DumpIDStructure (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "ID Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IdStructureParser)
+ );
+}
+
+/**
+ This function parses the ACPI PPTT table.
+ When trace is enabled this function parses the PPTT table and
+ traces the ACPI table fields.
+
+ This function parses the following processor topology structures:
+ - Processor hierarchy node structure (Type 0)
+ - Cache Type Structure (Type 1)
+ - ID structure (Type 2)
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiPptt (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT8* ProcessorTopologyStructurePtr;
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "PPTT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (PpttParser)
+ );
+
+ ProcessorTopologyStructurePtr = Ptr + Offset;
+
+ while (Offset < AcpiTableLength) {
+ // Parse Processor Hierarchy Node Structure to obtain Type and Length.
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ ProcessorTopologyStructurePtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (ProcessorTopologyStructureHeaderParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((ProcessorTopologyStructureType == NULL) ||
+ (ProcessorTopologyStructureLength == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"processor topology structure header. Length = %d.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate Processor Topology Structure length
+ if ((*ProcessorTopologyStructureLength == 0) ||
+ ((Offset + (*ProcessorTopologyStructureLength)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Processor Topology Structure length. " \
+ L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
+ *ProcessorTopologyStructureLength,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ PrintFieldName (2, L"* Structure Offset *");
+ Print (L"0x%x\n", Offset);
+
+ switch (*ProcessorTopologyStructureType) {
+ case EFI_ACPI_6_2_PPTT_TYPE_PROCESSOR:
+ DumpProcessorHierarchyNodeStructure (
+ ProcessorTopologyStructurePtr,
+ *ProcessorTopologyStructureLength
+ );
+ break;
+ case EFI_ACPI_6_2_PPTT_TYPE_CACHE:
+ DumpCacheTypeStructure (
+ ProcessorTopologyStructurePtr,
+ *ProcessorTopologyStructureLength
+ );
+ break;
+ case EFI_ACPI_6_2_PPTT_TYPE_ID:
+ DumpIDStructure (
+ ProcessorTopologyStructurePtr,
+ *ProcessorTopologyStructureLength
+ );
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Unknown processor topology structure:"
+ L" Type = %d, Length = %d\n",
+ *ProcessorTopologyStructureType,
+ *ProcessorTopologyStructureLength
+ );
+ }
+
+ ProcessorTopologyStructurePtr += *ProcessorTopologyStructureLength;
+ Offset += *ProcessorTopologyStructureLength;
+ } // while
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.h b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.h
new file mode 100644
index 000000000..2a671203f
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.h
@@ -0,0 +1,38 @@
+/** @file
+ Header file for PPTT parser
+
+ Copyright (c) 2019, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ARM Architecture Reference Manual ARMv8 (D.a)
+**/
+
+#ifndef PPTT_PARSER_H_
+#define PPTT_PARSER_H_
+
+#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+
+/// Cache parameters allowed by the architecture with
+/// ARMv8.3-CCIDX (Cache extended number of sets)
+/// Derived from CCSIDR_EL1 when ID_AA64MMFR2_EL1.CCIDX==0001
+#define PPTT_ARM_CCIDX_CACHE_NUMBER_OF_SETS_MAX (1 << 24)
+#define PPTT_ARM_CCIDX_CACHE_ASSOCIATIVITY_MAX (1 << 21)
+
+/// Cache parameters allowed by the architecture without
+/// ARMv8.3-CCIDX (Cache extended number of sets)
+/// Derived from CCSIDR_EL1 when ID_AA64MMFR2_EL1.CCIDX==0000
+#define PPTT_ARM_CACHE_NUMBER_OF_SETS_MAX (1 << 15)
+#define PPTT_ARM_CACHE_ASSOCIATIVITY_MAX (1 << 10)
+
+/// Common cache parameters
+/// Derived from CCSIDR_EL1
+/// The LineSize is represented by bits 2:0
+/// (Log2(Number of bytes in cache line)) - 4 is used to represent
+/// the LineSize bits.
+#define PPTT_ARM_CACHE_LINE_SIZE_MAX (1 << 11)
+#define PPTT_ARM_CACHE_LINE_SIZE_MIN (1 << 4)
+
+#endif // if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+
+#endif // PPTT_PARSER_H_
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c
new file mode 100644
index 000000000..f4a8732a7
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c
@@ -0,0 +1,164 @@
+/** @file
+ RSDP table parser
+
+ Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.2 Specification - Errata A, September 2017
+**/
+
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+// Local Variables
+STATIC CONST UINT64* XsdtAddress;
+
+/**
+ This function validates the RSDT Address.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateRsdtAddress (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ // Reference: Server Base Boot Requirements System Software on ARM Platforms
+ // Section: 4.2.1.1 RSDP
+ // Root System Description Pointer (RSDP), ACPI ? 5.2.5.
+ // - Within the RSDP, the RsdtAddress field must be null (zero) and the
+ // XsdtAddresss MUST be a valid, non-null, 64-bit value.
+ UINT32 RsdtAddr;
+
+ RsdtAddr = *(UINT32*)Ptr;
+
+ if (RsdtAddr != 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Rsdt Address = 0x%p. This must be NULL on ARM Platforms.",
+ RsdtAddr
+ );
+ }
+#endif
+}
+
+/**
+ This function validates the XSDT Address.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateXsdtAddress (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ // Reference: Server Base Boot Requirements System Software on ARM Platforms
+ // Section: 4.2.1.1 RSDP
+ // Root System Description Pointer (RSDP), ACPI ? 5.2.5.
+ // - Within the RSDP, the RsdtAddress field must be null (zero) and the
+ // XsdtAddresss MUST be a valid, non-null, 64-bit value.
+ UINT64 XsdtAddr;
+
+ XsdtAddr = *(UINT64*)Ptr;
+
+ if (XsdtAddr == 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Xsdt Address = 0x%p. This must not be NULL on ARM Platforms.",
+ XsdtAddr
+ );
+ }
+#endif
+}
+
+/**
+ An array describing the ACPI RSDP Table.
+**/
+STATIC CONST ACPI_PARSER RsdpParser[] = {
+ {L"Signature", 8, 0, NULL, Dump8Chars, NULL, NULL, NULL},
+ {L"Checksum", 1, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Oem ID", 6, 9, NULL, Dump6Chars, NULL, NULL, NULL},
+ {L"Revision", 1, 15, L"%d", NULL, NULL, NULL, NULL},
+ {L"RSDT Address", 4, 16, L"0x%x", NULL, NULL, ValidateRsdtAddress, NULL},
+ {L"Length", 4, 20, L"%d", NULL, NULL, NULL, NULL},
+ {L"XSDT Address", 8, 24, L"0x%lx", NULL, (VOID**)&XsdtAddress,
+ ValidateXsdtAddress, NULL},
+ {L"Extended Checksum", 1, 32, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 3, 33, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}
+};
+
+/**
+ This function parses the ACPI RSDP table.
+
+ This function invokes the parser for the XSDT table.
+ * Note - This function does not support parsing of RSDT table.
+
+ This function also performs a RAW dump of the ACPI table and
+ validates the checksum.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiRsdp (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ if (Trace) {
+ DumpRaw (Ptr, AcpiTableLength);
+ VerifyChecksum (TRUE, Ptr, AcpiTableLength);
+ }
+
+ ParseAcpi (
+ Trace,
+ 0,
+ "RSDP",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (RsdpParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if (XsdtAddress == NULL) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient table length. AcpiTableLength = %d." \
+ L"RSDP parsing aborted.\n",
+ AcpiTableLength
+ );
+ return;
+ }
+
+ // This code currently supports parsing of XSDT table only
+ // and does not parse the RSDT table. Platforms provide the
+ // RSDT to enable compatibility with ACPI 1.0 operating systems.
+ // Therefore the RSDT should not be used on ARM platforms.
+ if ((*XsdtAddress) == 0) {
+ IncrementErrorCount ();
+ Print (L"ERROR: XSDT Pointer is not set. RSDP parsing aborted.\n");
+ return;
+ }
+
+ ProcessAcpiTable ((UINT8*)(UINTN)(*XsdtAddress));
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c
new file mode 100644
index 000000000..e4625ee8b
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c
@@ -0,0 +1,188 @@
+/** @file
+ SLIT table parser
+
+ Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.2 Specification - Errata A, September 2017
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+// Local Variables
+STATIC CONST UINT64* SlitSystemLocalityCount;
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ An ACPI_PARSER array describing the ACPI SLIT table.
+**/
+STATIC CONST ACPI_PARSER SlitParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"Number of System Localities", 8, 36, L"0x%lx", NULL,
+ (VOID**)&SlitSystemLocalityCount, NULL, NULL}
+};
+
+/**
+ Macro to get the value of a System Locality
+**/
+#define SLIT_ELEMENT(Ptr, i, j) *(Ptr + (i * LocalityCount) + j)
+
+/**
+ This function parses the ACPI SLIT table.
+ When trace is enabled this function parses the SLIT table and
+ traces the ACPI table fields.
+
+ This function also validates System Localities for the following:
+ - Diagonal elements have a normalized value of 10
+ - Relative distance from System Locality at i*N+j is same as
+ j*N+i
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiSlit (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT32 Count;
+ UINT32 Index;
+ UINT32 LocalityCount;
+ UINT8* LocalityPtr;
+ CHAR16 Buffer[80]; // Used for AsciiName param of ParseAcpi
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "SLIT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (SlitParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if (SlitSystemLocalityCount == NULL) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient table length. AcpiTableLength = %d.\n",
+ AcpiTableLength
+ );
+ return;
+ }
+
+ /*
+ Despite the 'Number of System Localities' being a 64-bit field in SLIT,
+ the maximum number of localities that can be represented in SLIT is limited
+ by the 'Length' field of the ACPI table.
+
+ Since the ACPI table length field is 32-bit wide. The maximum number of
+ localities that can be represented in SLIT can be calculated as:
+
+ MaxLocality = sqrt (MAX_UINT32 - sizeof (EFI_ACPI_6_3_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER))
+ = 65535
+ = MAX_UINT16
+ */
+ if (*SlitSystemLocalityCount > MAX_UINT16) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: The Number of System Localities provided can't be represented " \
+ L"in the SLIT table. SlitSystemLocalityCount = %ld. " \
+ L"MaxLocalityCountAllowed = %d.\n",
+ *SlitSystemLocalityCount,
+ MAX_UINT16
+ );
+ return;
+ }
+
+ LocalityCount = (UINT32)*SlitSystemLocalityCount;
+
+ // Make sure system localities fit in the table buffer provided
+ if (Offset + (LocalityCount * LocalityCount) > AcpiTableLength) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Number of System Localities. " \
+ L"SlitSystemLocalityCount = %ld. AcpiTableLength = %d.\n",
+ *SlitSystemLocalityCount,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ LocalityPtr = Ptr + Offset;
+
+ // We only print the Localities if the count is less than 16
+ // If the locality count is more than 16 then refer to the
+ // raw data dump.
+ if (LocalityCount < 16) {
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"Entry[0x%lx][0x%lx]",
+ LocalityCount,
+ LocalityCount
+ );
+ PrintFieldName (0, Buffer);
+ Print (L"\n");
+ Print (L" ");
+ for (Index = 0; Index < LocalityCount; Index++) {
+ Print (L" (%3d) ", Index);
+ }
+ Print (L"\n");
+ for (Count = 0; Count< LocalityCount; Count++) {
+ Print (L" (%3d) ", Count);
+ for (Index = 0; Index < LocalityCount; Index++) {
+ Print (L" %3d ", SLIT_ELEMENT (LocalityPtr, Count, Index));
+ }
+ Print (L"\n");
+ }
+ }
+
+ // Validate
+ for (Count = 0; Count < LocalityCount; Count++) {
+ for (Index = 0; Index < LocalityCount; Index++) {
+ // Element[x][x] must be equal to 10
+ if ((Count == Index) && (SLIT_ELEMENT (LocalityPtr, Count,Index) != 10)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Diagonal Element[0x%lx][0x%lx] (%3d)."
+ L" Normalized Value is not 10\n",
+ Count,
+ Index,
+ SLIT_ELEMENT (LocalityPtr, Count, Index)
+ );
+ }
+ // Element[i][j] must be equal to Element[j][i]
+ if (SLIT_ELEMENT (LocalityPtr, Count, Index) !=
+ SLIT_ELEMENT (LocalityPtr, Index, Count)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Relative distances for Element[0x%lx][0x%lx] (%3d) and \n"
+ L"Element[0x%lx][0x%lx] (%3d) do not match.\n",
+ Count,
+ Index,
+ SLIT_ELEMENT (LocalityPtr, Count, Index),
+ Index,
+ Count,
+ SLIT_ELEMENT (LocalityPtr, Index, Count)
+ );
+ }
+ }
+ }
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c
new file mode 100644
index 000000000..3b06b05de
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c
@@ -0,0 +1,144 @@
+/** @file
+ SPCR table parser
+
+ Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - Microsoft Serial Port Console Redirection Table
+ Specification - Version 1.03 - August 10, 2015.
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+// Local variables
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ This function validates the Interrupt Type.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateInterruptType (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ UINT8 InterruptType;
+
+ InterruptType = *Ptr;
+
+ if (InterruptType !=
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: InterruptType = %d. This must be 8 on ARM Platforms",
+ InterruptType
+ );
+ }
+#endif
+}
+
+/**
+ This function validates the Irq.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateIrq (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+#if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
+ UINT8 Irq;
+
+ Irq = *Ptr;
+
+ if (Irq != 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Irq = %d. This must be zero on ARM Platforms\n",
+ Irq
+ );
+ }
+#endif
+}
+
+/**
+ An ACPI_PARSER array describing the ACPI SPCR Table.
+**/
+STATIC CONST ACPI_PARSER SpcrParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"Interface Type", 1, 36, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 3, 37, L"%x %x %x", Dump3Chars, NULL, NULL, NULL},
+ {L"Base Address", 12, 40, NULL, DumpGas, NULL, NULL, NULL},
+ {L"Interrupt Type", 1, 52, L"%d", NULL, NULL, ValidateInterruptType, NULL},
+ {L"IRQ", 1, 53, L"%d", NULL, NULL, ValidateIrq, NULL},
+ {L"Global System Interrupt", 4, 54, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Baud Rate", 1, 58, L"%d", NULL, NULL, NULL, NULL},
+ {L"Parity", 1, 59, L"%d", NULL, NULL, NULL, NULL},
+ {L"Stop Bits", 1, 60, L"%d", NULL, NULL, NULL, NULL},
+ {L"Flow Control", 1, 61, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Terminal Type", 1, 62, L"%d", NULL, NULL, NULL, NULL},
+ {L"Reserved", 1, 63, L"%x", NULL, NULL, NULL, NULL},
+
+ {L"PCI Device ID", 2, 64, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PCI Vendor ID", 2, 66, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PCI Bus Number", 1, 68, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PCI Device Number", 1, 69, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PCI Function Number", 1, 70, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PCI Flags", 4, 71, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PCI Segment", 1, 75, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 76, L"%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ This function parses the ACPI SPCR table.
+ When trace is enabled this function parses the SPCR table and
+ traces the ACPI table fields.
+
+ This function also performs validations of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiSpcr (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ if (!Trace) {
+ return;
+ }
+
+ // Dump the SPCR
+ ParseAcpi (
+ TRUE,
+ 0,
+ "SPCR",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (SpcrParser)
+ );
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c
new file mode 100644
index 000000000..b9b67820b
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c
@@ -0,0 +1,542 @@
+/** @file
+ SRAT table parser
+
+ Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification - January 2019
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+#include "AcpiViewConfig.h"
+
+// Local Variables
+STATIC CONST UINT8* SratRAType;
+STATIC CONST UINT8* SratRALength;
+STATIC CONST UINT8* SratDeviceHandleType;
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ This function validates the Reserved field in the SRAT table header.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateSratReserved (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT32*)Ptr != 1) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Reserved should be 1 for backward compatibility.\n");
+ }
+}
+
+/**
+ This function validates the Device Handle Type field in the Generic Initiator
+ Affinity Structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateSratDeviceHandleType (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT8 DeviceHandleType;
+
+ DeviceHandleType = *Ptr;
+
+ if (DeviceHandleType > EFI_ACPI_6_3_PCI_DEVICE_HANDLE) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Invalid Device Handle Type: %d. Must be between 0 and %d.",
+ DeviceHandleType,
+ EFI_ACPI_6_3_PCI_DEVICE_HANDLE
+ );
+ }
+}
+
+/**
+ This function traces the PCI BDF Number field inside Device Handle - PCI
+
+ @param [in] Format Format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpSratPciBdfNumber (
+ IN CONST CHAR16* Format,
+ IN UINT8* Ptr
+ )
+{
+ CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];
+
+ Print (L"\n");
+
+ /*
+ The PCI BDF Number subfields are printed in the order specified in the ACPI
+ specification. The format of the 16-bit PCI BDF Number field is as follows:
+
+ +-----+------+------+
+ |DEV | FUNC | BUS |
+ +-----+------+------+
+ |15:11| 10:8 | 7:0 |
+ +-----+------+------+
+ */
+
+ // Print PCI Bus Number (Bits 7:0 of Byte 2)
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"PCI Bus Number"
+ );
+ PrintFieldName (4, Buffer);
+ Print (
+ L"0x%x\n",
+ *Ptr
+ );
+
+ Ptr++;
+
+ // Print PCI Device Number (Bits 7:3 of Byte 3)
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"PCI Device Number"
+ );
+ PrintFieldName (4, Buffer);
+ Print (
+ L"0x%x\n",
+ (*Ptr & (BIT7 | BIT6 | BIT5 | BIT4 | BIT3)) >> 3
+ );
+
+ // PCI Function Number (Bits 2:0 of Byte 3)
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"PCI Function Number"
+ );
+ PrintFieldName (4, Buffer);
+ Print (
+ L"0x%x\n",
+ *Ptr & (BIT2 | BIT1 | BIT0)
+ );
+}
+
+/**
+ An ACPI_PARSER array describing the Device Handle - ACPI
+**/
+STATIC CONST ACPI_PARSER SratDeviceHandleAcpiParser[] = {
+ {L"ACPI_HID", 8, 0, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"ACPI_UID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Device Handle - PCI
+**/
+STATIC CONST ACPI_PARSER SratDeviceHandlePciParser[] = {
+ {L"PCI Segment", 2, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"PCI BDF Number", 2, 2, NULL, DumpSratPciBdfNumber, NULL, NULL, NULL},
+ {L"Reserved", 12, 4, L"%x %x %x %x - %x %x %x %x - %x %x %x %x", Dump12Chars,
+ NULL, NULL, NULL}
+};
+
+/**
+ This function traces the Device Handle field inside Generic Initiator
+ Affinity Structure.
+
+ @param [in] Format Format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpSratDeviceHandle (
+ IN CONST CHAR16* Format,
+ IN UINT8* Ptr
+ )
+{
+ if (SratDeviceHandleType == NULL) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Device Handle Type read incorrectly.\n");
+ return;
+ }
+
+ Print (L"\n");
+
+ if (*SratDeviceHandleType == EFI_ACPI_6_3_ACPI_DEVICE_HANDLE) {
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ sizeof (EFI_ACPI_6_3_DEVICE_HANDLE_ACPI),
+ PARSER_PARAMS (SratDeviceHandleAcpiParser)
+ );
+ } else if (*SratDeviceHandleType == EFI_ACPI_6_3_PCI_DEVICE_HANDLE) {
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ sizeof (EFI_ACPI_6_3_DEVICE_HANDLE_PCI),
+ PARSER_PARAMS (SratDeviceHandlePciParser)
+ );
+ }
+}
+
+/**
+ This function traces the APIC Proximity Domain field.
+
+ @param [in] Format Format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpSratApicProximity (
+ IN CONST CHAR16* Format,
+ IN UINT8* Ptr
+ )
+{
+ UINT32 ProximityDomain;
+
+ ProximityDomain = Ptr[0] | (Ptr[1] << 8) | (Ptr[2] << 16);
+
+ Print (Format, ProximityDomain);
+}
+
+/**
+ An ACPI_PARSER array describing the SRAT Table.
+**/
+STATIC CONST ACPI_PARSER SratParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"Reserved", 4, 36, L"0x%x", NULL, NULL, ValidateSratReserved, NULL},
+ {L"Reserved", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Resource Allocation structure header.
+**/
+STATIC CONST ACPI_PARSER SratResourceAllocationParser[] = {
+ {L"Type", 1, 0, NULL, NULL, (VOID**)&SratRAType, NULL, NULL},
+ {L"Length", 1, 1, NULL, NULL, (VOID**)&SratRALength, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the GICC Affinity structure.
+**/
+STATIC CONST ACPI_PARSER SratGicCAffinityParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"ACPI Processor UID", 4, 6, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 10, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Clock Domain", 4, 14, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the GIC ITS Affinity structure.
+**/
+STATIC CONST ACPI_PARSER SratGicITSAffinityParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"ITS Id", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+};
+
+/**
+ An ACPI_PARSER array describing the Generic Initiator Affinity Structure
+**/
+STATIC CONST ACPI_PARSER SratGenericInitiatorAffinityParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Reserved", 1, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Device Handle Type", 1, 3, L"%d", NULL, (VOID**)&SratDeviceHandleType,
+ ValidateSratDeviceHandleType, NULL},
+ {L"Proximity Domain", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Device Handle", 16, 8, L"%s", DumpSratDeviceHandle, NULL, NULL, NULL},
+ {L"Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 28, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Memory Affinity structure.
+**/
+STATIC CONST ACPI_PARSER SratMemAffinityParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Proximity Domain", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 6, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Base Address Low", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Base Address High", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length Low", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length High", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the APIC/SAPIC Affinity structure.
+**/
+STATIC CONST ACPI_PARSER SratApciSapicAffinityParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Proximity Domain [7:0]", 1, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"APIC ID", 1, 3, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Local SAPIC EID", 1, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Proximity Domain [31:8]", 3, 9, L"0x%x", DumpSratApicProximity,
+ NULL, NULL, NULL},
+ {L"Clock Domain", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the Processor Local x2APIC Affinity structure.
+**/
+STATIC CONST ACPI_PARSER SratX2ApciAffinityParser[] = {
+ {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},
+
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Proximity Domain", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"X2APIC ID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Clock Domain", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ This function parses the ACPI SRAT table.
+ When trace is enabled this function parses the SRAT table and
+ traces the ACPI table fields.
+
+ This function parses the following Resource Allocation Structures:
+ - Processor Local APIC/SAPIC Affinity Structure
+ - Memory Affinity Structure
+ - Processor Local x2APIC Affinity Structure
+ - GICC Affinity Structure
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiSrat (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT8* ResourcePtr;
+ UINT32 GicCAffinityIndex;
+ UINT32 GicITSAffinityIndex;
+ UINT32 GenericInitiatorAffinityIndex;
+ UINT32 MemoryAffinityIndex;
+ UINT32 ApicSapicAffinityIndex;
+ UINT32 X2ApicAffinityIndex;
+ CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi
+
+ GicCAffinityIndex = 0;
+ GicITSAffinityIndex = 0;
+ GenericInitiatorAffinityIndex = 0;
+ MemoryAffinityIndex = 0;
+ ApicSapicAffinityIndex = 0;
+ X2ApicAffinityIndex = 0;
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "SRAT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (SratParser)
+ );
+
+ ResourcePtr = Ptr + Offset;
+
+ while (Offset < AcpiTableLength) {
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ ResourcePtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (SratResourceAllocationParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((SratRAType == NULL) ||
+ (SratRALength == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"Static Resource Allocation structure header. Length = %d.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate Static Resource Allocation Structure length
+ if ((*SratRALength == 0) ||
+ ((Offset + (*SratRALength)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Static Resource Allocation Structure length. " \
+ L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
+ *SratRALength,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ switch (*SratRAType) {
+ case EFI_ACPI_6_3_GICC_AFFINITY:
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "GICC Affinity Structure [%d]",
+ GicCAffinityIndex++
+ );
+ ParseAcpi (
+ TRUE,
+ 2,
+ Buffer,
+ ResourcePtr,
+ *SratRALength,
+ PARSER_PARAMS (SratGicCAffinityParser)
+ );
+ break;
+
+ case EFI_ACPI_6_3_GIC_ITS_AFFINITY:
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "GIC ITS Affinity Structure [%d]",
+ GicITSAffinityIndex++
+ );
+ ParseAcpi (
+ TRUE,
+ 2,
+ Buffer,
+ ResourcePtr,
+ *SratRALength,
+ PARSER_PARAMS (SratGicITSAffinityParser)
+ );
+ break;
+
+ case EFI_ACPI_6_3_GENERIC_INITIATOR_AFFINITY:
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "Generic Initiator Affinity Structure [%d]",
+ GenericInitiatorAffinityIndex++
+ );
+ ParseAcpi (
+ TRUE,
+ 2,
+ Buffer,
+ ResourcePtr,
+ *SratRALength,
+ PARSER_PARAMS (SratGenericInitiatorAffinityParser)
+ );
+ break;
+
+ case EFI_ACPI_6_3_MEMORY_AFFINITY:
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "Memory Affinity Structure [%d]",
+ MemoryAffinityIndex++
+ );
+ ParseAcpi (
+ TRUE,
+ 2,
+ Buffer,
+ ResourcePtr,
+ *SratRALength,
+ PARSER_PARAMS (SratMemAffinityParser)
+ );
+ break;
+
+ case EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY:
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "APIC/SAPIC Affinity Structure [%d]",
+ ApicSapicAffinityIndex++
+ );
+ ParseAcpi (
+ TRUE,
+ 2,
+ Buffer,
+ ResourcePtr,
+ *SratRALength,
+ PARSER_PARAMS (SratApciSapicAffinityParser)
+ );
+ break;
+
+ case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC_AFFINITY:
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "X2APIC Affinity Structure [%d]",
+ X2ApicAffinityIndex++
+ );
+ ParseAcpi (
+ TRUE,
+ 2,
+ Buffer,
+ ResourcePtr,
+ *SratRALength,
+ PARSER_PARAMS (SratX2ApciAffinityParser)
+ );
+ break;
+
+ default:
+ IncrementErrorCount ();
+ Print (L"ERROR: Unknown SRAT Affinity type = 0x%x\n", *SratRAType);
+ break;
+ }
+
+ ResourcePtr += (*SratRALength);
+ Offset += (*SratRALength);
+ }
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c
new file mode 100644
index 000000000..f18664b8a
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c
@@ -0,0 +1,42 @@
+/** @file
+ SSDT table parser
+
+ Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.2 Specification - Errata A, September 2017
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+/**
+ This function parses the ACPI SSDT table.
+ When trace is enabled this function parses the SSDT table and
+ traces the ACPI table fields.
+ For the SSDT table only the ACPI header fields are
+ parsed and traced.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiSsdt (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ if (!Trace) {
+ return;
+ }
+
+ DumpAcpiHeader (Ptr);
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c
new file mode 100644
index 000000000..e39061f8e
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c
@@ -0,0 +1,140 @@
+/** @file
+ XSDT table parser
+
+ Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.2 Specification - Errata A, September 2017
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+
+// Local variables
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/** An ACPI_PARSER array describing the ACPI XSDT table.
+*/
+STATIC CONST ACPI_PARSER XsdtParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo)
+};
+
+/**
+ Get the ACPI XSDT header info.
+**/
+CONST ACPI_DESCRIPTION_HEADER_INFO *
+EFIAPI
+GetAcpiXsdtHeaderInfo (
+ VOID
+)
+{
+ return &AcpiHdrInfo;
+}
+
+/**
+ This function parses the ACPI XSDT table and optionally traces the ACPI table fields.
+
+ This function also performs validation of the XSDT table.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiXsdt (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT32 TableOffset;
+ UINT64* TablePointer;
+ UINTN EntryIndex;
+ CHAR16 Buffer[32];
+
+ Offset = ParseAcpi (
+ Trace,
+ 0,
+ "XSDT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (XsdtParser)
+ );
+
+ TableOffset = Offset;
+
+ if (Trace) {
+ EntryIndex = 0;
+ TablePointer = (UINT64*)(Ptr + TableOffset);
+ while (Offset < AcpiTableLength) {
+ CONST UINT32* Signature;
+ CONST UINT32* Length;
+ CONST UINT8* Revision;
+
+ if ((UINT64*)(UINTN)(*TablePointer) != NULL) {
+ UINT8* SignaturePtr;
+
+ ParseAcpiHeader (
+ (UINT8*)(UINTN)(*TablePointer),
+ &Signature,
+ &Length,
+ &Revision
+ );
+
+ SignaturePtr = (UINT8*)Signature;
+
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"Entry[%d] - %c%c%c%c",
+ EntryIndex++,
+ SignaturePtr[0],
+ SignaturePtr[1],
+ SignaturePtr[2],
+ SignaturePtr[3]
+ );
+ } else {
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"Entry[%d]",
+ EntryIndex++
+ );
+ }
+
+ PrintFieldName (2, Buffer);
+ Print (L"0x%lx\n", *TablePointer);
+
+ // Validate the table pointers are not NULL
+ if ((UINT64*)(UINTN)(*TablePointer) == NULL) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid table entry at 0x%lx, table address is 0x%lx\n",
+ TablePointer,
+ *TablePointer
+ );
+ }
+ Offset += sizeof (UINT64);
+ TablePointer++;
+ } // while
+ }
+
+ // Process the tables
+ Offset = TableOffset;
+ TablePointer = (UINT64*)(Ptr + TableOffset);
+ while (Offset < AcpiTableLength) {
+ if ((UINT64*)(UINTN)(*TablePointer) != NULL) {
+ ProcessAcpiTable ((UINT8*)(UINTN)(*TablePointer));
+ }
+ Offset += sizeof (UINT64);
+ TablePointer++;
+ } // while
+}