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