]>
Commit | Line | Data |
---|---|---|
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 | |
24 | STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r | |
25 | \r | |
26 | /** The EIORT_NODE enum describes the IORT Node types.\r | |
27 | */\r | |
28 | typedef 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 | |
39 | STATIC CONST UINT32* IortNodeCount;\r | |
40 | STATIC CONST UINT32* IortNodeOffset;\r | |
41 | \r | |
42 | STATIC CONST UINT8* IortNodeType;\r | |
43 | STATIC CONST UINT16* IortNodeLength;\r | |
44 | STATIC CONST UINT32* IortIdMappingCount;\r | |
45 | STATIC CONST UINT32* IortIdMappingOffset;\r | |
46 | \r | |
47 | STATIC CONST UINT32* InterruptContextCount;\r | |
48 | STATIC CONST UINT32* InterruptContextOffset;\r | |
49 | STATIC CONST UINT32* PmuInterruptCount;\r | |
50 | STATIC CONST UINT32* PmuInterruptOffset;\r | |
51 | \r | |
52 | STATIC 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 | |
60 | STATIC\r | |
61 | VOID\r | |
62 | EFIAPI\r | |
63 | ValidateItsIdMappingCount (\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 | |
74 | STATIC\r | |
75 | VOID\r | |
76 | EFIAPI\r | |
77 | ValidateItsIdArrayReference (\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 | |
103 | STATIC 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 | |
114 | STATIC 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 | |
120 | STATIC 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 | |
146 | STATIC 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 | |
153 | STATIC 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 | |
163 | STATIC 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 | |
178 | STATIC 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 | |
188 | STATIC 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 | |
194 | STATIC 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 | |
203 | STATIC 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 | |
212 | STATIC 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 | |
225 | STATIC\r | |
226 | VOID\r | |
227 | EFIAPI\r | |
228 | ValidateItsIdMappingCount (\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 | |
245 | STATIC\r | |
246 | VOID\r | |
247 | EFIAPI\r | |
248 | ValidateItsIdArrayReference (\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 | |
266 | STATIC\r | |
267 | VOID\r | |
268 | DumpIortNodeIdMappings (\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 | |
309 | STATIC\r | |
310 | VOID\r | |
311 | DumpIortNodeSmmuV1V2 (\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 | |
388 | STATIC\r | |
389 | VOID\r | |
390 | DumpIortNodeSmmuV3 (\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 | |
416 | STATIC\r | |
417 | VOID\r | |
418 | DumpIortNodeIts (\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 | |
469 | STATIC\r | |
470 | VOID\r | |
471 | DumpIortNodeNamedComponent (\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 | |
515 | STATIC\r | |
516 | VOID\r | |
517 | DumpIortNodeRootComplex (\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 | |
546 | STATIC\r | |
547 | VOID\r | |
548 | DumpIortNodePmcg (\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 | |
596 | VOID\r | |
597 | EFIAPI\r | |
598 | ParseAcpiIort (\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 |