4 Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - IO Remapping Table, Platform Design Document, Revision C, 15 May 2017
11 #include <IndustryStandard/IoRemappingTable.h>
12 #include <Library/PrintLib.h>
13 #include <Library/UefiLib.h>
14 #include "AcpiParser.h"
15 #include "AcpiTableParser.h"
18 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
20 STATIC CONST UINT32
* IortNodeCount
;
21 STATIC CONST UINT32
* IortNodeOffset
;
23 STATIC CONST UINT8
* IortNodeType
;
24 STATIC CONST UINT16
* IortNodeLength
;
25 STATIC CONST UINT32
* IortIdMappingCount
;
26 STATIC CONST UINT32
* IortIdMappingOffset
;
28 STATIC CONST UINT32
* InterruptContextCount
;
29 STATIC CONST UINT32
* InterruptContextOffset
;
30 STATIC CONST UINT32
* PmuInterruptCount
;
31 STATIC CONST UINT32
* PmuInterruptOffset
;
33 STATIC CONST UINT32
* ItsCount
;
36 This function validates the ID Mapping array count for the ITS node.
38 @param [in] Ptr Pointer to the start of the field data.
39 @param [in] Context Pointer to context specific information e.g. this
40 could be a pointer to the ACPI table header.
45 ValidateItsIdMappingCount (
51 This function validates the ID Mapping array offset for the ITS node.
53 @param [in] Ptr Pointer to the start of the field data.
54 @param [in] Context Pointer to context specific information e.g. this
55 could be a pointer to the ACPI table header.
60 ValidateItsIdArrayReference (
66 Helper Macro for populating the IORT Node header in the ACPI_PARSER array.
68 @param [out] ValidateIdMappingCount Optional pointer to a function for
69 validating the ID Mapping count.
70 @param [out] ValidateIdArrayReference Optional pointer to a function for
71 validating the ID Array reference.
73 #define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount, \
74 ValidateIdArrayReference) \
75 { L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \
76 { L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \
77 { L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \
78 { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
79 { L"Number of ID mappings", 4, 8, L"%d", NULL, \
80 (VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \
81 { L"Reference to ID Array", 4, 12, L"0x%x", NULL, \
82 (VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL }
85 An ACPI_PARSER array describing the ACPI IORT Table
87 STATIC CONST ACPI_PARSER IortParser
[] = {
88 PARSE_ACPI_HEADER (&AcpiHdrInfo
),
89 {L
"Number of IORT Nodes", 4, 36, L
"%d", NULL
,
90 (VOID
**)&IortNodeCount
, NULL
, NULL
},
91 {L
"Offset to Array of IORT Nodes", 4, 40, L
"0x%x", NULL
,
92 (VOID
**)&IortNodeOffset
, NULL
, NULL
},
93 {L
"Reserved", 4, 44, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
97 An ACPI_PARSER array describing the IORT node header structure.
99 STATIC CONST ACPI_PARSER IortNodeHeaderParser
[] = {
100 PARSE_IORT_NODE_HEADER (NULL
, NULL
)
104 An ACPI_PARSER array describing the IORT SMMUv1/2 node.
106 STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser
[] = {
107 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
108 {L
"Base Address", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
109 {L
"Span", 8, 24, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
110 {L
"Model", 4, 32, L
"%d", NULL
, NULL
, NULL
, NULL
},
111 {L
"Flags", 4, 36, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
112 {L
"Reference to Global Interrupt Array", 4, 40, L
"0x%x", NULL
, NULL
, NULL
,
114 {L
"Number of context interrupts", 4, 44, L
"%d", NULL
,
115 (VOID
**)&InterruptContextCount
, NULL
, NULL
},
116 {L
"Reference to Context Interrupt Array", 4, 48, L
"0x%x", NULL
,
117 (VOID
**)&InterruptContextOffset
, NULL
, NULL
},
118 {L
"Number of PMU Interrupts", 4, 52, L
"%d", NULL
,
119 (VOID
**)&PmuInterruptCount
, NULL
, NULL
},
120 {L
"Reference to PMU Interrupt Array", 4, 56, L
"0x%x", NULL
,
121 (VOID
**)&PmuInterruptOffset
, NULL
, NULL
},
124 {L
"SMMU_NSgIrpt", 4, 60, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
125 {L
"SMMU_NSgIrpt interrupt flags", 4, 64, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
126 {L
"SMMU_NSgCfgIrpt", 4, 68, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
127 {L
"SMMU_NSgCfgIrpt interrupt flags", 4, 72, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
131 An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array.
133 STATIC CONST ACPI_PARSER InterruptArrayParser
[] = {
134 {L
" Interrupt GSIV", 4, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
135 {L
" Flags", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
139 An ACPI_PARSER array describing the IORT ID Mapping.
141 STATIC CONST ACPI_PARSER IortNodeIdMappingParser
[] = {
142 {L
" Input base", 4, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
143 {L
" Number of IDs", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
144 {L
" Output base", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
145 {L
" Output reference", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
146 {L
" Flags", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
150 An ACPI_PARSER array describing the IORT SMMUv3 node.
152 STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser
[] = {
153 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
154 {L
"Base Address", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
155 {L
"Flags", 4, 24, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
156 {L
"Reserved", 4, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
157 {L
"VATOS Address", 8, 32, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
158 {L
"Model", 4, 40, L
"%d", NULL
, NULL
, NULL
, NULL
},
159 {L
"Event", 4, 44, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
160 {L
"PRI", 4, 48, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
161 {L
"GERR", 4, 52, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
162 {L
"Sync", 4, 56, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
166 An ACPI_PARSER array describing the IORT ITS node.
168 STATIC CONST ACPI_PARSER IortNodeItsParser
[] = {
169 PARSE_IORT_NODE_HEADER (
170 ValidateItsIdMappingCount
,
171 ValidateItsIdArrayReference
173 {L
" Number of ITSs", 4, 16, L
"%d", NULL
, (VOID
**)&ItsCount
, NULL
}
177 An ACPI_PARSER array describing the ITS ID.
179 STATIC CONST ACPI_PARSER ItsIdParser
[] = {
180 { L
" GIC ITS Identifier", 4, 0, L
"%d", NULL
, NULL
, NULL
}
184 An ACPI_PARSER array describing the IORT Names Component node.
186 STATIC CONST ACPI_PARSER IortNodeNamedComponentParser
[] = {
187 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
188 {L
"Node Flags", 4, 16, L
"%d", NULL
, NULL
, NULL
, NULL
},
189 {L
"Memory access properties", 8, 20, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
190 {L
"Device memory address size limit", 1, 28, L
"%d", NULL
, NULL
, NULL
, NULL
}
194 An ACPI_PARSER array describing the IORT Root Complex node.
196 STATIC CONST ACPI_PARSER IortNodeRootComplexParser
[] = {
197 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
198 {L
"Memory access properties", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
199 {L
"ATS Attribute", 4, 24, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
200 {L
"PCI Segment number", 4, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
204 An ACPI_PARSER array describing the IORT PMCG node.
206 STATIC CONST ACPI_PARSER IortNodePmcgParser
[] = {
207 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
208 {L
"Base Address", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
209 {L
"Overflow interrupt GSIV", 4, 24, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
210 {L
"Node reference", 4, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
214 This function validates the ID Mapping array count for the ITS node.
216 @param [in] Ptr Pointer to the start of the field data.
217 @param [in] Context Pointer to context specific information e.g. this
218 could be a pointer to the ACPI table header.
223 ValidateItsIdMappingCount (
228 if (*(UINT32
*)Ptr
!= 0) {
229 IncrementErrorCount ();
230 Print (L
"\nERROR: IORT ID Mapping count must be zero.");
235 This function validates the ID Mapping array offset for the ITS node.
237 @param [in] Ptr Pointer to the start of the field data.
238 @param [in] Context Pointer to context specific information e.g. this
239 could be a pointer to the ACPI table header.
244 ValidateItsIdArrayReference (
249 if (*(UINT32
*)Ptr
!= 0) {
250 IncrementErrorCount ();
251 Print (L
"\nERROR: IORT ID Mapping offset must be zero.");
256 This function parses the IORT Node Id Mapping array.
258 @param [in] Ptr Pointer to the start of the IORT Table.
259 @param [in] MappingCount The ID Mapping count.
260 @param [in] MappingOffset The offset of the ID Mapping array
261 from the start of the IORT table.
265 DumpIortNodeIdMappings (
267 IN UINT32 MappingCount
,
268 IN UINT32 MappingOffset
274 CHAR8 Buffer
[40]; // Used for AsciiName param of ParseAcpi
276 IdMappingPtr
= Ptr
+ MappingOffset
;
278 while (Index
< MappingCount
) {
291 PARSER_PARAMS (IortNodeIdMappingParser
)
293 IdMappingPtr
+= Offset
;
299 This function parses the IORT SMMUv1/2 node.
301 @param [in] Ptr Pointer to the start of the buffer.
302 @param [in] Length Length of the buffer.
303 @param [in] MappingCount The ID Mapping count.
304 @param [in] MappingOffset The offset of the ID Mapping array
305 from the start of the IORT table.
309 DumpIortNodeSmmuV1V2 (
312 IN UINT32 MappingCount
,
313 IN UINT32 MappingOffset
318 CHAR8 Buffer
[50]; // Used for AsciiName param of ParseAcpi
325 "SMMUv1 or SMMUv2 Node",
328 PARSER_PARAMS (IortNodeSmmuV1V2Parser
)
331 ArrayPtr
= Ptr
+ *InterruptContextOffset
;
333 while (Index
< *InterruptContextCount
) {
337 "Context Interrupts Array [%d]",
346 PARSER_PARAMS (InterruptArrayParser
)
352 ArrayPtr
= Ptr
+ *PmuInterruptOffset
;
354 while (Index
< *PmuInterruptCount
) {
358 "PMU Interrupts Array [%d]",
367 PARSER_PARAMS (InterruptArrayParser
)
373 if (*IortIdMappingCount
!= 0) {
374 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
379 This function parses the IORT SMMUv3 node.
381 @param [in] Ptr Pointer to the start of the buffer.
382 @param [in] Length Length of the buffer.
383 @param [in] MappingCount The ID Mapping count.
384 @param [in] MappingOffset The offset of the ID Mapping array
385 from the start of the IORT table.
392 IN UINT32 MappingCount
,
393 IN UINT32 MappingOffset
402 PARSER_PARAMS (IortNodeSmmuV3Parser
)
405 if (*IortIdMappingCount
!= 0) {
406 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
411 This function parses the IORT ITS node.
413 @param [in] Ptr Pointer to the start of the buffer.
414 @param [in] Length Length of the buffer.
426 CHAR8 Buffer
[80]; // Used for AsciiName param of ParseAcpi
434 PARSER_PARAMS (IortNodeItsParser
)
437 ItsIdPtr
= Ptr
+ Offset
;
439 while (Index
< *ItsCount
) {
443 "GIC ITS Identifier Array [%d]",
452 PARSER_PARAMS (ItsIdParser
)
458 // Note: ITS does not have the ID Mappings Array
462 This function parses the IORT Named Component node.
464 @param [in] Ptr Pointer to the start of the buffer.
465 @param [in] Length Length of the buffer.
466 @param [in] MappingCount The ID Mapping count.
467 @param [in] MappingOffset The offset of the ID Mapping array
468 from the start of the IORT table.
472 DumpIortNodeNamedComponent (
475 IN UINT32 MappingCount
,
476 IN UINT32 MappingOffset
481 UINT8
* DeviceNamePtr
;
482 UINT32 DeviceNameLength
;
487 "Named Component Node",
490 PARSER_PARAMS (IortNodeNamedComponentParser
)
493 DeviceNamePtr
= Ptr
+ Offset
;
494 // Estimate the Device Name length
495 DeviceNameLength
= Length
- Offset
- (MappingCount
* 20);
496 PrintFieldName (2, L
"Device Object Name");
498 while ((Index
< DeviceNameLength
) && (DeviceNamePtr
[Index
] != 0)) {
499 Print (L
"%c", DeviceNamePtr
[Index
++]);
503 if (*IortIdMappingCount
!= 0) {
504 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
509 This function parses the IORT Root Complex node.
511 @param [in] Ptr Pointer to the start of the buffer.
512 @param [in] Length Length of the buffer.
513 @param [in] MappingCount The ID Mapping count.
514 @param [in] MappingOffset The offset of the ID Mapping array
515 from the start of the IORT table.
519 DumpIortNodeRootComplex (
522 IN UINT32 MappingCount
,
523 IN UINT32 MappingOffset
532 PARSER_PARAMS (IortNodeRootComplexParser
)
535 if (*IortIdMappingCount
!= 0) {
536 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
541 This function parses the IORT PMCG node.
543 @param [in] Ptr Pointer to the start of the buffer.
544 @param [in] Length Length of the buffer.
545 @param [in] MappingCount The ID Mapping count.
546 @param [in] MappingOffset The offset of the ID Mapping array
547 from the start of the IORT table.
554 IN UINT32 MappingCount
,
555 IN UINT32 MappingOffset
564 PARSER_PARAMS (IortNodePmcgParser
)
567 if (*IortIdMappingCount
!= 0) {
568 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
571 if (*IortIdMappingCount
> 1) {
572 IncrementErrorCount ();
574 L
"ERROR: ID mapping must not be greater than 1. Id Mapping Count =%d\n",
581 This function parses the ACPI IORT table.
582 When trace is enabled this function parses the IORT table and traces the ACPI fields.
584 This function also parses the following nodes:
592 This function also performs validation of the ACPI table fields.
594 @param [in] Trace If TRUE, trace the ACPI fields.
595 @param [in] Ptr Pointer to the start of the buffer.
596 @param [in] AcpiTableLength Length of the ACPI table.
597 @param [in] AcpiTableRevision Revision of the ACPI table.
604 IN UINT32 AcpiTableLength
,
605 IN UINT8 AcpiTableRevision
622 PARSER_PARAMS (IortParser
)
624 Offset
= *IortNodeOffset
;
625 NodePtr
= Ptr
+ Offset
;
628 while ((Index
< *IortNodeCount
) && (Offset
< AcpiTableLength
)) {
629 // Parse the IORT Node Header
636 PARSER_PARAMS (IortNodeHeaderParser
)
638 if (*IortNodeLength
== 0) {
639 IncrementErrorCount ();
640 Print (L
"ERROR: Parser error. Invalid table data.\n");
644 PrintFieldName (2, L
"* Node Offset *");
645 Print (L
"0x%x\n", Offset
);
647 switch (*IortNodeType
) {
648 case EFI_ACPI_IORT_TYPE_ITS_GROUP
:
654 case EFI_ACPI_IORT_TYPE_NAMED_COMP
:
655 DumpIortNodeNamedComponent (
662 case EFI_ACPI_IORT_TYPE_ROOT_COMPLEX
:
663 DumpIortNodeRootComplex (
670 case EFI_ACPI_IORT_TYPE_SMMUv1v2
:
671 DumpIortNodeSmmuV1V2 (
678 case EFI_ACPI_IORT_TYPE_SMMUv3
:
686 case EFI_ACPI_IORT_TYPE_PMCG
:
696 IncrementErrorCount ();
697 Print (L
"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType
);
700 NodePtr
+= (*IortNodeLength
);
701 Offset
+= (*IortNodeLength
);