4 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 - IO Remapping Table, Platform Design Document, Revision C, 15 May 2017
17 #include <IndustryStandard/IoRemappingTable.h>
18 #include <Library/PrintLib.h>
19 #include <Library/UefiLib.h>
20 #include "AcpiParser.h"
21 #include "AcpiTableParser.h"
24 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
27 The EIORT_NODE enum describes the IORT Node types.
29 typedef enum IortNode
{
30 EIORT_NODE_ITS_GROUP
, ///< ITS Group node
31 EIORT_NODE_NAMED_COMPONENT
, ///< Named Component node
32 EIORT_NODE_ROOT_COMPLEX
, ///< Root Complex node
33 EIORT_NODE_SMMUV1_V2
, ///< SMMU v1/v2 node
34 EIORT_NODE_SMMUV3
, ///< SMMU v3 node
35 EIORT_NODE_PMCG
, ///< PMC group node
40 STATIC CONST UINT32
* IortNodeCount
;
41 STATIC CONST UINT32
* IortNodeOffset
;
43 STATIC CONST UINT8
* IortNodeType
;
44 STATIC CONST UINT16
* IortNodeLength
;
45 STATIC CONST UINT32
* IortIdMappingCount
;
46 STATIC CONST UINT32
* IortIdMappingOffset
;
48 STATIC CONST UINT32
* InterruptContextCount
;
49 STATIC CONST UINT32
* InterruptContextOffset
;
50 STATIC CONST UINT32
* PmuInterruptCount
;
51 STATIC CONST UINT32
* PmuInterruptOffset
;
53 STATIC CONST UINT32
* ItsCount
;
56 This function validates the ID Mapping array count for the ITS node.
58 @param [in] Ptr Pointer to the start of the field data.
59 @param [in] Context Pointer to context specific information e.g. this
60 could be a pointer to the ACPI table header.
65 ValidateItsIdMappingCount (
71 This function validates the ID Mapping array offset for the ITS node.
73 @param [in] Ptr Pointer to the start of the field data.
74 @param [in] Context Pointer to context specific information e.g. this
75 could be a pointer to the ACPI table header.
80 ValidateItsIdArrayReference (
86 Helper Macro for populating the IORT Node header in the ACPI_PARSER array.
88 @param [out] ValidateIdMappingCount Optional pointer to a function for
89 validating the ID Mapping count.
90 @param [out] ValidateIdArrayReference Optional pointer to a function for
91 validating the ID Array reference.
93 #define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount, \
94 ValidateIdArrayReference) \
95 { L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \
96 { L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \
97 { L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \
98 { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \
99 { L"Number of ID mappings", 4, 8, L"%d", NULL, \
100 (VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \
101 { L"Reference to ID Array", 4, 12, L"0x%x", NULL, \
102 (VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL }
105 An ACPI_PARSER array describing the ACPI IORT Table
107 STATIC CONST ACPI_PARSER IortParser
[] = {
108 PARSE_ACPI_HEADER (&AcpiHdrInfo
),
109 {L
"Number of IORT Nodes", 4, 36, L
"%d", NULL
,
110 (VOID
**)&IortNodeCount
, NULL
, NULL
},
111 {L
"Offset to Array of IORT Nodes", 4, 40, L
"0x%x", NULL
,
112 (VOID
**)&IortNodeOffset
, NULL
, NULL
},
113 {L
"Reserved", 4, 44, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
117 An ACPI_PARSER array describing the IORT node header structure.
119 STATIC CONST ACPI_PARSER IortNodeHeaderParser
[] = {
120 PARSE_IORT_NODE_HEADER (NULL
, NULL
)
124 An ACPI_PARSER array describing the IORT SMMUv1/2 node.
126 STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser
[] = {
127 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
128 {L
"Base Address", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
129 {L
"Span", 8, 24, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
130 {L
"Model", 4, 32, L
"%d", NULL
, NULL
, NULL
, NULL
},
131 {L
"Flags", 4, 36, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
132 {L
"Reference to Global Interrupt Array", 4, 40, L
"0x%x", NULL
, NULL
, NULL
,
134 {L
"Number of context interrupts", 4, 44, L
"%d", NULL
,
135 (VOID
**)&InterruptContextCount
, NULL
, NULL
},
136 {L
"Reference to Context Interrupt Array", 4, 48, L
"0x%x", NULL
,
137 (VOID
**)&InterruptContextOffset
, NULL
, NULL
},
138 {L
"Number of PMU Interrupts", 4, 52, L
"%d", NULL
,
139 (VOID
**)&PmuInterruptCount
, NULL
, NULL
},
140 {L
"Reference to PMU Interrupt Array", 4, 56, L
"0x%x", NULL
,
141 (VOID
**)&PmuInterruptOffset
, NULL
, NULL
},
144 {L
"SMMU_NSgIrpt", 4, 60, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
145 {L
"SMMU_NSgIrpt interrupt flags", 4, 64, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
146 {L
"SMMU_NSgCfgIrpt", 4, 68, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
147 {L
"SMMU_NSgCfgIrpt interrupt flags", 4, 72, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
151 An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array.
153 STATIC CONST ACPI_PARSER InterruptArrayParser
[] = {
154 {L
" Interrupt GSIV", 4, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
155 {L
" Flags", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
159 An ACPI_PARSER array describing the IORT ID Mapping.
161 STATIC CONST ACPI_PARSER IortNodeIdMappingParser
[] = {
162 {L
" Input base", 4, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
163 {L
" Number of IDs", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
164 {L
" Output base", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
165 {L
" Output reference", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
166 {L
" Flags", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
170 An ACPI_PARSER array describing the IORT SMMUv3 node.
172 STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser
[] = {
173 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
174 {L
"Base Address", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
175 {L
"Flags", 4, 24, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
176 {L
"Reserved", 4, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
177 {L
"VATOS Address", 8, 32, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
178 {L
"Model", 4, 40, L
"%d", NULL
, NULL
, NULL
, NULL
},
179 {L
"Event", 4, 44, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
180 {L
"PRI", 4, 48, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
181 {L
"GERR", 4, 52, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
182 {L
"Sync", 4, 56, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
186 An ACPI_PARSER array describing the IORT ITS node.
188 STATIC CONST ACPI_PARSER IortNodeItsParser
[] = {
189 PARSE_IORT_NODE_HEADER (
190 ValidateItsIdMappingCount
,
191 ValidateItsIdArrayReference
193 {L
" Number of ITSs", 4, 16, L
"%d", NULL
, (VOID
**)&ItsCount
, NULL
}
197 An ACPI_PARSER array describing the ITS ID.
199 STATIC CONST ACPI_PARSER ItsIdParser
[] = {
200 { L
" GIC ITS Identifier", 4, 0, L
"%d", NULL
, NULL
, NULL
}
204 An ACPI_PARSER array describing the IORT Names Component node.
206 STATIC CONST ACPI_PARSER IortNodeNamedComponentParser
[] = {
207 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
208 {L
"Node Flags", 4, 16, L
"%d", NULL
, NULL
, NULL
, NULL
},
209 {L
"Memory access properties", 8, 20, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
210 {L
"Device memory address size limit", 1, 28, L
"%d", NULL
, NULL
, NULL
, NULL
}
214 An ACPI_PARSER array describing the IORT Root Complex node.
216 STATIC CONST ACPI_PARSER IortNodeRootComplexParser
[] = {
217 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
218 {L
"Memory access properties", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
219 {L
"ATS Attribute", 4, 24, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
220 {L
"PCI Segment number", 4, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
224 An ACPI_PARSER array describing the IORT PMCG node.
226 STATIC CONST ACPI_PARSER IortNodePmcgParser
[] = {
227 PARSE_IORT_NODE_HEADER (NULL
, NULL
),
228 {L
"Base Address", 8, 16, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
229 {L
"Overflow interrupt GSIV", 4, 24, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
230 {L
"Node reference", 4, 28, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
234 This function validates the ID Mapping array count for the ITS node.
236 @param [in] Ptr Pointer to the start of the field data.
237 @param [in] Context Pointer to context specific information e.g. this
238 could be a pointer to the ACPI table header.
243 ValidateItsIdMappingCount (
248 if (*(UINT32
*)Ptr
!= 0) {
249 IncrementErrorCount ();
250 Print (L
"\nERROR: IORT ID Mapping count must be zero.");
255 This function validates the ID Mapping array offset for the ITS node.
257 @param [in] Ptr Pointer to the start of the field data.
258 @param [in] Context Pointer to context specific information e.g. this
259 could be a pointer to the ACPI table header.
264 ValidateItsIdArrayReference (
269 if (*(UINT32
*)Ptr
!= 0) {
270 IncrementErrorCount ();
271 Print (L
"\nERROR: IORT ID Mapping offset must be zero.");
276 This function parses the IORT Node Id Mapping array.
278 @param [in] Ptr Pointer to the start of the IORT Table.
279 @param [in] MappingCount The ID Mapping count.
280 @param [in] MappingOffset The offset of the ID Mapping array
281 from the start of the IORT table.
285 DumpIortNodeIdMappings (
287 IN UINT32 MappingCount
,
288 IN UINT32 MappingOffset
294 CHAR8 Buffer
[40]; // Used for AsciiName param of ParseAcpi
296 IdMappingPtr
= Ptr
+ MappingOffset
;
298 while (Index
< MappingCount
) {
311 PARSER_PARAMS (IortNodeIdMappingParser
)
313 IdMappingPtr
+= Offset
;
319 This function parses the IORT SMMUv1/2 node.
321 @param [in] Ptr Pointer to the start of the buffer.
322 @param [in] Length Length of the buffer.
323 @param [in] MappingCount The ID Mapping count.
324 @param [in] MappingOffset The offset of the ID Mapping array
325 from the start of the IORT table.
329 DumpIortNodeSmmuV1V2 (
332 IN UINT32 MappingCount
,
333 IN UINT32 MappingOffset
338 CHAR8 Buffer
[50]; // Used for AsciiName param of ParseAcpi
345 "SMMUv1 or SMMUv2 Node",
348 PARSER_PARAMS (IortNodeSmmuV1V2Parser
)
351 ArrayPtr
= Ptr
+ *InterruptContextOffset
;
353 while (Index
< *InterruptContextCount
) {
357 "Context Interrupts Array [%d]",
366 PARSER_PARAMS (InterruptArrayParser
)
372 ArrayPtr
= Ptr
+ *PmuInterruptOffset
;
374 while (Index
< *PmuInterruptCount
) {
378 "PMU Interrupts Array [%d]",
387 PARSER_PARAMS (InterruptArrayParser
)
393 if (*IortIdMappingCount
!= 0) {
394 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
399 This function parses the IORT SMMUv3 node.
401 @param [in] Ptr Pointer to the start of the buffer.
402 @param [in] Length Length of the buffer.
403 @param [in] MappingCount The ID Mapping count.
404 @param [in] MappingOffset The offset of the ID Mapping array
405 from the start of the IORT table.
412 IN UINT32 MappingCount
,
413 IN UINT32 MappingOffset
422 PARSER_PARAMS (IortNodeSmmuV3Parser
)
425 if (*IortIdMappingCount
!= 0) {
426 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
431 This function parses the IORT ITS node.
433 @param [in] Ptr Pointer to the start of the buffer.
434 @param [in] Length Length of the buffer.
446 CHAR8 Buffer
[80]; // Used for AsciiName param of ParseAcpi
454 PARSER_PARAMS (IortNodeItsParser
)
457 ItsIdPtr
= Ptr
+ Offset
;
459 while (Index
< *ItsCount
) {
463 "GIC ITS Identifier Array [%d]",
472 PARSER_PARAMS (ItsIdParser
)
478 // Note: ITS does not have the ID Mappings Array
482 This function parses the IORT Named Component node.
484 @param [in] Ptr Pointer to the start of the buffer.
485 @param [in] Length Length of the buffer.
486 @param [in] MappingCount The ID Mapping count.
487 @param [in] MappingOffset The offset of the ID Mapping array
488 from the start of the IORT table.
492 DumpIortNodeNamedComponent (
495 IN UINT32 MappingCount
,
496 IN UINT32 MappingOffset
501 UINT8
* DeviceNamePtr
;
502 UINT32 DeviceNameLength
;
507 "Named Component Node",
510 PARSER_PARAMS (IortNodeNamedComponentParser
)
513 DeviceNamePtr
= Ptr
+ Offset
;
514 // Estimate the Device Name length
515 DeviceNameLength
= Length
- Offset
- (MappingCount
* 20);
516 PrintFieldName (2, L
"Device Object Name");
518 while ((Index
< DeviceNameLength
) && (DeviceNamePtr
[Index
] != 0)) {
519 Print (L
"%c", DeviceNamePtr
[Index
++]);
523 if (*IortIdMappingCount
!= 0) {
524 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
529 This function parses the IORT Root Complex node.
531 @param [in] Ptr Pointer to the start of the buffer.
532 @param [in] Length Length of the buffer.
533 @param [in] MappingCount The ID Mapping count.
534 @param [in] MappingOffset The offset of the ID Mapping array
535 from the start of the IORT table.
539 DumpIortNodeRootComplex (
542 IN UINT32 MappingCount
,
543 IN UINT32 MappingOffset
552 PARSER_PARAMS (IortNodeRootComplexParser
)
555 if (*IortIdMappingCount
!= 0) {
556 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
561 This function parses the IORT PMCG node.
563 @param [in] Ptr Pointer to the start of the buffer.
564 @param [in] Length Length of the buffer.
565 @param [in] MappingCount The ID Mapping count.
566 @param [in] MappingOffset The offset of the ID Mapping array
567 from the start of the IORT table.
574 IN UINT32 MappingCount
,
575 IN UINT32 MappingOffset
584 PARSER_PARAMS (IortNodePmcgParser
)
587 if (*IortIdMappingCount
!= 0) {
588 DumpIortNodeIdMappings (Ptr
, MappingCount
, MappingOffset
);
591 if (*IortIdMappingCount
> 1) {
592 IncrementErrorCount ();
594 L
"ERROR: ID mapping must not be greater than 1. Id Mapping Count =%d\n",
601 This function parses the ACPI IORT table.
602 When trace is enabled this function parses the IORT table and traces the ACPI fields.
604 This function also parses the following nodes:
612 This function also performs validation of the ACPI table fields.
614 @param [in] Trace If TRUE, trace the ACPI fields.
615 @param [in] Ptr Pointer to the start of the buffer.
616 @param [in] AcpiTableLength Length of the ACPI table.
617 @param [in] AcpiTableRevision Revision of the ACPI table.
624 IN UINT32 AcpiTableLength
,
625 IN UINT8 AcpiTableRevision
642 PARSER_PARAMS (IortParser
)
644 Offset
= *IortNodeOffset
;
645 NodePtr
= Ptr
+ Offset
;
648 while ((Index
< *IortNodeCount
) && (Offset
< AcpiTableLength
)) {
649 // Parse the IORT Node Header
656 PARSER_PARAMS (IortNodeHeaderParser
)
658 if (*IortNodeLength
== 0) {
659 IncrementErrorCount ();
660 Print (L
"ERROR: Parser error. Invalid table data.\n");
664 PrintFieldName (2, L
"* Node Offset *");
665 Print (L
"0x%x\n", Offset
);
667 switch (*IortNodeType
) {
668 case EIORT_NODE_ITS_GROUP
:
674 case EIORT_NODE_NAMED_COMPONENT
:
675 DumpIortNodeNamedComponent (
682 case EIORT_NODE_ROOT_COMPLEX
:
683 DumpIortNodeRootComplex (
690 case EIORT_NODE_SMMUV1_V2
:
691 DumpIortNodeSmmuV1V2 (
698 case EIORT_NODE_SMMUV3
:
706 case EIORT_NODE_PMCG
:
716 IncrementErrorCount ();
717 Print (L
"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType
);
720 NodePtr
+= (*IortNodeLength
);
721 Offset
+= (*IortNodeLength
);