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