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