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