]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
MdePkg: IORT header update for IORT Rev E.d spec
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Iort / IortParser.c
CommitLineData
a6eaba4d 1/** @file\r
ee4dc24f
RN
2 IORT table parser\r
3\r
8a210b9a 4 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.\r
56ba3746 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
ee4dc24f
RN
6\r
7 @par Reference(s):\r
8a210b9a
SM
8 - IO Remapping Table, Platform Design Document, Revision D, March 2018\r
9\r
10 @par Glossary:\r
11 - Ref - Reference\r
ee4dc24f
RN
12**/\r
13\r
14#include <IndustryStandard/IoRemappingTable.h>\r
15#include <Library/PrintLib.h>\r
16#include <Library/UefiLib.h>\r
17#include "AcpiParser.h"\r
18#include "AcpiTableParser.h"\r
e18ac66d 19#include "AcpiViewConfig.h"\r
ee4dc24f
RN
20\r
21// Local variables\r
47d20b54 22STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
ee4dc24f 23\r
47d20b54
MK
24STATIC CONST UINT32 *IortNodeCount;\r
25STATIC CONST UINT32 *IortNodeOffset;\r
ee4dc24f 26\r
47d20b54
MK
27STATIC CONST UINT8 *IortNodeType;\r
28STATIC CONST UINT16 *IortNodeLength;\r
29STATIC CONST UINT32 *IortIdMappingCount;\r
30STATIC CONST UINT32 *IortIdMappingOffset;\r
ee4dc24f 31\r
47d20b54
MK
32STATIC CONST UINT32 *InterruptContextCount;\r
33STATIC CONST UINT32 *InterruptContextOffset;\r
34STATIC CONST UINT32 *PmuInterruptCount;\r
35STATIC CONST UINT32 *PmuInterruptOffset;\r
ee4dc24f 36\r
47d20b54 37STATIC CONST UINT32 *ItsCount;\r
ee4dc24f 38\r
a6eaba4d
DB
39/**\r
40 This function validates the ID Mapping array count for the ITS node.\r
ee4dc24f
RN
41\r
42 @param [in] Ptr Pointer to the start of the field data.\r
43 @param [in] Context Pointer to context specific information e.g. this\r
44 could be a pointer to the ACPI table header.\r
a6eaba4d 45**/\r
ee4dc24f
RN
46STATIC\r
47VOID\r
48EFIAPI\r
49ValidateItsIdMappingCount (\r
47d20b54
MK
50 IN UINT8 *Ptr,\r
51 IN VOID *Context\r
795e706f
KK
52 )\r
53{\r
47d20b54 54 if (*(UINT32 *)Ptr != 0) {\r
795e706f
KK
55 IncrementErrorCount ();\r
56 Print (L"\nERROR: IORT ID Mapping count must be zero.");\r
57 }\r
58}\r
ee4dc24f 59\r
05f8e85f
KK
60/**\r
61 This function validates the ID Mapping array count for the Performance\r
62 Monitoring Counter Group (PMCG) node.\r
63\r
64 @param [in] Ptr Pointer to the start of the field data.\r
65 @param [in] Context Pointer to context specific information e.g. this\r
66 could be a pointer to the ACPI table header.\r
67**/\r
68STATIC\r
69VOID\r
70EFIAPI\r
71ValidatePmcgIdMappingCount (\r
47d20b54
MK
72 IN UINT8 *Ptr,\r
73 IN VOID *Context\r
05f8e85f
KK
74 )\r
75{\r
47d20b54 76 if (*(UINT32 *)Ptr > 1) {\r
05f8e85f
KK
77 IncrementErrorCount ();\r
78 Print (L"\nERROR: IORT ID Mapping count must not be greater than 1.");\r
79 }\r
80}\r
81\r
a6eaba4d
DB
82/**\r
83 This function validates the ID Mapping array offset for the ITS node.\r
ee4dc24f
RN
84\r
85 @param [in] Ptr Pointer to the start of the field data.\r
86 @param [in] Context Pointer to context specific information e.g. this\r
87 could be a pointer to the ACPI table header.\r
a6eaba4d 88**/\r
ee4dc24f
RN
89STATIC\r
90VOID\r
91EFIAPI\r
92ValidateItsIdArrayReference (\r
47d20b54
MK
93 IN UINT8 *Ptr,\r
94 IN VOID *Context\r
795e706f
KK
95 )\r
96{\r
47d20b54 97 if (*(UINT32 *)Ptr != 0) {\r
795e706f
KK
98 IncrementErrorCount ();\r
99 Print (L"\nERROR: IORT ID Mapping offset must be zero.");\r
100 }\r
101}\r
ee4dc24f 102\r
a6eaba4d
DB
103/**\r
104 Helper Macro for populating the IORT Node header in the ACPI_PARSER array.\r
ee4dc24f
RN
105\r
106 @param [out] ValidateIdMappingCount Optional pointer to a function for\r
107 validating the ID Mapping count.\r
108 @param [out] ValidateIdArrayReference Optional pointer to a function for\r
109 validating the ID Array reference.\r
a6eaba4d 110**/\r
ee4dc24f
RN
111#define PARSE_IORT_NODE_HEADER(ValidateIdMappingCount, \\r
112 ValidateIdArrayReference) \\r
113 { L"Type", 1, 0, L"%d", NULL, (VOID**)&IortNodeType, NULL, NULL }, \\r
114 { L"Length", 2, 1, L"%d", NULL, (VOID**)&IortNodeLength, NULL, NULL }, \\r
115 { L"Revision", 1, 3, L"%d", NULL, NULL, NULL, NULL }, \\r
116 { L"Reserved", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }, \\r
117 { L"Number of ID mappings", 4, 8, L"%d", NULL, \\r
118 (VOID**)&IortIdMappingCount, ValidateIdMappingCount, NULL }, \\r
119 { L"Reference to ID Array", 4, 12, L"0x%x", NULL, \\r
120 (VOID**)&IortIdMappingOffset, ValidateIdArrayReference, NULL }\r
121\r
a6eaba4d
DB
122/**\r
123 An ACPI_PARSER array describing the ACPI IORT Table\r
124**/\r
47d20b54 125STATIC CONST ACPI_PARSER IortParser[] = {\r
ee4dc24f 126 PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
47d20b54
MK
127 { L"Number of IORT Nodes", 4, 36, L"%d", NULL,\r
128 (VOID **)&IortNodeCount, NULL, NULL },\r
129 { L"Offset to Array of IORT Nodes",4, 40, L"0x%x", NULL,\r
130 (VOID **)&IortNodeOffset, NULL, NULL },\r
131 { L"Reserved", 4, 44, L"0x%x", NULL,NULL,NULL, NULL }\r
ee4dc24f
RN
132};\r
133\r
a6eaba4d
DB
134/**\r
135 An ACPI_PARSER array describing the IORT node header structure.\r
136**/\r
47d20b54 137STATIC CONST ACPI_PARSER IortNodeHeaderParser[] = {\r
ee4dc24f
RN
138 PARSE_IORT_NODE_HEADER (NULL, NULL)\r
139};\r
140\r
a6eaba4d
DB
141/**\r
142 An ACPI_PARSER array describing the IORT SMMUv1/2 node.\r
143**/\r
47d20b54
MK
144STATIC CONST ACPI_PARSER IortNodeSmmuV1V2Parser[] = {\r
145 PARSE_IORT_NODE_HEADER (NULL, NULL),\r
146 { L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL },\r
147 { L"Span", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL },\r
148 { L"Model", 4, 32, L"%d", NULL, NULL, NULL, NULL },\r
149 { L"Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL },\r
8a210b9a 150 { L"Global Interrupt Array Ref", 4, 40, L"0x%x", NULL, NULL, NULL,\r
47d20b54
MK
151 NULL },\r
152 { L"Number of context interrupts", 4, 44, L"%d", NULL,\r
153 (VOID **)&InterruptContextCount, NULL, NULL },\r
8a210b9a 154 { L"Context Interrupt Array Ref", 4, 48, L"0x%x", NULL,\r
47d20b54
MK
155 (VOID **)&InterruptContextOffset, NULL, NULL },\r
156 { L"Number of PMU Interrupts", 4, 52, L"%d", NULL,\r
157 (VOID **)&PmuInterruptCount, NULL, NULL },\r
8a210b9a 158 { L"PMU Interrupt Array Ref", 4, 56, L"0x%x", NULL,\r
47d20b54 159 (VOID **)&PmuInterruptOffset, NULL, NULL },\r
ee4dc24f
RN
160\r
161 // Interrupt Array\r
47d20b54
MK
162 { L"SMMU_NSgIrpt", 4, 60, L"0x%x", NULL, NULL, NULL, NULL },\r
163 { L"SMMU_NSgIrpt interrupt flags", 4, 64, L"0x%x", NULL, NULL, NULL, NULL },\r
164 { L"SMMU_NSgCfgIrpt", 4, 68, L"0x%x", NULL, NULL, NULL, NULL },\r
165 { L"SMMU_NSgCfgIrpt interrupt flags",4, 72, L"0x%x", NULL, NULL, NULL, NULL }\r
ee4dc24f
RN
166};\r
167\r
a6eaba4d
DB
168/**\r
169 An ACPI_PARSER array describing the SMMUv1/2 Node Interrupt Array.\r
170**/\r
47d20b54
MK
171STATIC CONST ACPI_PARSER InterruptArrayParser[] = {\r
172 { L"Interrupt GSIV", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },\r
173 { L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }\r
ee4dc24f
RN
174};\r
175\r
a6eaba4d
DB
176/**\r
177 An ACPI_PARSER array describing the IORT ID Mapping.\r
178**/\r
47d20b54
MK
179STATIC CONST ACPI_PARSER IortNodeIdMappingParser[] = {\r
180 { L"Input base", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },\r
181 { L"Number of IDs", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r
182 { L"Output base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL },\r
183 { L"Output reference", 4, 12, L"0x%x", NULL, NULL, NULL, NULL },\r
184 { L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL }\r
ee4dc24f
RN
185};\r
186\r
a6eaba4d
DB
187/**\r
188 An ACPI_PARSER array describing the IORT SMMUv3 node.\r
189**/\r
47d20b54 190STATIC CONST ACPI_PARSER IortNodeSmmuV3Parser[] = {\r
ee4dc24f 191 PARSE_IORT_NODE_HEADER (NULL, NULL),\r
47d20b54
MK
192 { L"Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL },\r
193 { L"Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL },\r
194 { L"Reserved", 4, 28, L"0x%x", NULL, NULL, NULL, NULL },\r
195 { L"VATOS Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL },\r
196 { L"Model", 4, 40, L"%d", NULL, NULL, NULL, NULL },\r
197 { L"Event", 4, 44, L"0x%x", NULL, NULL, NULL, NULL },\r
198 { L"PRI", 4, 48, L"0x%x", NULL, NULL, NULL, NULL },\r
199 { L"GERR", 4, 52, L"0x%x", NULL, NULL, NULL, NULL },\r
200 { L"Sync", 4, 56, L"0x%x", NULL, NULL, NULL, NULL },\r
201 { L"Proximity domain", 4, 60, L"0x%x", NULL, NULL, NULL, NULL },\r
202 { L"Device ID mapping index", 4, 64, L"%d", NULL, NULL, NULL, NULL }\r
ee4dc24f
RN
203};\r
204\r
a6eaba4d
DB
205/**\r
206 An ACPI_PARSER array describing the IORT ITS node.\r
207**/\r
47d20b54 208STATIC CONST ACPI_PARSER IortNodeItsParser[] = {\r
ee4dc24f
RN
209 PARSE_IORT_NODE_HEADER (\r
210 ValidateItsIdMappingCount,\r
211 ValidateItsIdArrayReference\r
212 ),\r
47d20b54 213 { L"Number of ITSs", 4,16, L"%d", NULL, (VOID **)&ItsCount, NULL }\r
ee4dc24f
RN
214};\r
215\r
a6eaba4d
DB
216/**\r
217 An ACPI_PARSER array describing the ITS ID.\r
218**/\r
47d20b54 219STATIC CONST ACPI_PARSER ItsIdParser[] = {\r
5ed3b562 220 { L"GIC ITS Identifier", 4, 0, L"%d", NULL, NULL, NULL }\r
ee4dc24f
RN
221};\r
222\r
a6eaba4d
DB
223/**\r
224 An ACPI_PARSER array describing the IORT Names Component node.\r
225**/\r
47d20b54 226STATIC CONST ACPI_PARSER IortNodeNamedComponentParser[] = {\r
ee4dc24f 227 PARSE_IORT_NODE_HEADER (NULL, NULL),\r
47d20b54
MK
228 { L"Node Flags", 4, 16, L"%d", NULL, NULL, NULL, NULL },\r
229 { L"Memory access properties",8, 20, L"0x%lx", NULL, NULL, NULL, NULL },\r
230 { L"Device memory address size limit",1, 28, L"%d", NULL, NULL, NULL, NULL }\r
ee4dc24f
RN
231};\r
232\r
a6eaba4d
DB
233/**\r
234 An ACPI_PARSER array describing the IORT Root Complex node.\r
235**/\r
47d20b54 236STATIC CONST ACPI_PARSER IortNodeRootComplexParser[] = {\r
ee4dc24f 237 PARSE_IORT_NODE_HEADER (NULL, NULL),\r
47d20b54
MK
238 { L"Memory access properties",8, 16, L"0x%lx", NULL, NULL, NULL, NULL },\r
239 { L"ATS Attribute", 4, 24, L"0x%x", NULL, NULL, NULL, NULL },\r
240 { L"PCI Segment number", 4, 28, L"0x%x", NULL, NULL, NULL, NULL },\r
241 { L"Memory access size limit",1, 32, L"0x%x", NULL, NULL, NULL, NULL },\r
242 { L"Reserved", 3, 33, L"%x %x %x", Dump3Chars, NULL, NULL, NULL }\r
ee4dc24f
RN
243};\r
244\r
a6eaba4d
DB
245/**\r
246 An ACPI_PARSER array describing the IORT PMCG node.\r
247**/\r
47d20b54 248STATIC CONST ACPI_PARSER IortNodePmcgParser[] = {\r
05f8e85f 249 PARSE_IORT_NODE_HEADER (ValidatePmcgIdMappingCount, NULL),\r
47d20b54
MK
250 { L"Page 0 Base Address", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL },\r
251 { L"Overflow interrupt GSIV", 4, 24, L"0x%x", NULL, NULL, NULL, NULL },\r
252 { L"Node reference", 4, 28, L"0x%x", NULL, NULL, NULL, NULL },\r
253 { L"Page 1 Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL }\r
ee4dc24f
RN
254};\r
255\r
a6eaba4d
DB
256/**\r
257 This function parses the IORT Node Id Mapping array.\r
ee4dc24f 258\r
62cefaf4
KK
259 @param [in] Ptr Pointer to the start of the ID mapping array.\r
260 @param [in] Length Length of the buffer.\r
ee4dc24f 261 @param [in] MappingCount The ID Mapping count.\r
a6eaba4d 262**/\r
ee4dc24f
RN
263STATIC\r
264VOID\r
265DumpIortNodeIdMappings (\r
47d20b54
MK
266 IN UINT8 *Ptr,\r
267 IN UINT32 Length,\r
268 IN UINT32 MappingCount\r
ee4dc24f
RN
269 )\r
270{\r
47d20b54
MK
271 UINT32 Index;\r
272 UINT32 Offset;\r
273 CHAR8 Buffer[40]; // Used for AsciiName param of ParseAcpi\r
ee4dc24f 274\r
47d20b54 275 Index = 0;\r
62cefaf4
KK
276 Offset = 0;\r
277\r
278 while ((Index < MappingCount) &&\r
47d20b54
MK
279 (Offset < Length))\r
280 {\r
ee4dc24f
RN
281 AsciiSPrint (\r
282 Buffer,\r
283 sizeof (Buffer),\r
284 "ID Mapping [%d]",\r
285 Index\r
286 );\r
62cefaf4
KK
287 Offset += ParseAcpi (\r
288 TRUE,\r
289 4,\r
290 Buffer,\r
291 Ptr + Offset,\r
292 Length - Offset,\r
293 PARSER_PARAMS (IortNodeIdMappingParser)\r
294 );\r
ee4dc24f
RN
295 Index++;\r
296 }\r
297}\r
298\r
a6eaba4d
DB
299/**\r
300 This function parses the IORT SMMUv1/2 node.\r
ee4dc24f
RN
301\r
302 @param [in] Ptr Pointer to the start of the buffer.\r
303 @param [in] Length Length of the buffer.\r
304 @param [in] MappingCount The ID Mapping count.\r
305 @param [in] MappingOffset The offset of the ID Mapping array\r
306 from the start of the IORT table.\r
a6eaba4d 307**/\r
ee4dc24f
RN
308STATIC\r
309VOID\r
310DumpIortNodeSmmuV1V2 (\r
47d20b54
MK
311 IN UINT8 *Ptr,\r
312 IN UINT16 Length,\r
313 IN UINT32 MappingCount,\r
314 IN UINT32 MappingOffset\r
ee4dc24f
RN
315 )\r
316{\r
47d20b54
MK
317 UINT32 Index;\r
318 UINT32 Offset;\r
319 CHAR8 Buffer[50]; // Used for AsciiName param of ParseAcpi\r
ee4dc24f 320\r
ee4dc24f
RN
321 ParseAcpi (\r
322 TRUE,\r
323 2,\r
324 "SMMUv1 or SMMUv2 Node",\r
325 Ptr,\r
326 Length,\r
327 PARSER_PARAMS (IortNodeSmmuV1V2Parser)\r
328 );\r
329\r
ea26838a
KK
330 // Check if the values used to control the parsing logic have been\r
331 // successfully read.\r
332 if ((InterruptContextCount == NULL) ||\r
333 (InterruptContextOffset == NULL) ||\r
334 (PmuInterruptCount == NULL) ||\r
47d20b54
MK
335 (PmuInterruptOffset == NULL))\r
336 {\r
ea26838a
KK
337 IncrementErrorCount ();\r
338 Print (\r
339 L"ERROR: Insufficient SMMUv1/2 node length. Length = %d\n",\r
340 Length\r
341 );\r
342 return;\r
343 }\r
344\r
62cefaf4 345 Offset = *InterruptContextOffset;\r
47d20b54 346 Index = 0;\r
62cefaf4
KK
347\r
348 while ((Index < *InterruptContextCount) &&\r
47d20b54
MK
349 (Offset < Length))\r
350 {\r
ee4dc24f
RN
351 AsciiSPrint (\r
352 Buffer,\r
353 sizeof (Buffer),\r
354 "Context Interrupts Array [%d]",\r
355 Index\r
356 );\r
62cefaf4
KK
357 Offset += ParseAcpi (\r
358 TRUE,\r
359 4,\r
360 Buffer,\r
361 Ptr + Offset,\r
362 Length - Offset,\r
363 PARSER_PARAMS (InterruptArrayParser)\r
364 );\r
ee4dc24f
RN
365 Index++;\r
366 }\r
367\r
62cefaf4 368 Offset = *PmuInterruptOffset;\r
47d20b54 369 Index = 0;\r
62cefaf4
KK
370\r
371 while ((Index < *PmuInterruptCount) &&\r
47d20b54
MK
372 (Offset < Length))\r
373 {\r
ee4dc24f
RN
374 AsciiSPrint (\r
375 Buffer,\r
376 sizeof (Buffer),\r
377 "PMU Interrupts Array [%d]",\r
378 Index\r
379 );\r
62cefaf4
KK
380 Offset += ParseAcpi (\r
381 TRUE,\r
382 4,\r
383 Buffer,\r
384 Ptr + Offset,\r
385 Length - Offset,\r
386 PARSER_PARAMS (InterruptArrayParser)\r
387 );\r
ee4dc24f
RN
388 Index++;\r
389 }\r
390\r
62cefaf4
KK
391 DumpIortNodeIdMappings (\r
392 Ptr + MappingOffset,\r
393 Length - MappingOffset,\r
394 MappingCount\r
395 );\r
ee4dc24f
RN
396}\r
397\r
a6eaba4d
DB
398/**\r
399 This function parses the IORT SMMUv3 node.\r
ee4dc24f
RN
400\r
401 @param [in] Ptr Pointer to the start of the buffer.\r
402 @param [in] Length Length of the buffer.\r
403 @param [in] MappingCount The ID Mapping count.\r
404 @param [in] MappingOffset The offset of the ID Mapping array\r
405 from the start of the IORT table.\r
a6eaba4d 406**/\r
ee4dc24f
RN
407STATIC\r
408VOID\r
409DumpIortNodeSmmuV3 (\r
47d20b54
MK
410 IN UINT8 *Ptr,\r
411 IN UINT16 Length,\r
412 IN UINT32 MappingCount,\r
413 IN UINT32 MappingOffset\r
ee4dc24f
RN
414 )\r
415{\r
416 ParseAcpi (\r
417 TRUE,\r
418 2,\r
419 "SMMUV3 Node",\r
420 Ptr,\r
421 Length,\r
422 PARSER_PARAMS (IortNodeSmmuV3Parser)\r
423 );\r
424\r
62cefaf4
KK
425 DumpIortNodeIdMappings (\r
426 Ptr + MappingOffset,\r
427 Length - MappingOffset,\r
428 MappingCount\r
429 );\r
ee4dc24f
RN
430}\r
431\r
a6eaba4d
DB
432/**\r
433 This function parses the IORT ITS node.\r
ee4dc24f
RN
434\r
435 @param [in] Ptr Pointer to the start of the buffer.\r
436 @param [in] Length Length of the buffer.\r
a6eaba4d 437**/\r
ee4dc24f
RN
438STATIC\r
439VOID\r
440DumpIortNodeIts (\r
47d20b54
MK
441 IN UINT8 *Ptr,\r
442 IN UINT16 Length\r
ee4dc24f
RN
443 )\r
444{\r
47d20b54
MK
445 UINT32 Offset;\r
446 UINT32 Index;\r
447 CHAR8 Buffer[80]; // Used for AsciiName param of ParseAcpi\r
ee4dc24f
RN
448\r
449 Offset = ParseAcpi (\r
47d20b54
MK
450 TRUE,\r
451 2,\r
452 "ITS Node",\r
453 Ptr,\r
454 Length,\r
455 PARSER_PARAMS (IortNodeItsParser)\r
456 );\r
ee4dc24f 457\r
ea26838a
KK
458 // Check if the values used to control the parsing logic have been\r
459 // successfully read.\r
460 if (ItsCount == NULL) {\r
461 IncrementErrorCount ();\r
462 Print (\r
463 L"ERROR: Insufficient ITS group length. Length = %d.\n",\r
464 Length\r
465 );\r
466 return;\r
467 }\r
468\r
ee4dc24f 469 Index = 0;\r
62cefaf4
KK
470\r
471 while ((Index < *ItsCount) &&\r
47d20b54
MK
472 (Offset < Length))\r
473 {\r
ee4dc24f
RN
474 AsciiSPrint (\r
475 Buffer,\r
476 sizeof (Buffer),\r
477 "GIC ITS Identifier Array [%d]",\r
478 Index\r
479 );\r
62cefaf4
KK
480 Offset += ParseAcpi (\r
481 TRUE,\r
482 4,\r
483 Buffer,\r
484 Ptr + Offset,\r
485 Length - Offset,\r
486 PARSER_PARAMS (ItsIdParser)\r
487 );\r
ee4dc24f
RN
488 Index++;\r
489 }\r
490\r
491 // Note: ITS does not have the ID Mappings Array\r
492}\r
493\r
a6eaba4d
DB
494/**\r
495 This function parses the IORT Named Component node.\r
ee4dc24f
RN
496\r
497 @param [in] Ptr Pointer to the start of the buffer.\r
498 @param [in] Length Length of the buffer.\r
499 @param [in] MappingCount The ID Mapping count.\r
500 @param [in] MappingOffset The offset of the ID Mapping array\r
501 from the start of the IORT table.\r
a6eaba4d 502**/\r
ee4dc24f
RN
503STATIC\r
504VOID\r
505DumpIortNodeNamedComponent (\r
47d20b54
MK
506 IN UINT8 *Ptr,\r
507 IN UINT16 Length,\r
508 IN UINT32 MappingCount,\r
509 IN UINT32 MappingOffset\r
ee4dc24f
RN
510 )\r
511{\r
47d20b54 512 UINT32 Offset;\r
ee4dc24f
RN
513\r
514 Offset = ParseAcpi (\r
515 TRUE,\r
516 2,\r
517 "Named Component Node",\r
518 Ptr,\r
519 Length,\r
520 PARSER_PARAMS (IortNodeNamedComponentParser)\r
521 );\r
522\r
ee4dc24f 523 // Estimate the Device Name length\r
ee4dc24f 524 PrintFieldName (2, L"Device Object Name");\r
62cefaf4
KK
525\r
526 while ((*(Ptr + Offset) != 0) &&\r
47d20b54
MK
527 (Offset < Length))\r
528 {\r
62cefaf4
KK
529 Print (L"%c", *(Ptr + Offset));\r
530 Offset++;\r
ee4dc24f 531 }\r
47d20b54 532\r
ee4dc24f
RN
533 Print (L"\n");\r
534\r
62cefaf4
KK
535 DumpIortNodeIdMappings (\r
536 Ptr + MappingOffset,\r
537 Length - MappingOffset,\r
538 MappingCount\r
539 );\r
ee4dc24f
RN
540}\r
541\r
a6eaba4d
DB
542/**\r
543 This function parses the IORT Root Complex node.\r
ee4dc24f
RN
544\r
545 @param [in] Ptr Pointer to the start of the buffer.\r
546 @param [in] Length Length of the buffer.\r
547 @param [in] MappingCount The ID Mapping count.\r
548 @param [in] MappingOffset The offset of the ID Mapping array\r
549 from the start of the IORT table.\r
a6eaba4d 550**/\r
ee4dc24f
RN
551STATIC\r
552VOID\r
553DumpIortNodeRootComplex (\r
47d20b54
MK
554 IN UINT8 *Ptr,\r
555 IN UINT16 Length,\r
556 IN UINT32 MappingCount,\r
557 IN UINT32 MappingOffset\r
ee4dc24f
RN
558 )\r
559{\r
560 ParseAcpi (\r
561 TRUE,\r
562 2,\r
563 "Root Complex Node",\r
564 Ptr,\r
565 Length,\r
566 PARSER_PARAMS (IortNodeRootComplexParser)\r
567 );\r
568\r
62cefaf4
KK
569 DumpIortNodeIdMappings (\r
570 Ptr + MappingOffset,\r
571 Length - MappingOffset,\r
572 MappingCount\r
573 );\r
ee4dc24f
RN
574}\r
575\r
a6eaba4d
DB
576/**\r
577 This function parses the IORT PMCG node.\r
ee4dc24f
RN
578\r
579 @param [in] Ptr Pointer to the start of the buffer.\r
580 @param [in] Length Length of the buffer.\r
581 @param [in] MappingCount The ID Mapping count.\r
582 @param [in] MappingOffset The offset of the ID Mapping array\r
583 from the start of the IORT table.\r
a6eaba4d 584**/\r
ee4dc24f
RN
585STATIC\r
586VOID\r
587DumpIortNodePmcg (\r
47d20b54
MK
588 IN UINT8 *Ptr,\r
589 IN UINT16 Length,\r
590 IN UINT32 MappingCount,\r
591 IN UINT32 MappingOffset\r
592 )\r
ee4dc24f
RN
593{\r
594 ParseAcpi (\r
595 TRUE,\r
596 2,\r
597 "PMCG Node",\r
598 Ptr,\r
599 Length,\r
600 PARSER_PARAMS (IortNodePmcgParser)\r
62cefaf4 601 );\r
ee4dc24f 602\r
62cefaf4
KK
603 DumpIortNodeIdMappings (\r
604 Ptr + MappingOffset,\r
605 Length - MappingOffset,\r
606 MappingCount\r
607 );\r
ee4dc24f
RN
608}\r
609\r
a6eaba4d
DB
610/**\r
611 This function parses the ACPI IORT table.\r
612 When trace is enabled this function parses the IORT table and traces the ACPI fields.\r
ee4dc24f
RN
613\r
614 This function also parses the following nodes:\r
615 - ITS Group\r
616 - Named Component\r
617 - Root Complex\r
618 - SMMUv1/2\r
619 - SMMUv3\r
620 - PMCG\r
621\r
622 This function also performs validation of the ACPI table fields.\r
623\r
624 @param [in] Trace If TRUE, trace the ACPI fields.\r
625 @param [in] Ptr Pointer to the start of the buffer.\r
626 @param [in] AcpiTableLength Length of the ACPI table.\r
627 @param [in] AcpiTableRevision Revision of the ACPI table.\r
a6eaba4d 628**/\r
ee4dc24f
RN
629VOID\r
630EFIAPI\r
631ParseAcpiIort (\r
47d20b54
MK
632 IN BOOLEAN Trace,\r
633 IN UINT8 *Ptr,\r
634 IN UINT32 AcpiTableLength,\r
635 IN UINT8 AcpiTableRevision\r
ee4dc24f
RN
636 )\r
637{\r
47d20b54
MK
638 UINT32 Offset;\r
639 UINT32 Index;\r
640 UINT8 *NodePtr;\r
ee4dc24f
RN
641\r
642 if (!Trace) {\r
643 return;\r
644 }\r
645\r
646 ParseAcpi (\r
647 TRUE,\r
648 0,\r
649 "IORT",\r
650 Ptr,\r
651 AcpiTableLength,\r
652 PARSER_PARAMS (IortParser)\r
653 );\r
62cefaf4 654\r
ea26838a
KK
655 // Check if the values used to control the parsing logic have been\r
656 // successfully read.\r
657 if ((IortNodeCount == NULL) ||\r
47d20b54
MK
658 (IortNodeOffset == NULL))\r
659 {\r
ea26838a
KK
660 IncrementErrorCount ();\r
661 Print (\r
662 L"ERROR: Insufficient table length. AcpiTableLength = %d.\n",\r
663 AcpiTableLength\r
664 );\r
665 return;\r
666 }\r
667\r
47d20b54 668 Offset = *IortNodeOffset;\r
ee4dc24f 669 NodePtr = Ptr + Offset;\r
47d20b54 670 Index = 0;\r
ee4dc24f 671\r
62cefaf4
KK
672 // Parse the specified number of IORT nodes or the IORT table buffer length.\r
673 // Whichever is minimum.\r
674 while ((Index++ < *IortNodeCount) &&\r
47d20b54
MK
675 (Offset < AcpiTableLength))\r
676 {\r
ee4dc24f
RN
677 // Parse the IORT Node Header\r
678 ParseAcpi (\r
679 FALSE,\r
680 0,\r
681 "IORT Node Header",\r
682 NodePtr,\r
62cefaf4 683 AcpiTableLength - Offset,\r
ee4dc24f
RN
684 PARSER_PARAMS (IortNodeHeaderParser)\r
685 );\r
62cefaf4 686\r
ea26838a
KK
687 // Check if the values used to control the parsing logic have been\r
688 // successfully read.\r
689 if ((IortNodeType == NULL) ||\r
690 (IortNodeLength == NULL) ||\r
691 (IortIdMappingCount == NULL) ||\r
47d20b54
MK
692 (IortIdMappingOffset == NULL))\r
693 {\r
ea26838a
KK
694 IncrementErrorCount ();\r
695 Print (\r
696 L"ERROR: Insufficient remaining table buffer length to read the " \\r
47d20b54 697 L"IORT node header. Length = %d.\n",\r
ea26838a
KK
698 AcpiTableLength - Offset\r
699 );\r
700 return;\r
701 }\r
702\r
b8504826
KK
703 // Validate IORT Node length\r
704 if ((*IortNodeLength == 0) ||\r
47d20b54
MK
705 ((Offset + (*IortNodeLength)) > AcpiTableLength))\r
706 {\r
ee4dc24f 707 IncrementErrorCount ();\r
62cefaf4 708 Print (\r
b8504826 709 L"ERROR: Invalid IORT Node length. " \\r
47d20b54 710 L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r
62cefaf4 711 *IortNodeLength,\r
b8504826
KK
712 Offset,\r
713 AcpiTableLength\r
62cefaf4 714 );\r
ee4dc24f
RN
715 return;\r
716 }\r
717\r
718 PrintFieldName (2, L"* Node Offset *");\r
719 Print (L"0x%x\n", Offset);\r
720\r
721 switch (*IortNodeType) {\r
f17dad04 722 case EFI_ACPI_IORT_TYPE_ITS_GROUP:\r
ee4dc24f
RN
723 DumpIortNodeIts (\r
724 NodePtr,\r
725 *IortNodeLength\r
726 );\r
727 break;\r
f17dad04 728 case EFI_ACPI_IORT_TYPE_NAMED_COMP:\r
ee4dc24f
RN
729 DumpIortNodeNamedComponent (\r
730 NodePtr,\r
731 *IortNodeLength,\r
732 *IortIdMappingCount,\r
733 *IortIdMappingOffset\r
734 );\r
735 break;\r
f17dad04 736 case EFI_ACPI_IORT_TYPE_ROOT_COMPLEX:\r
ee4dc24f
RN
737 DumpIortNodeRootComplex (\r
738 NodePtr,\r
739 *IortNodeLength,\r
740 *IortIdMappingCount,\r
741 *IortIdMappingOffset\r
742 );\r
743 break;\r
f17dad04 744 case EFI_ACPI_IORT_TYPE_SMMUv1v2:\r
ee4dc24f
RN
745 DumpIortNodeSmmuV1V2 (\r
746 NodePtr,\r
747 *IortNodeLength,\r
748 *IortIdMappingCount,\r
749 *IortIdMappingOffset\r
750 );\r
751 break;\r
f17dad04 752 case EFI_ACPI_IORT_TYPE_SMMUv3:\r
ee4dc24f
RN
753 DumpIortNodeSmmuV3 (\r
754 NodePtr,\r
755 *IortNodeLength,\r
756 *IortIdMappingCount,\r
757 *IortIdMappingOffset\r
758 );\r
759 break;\r
f17dad04 760 case EFI_ACPI_IORT_TYPE_PMCG:\r
ee4dc24f
RN
761 DumpIortNodePmcg (\r
762 NodePtr,\r
763 *IortNodeLength,\r
764 *IortIdMappingCount,\r
765 *IortIdMappingOffset\r
47d20b54 766 );\r
ee4dc24f
RN
767 break;\r
768\r
769 default:\r
770 IncrementErrorCount ();\r
771 Print (L"ERROR: Unsupported IORT Node type = %d\n", *IortNodeType);\r
772 } // switch\r
773\r
774 NodePtr += (*IortNodeLength);\r
47d20b54 775 Offset += (*IortNodeLength);\r
ee4dc24f
RN
776 } // while\r
777}\r