summaryrefslogtreecommitdiff
path: root/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort
diff options
context:
space:
mode:
Diffstat (limited to 'ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort')
-rw-r--r--ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c1942
1 files changed, 971 insertions, 971 deletions
diff --git a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
index 599cf0ee8f..6468b818c2 100644
--- a/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
+++ b/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
@@ -1,971 +1,971 @@
-/** @file
- IORT table parser
-
- Copyright (c) 2016 - 2022, Arm Limited. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
- @par Reference(s):
- - IO Remapping Table, Platform Design Document, Revision E.d, Feb 2022
- (https://developer.arm.com/documentation/den0049/)
-
- @par Glossary:
- - Ref - Reference
- - Desc - Descriptor
-**/
-
-#include <IndustryStandard/IoRemappingTable.h>
-#include <Library/PrintLib.h>
-#include <Library/UefiLib.h>
-#include "AcpiParser.h"
-#include "AcpiTableParser.h"
-#include "AcpiViewConfig.h"
-
-// Local variables
-STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
-
-STATIC CONST UINT32 *IortNodeCount;
-STATIC CONST UINT32 *IortNodeOffset;
-
-STATIC CONST UINT8 *IortNodeType;
-STATIC CONST UINT16 *IortNodeLength;
-STATIC CONST UINT8 *IortNodeRevision;
-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;
-
-STATIC CONST UINT32 *RmrMemDescCount;
-STATIC CONST UINT32 *RmrMemDescOffset;
-
-/**
- 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.");
- }
-}
-
-/**
- This function validates that the Physical Range address or length is not zero
- and is 64K aligned.
-
- @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
-ValidatePhysicalRange (
- IN UINT8 *Ptr,
- IN VOID *Context
- )
-{
- UINT64 Value;
-
- Value = *(UINT64 *)Ptr;
- if ((Value == 0) || ((Value & (SIZE_64KB - 1)) != 0)) {
- IncrementErrorCount ();
- Print (L"\nERROR: Physical Range must be 64K aligned and cannot be zero.");
- }
-}
-
-/**
- This function validates that the RMR memory range descriptor 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
-ValidateRmrMemDescCount (
- IN UINT8 *Ptr,
- IN VOID *Context
- )
-{
- if (*(UINT32 *)Ptr == 0) {
- IncrementErrorCount ();
- Print (L"\nERROR: Memory Range Descriptor count must be >=1.");
- }
-}
-
-/**
- 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, (VOID**)&IortNodeRevision, NULL, NULL }, \
- { L"Identifier", 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"Global Interrupt Array Ref", 4, 40, L"0x%x", NULL, NULL, NULL,
- NULL },
- { L"Number of context interrupts", 4, 44, L"%d", NULL,
- (VOID **)&InterruptContextCount, NULL, NULL },
- { L"Context Interrupt Array Ref", 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"PMU Interrupt Array Ref", 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"PASID capabilities", 2, 33, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Reserved", 1, 35, L"%x", NULL, NULL, NULL, NULL },
- { L"Flags", 4, 36, L"0x%x", NULL, 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 }
-};
-
-/**
- An ACPI_PARSER array describing the IORT RMR node.
-**/
-STATIC CONST ACPI_PARSER IortNodeRmrParser[] = {
- PARSE_IORT_NODE_HEADER (NULL, NULL),
- { L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },
- { L"Memory Range Desc count", 4, 20, L"%d", NULL,
- (VOID **)&RmrMemDescCount, ValidateRmrMemDescCount,NULL },
- { L"Memory Range Desc Ref", 4, 24, L"0x%x", NULL,
- (VOID **)&RmrMemDescOffset, NULL, NULL }
-};
-
-/**
- An ACPI_PARSER array describing the IORT RMR Memory Range Descriptor.
-**/
-STATIC CONST ACPI_PARSER IortNodeRmrMemRangeDescParser[] = {
- { L"Physical Range offset", 8, 0, L"0x%lx", NULL, NULL, ValidatePhysicalRange,
- NULL },
- { L"Physical Range length", 8, 8, L"0x%lx", NULL, NULL, ValidatePhysicalRange,
- NULL },
- { L"Reserved", 4, 16, L"0x%x", 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 IORT RMR Node Memory Range Descriptor array.
-
- @param [in] Ptr Pointer to the start of the Memory Range Descriptor
- array.
- @param [in] Length Length of the buffer.
- @param [in] DescCount Memory Range Descriptor count.
-**/
-STATIC
-VOID
-DumpIortNodeRmrMemRangeDesc (
- IN UINT8 *Ptr,
- IN UINT32 Length,
- IN UINT32 DescCount
- )
-{
- UINT32 Index;
- UINT32 Offset;
- CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi
-
- Index = 0;
- Offset = 0;
-
- while ((Index < DescCount) &&
- (Offset < Length))
- {
- AsciiSPrint (
- Buffer,
- sizeof (Buffer),
- "Mem range Descriptor [%d]",
- Index
- );
- Offset += ParseAcpi (
- TRUE,
- 4,
- Buffer,
- Ptr + Offset,
- Length - Offset,
- PARSER_PARAMS (IortNodeRmrMemRangeDescParser)
- );
- Index++;
- }
-}
-
-/**
- This function parses the IORT RMR 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
-DumpIortNodeRmr (
- IN UINT8 *Ptr,
- IN UINT16 Length,
- IN UINT32 MappingCount,
- IN UINT32 MappingOffset
- )
-{
- ParseAcpi (
- TRUE,
- 2,
- "RMR Node",
- Ptr,
- Length,
- PARSER_PARAMS (IortNodeRmrParser)
- );
-
- if (*IortNodeRevision == EFI_ACPI_IORT_RMR_NODE_REVISION_02) {
- IncrementErrorCount ();
- Print (
- L"ERROR: RMR node Rev 2 (defined in IORT Rev E.c) must not be used."
- L" IORT tabe Revision E.c is deprecated and must not be used.\n"
- );
- }
-
- DumpIortNodeIdMappings (
- Ptr + MappingOffset,
- Length - MappingOffset,
- MappingCount
- );
-
- DumpIortNodeRmrMemRangeDesc (
- Ptr + (*RmrMemDescOffset),
- Length - (*RmrMemDescOffset),
- *RmrMemDescCount
- );
-}
-
-/**
- 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
- - RMR
-
- 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;
- }
-
- if ((AcpiTableRevision > EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00) &&
- (AcpiTableRevision < EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05))
- {
- Print (
- L"ERROR: Parsing not supported for IORT tabe Revision E, E.<a,b,c>.\n"
- );
- if (AcpiTableRevision == EFI_ACPI_IO_REMAPPING_TABLE_REVISION_04) {
- IncrementErrorCount ();
- Print (
- L"ERROR: IORT tabe Revision E.c is deprecated and must not be used.\n"
- );
- }
-
- 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;
- case EFI_ACPI_IORT_TYPE_RMR:
- DumpIortNodeRmr (
- NodePtr,
- *IortNodeLength,
- *IortIdMappingCount,
- *IortIdMappingOffset
- );
- break;
- default:
- IncrementErrorCount ();
- Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);
- } // switch
-
- NodePtr += (*IortNodeLength);
- Offset += (*IortNodeLength);
- } // while
-}
+/** @file
+ IORT table parser
+
+ Copyright (c) 2016 - 2022, Arm Limited. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - IO Remapping Table, Platform Design Document, Revision E.d, Feb 2022
+ (https://developer.arm.com/documentation/den0049/)
+
+ @par Glossary:
+ - Ref - Reference
+ - Desc - Descriptor
+**/
+
+#include <IndustryStandard/IoRemappingTable.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiTableParser.h"
+#include "AcpiViewConfig.h"
+
+// Local variables
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+STATIC CONST UINT32 *IortNodeCount;
+STATIC CONST UINT32 *IortNodeOffset;
+
+STATIC CONST UINT8 *IortNodeType;
+STATIC CONST UINT16 *IortNodeLength;
+STATIC CONST UINT8 *IortNodeRevision;
+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;
+
+STATIC CONST UINT32 *RmrMemDescCount;
+STATIC CONST UINT32 *RmrMemDescOffset;
+
+/**
+ 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.");
+ }
+}
+
+/**
+ This function validates that the Physical Range address or length is not zero
+ and is 64K aligned.
+
+ @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
+ValidatePhysicalRange (
+ IN UINT8 *Ptr,
+ IN VOID *Context
+ )
+{
+ UINT64 Value;
+
+ Value = *(UINT64 *)Ptr;
+ if ((Value == 0) || ((Value & (SIZE_64KB - 1)) != 0)) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Physical Range must be 64K aligned and cannot be zero.");
+ }
+}
+
+/**
+ This function validates that the RMR memory range descriptor 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
+ValidateRmrMemDescCount (
+ IN UINT8 *Ptr,
+ IN VOID *Context
+ )
+{
+ if (*(UINT32 *)Ptr == 0) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: Memory Range Descriptor count must be >=1.");
+ }
+}
+
+/**
+ 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, (VOID**)&IortNodeRevision, NULL, NULL }, \
+ { L"Identifier", 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"Global Interrupt Array Ref", 4, 40, L"0x%x", NULL, NULL, NULL,
+ NULL },
+ { L"Number of context interrupts", 4, 44, L"%d", NULL,
+ (VOID **)&InterruptContextCount, NULL, NULL },
+ { L"Context Interrupt Array Ref", 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"PMU Interrupt Array Ref", 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"PASID capabilities", 2, 33, L"0x%x", NULL, NULL, NULL, NULL },
+ { L"Reserved", 1, 35, L"%x", NULL, NULL, NULL, NULL },
+ { L"Flags", 4, 36, L"0x%x", NULL, 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 }
+};
+
+/**
+ An ACPI_PARSER array describing the IORT RMR node.
+**/
+STATIC CONST ACPI_PARSER IortNodeRmrParser[] = {
+ PARSE_IORT_NODE_HEADER (NULL, NULL),
+ { L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },
+ { L"Memory Range Desc count", 4, 20, L"%d", NULL,
+ (VOID **)&RmrMemDescCount, ValidateRmrMemDescCount,NULL },
+ { L"Memory Range Desc Ref", 4, 24, L"0x%x", NULL,
+ (VOID **)&RmrMemDescOffset, NULL, NULL }
+};
+
+/**
+ An ACPI_PARSER array describing the IORT RMR Memory Range Descriptor.
+**/
+STATIC CONST ACPI_PARSER IortNodeRmrMemRangeDescParser[] = {
+ { L"Physical Range offset", 8, 0, L"0x%lx", NULL, NULL, ValidatePhysicalRange,
+ NULL },
+ { L"Physical Range length", 8, 8, L"0x%lx", NULL, NULL, ValidatePhysicalRange,
+ NULL },
+ { L"Reserved", 4, 16, L"0x%x", 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 IORT RMR Node Memory Range Descriptor array.
+
+ @param [in] Ptr Pointer to the start of the Memory Range Descriptor
+ array.
+ @param [in] Length Length of the buffer.
+ @param [in] DescCount Memory Range Descriptor count.
+**/
+STATIC
+VOID
+DumpIortNodeRmrMemRangeDesc (
+ IN UINT8 *Ptr,
+ IN UINT32 Length,
+ IN UINT32 DescCount
+ )
+{
+ UINT32 Index;
+ UINT32 Offset;
+ CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi
+
+ Index = 0;
+ Offset = 0;
+
+ while ((Index < DescCount) &&
+ (Offset < Length))
+ {
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "Mem range Descriptor [%d]",
+ Index
+ );
+ Offset += ParseAcpi (
+ TRUE,
+ 4,
+ Buffer,
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (IortNodeRmrMemRangeDescParser)
+ );
+ Index++;
+ }
+}
+
+/**
+ This function parses the IORT RMR 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
+DumpIortNodeRmr (
+ IN UINT8 *Ptr,
+ IN UINT16 Length,
+ IN UINT32 MappingCount,
+ IN UINT32 MappingOffset
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "RMR Node",
+ Ptr,
+ Length,
+ PARSER_PARAMS (IortNodeRmrParser)
+ );
+
+ if (*IortNodeRevision == EFI_ACPI_IORT_RMR_NODE_REVISION_02) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: RMR node Rev 2 (defined in IORT Rev E.c) must not be used."
+ L" IORT tabe Revision E.c is deprecated and must not be used.\n"
+ );
+ }
+
+ DumpIortNodeIdMappings (
+ Ptr + MappingOffset,
+ Length - MappingOffset,
+ MappingCount
+ );
+
+ DumpIortNodeRmrMemRangeDesc (
+ Ptr + (*RmrMemDescOffset),
+ Length - (*RmrMemDescOffset),
+ *RmrMemDescCount
+ );
+}
+
+/**
+ 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
+ - RMR
+
+ 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;
+ }
+
+ if ((AcpiTableRevision > EFI_ACPI_IO_REMAPPING_TABLE_REVISION_00) &&
+ (AcpiTableRevision < EFI_ACPI_IO_REMAPPING_TABLE_REVISION_05))
+ {
+ Print (
+ L"ERROR: Parsing not supported for IORT tabe Revision E, E.<a,b,c>.\n"
+ );
+ if (AcpiTableRevision == EFI_ACPI_IO_REMAPPING_TABLE_REVISION_04) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: IORT tabe Revision E.c is deprecated and must not be used.\n"
+ );
+ }
+
+ 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;
+ case EFI_ACPI_IORT_TYPE_RMR:
+ DumpIortNodeRmr (
+ NodePtr,
+ *IortNodeLength,
+ *IortIdMappingCount,
+ *IortIdMappingOffset
+ );
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);
+ } // switch
+
+ NodePtr += (*IortNodeLength);
+ Offset += (*IortNodeLength);
+ } // while
+}