diff options
Diffstat (limited to 'ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort')
| -rw-r--r-- | ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c | 1942 |
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 +} |
