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