]>
Commit | Line | Data |
---|---|---|
a6eaba4d | 1 | /** @file\r |
ee4dc24f RN |
2 | MADT table parser\r |
3 | \r | |
b8504826 | 4 | Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.\r |
d5fd86f2 | 5 | Copyright (c) 2022, AMD Incorporated. All rights reserved.\r |
56ba3746 | 6 | SPDX-License-Identifier: BSD-2-Clause-Patent\r |
ee4dc24f RN |
7 | \r |
8 | @par Reference(s):\r | |
8a08dc54 KK |
9 | - ACPI 6.3 Specification - January 2019\r |
10 | - Arm Generic Interrupt Controller Architecture Specification,\r | |
11 | GIC architecture version 3 and version 4, issue E\r | |
12 | - Arm Server Base System Architecture 5.0\r | |
ee4dc24f RN |
13 | **/\r |
14 | \r | |
15 | #include <IndustryStandard/Acpi.h>\r | |
16 | #include <Library/UefiLib.h>\r | |
17 | #include "AcpiParser.h"\r | |
18 | #include "AcpiTableParser.h"\r | |
e18ac66d | 19 | #include "AcpiViewConfig.h"\r |
8a08dc54 | 20 | #include "MadtParser.h"\r |
ee4dc24f RN |
21 | \r |
22 | // Local Variables\r | |
47d20b54 MK |
23 | STATIC CONST UINT8 *MadtInterruptControllerType;\r |
24 | STATIC CONST UINT8 *MadtInterruptControllerLength;\r | |
25 | STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r | |
ee4dc24f | 26 | \r |
a6eaba4d DB |
27 | /**\r |
28 | This function validates the System Vector Base in the GICD.\r | |
29 | \r | |
30 | @param [in] Ptr Pointer to the start of the field data.\r | |
31 | @param [in] Context Pointer to context specific information e.g. this\r | |
32 | could be a pointer to the ACPI table header.\r | |
33 | **/\r | |
ee4dc24f RN |
34 | STATIC\r |
35 | VOID\r | |
36 | EFIAPI\r | |
37 | ValidateGICDSystemVectorBase (\r | |
47d20b54 MK |
38 | IN UINT8 *Ptr,\r |
39 | IN VOID *Context\r | |
40 | )\r | |
9cb5bcce | 41 | {\r |
47d20b54 | 42 | if (*(UINT32 *)Ptr != 0) {\r |
9cb5bcce KK |
43 | IncrementErrorCount ();\r |
44 | Print (\r | |
45 | L"\nERROR: System Vector Base must be zero."\r | |
47d20b54 | 46 | );\r |
9cb5bcce KK |
47 | }\r |
48 | }\r | |
ee4dc24f | 49 | \r |
8a08dc54 KK |
50 | /**\r |
51 | This function validates the SPE Overflow Interrupt in the GICC.\r | |
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 | |
56 | **/\r | |
57 | STATIC\r | |
58 | VOID\r | |
59 | EFIAPI\r | |
60 | ValidateSpeOverflowInterrupt (\r | |
47d20b54 MK |
61 | IN UINT8 *Ptr,\r |
62 | IN VOID *Context\r | |
9cb5bcce KK |
63 | )\r |
64 | {\r | |
47d20b54 | 65 | UINT16 SpeOverflowInterrupt;\r |
9cb5bcce | 66 | \r |
47d20b54 | 67 | SpeOverflowInterrupt = *(UINT16 *)Ptr;\r |
9cb5bcce KK |
68 | \r |
69 | // SPE not supported by this processor\r | |
70 | if (SpeOverflowInterrupt == 0) {\r | |
71 | return;\r | |
72 | }\r | |
73 | \r | |
74 | if ((SpeOverflowInterrupt < ARM_PPI_ID_MIN) ||\r | |
75 | ((SpeOverflowInterrupt > ARM_PPI_ID_MAX) &&\r | |
76 | (SpeOverflowInterrupt < ARM_PPI_ID_EXTENDED_MIN)) ||\r | |
47d20b54 MK |
77 | (SpeOverflowInterrupt > ARM_PPI_ID_EXTENDED_MAX))\r |
78 | {\r | |
9cb5bcce KK |
79 | IncrementErrorCount ();\r |
80 | Print (\r | |
81 | L"\nERROR: SPE Overflow Interrupt ID of %d is not in the allowed PPI ID "\r | |
47d20b54 | 82 | L"ranges of %d-%d or %d-%d (for GICv3.1 or later).",\r |
9cb5bcce KK |
83 | SpeOverflowInterrupt,\r |
84 | ARM_PPI_ID_MIN,\r | |
85 | ARM_PPI_ID_MAX,\r | |
86 | ARM_PPI_ID_EXTENDED_MIN,\r | |
87 | ARM_PPI_ID_EXTENDED_MAX\r | |
47d20b54 | 88 | );\r |
9cb5bcce | 89 | } else if (SpeOverflowInterrupt != ARM_PPI_ID_PMBIRQ) {\r |
47d20b54 | 90 | IncrementWarningCount ();\r |
9cb5bcce KK |
91 | Print (\r |
92 | L"\nWARNING: SPE Overflow Interrupt ID of %d is not compliant with SBSA "\r | |
47d20b54 | 93 | L"Level 3 PPI ID assignment: %d.",\r |
9cb5bcce KK |
94 | SpeOverflowInterrupt,\r |
95 | ARM_PPI_ID_PMBIRQ\r | |
47d20b54 | 96 | );\r |
9cb5bcce KK |
97 | }\r |
98 | }\r | |
8a08dc54 | 99 | \r |
a6eaba4d DB |
100 | /**\r |
101 | An ACPI_PARSER array describing the GICC Interrupt Controller Structure.\r | |
102 | **/\r | |
47d20b54 MK |
103 | STATIC CONST ACPI_PARSER GicCParser[] = {\r |
104 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
105 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
106 | { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
107 | \r | |
108 | { L"CPU Interface Number", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r | |
109 | { L"ACPI Processor UID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL },\r | |
110 | { L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL },\r | |
111 | { L"Parking Protocol Version", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },\r | |
112 | \r | |
113 | { L"Performance Interrupt GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },\r | |
114 | { L"Parked Address", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL },\r | |
115 | { L"Physical Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL },\r | |
116 | { L"GICV", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL },\r | |
117 | { L"GICH", 8, 48, L"0x%lx", NULL, NULL, NULL, NULL },\r | |
118 | { L"VGIC Maintenance interrupt", 4, 56, L"0x%x", NULL, NULL, NULL, NULL },\r | |
119 | { L"GICR Base Address", 8, 60, L"0x%lx", NULL, NULL, NULL, NULL },\r | |
120 | { L"MPIDR", 8, 68, L"0x%lx", NULL, NULL, NULL, NULL },\r | |
121 | { L"Processor Power Efficiency Class", 1, 76, L"0x%x", NULL, NULL, NULL,\r | |
122 | NULL },\r | |
123 | { L"Reserved", 1, 77, L"0x%x", NULL, NULL, NULL, NULL },\r | |
124 | { L"SPE overflow Interrupt", 2, 78, L"0x%x", NULL, NULL,\r | |
125 | ValidateSpeOverflowInterrupt, NULL }\r | |
ee4dc24f RN |
126 | };\r |
127 | \r | |
a6eaba4d DB |
128 | /**\r |
129 | An ACPI_PARSER array describing the GICD Interrupt Controller Structure.\r | |
130 | **/\r | |
47d20b54 MK |
131 | STATIC CONST ACPI_PARSER GicDParser[] = {\r |
132 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
133 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
134 | { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
135 | \r | |
136 | { L"GIC ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r | |
137 | { L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },\r | |
138 | { L"System Vector Base", 4, 16, L"0x%x", NULL, NULL,\r | |
139 | ValidateGICDSystemVectorBase, NULL },\r | |
140 | { L"GIC Version", 1, 20, L"%d", NULL, NULL, NULL, NULL },\r | |
141 | { L"Reserved", 3, 21, L"%x %x %x", Dump3Chars, NULL, NULL, NULL }\r | |
ee4dc24f RN |
142 | };\r |
143 | \r | |
a6eaba4d DB |
144 | /**\r |
145 | An ACPI_PARSER array describing the MSI Frame Interrupt Controller Structure.\r | |
146 | **/\r | |
47d20b54 MK |
147 | STATIC CONST ACPI_PARSER GicMSIFrameParser[] = {\r |
148 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
149 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
150 | { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
ee4dc24f | 151 | \r |
47d20b54 MK |
152 | { L"MSI Frame ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r |
153 | { L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },\r | |
154 | { L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL },\r | |
ee4dc24f | 155 | \r |
47d20b54 MK |
156 | { L"SPI Count", 2, 20, L"%d", NULL, NULL, NULL, NULL },\r |
157 | { L"SPI Base", 2, 22, L"0x%x", NULL, NULL, NULL, NULL }\r | |
ee4dc24f RN |
158 | };\r |
159 | \r | |
a6eaba4d DB |
160 | /**\r |
161 | An ACPI_PARSER array describing the GICR Interrupt Controller Structure.\r | |
162 | **/\r | |
47d20b54 MK |
163 | STATIC CONST ACPI_PARSER GicRParser[] = {\r |
164 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
165 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
166 | { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
167 | \r | |
168 | { L"Discovery Range Base Address", 8, 4, L"0x%lx", NULL, NULL, NULL,\r | |
169 | NULL },\r | |
170 | { L"Discovery Range Length", 4, 12, 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 GIC ITS Interrupt Controller Structure.\r | |
175 | **/\r | |
47d20b54 MK |
176 | STATIC CONST ACPI_PARSER GicITSParser[] = {\r |
177 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
178 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
179 | { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
180 | \r | |
181 | { L"GIC ITS ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r | |
182 | { L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },\r | |
183 | { L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL }\r | |
ee4dc24f RN |
184 | };\r |
185 | \r | |
2f286930 ALA |
186 | /**\r |
187 | An ACPI_PARSER array describing the IO APIC Structure.\r | |
188 | **/\r | |
47d20b54 MK |
189 | STATIC CONST ACPI_PARSER IoApic[] = {\r |
190 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
191 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
192 | { L"I/O APIC ID", 1, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
193 | { L"Reserved", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },\r | |
194 | { L"I/O APIC Address", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r | |
195 | { L"Global System Interrupt Base", 4, 8, L"0x%x", NULL, NULL, NULL, NULL }\r | |
2f286930 ALA |
196 | };\r |
197 | \r | |
198 | /**\r | |
199 | An ACPI_PARSER array describing the Interrupt Source Override Structure.\r | |
200 | **/\r | |
47d20b54 MK |
201 | STATIC CONST ACPI_PARSER InterruptSourceOverride[] = {\r |
202 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
203 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
204 | { L"Bus", 1, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
205 | { L"Source", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },\r | |
206 | { L"Global System Interrupt", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r | |
207 | { L"Flags", 2, 8, L"0x%x", NULL, NULL, NULL, NULL }\r | |
2f286930 ALA |
208 | };\r |
209 | \r | |
d5fd86f2 ALA |
210 | STATIC CONST ACPI_PARSER LocalApicFlags[] = {\r |
211 | { L"Enabled", 1, 0, L"%d", NULL, NULL, NULL, NULL },\r | |
212 | { L"Online Capable", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
213 | { L"Reserved", 30, 2, L"%d", NULL, NULL, NULL, NULL }\r | |
214 | };\r | |
215 | \r | |
216 | /**\r | |
217 | This function traces Bit Flags fields.\r | |
218 | If no format string is specified the Format must be NULL.\r | |
219 | \r | |
220 | @param [in] Format Optional format string for tracing the data.\r | |
221 | @param [in] Ptr Pointer to the start of the buffer.\r | |
222 | **/\r | |
223 | VOID\r | |
224 | EFIAPI\r | |
225 | DumpLocalApicBitFlags (\r | |
226 | IN CONST CHAR16 *Format OPTIONAL,\r | |
227 | IN UINT8 *Ptr\r | |
228 | )\r | |
229 | {\r | |
230 | if (Format != NULL) {\r | |
231 | Print (Format, *(UINT32 *)Ptr);\r | |
232 | return;\r | |
233 | }\r | |
234 | \r | |
235 | Print (L"0x%X\n", *(UINT32 *)Ptr);\r | |
236 | ParseAcpiBitFields (\r | |
237 | TRUE,\r | |
238 | 2,\r | |
239 | NULL,\r | |
240 | Ptr,\r | |
241 | 4,\r | |
242 | PARSER_PARAMS (LocalApicFlags)\r | |
243 | );\r | |
244 | }\r | |
245 | \r | |
246 | /**\r | |
247 | An ACPI_PARSER array describing the Processor Local APIC Structure.\r | |
248 | **/\r | |
249 | STATIC CONST ACPI_PARSER ProcessorLocalApic[] = {\r | |
250 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
251 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
252 | \r | |
253 | { L"ACPI Processor UID", 1, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
254 | { L"APIC ID", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },\r | |
255 | { L"Flags", 4, 4, NULL, DumpLocalApicBitFlags, NULL, NULL, NULL }\r | |
256 | };\r | |
257 | \r | |
2f286930 ALA |
258 | /**\r |
259 | An ACPI_PARSER array describing the Processor Local x2APIC Structure.\r | |
260 | **/\r | |
47d20b54 | 261 | STATIC CONST ACPI_PARSER ProcessorLocalX2Apic[] = {\r |
d5fd86f2 ALA |
262 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r |
263 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
264 | { L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
47d20b54 | 265 | \r |
d5fd86f2 ALA |
266 | { L"X2APIC ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r |
267 | { L"Flags", 4, 8, NULL, DumpLocalApicBitFlags, NULL, NULL, NULL },\r | |
268 | { L"ACPI Processor UID", 4, 12, L"0x%x", NULL, NULL, NULL, NULL }\r | |
2f286930 ALA |
269 | };\r |
270 | \r | |
271 | /**\r | |
272 | An ACPI_PARSER array describing the Local x2APIC NMI Structure.\r | |
273 | **/\r | |
47d20b54 MK |
274 | STATIC CONST ACPI_PARSER LocalX2ApicNmi[] = {\r |
275 | { L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r | |
276 | { L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r | |
277 | { L"Flags", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },\r | |
278 | \r | |
279 | { L"ACPI Processor UID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL },\r | |
280 | { L"Local x2APIC LINT#", 1, 8, L"0x%x", NULL, NULL, NULL, NULL },\r | |
281 | { L"Reserved", 3, 9, L"0x%x%x%x", Dump3Chars, NULL, NULL, NULL }\r | |
2f286930 ALA |
282 | };\r |
283 | \r | |
a6eaba4d DB |
284 | /**\r |
285 | An ACPI_PARSER array describing the ACPI MADT Table.\r | |
286 | **/\r | |
47d20b54 | 287 | STATIC CONST ACPI_PARSER MadtParser[] = {\r |
ee4dc24f | 288 | PARSE_ACPI_HEADER (&AcpiHdrInfo),\r |
47d20b54 MK |
289 | { L"Local Interrupt Controller Address",4, 36, L"0x%x", NULL, NULL, NULL,\r |
290 | NULL },\r | |
291 | { L"Flags", 4, 40, L"0x%x", NULL, NULL, NULL,NULL}\r | |
ee4dc24f RN |
292 | };\r |
293 | \r | |
a6eaba4d DB |
294 | /**\r |
295 | An ACPI_PARSER array describing the MADT Interrupt Controller Structure Header Structure.\r | |
296 | **/\r | |
47d20b54 MK |
297 | STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser[] = {\r |
298 | { NULL, 1, 0, NULL, NULL, (VOID **)&MadtInterruptControllerType, NULL, NULL },\r | |
299 | { L"Length", 1, 1, NULL, NULL, (VOID **)&MadtInterruptControllerLength, NULL,\r | |
300 | NULL },\r | |
301 | { L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL }\r | |
ee4dc24f RN |
302 | };\r |
303 | \r | |
a6eaba4d DB |
304 | /**\r |
305 | This function parses the ACPI MADT table.\r | |
ee4dc24f RN |
306 | When trace is enabled this function parses the MADT table and\r |
307 | traces the ACPI table fields.\r | |
308 | \r | |
309 | This function currently parses the following Interrupt Controller\r | |
310 | Structures:\r | |
311 | - GICC\r | |
312 | - GICD\r | |
313 | - GIC MSI Frame\r | |
314 | - GICR\r | |
315 | - GIC ITS\r | |
316 | \r | |
317 | This function also performs validation of the ACPI table fields.\r | |
318 | \r | |
319 | @param [in] Trace If TRUE, trace the ACPI fields.\r | |
320 | @param [in] Ptr Pointer to the start of the buffer.\r | |
321 | @param [in] AcpiTableLength Length of the ACPI table.\r | |
322 | @param [in] AcpiTableRevision Revision of the ACPI table.\r | |
a6eaba4d | 323 | **/\r |
ee4dc24f RN |
324 | VOID\r |
325 | EFIAPI\r | |
326 | ParseAcpiMadt (\r | |
47d20b54 MK |
327 | IN BOOLEAN Trace,\r |
328 | IN UINT8 *Ptr,\r | |
329 | IN UINT32 AcpiTableLength,\r | |
330 | IN UINT8 AcpiTableRevision\r | |
ee4dc24f RN |
331 | )\r |
332 | {\r | |
47d20b54 MK |
333 | UINT32 Offset;\r |
334 | UINT8 *InterruptContollerPtr;\r | |
335 | UINT32 GICDCount;\r | |
f75c7478 DB |
336 | \r |
337 | GICDCount = 0;\r | |
ee4dc24f RN |
338 | \r |
339 | if (!Trace) {\r | |
340 | return;\r | |
341 | }\r | |
342 | \r | |
343 | Offset = ParseAcpi (\r | |
344 | TRUE,\r | |
345 | 0,\r | |
346 | "MADT",\r | |
347 | Ptr,\r | |
348 | AcpiTableLength,\r | |
349 | PARSER_PARAMS (MadtParser)\r | |
350 | );\r | |
351 | InterruptContollerPtr = Ptr + Offset;\r | |
352 | \r | |
353 | while (Offset < AcpiTableLength) {\r | |
354 | // Parse Interrupt Controller Structure to obtain Length.\r | |
355 | ParseAcpi (\r | |
356 | FALSE,\r | |
357 | 0,\r | |
358 | NULL,\r | |
359 | InterruptContollerPtr,\r | |
05d40295 | 360 | AcpiTableLength - Offset,\r |
ee4dc24f RN |
361 | PARSER_PARAMS (MadtInterruptControllerHeaderParser)\r |
362 | );\r | |
363 | \r | |
c4a53853 KK |
364 | // Check if the values used to control the parsing logic have been\r |
365 | // successfully read.\r | |
366 | if ((MadtInterruptControllerType == NULL) ||\r | |
47d20b54 MK |
367 | (MadtInterruptControllerLength == NULL))\r |
368 | {\r | |
c4a53853 KK |
369 | IncrementErrorCount ();\r |
370 | Print (\r | |
371 | L"ERROR: Insufficient remaining table buffer length to read the " \\r | |
47d20b54 | 372 | L"Interrupt Controller Structure header. Length = %d.\n",\r |
c4a53853 KK |
373 | AcpiTableLength - Offset\r |
374 | );\r | |
375 | return;\r | |
376 | }\r | |
377 | \r | |
b8504826 KK |
378 | // Validate Interrupt Controller Structure length\r |
379 | if ((*MadtInterruptControllerLength == 0) ||\r | |
47d20b54 MK |
380 | ((Offset + (*MadtInterruptControllerLength)) > AcpiTableLength))\r |
381 | {\r | |
ee4dc24f RN |
382 | IncrementErrorCount ();\r |
383 | Print (\r | |
b8504826 | 384 | L"ERROR: Invalid Interrupt Controller Structure length. " \\r |
47d20b54 | 385 | L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r |
d23bf797 | 386 | *MadtInterruptControllerLength,\r |
b8504826 KK |
387 | Offset,\r |
388 | AcpiTableLength\r | |
d23bf797 KK |
389 | );\r |
390 | return;\r | |
ee4dc24f RN |
391 | }\r |
392 | \r | |
393 | switch (*MadtInterruptControllerType) {\r | |
47d20b54 MK |
394 | case EFI_ACPI_6_3_GIC:\r |
395 | {\r | |
ee4dc24f RN |
396 | ParseAcpi (\r |
397 | TRUE,\r | |
398 | 2,\r | |
399 | "GICC",\r | |
400 | InterruptContollerPtr,\r | |
401 | *MadtInterruptControllerLength,\r | |
402 | PARSER_PARAMS (GicCParser)\r | |
403 | );\r | |
404 | break;\r | |
405 | }\r | |
406 | \r | |
47d20b54 MK |
407 | case EFI_ACPI_6_3_GICD:\r |
408 | {\r | |
ee4dc24f RN |
409 | if (++GICDCount > 1) {\r |
410 | IncrementErrorCount ();\r | |
411 | Print (\r | |
412 | L"ERROR: Only one GICD must be present,"\r | |
47d20b54 | 413 | L" GICDCount = %d\n",\r |
ee4dc24f RN |
414 | GICDCount\r |
415 | );\r | |
416 | }\r | |
47d20b54 | 417 | \r |
ee4dc24f RN |
418 | ParseAcpi (\r |
419 | TRUE,\r | |
420 | 2,\r | |
421 | "GICD",\r | |
422 | InterruptContollerPtr,\r | |
423 | *MadtInterruptControllerLength,\r | |
424 | PARSER_PARAMS (GicDParser)\r | |
425 | );\r | |
426 | break;\r | |
427 | }\r | |
428 | \r | |
47d20b54 MK |
429 | case EFI_ACPI_6_3_GIC_MSI_FRAME:\r |
430 | {\r | |
ee4dc24f RN |
431 | ParseAcpi (\r |
432 | TRUE,\r | |
433 | 2,\r | |
434 | "GIC MSI Frame",\r | |
435 | InterruptContollerPtr,\r | |
436 | *MadtInterruptControllerLength,\r | |
437 | PARSER_PARAMS (GicMSIFrameParser)\r | |
438 | );\r | |
439 | break;\r | |
440 | }\r | |
441 | \r | |
47d20b54 MK |
442 | case EFI_ACPI_6_3_GICR:\r |
443 | {\r | |
ee4dc24f RN |
444 | ParseAcpi (\r |
445 | TRUE,\r | |
446 | 2,\r | |
447 | "GICR",\r | |
448 | InterruptContollerPtr,\r | |
449 | *MadtInterruptControllerLength,\r | |
450 | PARSER_PARAMS (GicRParser)\r | |
451 | );\r | |
452 | break;\r | |
453 | }\r | |
454 | \r | |
47d20b54 MK |
455 | case EFI_ACPI_6_3_GIC_ITS:\r |
456 | {\r | |
ee4dc24f RN |
457 | ParseAcpi (\r |
458 | TRUE,\r | |
459 | 2,\r | |
460 | "GIC ITS",\r | |
461 | InterruptContollerPtr,\r | |
462 | *MadtInterruptControllerLength,\r | |
463 | PARSER_PARAMS (GicITSParser)\r | |
464 | );\r | |
465 | break;\r | |
466 | }\r | |
467 | \r | |
47d20b54 MK |
468 | case EFI_ACPI_6_3_IO_APIC:\r |
469 | {\r | |
2f286930 ALA |
470 | ParseAcpi (\r |
471 | TRUE,\r | |
472 | 2,\r | |
473 | "IO APIC",\r | |
474 | InterruptContollerPtr,\r | |
475 | *MadtInterruptControllerLength,\r | |
476 | PARSER_PARAMS (IoApic)\r | |
477 | );\r | |
478 | break;\r | |
479 | }\r | |
480 | \r | |
47d20b54 MK |
481 | case EFI_ACPI_6_3_INTERRUPT_SOURCE_OVERRIDE:\r |
482 | {\r | |
2f286930 ALA |
483 | ParseAcpi (\r |
484 | TRUE,\r | |
485 | 2,\r | |
486 | "INTERRUPT SOURCE OVERRIDE",\r | |
487 | InterruptContollerPtr,\r | |
488 | *MadtInterruptControllerLength,\r | |
489 | PARSER_PARAMS (InterruptSourceOverride)\r | |
490 | );\r | |
491 | break;\r | |
492 | }\r | |
d5fd86f2 ALA |
493 | case EFI_ACPI_6_3_PROCESSOR_LOCAL_APIC:\r |
494 | {\r | |
495 | ParseAcpi (\r | |
496 | TRUE,\r | |
497 | 2,\r | |
498 | "PROCESSOR LOCAL APIC",\r | |
499 | InterruptContollerPtr,\r | |
500 | *MadtInterruptControllerLength,\r | |
501 | PARSER_PARAMS (ProcessorLocalApic)\r | |
502 | );\r | |
503 | break;\r | |
504 | }\r | |
47d20b54 MK |
505 | case EFI_ACPI_6_3_PROCESSOR_LOCAL_X2APIC:\r |
506 | {\r | |
2f286930 ALA |
507 | ParseAcpi (\r |
508 | TRUE,\r | |
509 | 2,\r | |
510 | "PROCESSOR LOCAL X2APIC",\r | |
511 | InterruptContollerPtr,\r | |
512 | *MadtInterruptControllerLength,\r | |
513 | PARSER_PARAMS (ProcessorLocalX2Apic)\r | |
514 | );\r | |
515 | break;\r | |
516 | }\r | |
517 | \r | |
47d20b54 MK |
518 | case EFI_ACPI_6_3_LOCAL_X2APIC_NMI:\r |
519 | {\r | |
2f286930 ALA |
520 | ParseAcpi (\r |
521 | TRUE,\r | |
522 | 2,\r | |
523 | "LOCAL x2APIC NMI",\r | |
524 | InterruptContollerPtr,\r | |
525 | *MadtInterruptControllerLength,\r | |
526 | PARSER_PARAMS (LocalX2ApicNmi)\r | |
527 | );\r | |
528 | break;\r | |
529 | }\r | |
530 | \r | |
47d20b54 MK |
531 | default:\r |
532 | {\r | |
ee4dc24f RN |
533 | IncrementErrorCount ();\r |
534 | Print (\r | |
535 | L"ERROR: Unknown Interrupt Controller Structure,"\r | |
47d20b54 | 536 | L" Type = %d, Length = %d\n",\r |
ee4dc24f RN |
537 | *MadtInterruptControllerType,\r |
538 | *MadtInterruptControllerLength\r | |
539 | );\r | |
540 | }\r | |
541 | } // switch\r | |
542 | \r | |
543 | InterruptContollerPtr += *MadtInterruptControllerLength;\r | |
47d20b54 | 544 | Offset += *MadtInterruptControllerLength;\r |
ee4dc24f RN |
545 | } // while\r |
546 | }\r |