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