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