From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../Parsers/Bgrt/BgrtParser.c | 65 ++ .../Parsers/Dbg2/Dbg2Parser.c | 302 ++++++++ .../Parsers/Dsdt/DsdtParser.c | 42 ++ .../Parsers/Facs/FacsParser.c | 71 ++ .../Parsers/Fadt/FadtParser.c | 319 +++++++++ .../Parsers/Gtdt/GtdtParser.c | 364 ++++++++++ .../Parsers/Iort/IortParser.c | 764 +++++++++++++++++++++ .../Parsers/Madt/MadtParser.c | 374 ++++++++++ .../Parsers/Madt/MadtParser.h | 40 ++ .../Parsers/Mcfg/McfgParser.c | 90 +++ .../Parsers/Pptt/PpttParser.c | 478 +++++++++++++ .../Parsers/Pptt/PpttParser.h | 38 + .../Parsers/Rsdp/RsdpParser.c | 164 +++++ .../Parsers/Slit/SlitParser.c | 188 +++++ .../Parsers/Spcr/SpcrParser.c | 144 ++++ .../Parsers/Srat/SratParser.c | 542 +++++++++++++++ .../Parsers/Ssdt/SsdtParser.c | 42 ++ .../Parsers/Xsdt/XsdtParser.c | 140 ++++ 18 files changed, 4167 insertions(+) create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Bgrt/BgrtParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dbg2/Dbg2Parser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Dsdt/DsdtParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Facs/FacsParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.h create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Mcfg/McfgParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.h create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Rsdp/RsdpParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Slit/SlitParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Spcr/SpcrParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Ssdt/SsdtParser.c create mode 100644 roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Xsdt/XsdtParser.c (limited to 'roms/edk2/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers') 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 +#include +#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 +#include +#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 +#include +#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 +#include +#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 +#include +#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 +#include +#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 +#include +#include +#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 +#include +#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 +#include +#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 +#include +#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 +#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 +#include +#include +#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 +#include +#include +#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 +#include +#include +#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 +#include +#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 +#include +#include +#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 +} -- cgit 1.2.3-korg