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