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