]>
Commit | Line | Data |
---|---|---|
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 | |
24 | STATIC 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 | 29 | typedef 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 | |
40 | STATIC CONST UINT32* IortNodeCount;\r | |
41 | STATIC CONST UINT32* IortNodeOffset;\r | |
42 | \r | |
43 | STATIC CONST UINT8* IortNodeType;\r | |
44 | STATIC CONST UINT16* IortNodeLength;\r | |
45 | STATIC CONST UINT32* IortIdMappingCount;\r | |
46 | STATIC CONST UINT32* IortIdMappingOffset;\r | |
47 | \r | |
48 | STATIC CONST UINT32* InterruptContextCount;\r | |
49 | STATIC CONST UINT32* InterruptContextOffset;\r | |
50 | STATIC CONST UINT32* PmuInterruptCount;\r | |
51 | STATIC CONST UINT32* PmuInterruptOffset;\r | |
52 | \r | |
53 | STATIC 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 |
62 | STATIC\r |
63 | VOID\r | |
64 | EFIAPI\r | |
65 | ValidateItsIdMappingCount (\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 |
77 | STATIC\r |
78 | VOID\r | |
79 | EFIAPI\r | |
80 | ValidateItsIdArrayReference (\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 |
107 | STATIC 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 |
119 | STATIC 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 |
126 | STATIC 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 |
153 | STATIC 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 |
161 | STATIC 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 |
172 | STATIC 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 |
188 | STATIC 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 |
199 | STATIC 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 |
206 | STATIC 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 |
216 | STATIC 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 |
226 | STATIC 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 |
240 | STATIC\r |
241 | VOID\r | |
242 | EFIAPI\r | |
243 | ValidateItsIdMappingCount (\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 |
261 | STATIC\r |
262 | VOID\r | |
263 | EFIAPI\r | |
264 | ValidateItsIdArrayReference (\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 |
283 | STATIC\r |
284 | VOID\r | |
285 | DumpIortNodeIdMappings (\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 |
327 | STATIC\r |
328 | VOID\r | |
329 | DumpIortNodeSmmuV1V2 (\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 |
407 | STATIC\r |
408 | VOID\r | |
409 | DumpIortNodeSmmuV3 (\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 |
436 | STATIC\r |
437 | VOID\r | |
438 | DumpIortNodeIts (\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 |
490 | STATIC\r |
491 | VOID\r | |
492 | DumpIortNodeNamedComponent (\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 |
537 | STATIC\r |
538 | VOID\r | |
539 | DumpIortNodeRootComplex (\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 |
569 | STATIC\r |
570 | VOID\r | |
571 | DumpIortNodePmcg (\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 |
619 | VOID\r |
620 | EFIAPI\r | |
621 | ParseAcpiIort (\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 |