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 (
50 if (*(UINT32
*)Ptr
!= 0) {
51 IncrementErrorCount ();
52 Print (L
"\nERROR: IORT ID Mapping count must be zero.");
57 This function validates the ID Mapping array count for the Performance
58 Monitoring Counter Group (PMCG) node.
60 @param [in] Ptr Pointer to the start of the field data.
61 @param [in] Context Pointer to context specific information e.g. this
62 could be a pointer to the ACPI table header.
67 ValidatePmcgIdMappingCount (
72 if (*(UINT32
*)Ptr
> 1) {
73 IncrementErrorCount ();
74 Print (L
"\nERROR: IORT ID Mapping count must not be greater than 1.");
79 This function validates the ID Mapping array offset for the ITS node.
81 @param [in] Ptr Pointer to the start of the field data.
82 @param [in] Context Pointer to context specific information e.g. this
83 could be a pointer to the ACPI table header.
88 ValidateItsIdArrayReference (
93 if (*(UINT32
*)Ptr
!= 0) {
94 IncrementErrorCount ();
95 Print (L
"\nERROR: IORT ID Mapping offset must be zero.");
100 Helper Macro for populating the IORT Node header in the ACPI_PARSER array.
102 @param [out] ValidateIdMappingCount Optional pointer to a function for
103 validating the ID Mapping count.
104 @param [out] ValidateIdArrayReference Optional pointer to a function for
105 validating the ID Array reference.
107 #define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount, \
108 ValidateIdArrayReference) \
109 { L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \
110 { L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \
111 { L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \
112 { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
113 { L"Number of ID mappings", 4, 8, L"%d", NULL, \
114 (VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \
115 { L"Reference to ID Array", 4, 12, L"0x%x", NULL, \
116 (VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL }
119 An ACPI_PARSER array describing the ACPI IORT Table
121 STATIC CONST ACPI_PARSER IortParser
[] = {
122 PARSE_ACPI_HEADER (&AcpiHdrInfo
),
123 {L
"Number of IORT Nodes", 4, 36, L
"%d", NULL
,
124 (VOID
**)&IortNodeCount
, NULL
, NULL
},
125 {L
"Offset to Array of IORT Nodes", 4, 40, L
"0x%x", NULL
,
126 (VOID
**)&IortNodeOffset
, NULL
, NULL
},
127 {L
"Reserved", 4, 44, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
131 An ACPI_PARSER array describing the IORT node header structure.
133 STATIC CONST ACPI_PARSER IortNodeHeaderParser
[] = {
134 PARSE_IORT_NODE_HEADER (NULL
, NULL
)
138 An ACPI_PARSER array describing the IORT SMMUv1/2 node.
140 STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser
[] = {
141 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
142 {L
"Base Address", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
143 {L
"Span", 8, 24, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
144 {L
"Model", 4, 32, L
"%d", NULL
, NULL
, NULL
, NULL
},
145 {L
"Flags", 4, 36, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
146 {L
"Reference to Global Interrupt Array", 4, 40, L
"0x%x", NULL
, NULL
, NULL
,
148 {L
"Number of context interrupts", 4, 44, L
"%d", NULL
,
149 (VOID
**)&InterruptContextCount
, NULL
, NULL
},
150 {L
"Reference to Context Interrupt Array", 4, 48, L
"0x%x", NULL
,
151 (VOID
**)&InterruptContextOffset
, NULL
, NULL
},
152 {L
"Number of PMU Interrupts", 4, 52, L
"%d", NULL
,
153 (VOID
**)&PmuInterruptCount
, NULL
, NULL
},
154 {L
"Reference to PMU Interrupt Array", 4, 56, L
"0x%x", NULL
,
155 (VOID
**)&PmuInterruptOffset
, NULL
, NULL
},
158 {L
"SMMU_NSgIrpt", 4, 60, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
159 {L
"SMMU_NSgIrpt interrupt flags", 4, 64, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
160 {L
"SMMU_NSgCfgIrpt", 4, 68, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
161 {L
"SMMU_NSgCfgIrpt interrupt flags", 4, 72, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
165 An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array.
167 STATIC CONST ACPI_PARSER InterruptArrayParser
[] = {
168 {L
"Interrupt GSIV", 4, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
169 {L
"Flags", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
173 An ACPI_PARSER array describing the IORT ID Mapping.
175 STATIC CONST ACPI_PARSER IortNodeIdMappingParser
[] = {
176 {L
"Input base", 4, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
177 {L
"Number of IDs", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
178 {L
"Output base", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
179 {L
"Output reference", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
180 {L
"Flags", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
184 An ACPI_PARSER array describing the IORT SMMUv3 node.
186 STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser
[] = {
187 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
188 {L
"Base Address", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
189 {L
"Flags", 4, 24, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
190 {L
"Reserved", 4, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
191 {L
"VATOS Address", 8, 32, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
192 {L
"Model", 4, 40, L
"%d", NULL
, NULL
, NULL
, NULL
},
193 {L
"Event", 4, 44, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
194 {L
"PRI", 4, 48, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
195 {L
"GERR", 4, 52, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
196 {L
"Sync", 4, 56, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
200 An ACPI_PARSER array describing the IORT ITS node.
202 STATIC CONST ACPI_PARSER IortNodeItsParser
[] = {
203 PARSE_IORT_NODE_HEADER (
204 ValidateItsIdMappingCount
,
205 ValidateItsIdArrayReference
207 {L
"Number of ITSs", 4, 16, L
"%d", NULL
, (VOID
**)&ItsCount
, NULL
}
211 An ACPI_PARSER array describing the ITS ID.
213 STATIC CONST ACPI_PARSER ItsIdParser
[] = {
214 { L
"GIC ITS Identifier", 4, 0, L
"%d", NULL
, NULL
, NULL
}
218 An ACPI_PARSER array describing the IORT Names Component node.
220 STATIC CONST ACPI_PARSER IortNodeNamedComponentParser
[] = {
221 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
222 {L
"Node Flags", 4, 16, L
"%d", NULL
, NULL
, NULL
, NULL
},
223 {L
"Memory access properties", 8, 20, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
224 {L
"Device memory address size limit", 1, 28, L
"%d", NULL
, NULL
, NULL
, NULL
}
228 An ACPI_PARSER array describing the IORT Root Complex node.
230 STATIC CONST ACPI_PARSER IortNodeRootComplexParser
[] = {
231 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
232 {L
"Memory access properties", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
233 {L
"ATS Attribute", 4, 24, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
234 {L
"PCI Segment number", 4, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
238 An ACPI_PARSER array describing the IORT PMCG node.
240 STATIC CONST ACPI_PARSER IortNodePmcgParser
[] = {
241 PARSE_IORT_NODE_HEADER (ValidatePmcgIdMappingCount
, NULL
),
242 {L
"Base Address", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
243 {L
"Overflow interrupt GSIV", 4, 24, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
244 {L
"Node reference", 4, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
248 This function parses the IORT Node Id Mapping array.
250 @param [in] Ptr Pointer to the start of the ID mapping array.
251 @param [in] Length Length of the buffer.
252 @param [in] MappingCount The ID Mapping count.
256 DumpIortNodeIdMappings (
259 IN UINT32 MappingCount
264 CHAR8 Buffer
[40]; // Used for AsciiName param of ParseAcpi
269 while ((Index
< MappingCount
) &&
277 Offset
+= ParseAcpi (
283 PARSER_PARAMS (IortNodeIdMappingParser
)
290 This function parses the IORT SMMUv1/2 node.
292 @param [in] Ptr Pointer to the start of the buffer.
293 @param [in] Length Length of the buffer.
294 @param [in] MappingCount The ID Mapping count.
295 @param [in] MappingOffset The offset of the ID Mapping array
296 from the start of the IORT table.
300 DumpIortNodeSmmuV1V2 (
303 IN UINT32 MappingCount
,
304 IN UINT32 MappingOffset
309 CHAR8 Buffer
[50]; // Used for AsciiName param of ParseAcpi
314 "SMMUv1 or SMMUv2 Node",
317 PARSER_PARAMS (IortNodeSmmuV1V2Parser
)
320 Offset
= *InterruptContextOffset
;
323 while ((Index
< *InterruptContextCount
) &&
328 "Context Interrupts Array [%d]",
331 Offset
+= ParseAcpi (
337 PARSER_PARAMS (InterruptArrayParser
)
342 Offset
= *PmuInterruptOffset
;
345 while ((Index
< *PmuInterruptCount
) &&
350 "PMU Interrupts Array [%d]",
353 Offset
+= ParseAcpi (
359 PARSER_PARAMS (InterruptArrayParser
)
364 DumpIortNodeIdMappings (
366 Length
- MappingOffset
,
372 This function parses the IORT SMMUv3 node.
374 @param [in] Ptr Pointer to the start of the buffer.
375 @param [in] Length Length of the buffer.
376 @param [in] MappingCount The ID Mapping count.
377 @param [in] MappingOffset The offset of the ID Mapping array
378 from the start of the IORT table.
385 IN UINT32 MappingCount
,
386 IN UINT32 MappingOffset
395 PARSER_PARAMS (IortNodeSmmuV3Parser
)
398 DumpIortNodeIdMappings (
400 Length
- MappingOffset
,
406 This function parses the IORT ITS node.
408 @param [in] Ptr Pointer to the start of the buffer.
409 @param [in] Length Length of the buffer.
420 CHAR8 Buffer
[80]; // Used for AsciiName param of ParseAcpi
428 PARSER_PARAMS (IortNodeItsParser
)
433 while ((Index
< *ItsCount
) &&
438 "GIC ITS Identifier Array [%d]",
441 Offset
+= ParseAcpi (
447 PARSER_PARAMS (ItsIdParser
)
452 // Note: ITS does not have the ID Mappings Array
457 This function parses the IORT Named Component node.
459 @param [in] Ptr Pointer to the start of the buffer.
460 @param [in] Length Length of the buffer.
461 @param [in] MappingCount The ID Mapping count.
462 @param [in] MappingOffset The offset of the ID Mapping array
463 from the start of the IORT table.
467 DumpIortNodeNamedComponent (
470 IN UINT32 MappingCount
,
471 IN UINT32 MappingOffset
480 "Named Component Node",
483 PARSER_PARAMS (IortNodeNamedComponentParser
)
486 // Estimate the Device Name length
487 PrintFieldName (2, L
"Device Object Name");
490 while ((*(Ptr
+ Offset
) != 0) &&
492 Print (L
"%c", *(Ptr
+ Offset
));
497 DumpIortNodeIdMappings (
499 Length
- MappingOffset
,
505 This function parses the IORT Root Complex node.
507 @param [in] Ptr Pointer to the start of the buffer.
508 @param [in] Length Length of the buffer.
509 @param [in] MappingCount The ID Mapping count.
510 @param [in] MappingOffset The offset of the ID Mapping array
511 from the start of the IORT table.
515 DumpIortNodeRootComplex (
518 IN UINT32 MappingCount
,
519 IN UINT32 MappingOffset
528 PARSER_PARAMS (IortNodeRootComplexParser
)
531 DumpIortNodeIdMappings (
533 Length
- MappingOffset
,
539 This function parses the IORT PMCG node.
541 @param [in] Ptr Pointer to the start of the buffer.
542 @param [in] Length Length of the buffer.
543 @param [in] MappingCount The ID Mapping count.
544 @param [in] MappingOffset The offset of the ID Mapping array
545 from the start of the IORT table.
552 IN UINT32 MappingCount
,
553 IN UINT32 MappingOffset
562 PARSER_PARAMS (IortNodePmcgParser
)
565 DumpIortNodeIdMappings (
567 Length
- MappingOffset
,
573 This function parses the ACPI IORT table.
574 When trace is enabled this function parses the IORT table and traces the ACPI fields.
576 This function also parses the following nodes:
584 This function also performs validation of the ACPI table fields.
586 @param [in] Trace If TRUE, trace the ACPI fields.
587 @param [in] Ptr Pointer to the start of the buffer.
588 @param [in] AcpiTableLength Length of the ACPI table.
589 @param [in] AcpiTableRevision Revision of the ACPI table.
596 IN UINT32 AcpiTableLength
,
597 IN UINT8 AcpiTableRevision
614 PARSER_PARAMS (IortParser
)
617 Offset
= *IortNodeOffset
;
618 NodePtr
= Ptr
+ Offset
;
621 // Parse the specified number of IORT nodes or the IORT table buffer length.
622 // Whichever is minimum.
623 while ((Index
++ < *IortNodeCount
) &&
624 (Offset
< AcpiTableLength
)) {
625 // Parse the IORT Node Header
631 AcpiTableLength
- Offset
,
632 PARSER_PARAMS (IortNodeHeaderParser
)
635 // Make sure the IORT Node is inside the table
636 if ((Offset
+ (*IortNodeLength
)) > AcpiTableLength
) {
637 IncrementErrorCount ();
639 L
"ERROR: Invalid IORT node length. IortNodeLength = %d. " \
640 L
"RemainingTableBufferLength = %d. IORT parsing aborted.\n",
642 AcpiTableLength
- Offset
647 PrintFieldName (2, L
"* Node Offset *");
648 Print (L
"0x%x\n", Offset
);
650 switch (*IortNodeType
) {
651 case EFI_ACPI_IORT_TYPE_ITS_GROUP
:
657 case EFI_ACPI_IORT_TYPE_NAMED_COMP
:
658 DumpIortNodeNamedComponent (
665 case EFI_ACPI_IORT_TYPE_ROOT_COMPLEX
:
666 DumpIortNodeRootComplex (
673 case EFI_ACPI_IORT_TYPE_SMMUv1v2
:
674 DumpIortNodeSmmuV1V2 (
681 case EFI_ACPI_IORT_TYPE_SMMUv3
:
689 case EFI_ACPI_IORT_TYPE_PMCG
:
699 IncrementErrorCount ();
700 Print (L
"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType
);
703 NodePtr
+= (*IortNodeLength
);
704 Offset
+= (*IortNodeLength
);