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