In IortParser.c ,the variable Index is set but not used in function DumpIortNodeNamedComponent. This will cause build failure when building ShellPkg with GCC. Cc: Jaben Carsey <jaben.carsey@intel.com> Cc: Ray Ni <ray.ni@intel.com> Cc: Zhichao Gao <zhichao.gao@intel.com> Signed-off-by: Shenglei Zhang <shenglei.zhang@intel.com> Reviewed-by: Zhichao Gao <zhichao.gao@intel.com> Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>
		
			
				
	
	
		
			705 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			705 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   IORT table parser
 | |
| 
 | |
|   Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
|   @par Reference(s):
 | |
|     - IO Remapping Table, Platform Design Document, Revision C, 15 May 2017
 | |
| **/
 | |
| 
 | |
| #include <IndustryStandard/IoRemappingTable.h>
 | |
| #include <Library/PrintLib.h>
 | |
| #include <Library/UefiLib.h>
 | |
| #include "AcpiParser.h"
 | |
| #include "AcpiTableParser.h"
 | |
| 
 | |
| // Local variables
 | |
| STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
 | |
| 
 | |
| STATIC CONST UINT32* IortNodeCount;
 | |
| STATIC CONST UINT32* IortNodeOffset;
 | |
| 
 | |
| STATIC CONST UINT8*  IortNodeType;
 | |
| STATIC CONST UINT16* IortNodeLength;
 | |
| STATIC CONST UINT32* IortIdMappingCount;
 | |
| STATIC CONST UINT32* IortIdMappingOffset;
 | |
| 
 | |
| STATIC CONST UINT32* InterruptContextCount;
 | |
| STATIC CONST UINT32* InterruptContextOffset;
 | |
| STATIC CONST UINT32* PmuInterruptCount;
 | |
| STATIC CONST UINT32* PmuInterruptOffset;
 | |
| 
 | |
| STATIC CONST UINT32* ItsCount;
 | |
| 
 | |
| /**
 | |
|   This function validates the ID Mapping array count for the ITS node.
 | |
| 
 | |
|   @param [in] Ptr     Pointer to the start of the field data.
 | |
|   @param [in] Context Pointer to context specific information e.g. this
 | |
|                       could be a pointer to the ACPI table header.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| ValidateItsIdMappingCount (
 | |
|   IN UINT8* Ptr,
 | |
|   IN VOID*  Context
 | |
|   )
 | |
| {
 | |
|   if (*(UINT32*)Ptr != 0) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (L"\nERROR: IORT ID Mapping count must be zero.");
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function validates the ID Mapping array count for the Performance
 | |
|   Monitoring Counter Group (PMCG) node.
 | |
| 
 | |
|   @param [in] Ptr     Pointer to the start of the field data.
 | |
|   @param [in] Context Pointer to context specific information e.g. this
 | |
|                       could be a pointer to the ACPI table header.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| ValidatePmcgIdMappingCount (
 | |
|   IN UINT8* Ptr,
 | |
|   IN VOID*  Context
 | |
|   )
 | |
| {
 | |
|   if (*(UINT32*)Ptr > 1) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (L"\nERROR: IORT ID Mapping count must not be greater than 1.");
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function validates the ID Mapping array offset for the ITS node.
 | |
| 
 | |
|   @param [in] Ptr     Pointer to the start of the field data.
 | |
|   @param [in] Context Pointer to context specific information e.g. this
 | |
|                       could be a pointer to the ACPI table header.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| ValidateItsIdArrayReference (
 | |
|   IN UINT8* Ptr,
 | |
|   IN VOID*  Context
 | |
|   )
 | |
| {
 | |
|   if (*(UINT32*)Ptr != 0) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (L"\nERROR: IORT ID Mapping offset must be zero.");
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Helper Macro for populating the IORT Node header in the ACPI_PARSER array.
 | |
| 
 | |
|   @param [out] ValidateIdMappingCount    Optional pointer to a function for
 | |
|                                          validating the ID Mapping count.
 | |
|   @param [out] ValidateIdArrayReference  Optional pointer to a function for
 | |
|                                          validating the ID Array reference.
 | |
| **/
 | |
| #define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount,                   \
 | |
|                                ValidateIdArrayReference)                 \
 | |
|   { L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL },     \
 | |
|   { L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \
 | |
|   { L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL },                  \
 | |
|   { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },                \
 | |
|   { L"Number of ID mappings", 4, 8, L"%d", NULL,                         \
 | |
|     (VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL },         \
 | |
|   { L"Reference to ID Array", 4, 12, L"0x%x", NULL,                      \
 | |
|     (VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL }
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the ACPI IORT Table
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER IortParser[] = {
 | |
|   PARSE_ACPI_HEADER (&AcpiHdrInfo),
 | |
|   {L"Number of IORT Nodes", 4, 36, L"%d", NULL,
 | |
|    (VOID**)&IortNodeCount, NULL, NULL},
 | |
|   {L"Offset to Array of IORT Nodes", 4, 40, L"0x%x", NULL,
 | |
|    (VOID**)&IortNodeOffset, NULL, NULL},
 | |
|   {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the IORT node header structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER IortNodeHeaderParser[] = {
 | |
|   PARSE_IORT_NODE_HEADER (NULL, NULL)
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the IORT SMMUv1/2 node.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser[] = {
 | |
|   PARSE_IORT_NODE_HEADER (NULL, NULL),
 | |
|   {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"Span", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"Model", 4, 32, L"%d", NULL, NULL, NULL, NULL},
 | |
|   {L"Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Reference to Global Interrupt Array", 4, 40, L"0x%x", NULL, NULL, NULL,
 | |
|    NULL},
 | |
|   {L"Number of context interrupts", 4, 44, L"%d", NULL,
 | |
|    (VOID**)&InterruptContextCount, NULL, NULL},
 | |
|   {L"Reference to Context Interrupt Array", 4, 48, L"0x%x", NULL,
 | |
|    (VOID**)&InterruptContextOffset, NULL, NULL},
 | |
|   {L"Number of PMU Interrupts", 4, 52, L"%d", NULL,
 | |
|    (VOID**)&PmuInterruptCount, NULL, NULL},
 | |
|   {L"Reference to PMU Interrupt Array", 4, 56, L"0x%x", NULL,
 | |
|    (VOID**)&PmuInterruptOffset, NULL, NULL},
 | |
| 
 | |
|   // Interrupt Array
 | |
|   {L"SMMU_NSgIrpt", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"SMMU_NSgIrpt interrupt flags", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"SMMU_NSgCfgIrpt", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"SMMU_NSgCfgIrpt interrupt flags", 4, 72, L"0x%x", NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER InterruptArrayParser[] = {
 | |
|   {L"Interrupt GSIV", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the IORT ID Mapping.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER IortNodeIdMappingParser[] = {
 | |
|   {L"Input base", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Number of IDs", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Output base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Output reference", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the IORT SMMUv3 node.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser[] = {
 | |
|   PARSE_IORT_NODE_HEADER (NULL, NULL),
 | |
|   {L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Reserved", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"VATOS Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"Model", 4, 40, L"%d", NULL, NULL, NULL, NULL},
 | |
|   {L"Event", 4, 44, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"PRI", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"GERR", 4, 52, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Sync", 4, 56, L"0x%x", NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   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}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the IORT PMCG node.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER IortNodePmcgParser[] = {
 | |
|   PARSE_IORT_NODE_HEADER (ValidatePmcgIdMappingCount, NULL),
 | |
|   {L"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},
 | |
| };
 | |
| 
 | |
| /**
 | |
|   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)
 | |
|     );
 | |
| 
 | |
|   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)
 | |
|             );
 | |
| 
 | |
|   Index = 0;
 | |
| 
 | |
|   while ((Index < *ItsCount) &&
 | |
|          (Offset < Length)) {
 | |
|     AsciiSPrint (
 | |
|       Buffer,
 | |
|       sizeof (Buffer),
 | |
|       "GIC ITS Identifier Array [%d]",
 | |
|       Index
 | |
|       );
 | |
|     Offset += ParseAcpi (
 | |
|                 TRUE,
 | |
|                 4,
 | |
|                 Buffer,
 | |
|                 Ptr + Offset,
 | |
|                 Length - Offset,
 | |
|                 PARSER_PARAMS (ItsIdParser)
 | |
|                 );
 | |
|     Index++;
 | |
|   }
 | |
| 
 | |
|   // Note: ITS does not have the ID Mappings Array
 | |
| 
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function parses the IORT Named Component node.
 | |
| 
 | |
|   @param [in] Ptr            Pointer to the start of the buffer.
 | |
|   @param [in] Length         Length of the buffer.
 | |
|   @param [in] MappingCount   The ID Mapping count.
 | |
|   @param [in] MappingOffset  The offset of the ID Mapping array
 | |
|                              from the start of the IORT table.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpIortNodeNamedComponent (
 | |
|   IN UINT8* Ptr,
 | |
|   IN UINT16 Length,
 | |
|   IN UINT32 MappingCount,
 | |
|   IN UINT32 MappingOffset
 | |
|   )
 | |
| {
 | |
|   UINT32 Offset;
 | |
| 
 | |
|   Offset = ParseAcpi (
 | |
|              TRUE,
 | |
|              2,
 | |
|              "Named Component Node",
 | |
|              Ptr,
 | |
|              Length,
 | |
|              PARSER_PARAMS (IortNodeNamedComponentParser)
 | |
|              );
 | |
| 
 | |
|   // Estimate the Device Name length
 | |
|   PrintFieldName (2, L"Device Object Name");
 | |
| 
 | |
|   while ((*(Ptr + Offset) != 0) &&
 | |
|          (Offset < Length)) {
 | |
|     Print (L"%c", *(Ptr + Offset));
 | |
|     Offset++;
 | |
|   }
 | |
|   Print (L"\n");
 | |
| 
 | |
|   DumpIortNodeIdMappings (
 | |
|     Ptr + MappingOffset,
 | |
|     Length - MappingOffset,
 | |
|     MappingCount
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function parses the IORT Root Complex node.
 | |
| 
 | |
|   @param [in] Ptr            Pointer to the start of the buffer.
 | |
|   @param [in] Length         Length of the buffer.
 | |
|   @param [in] MappingCount   The ID Mapping count.
 | |
|   @param [in] MappingOffset  The offset of the ID Mapping array
 | |
|                              from the start of the IORT table.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpIortNodeRootComplex (
 | |
|   IN UINT8* Ptr,
 | |
|   IN UINT16 Length,
 | |
|   IN UINT32 MappingCount,
 | |
|   IN UINT32 MappingOffset
 | |
|   )
 | |
| {
 | |
|   ParseAcpi (
 | |
|     TRUE,
 | |
|     2,
 | |
|     "Root Complex Node",
 | |
|     Ptr,
 | |
|     Length,
 | |
|     PARSER_PARAMS (IortNodeRootComplexParser)
 | |
|     );
 | |
| 
 | |
|   DumpIortNodeIdMappings (
 | |
|     Ptr + MappingOffset,
 | |
|     Length - MappingOffset,
 | |
|     MappingCount
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function parses the IORT PMCG node.
 | |
| 
 | |
|   @param [in] Ptr            Pointer to the start of the buffer.
 | |
|   @param [in] Length         Length of the buffer.
 | |
|   @param [in] MappingCount   The ID Mapping count.
 | |
|   @param [in] MappingOffset  The offset of the ID Mapping array
 | |
|                              from the start of the IORT table.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpIortNodePmcg (
 | |
|   IN UINT8* Ptr,
 | |
|   IN UINT16 Length,
 | |
|   IN UINT32 MappingCount,
 | |
|   IN UINT32 MappingOffset
 | |
| )
 | |
| {
 | |
|   ParseAcpi (
 | |
|     TRUE,
 | |
|     2,
 | |
|     "PMCG Node",
 | |
|     Ptr,
 | |
|     Length,
 | |
|     PARSER_PARAMS (IortNodePmcgParser)
 | |
|     );
 | |
| 
 | |
|   DumpIortNodeIdMappings (
 | |
|     Ptr + MappingOffset,
 | |
|     Length - MappingOffset,
 | |
|     MappingCount
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function parses the ACPI IORT table.
 | |
|   When trace is enabled this function parses the IORT table and traces the ACPI fields.
 | |
| 
 | |
|   This function also parses the following nodes:
 | |
|     - ITS Group
 | |
|     - Named Component
 | |
|     - Root Complex
 | |
|     - SMMUv1/2
 | |
|     - SMMUv3
 | |
|     - PMCG
 | |
| 
 | |
|   This function also performs validation of the ACPI table fields.
 | |
| 
 | |
|   @param [in] Trace              If TRUE, trace the ACPI fields.
 | |
|   @param [in] Ptr                Pointer to the start of the buffer.
 | |
|   @param [in] AcpiTableLength    Length of the ACPI table.
 | |
|   @param [in] AcpiTableRevision  Revision of the ACPI table.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| ParseAcpiIort (
 | |
|   IN BOOLEAN Trace,
 | |
|   IN UINT8*  Ptr,
 | |
|   IN UINT32  AcpiTableLength,
 | |
|   IN UINT8   AcpiTableRevision
 | |
|   )
 | |
| {
 | |
|   UINT32 Offset;
 | |
|   UINT32 Index;
 | |
|   UINT8* NodePtr;
 | |
| 
 | |
|   if (!Trace) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   ParseAcpi (
 | |
|     TRUE,
 | |
|     0,
 | |
|     "IORT",
 | |
|     Ptr,
 | |
|     AcpiTableLength,
 | |
|     PARSER_PARAMS (IortParser)
 | |
|     );
 | |
| 
 | |
|   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)
 | |
|       );
 | |
| 
 | |
|     // Make sure the IORT Node is inside the table
 | |
|     if ((Offset + (*IortNodeLength)) > AcpiTableLength) {
 | |
|       IncrementErrorCount ();
 | |
|       Print (
 | |
|         L"ERROR: Invalid IORT node length. IortNodeLength = %d. " \
 | |
|           L"RemainingTableBufferLength = %d. IORT parsing aborted.\n",
 | |
|         *IortNodeLength,
 | |
|         AcpiTableLength - Offset
 | |
|         );
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     PrintFieldName (2, L"* Node Offset *");
 | |
|     Print (L"0x%x\n", Offset);
 | |
| 
 | |
|     switch (*IortNodeType) {
 | |
|       case EFI_ACPI_IORT_TYPE_ITS_GROUP:
 | |
|         DumpIortNodeIts (
 | |
|           NodePtr,
 | |
|           *IortNodeLength
 | |
|           );
 | |
|         break;
 | |
|       case EFI_ACPI_IORT_TYPE_NAMED_COMP:
 | |
|         DumpIortNodeNamedComponent (
 | |
|           NodePtr,
 | |
|           *IortNodeLength,
 | |
|           *IortIdMappingCount,
 | |
|           *IortIdMappingOffset
 | |
|           );
 | |
|         break;
 | |
|       case EFI_ACPI_IORT_TYPE_ROOT_COMPLEX:
 | |
|         DumpIortNodeRootComplex (
 | |
|           NodePtr,
 | |
|           *IortNodeLength,
 | |
|           *IortIdMappingCount,
 | |
|           *IortIdMappingOffset
 | |
|           );
 | |
|         break;
 | |
|       case EFI_ACPI_IORT_TYPE_SMMUv1v2:
 | |
|         DumpIortNodeSmmuV1V2 (
 | |
|           NodePtr,
 | |
|           *IortNodeLength,
 | |
|           *IortIdMappingCount,
 | |
|           *IortIdMappingOffset
 | |
|           );
 | |
|         break;
 | |
|       case EFI_ACPI_IORT_TYPE_SMMUv3:
 | |
|         DumpIortNodeSmmuV3 (
 | |
|           NodePtr,
 | |
|           *IortNodeLength,
 | |
|           *IortIdMappingCount,
 | |
|           *IortIdMappingOffset
 | |
|           );
 | |
|         break;
 | |
|       case EFI_ACPI_IORT_TYPE_PMCG:
 | |
|         DumpIortNodePmcg (
 | |
|           NodePtr,
 | |
|           *IortNodeLength,
 | |
|           *IortIdMappingCount,
 | |
|           *IortIdMappingOffset
 | |
|         );
 | |
|         break;
 | |
| 
 | |
|       default:
 | |
|         IncrementErrorCount ();
 | |
|         Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);
 | |
|     } // switch
 | |
| 
 | |
|     NodePtr += (*IortNodeLength);
 | |
|     Offset += (*IortNodeLength);
 | |
|   } // while
 | |
| }
 |