mirror of https://github.com/acidanthera/audk.git
765 lines
20 KiB
C
765 lines
20 KiB
C
/** @file
|
|
IORT table parser
|
|
|
|
Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
@par Reference(s):
|
|
- IO Remapping Table, Platform Design Document, Revision D, March 2018
|
|
**/
|
|
|
|
#include <IndustryStandard/IoRemappingTable.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include "AcpiParser.h"
|
|
#include "AcpiTableParser.h"
|
|
#include "AcpiViewConfig.h"
|
|
|
|
// Local variables
|
|
STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
|
|
|
|
STATIC CONST UINT32* IortNodeCount;
|
|
STATIC CONST UINT32* IortNodeOffset;
|
|
|
|
STATIC CONST UINT8* IortNodeType;
|
|
STATIC CONST UINT16* IortNodeLength;
|
|
STATIC CONST UINT32* IortIdMappingCount;
|
|
STATIC CONST UINT32* IortIdMappingOffset;
|
|
|
|
STATIC CONST UINT32* InterruptContextCount;
|
|
STATIC CONST UINT32* InterruptContextOffset;
|
|
STATIC CONST UINT32* PmuInterruptCount;
|
|
STATIC CONST UINT32* PmuInterruptOffset;
|
|
|
|
STATIC CONST UINT32* ItsCount;
|
|
|
|
/**
|
|
This function validates the ID Mapping array count for the ITS node.
|
|
|
|
@param [in] Ptr Pointer to the start of the field data.
|
|
@param [in] Context Pointer to context specific information e.g. this
|
|
could be a pointer to the ACPI table header.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
EFIAPI
|
|
ValidateItsIdMappingCount (
|
|
IN UINT8* Ptr,
|
|
IN VOID* Context
|
|
)
|
|
{
|
|
if (*(UINT32*)Ptr != 0) {
|
|
IncrementErrorCount ();
|
|
Print (L"\nERROR: IORT ID Mapping count must be zero.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
This function validates the ID Mapping array count for the Performance
|
|
Monitoring Counter Group (PMCG) node.
|
|
|
|
@param [in] Ptr Pointer to the start of the field data.
|
|
@param [in] Context Pointer to context specific information e.g. this
|
|
could be a pointer to the ACPI table header.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
EFIAPI
|
|
ValidatePmcgIdMappingCount (
|
|
IN UINT8* Ptr,
|
|
IN VOID* Context
|
|
)
|
|
{
|
|
if (*(UINT32*)Ptr > 1) {
|
|
IncrementErrorCount ();
|
|
Print (L"\nERROR: IORT ID Mapping count must not be greater than 1.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
This function validates the ID Mapping array offset for the ITS node.
|
|
|
|
@param [in] Ptr Pointer to the start of the field data.
|
|
@param [in] Context Pointer to context specific information e.g. this
|
|
could be a pointer to the ACPI table header.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
EFIAPI
|
|
ValidateItsIdArrayReference (
|
|
IN UINT8* Ptr,
|
|
IN VOID* Context
|
|
)
|
|
{
|
|
if (*(UINT32*)Ptr != 0) {
|
|
IncrementErrorCount ();
|
|
Print (L"\nERROR: IORT ID Mapping offset must be zero.");
|
|
}
|
|
}
|
|
|
|
/**
|
|
Helper Macro for populating the IORT Node header in the ACPI_PARSER array.
|
|
|
|
@param [out] ValidateIdMappingCount Optional pointer to a function for
|
|
validating the ID Mapping count.
|
|
@param [out] ValidateIdArrayReference Optional pointer to a function for
|
|
validating the ID Array reference.
|
|
**/
|
|
#define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount, \
|
|
ValidateIdArrayReference) \
|
|
{ L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \
|
|
{ L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \
|
|
{ L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \
|
|
{ L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
|
|
{ L"Number of ID mappings", 4, 8, L"%d", NULL, \
|
|
(VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \
|
|
{ L"Reference to ID Array", 4, 12, L"0x%x", NULL, \
|
|
(VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL }
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the ACPI IORT Table
|
|
**/
|
|
STATIC CONST ACPI_PARSER IortParser[] = {
|
|
PARSE_ACPI_HEADER (&AcpiHdrInfo),
|
|
{L"Number of IORT Nodes", 4, 36, L"%d", NULL,
|
|
(VOID**)&IortNodeCount, NULL, NULL},
|
|
{L"Offset to Array of IORT Nodes", 4, 40, L"0x%x", NULL,
|
|
(VOID**)&IortNodeOffset, NULL, NULL},
|
|
{L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the IORT node header structure.
|
|
**/
|
|
STATIC CONST ACPI_PARSER IortNodeHeaderParser[] = {
|
|
PARSE_IORT_NODE_HEADER (NULL, NULL)
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the IORT SMMUv1/2 node.
|
|
**/
|
|
STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser[] = {
|
|
PARSE_IORT_NODE_HEADER (NULL, NULL),
|
|
{L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
|
|
{L"Span", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL},
|
|
{L"Model", 4, 32, L"%d", NULL, NULL, NULL, NULL},
|
|
{L"Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Reference to Global Interrupt Array", 4, 40, L"0x%x", NULL, NULL, NULL,
|
|
NULL},
|
|
{L"Number of context interrupts", 4, 44, L"%d", NULL,
|
|
(VOID**)&InterruptContextCount, NULL, NULL},
|
|
{L"Reference to Context Interrupt Array", 4, 48, L"0x%x", NULL,
|
|
(VOID**)&InterruptContextOffset, NULL, NULL},
|
|
{L"Number of PMU Interrupts", 4, 52, L"%d", NULL,
|
|
(VOID**)&PmuInterruptCount, NULL, NULL},
|
|
{L"Reference to PMU Interrupt Array", 4, 56, L"0x%x", NULL,
|
|
(VOID**)&PmuInterruptOffset, NULL, NULL},
|
|
|
|
// Interrupt Array
|
|
{L"SMMU_NSgIrpt", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"SMMU_NSgIrpt interrupt flags", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"SMMU_NSgCfgIrpt", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"SMMU_NSgCfgIrpt interrupt flags", 4, 72, L"0x%x", NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array.
|
|
**/
|
|
STATIC CONST ACPI_PARSER InterruptArrayParser[] = {
|
|
{L"Interrupt GSIV", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the IORT ID Mapping.
|
|
**/
|
|
STATIC CONST ACPI_PARSER IortNodeIdMappingParser[] = {
|
|
{L"Input base", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Number of IDs", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Output base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Output reference", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the IORT SMMUv3 node.
|
|
**/
|
|
STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser[] = {
|
|
PARSE_IORT_NODE_HEADER (NULL, NULL),
|
|
{L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
|
|
{L"Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Reserved", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"VATOS Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL},
|
|
{L"Model", 4, 40, L"%d", NULL, NULL, NULL, NULL},
|
|
{L"Event", 4, 44, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"PRI", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"GERR", 4, 52, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Sync", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Proximity domain", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Device ID mapping index", 4, 64, L"%d", NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the IORT ITS node.
|
|
**/
|
|
STATIC CONST ACPI_PARSER IortNodeItsParser[] = {
|
|
PARSE_IORT_NODE_HEADER (
|
|
ValidateItsIdMappingCount,
|
|
ValidateItsIdArrayReference
|
|
),
|
|
{L"Number of ITSs", 4, 16, L"%d", NULL, (VOID**)&ItsCount, NULL}
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the ITS ID.
|
|
**/
|
|
STATIC CONST ACPI_PARSER ItsIdParser[] = {
|
|
{ L"GIC ITS Identifier", 4, 0, L"%d", NULL, NULL, NULL }
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the IORT Names Component node.
|
|
**/
|
|
STATIC CONST ACPI_PARSER IortNodeNamedComponentParser[] = {
|
|
PARSE_IORT_NODE_HEADER (NULL, NULL),
|
|
{L"Node Flags", 4, 16, L"%d", NULL, NULL, NULL, NULL},
|
|
{L"Memory access properties", 8, 20, L"0x%lx", NULL, NULL, NULL, NULL},
|
|
{L"Device memory address size limit", 1, 28, L"%d", NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the IORT Root Complex node.
|
|
**/
|
|
STATIC CONST ACPI_PARSER IortNodeRootComplexParser[] = {
|
|
PARSE_IORT_NODE_HEADER (NULL, NULL),
|
|
{L"Memory access properties", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
|
|
{L"ATS Attribute", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"PCI Segment number", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Memory access size limit", 1, 32, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Reserved", 3, 33, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}
|
|
};
|
|
|
|
/**
|
|
An ACPI_PARSER array describing the IORT PMCG node.
|
|
**/
|
|
STATIC CONST ACPI_PARSER IortNodePmcgParser[] = {
|
|
PARSE_IORT_NODE_HEADER (ValidatePmcgIdMappingCount, NULL),
|
|
{L"Page 0 Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
|
|
{L"Overflow interrupt GSIV", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Node reference", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},
|
|
{L"Page 1 Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}
|
|
};
|
|
|
|
/**
|
|
This function parses the IORT Node Id Mapping array.
|
|
|
|
@param [in] Ptr Pointer to the start of the ID mapping array.
|
|
@param [in] Length Length of the buffer.
|
|
@param [in] MappingCount The ID Mapping count.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
DumpIortNodeIdMappings (
|
|
IN UINT8* Ptr,
|
|
IN UINT32 Length,
|
|
IN UINT32 MappingCount
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
UINT32 Offset;
|
|
CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi
|
|
|
|
Index = 0;
|
|
Offset = 0;
|
|
|
|
while ((Index < MappingCount) &&
|
|
(Offset < Length)) {
|
|
AsciiSPrint (
|
|
Buffer,
|
|
sizeof (Buffer),
|
|
"ID Mapping [%d]",
|
|
Index
|
|
);
|
|
Offset += ParseAcpi (
|
|
TRUE,
|
|
4,
|
|
Buffer,
|
|
Ptr + Offset,
|
|
Length - Offset,
|
|
PARSER_PARAMS (IortNodeIdMappingParser)
|
|
);
|
|
Index++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
This function parses the IORT SMMUv1/2 node.
|
|
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] Length Length of the buffer.
|
|
@param [in] MappingCount The ID Mapping count.
|
|
@param [in] MappingOffset The offset of the ID Mapping array
|
|
from the start of the IORT table.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
DumpIortNodeSmmuV1V2 (
|
|
IN UINT8* Ptr,
|
|
IN UINT16 Length,
|
|
IN UINT32 MappingCount,
|
|
IN UINT32 MappingOffset
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
UINT32 Offset;
|
|
CHAR8 Buffer[50]; // Used for AsciiName param of ParseAcpi
|
|
|
|
ParseAcpi (
|
|
TRUE,
|
|
2,
|
|
"SMMUv1 or SMMUv2 Node",
|
|
Ptr,
|
|
Length,
|
|
PARSER_PARAMS (IortNodeSmmuV1V2Parser)
|
|
);
|
|
|
|
// Check if the values used to control the parsing logic have been
|
|
// successfully read.
|
|
if ((InterruptContextCount == NULL) ||
|
|
(InterruptContextOffset == NULL) ||
|
|
(PmuInterruptCount == NULL) ||
|
|
(PmuInterruptOffset == NULL)) {
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Insufficient SMMUv1/2 node length. Length = %d\n",
|
|
Length
|
|
);
|
|
return;
|
|
}
|
|
|
|
Offset = *InterruptContextOffset;
|
|
Index = 0;
|
|
|
|
while ((Index < *InterruptContextCount) &&
|
|
(Offset < Length)) {
|
|
AsciiSPrint (
|
|
Buffer,
|
|
sizeof (Buffer),
|
|
"Context Interrupts Array [%d]",
|
|
Index
|
|
);
|
|
Offset += ParseAcpi (
|
|
TRUE,
|
|
4,
|
|
Buffer,
|
|
Ptr + Offset,
|
|
Length - Offset,
|
|
PARSER_PARAMS (InterruptArrayParser)
|
|
);
|
|
Index++;
|
|
}
|
|
|
|
Offset = *PmuInterruptOffset;
|
|
Index = 0;
|
|
|
|
while ((Index < *PmuInterruptCount) &&
|
|
(Offset < Length)) {
|
|
AsciiSPrint (
|
|
Buffer,
|
|
sizeof (Buffer),
|
|
"PMU Interrupts Array [%d]",
|
|
Index
|
|
);
|
|
Offset += ParseAcpi (
|
|
TRUE,
|
|
4,
|
|
Buffer,
|
|
Ptr + Offset,
|
|
Length - Offset,
|
|
PARSER_PARAMS (InterruptArrayParser)
|
|
);
|
|
Index++;
|
|
}
|
|
|
|
DumpIortNodeIdMappings (
|
|
Ptr + MappingOffset,
|
|
Length - MappingOffset,
|
|
MappingCount
|
|
);
|
|
}
|
|
|
|
/**
|
|
This function parses the IORT SMMUv3 node.
|
|
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] Length Length of the buffer.
|
|
@param [in] MappingCount The ID Mapping count.
|
|
@param [in] MappingOffset The offset of the ID Mapping array
|
|
from the start of the IORT table.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
DumpIortNodeSmmuV3 (
|
|
IN UINT8* Ptr,
|
|
IN UINT16 Length,
|
|
IN UINT32 MappingCount,
|
|
IN UINT32 MappingOffset
|
|
)
|
|
{
|
|
ParseAcpi (
|
|
TRUE,
|
|
2,
|
|
"SMMUV3 Node",
|
|
Ptr,
|
|
Length,
|
|
PARSER_PARAMS (IortNodeSmmuV3Parser)
|
|
);
|
|
|
|
DumpIortNodeIdMappings (
|
|
Ptr + MappingOffset,
|
|
Length - MappingOffset,
|
|
MappingCount
|
|
);
|
|
}
|
|
|
|
/**
|
|
This function parses the IORT ITS node.
|
|
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] Length Length of the buffer.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
DumpIortNodeIts (
|
|
IN UINT8* Ptr,
|
|
IN UINT16 Length
|
|
)
|
|
{
|
|
UINT32 Offset;
|
|
UINT32 Index;
|
|
CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi
|
|
|
|
Offset = ParseAcpi (
|
|
TRUE,
|
|
2,
|
|
"ITS Node",
|
|
Ptr,
|
|
Length,
|
|
PARSER_PARAMS (IortNodeItsParser)
|
|
);
|
|
|
|
// Check if the values used to control the parsing logic have been
|
|
// successfully read.
|
|
if (ItsCount == NULL) {
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Insufficient ITS group length. Length = %d.\n",
|
|
Length
|
|
);
|
|
return;
|
|
}
|
|
|
|
Index = 0;
|
|
|
|
while ((Index < *ItsCount) &&
|
|
(Offset < Length)) {
|
|
AsciiSPrint (
|
|
Buffer,
|
|
sizeof (Buffer),
|
|
"GIC ITS Identifier Array [%d]",
|
|
Index
|
|
);
|
|
Offset += ParseAcpi (
|
|
TRUE,
|
|
4,
|
|
Buffer,
|
|
Ptr + Offset,
|
|
Length - Offset,
|
|
PARSER_PARAMS (ItsIdParser)
|
|
);
|
|
Index++;
|
|
}
|
|
|
|
// Note: ITS does not have the ID Mappings Array
|
|
|
|
}
|
|
|
|
/**
|
|
This function parses the IORT Named Component node.
|
|
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] Length Length of the buffer.
|
|
@param [in] MappingCount The ID Mapping count.
|
|
@param [in] MappingOffset The offset of the ID Mapping array
|
|
from the start of the IORT table.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
DumpIortNodeNamedComponent (
|
|
IN UINT8* Ptr,
|
|
IN UINT16 Length,
|
|
IN UINT32 MappingCount,
|
|
IN UINT32 MappingOffset
|
|
)
|
|
{
|
|
UINT32 Offset;
|
|
|
|
Offset = ParseAcpi (
|
|
TRUE,
|
|
2,
|
|
"Named Component Node",
|
|
Ptr,
|
|
Length,
|
|
PARSER_PARAMS (IortNodeNamedComponentParser)
|
|
);
|
|
|
|
// Estimate the Device Name length
|
|
PrintFieldName (2, L"Device Object Name");
|
|
|
|
while ((*(Ptr + Offset) != 0) &&
|
|
(Offset < Length)) {
|
|
Print (L"%c", *(Ptr + Offset));
|
|
Offset++;
|
|
}
|
|
Print (L"\n");
|
|
|
|
DumpIortNodeIdMappings (
|
|
Ptr + MappingOffset,
|
|
Length - MappingOffset,
|
|
MappingCount
|
|
);
|
|
}
|
|
|
|
/**
|
|
This function parses the IORT Root Complex node.
|
|
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] Length Length of the buffer.
|
|
@param [in] MappingCount The ID Mapping count.
|
|
@param [in] MappingOffset The offset of the ID Mapping array
|
|
from the start of the IORT table.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
DumpIortNodeRootComplex (
|
|
IN UINT8* Ptr,
|
|
IN UINT16 Length,
|
|
IN UINT32 MappingCount,
|
|
IN UINT32 MappingOffset
|
|
)
|
|
{
|
|
ParseAcpi (
|
|
TRUE,
|
|
2,
|
|
"Root Complex Node",
|
|
Ptr,
|
|
Length,
|
|
PARSER_PARAMS (IortNodeRootComplexParser)
|
|
);
|
|
|
|
DumpIortNodeIdMappings (
|
|
Ptr + MappingOffset,
|
|
Length - MappingOffset,
|
|
MappingCount
|
|
);
|
|
}
|
|
|
|
/**
|
|
This function parses the IORT PMCG node.
|
|
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] Length Length of the buffer.
|
|
@param [in] MappingCount The ID Mapping count.
|
|
@param [in] MappingOffset The offset of the ID Mapping array
|
|
from the start of the IORT table.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
DumpIortNodePmcg (
|
|
IN UINT8* Ptr,
|
|
IN UINT16 Length,
|
|
IN UINT32 MappingCount,
|
|
IN UINT32 MappingOffset
|
|
)
|
|
{
|
|
ParseAcpi (
|
|
TRUE,
|
|
2,
|
|
"PMCG Node",
|
|
Ptr,
|
|
Length,
|
|
PARSER_PARAMS (IortNodePmcgParser)
|
|
);
|
|
|
|
DumpIortNodeIdMappings (
|
|
Ptr + MappingOffset,
|
|
Length - MappingOffset,
|
|
MappingCount
|
|
);
|
|
}
|
|
|
|
/**
|
|
This function parses the ACPI IORT table.
|
|
When trace is enabled this function parses the IORT table and traces the ACPI fields.
|
|
|
|
This function also parses the following nodes:
|
|
- ITS Group
|
|
- Named Component
|
|
- Root Complex
|
|
- SMMUv1/2
|
|
- SMMUv3
|
|
- PMCG
|
|
|
|
This function also performs validation of the ACPI table fields.
|
|
|
|
@param [in] Trace If TRUE, trace the ACPI fields.
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] AcpiTableLength Length of the ACPI table.
|
|
@param [in] AcpiTableRevision Revision of the ACPI table.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
ParseAcpiIort (
|
|
IN BOOLEAN Trace,
|
|
IN UINT8* Ptr,
|
|
IN UINT32 AcpiTableLength,
|
|
IN UINT8 AcpiTableRevision
|
|
)
|
|
{
|
|
UINT32 Offset;
|
|
UINT32 Index;
|
|
UINT8* NodePtr;
|
|
|
|
if (!Trace) {
|
|
return;
|
|
}
|
|
|
|
ParseAcpi (
|
|
TRUE,
|
|
0,
|
|
"IORT",
|
|
Ptr,
|
|
AcpiTableLength,
|
|
PARSER_PARAMS (IortParser)
|
|
);
|
|
|
|
// Check if the values used to control the parsing logic have been
|
|
// successfully read.
|
|
if ((IortNodeCount == NULL) ||
|
|
(IortNodeOffset == NULL)) {
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Insufficient table length. AcpiTableLength = %d.\n",
|
|
AcpiTableLength
|
|
);
|
|
return;
|
|
}
|
|
|
|
Offset = *IortNodeOffset;
|
|
NodePtr = Ptr + Offset;
|
|
Index = 0;
|
|
|
|
// Parse the specified number of IORT nodes or the IORT table buffer length.
|
|
// Whichever is minimum.
|
|
while ((Index++ < *IortNodeCount) &&
|
|
(Offset < AcpiTableLength)) {
|
|
// Parse the IORT Node Header
|
|
ParseAcpi (
|
|
FALSE,
|
|
0,
|
|
"IORT Node Header",
|
|
NodePtr,
|
|
AcpiTableLength - Offset,
|
|
PARSER_PARAMS (IortNodeHeaderParser)
|
|
);
|
|
|
|
// Check if the values used to control the parsing logic have been
|
|
// successfully read.
|
|
if ((IortNodeType == NULL) ||
|
|
(IortNodeLength == NULL) ||
|
|
(IortIdMappingCount == NULL) ||
|
|
(IortIdMappingOffset == NULL)) {
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Insufficient remaining table buffer length to read the " \
|
|
L"IORT node header. Length = %d.\n",
|
|
AcpiTableLength - Offset
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Validate IORT Node length
|
|
if ((*IortNodeLength == 0) ||
|
|
((Offset + (*IortNodeLength)) > AcpiTableLength)) {
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Invalid IORT Node length. " \
|
|
L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
|
|
*IortNodeLength,
|
|
Offset,
|
|
AcpiTableLength
|
|
);
|
|
return;
|
|
}
|
|
|
|
PrintFieldName (2, L"* Node Offset *");
|
|
Print (L"0x%x\n", Offset);
|
|
|
|
switch (*IortNodeType) {
|
|
case EFI_ACPI_IORT_TYPE_ITS_GROUP:
|
|
DumpIortNodeIts (
|
|
NodePtr,
|
|
*IortNodeLength
|
|
);
|
|
break;
|
|
case EFI_ACPI_IORT_TYPE_NAMED_COMP:
|
|
DumpIortNodeNamedComponent (
|
|
NodePtr,
|
|
*IortNodeLength,
|
|
*IortIdMappingCount,
|
|
*IortIdMappingOffset
|
|
);
|
|
break;
|
|
case EFI_ACPI_IORT_TYPE_ROOT_COMPLEX:
|
|
DumpIortNodeRootComplex (
|
|
NodePtr,
|
|
*IortNodeLength,
|
|
*IortIdMappingCount,
|
|
*IortIdMappingOffset
|
|
);
|
|
break;
|
|
case EFI_ACPI_IORT_TYPE_SMMUv1v2:
|
|
DumpIortNodeSmmuV1V2 (
|
|
NodePtr,
|
|
*IortNodeLength,
|
|
*IortIdMappingCount,
|
|
*IortIdMappingOffset
|
|
);
|
|
break;
|
|
case EFI_ACPI_IORT_TYPE_SMMUv3:
|
|
DumpIortNodeSmmuV3 (
|
|
NodePtr,
|
|
*IortNodeLength,
|
|
*IortIdMappingCount,
|
|
*IortIdMappingOffset
|
|
);
|
|
break;
|
|
case EFI_ACPI_IORT_TYPE_PMCG:
|
|
DumpIortNodePmcg (
|
|
NodePtr,
|
|
*IortNodeLength,
|
|
*IortIdMappingCount,
|
|
*IortIdMappingOffset
|
|
);
|
|
break;
|
|
|
|
default:
|
|
IncrementErrorCount ();
|
|
Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);
|
|
} // switch
|
|
|
|
NodePtr += (*IortNodeLength);
|
|
Offset += (*IortNodeLength);
|
|
} // while
|
|
}
|