4 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - ACPI 6.2 Specification - Errata A, September 2017
11 #include <IndustryStandard/Acpi.h>
12 #include <Library/UefiLib.h>
13 #include "AcpiParser.h"
14 #include "AcpiTableParser.h"
17 STATIC CONST UINT8
* MadtInterruptControllerType
;
18 STATIC CONST UINT8
* MadtInterruptControllerLength
;
19 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
22 This function validates the System Vector Base in the GICD.
24 @param [in] Ptr Pointer to the start of the field data.
25 @param [in] Context Pointer to context specific information e.g. this
26 could be a pointer to the ACPI table header.
31 ValidateGICDSystemVectorBase (
37 An ACPI_PARSER array describing the GICC Interrupt Controller Structure.
39 STATIC CONST ACPI_PARSER GicCParser
[] = {
40 {L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
41 {L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
42 {L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
44 {L
"CPU Interface Number", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
45 {L
"ACPI Processor UID", 4, 8, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
46 {L
"Flags", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
47 {L
"Parking Protocol Version", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
49 {L
"Performance Interrupt GSIV", 4, 20, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
50 {L
"Parked Address", 8, 24, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
51 {L
"Physical Base Address", 8, 32, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
52 {L
"GICV", 8, 40, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
53 {L
"GICH", 8, 48, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
54 {L
"VGIC Maintenance interrupt", 4, 56, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
55 {L
"GICR Base Address", 8, 60, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
56 {L
"MPIDR", 8, 68, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
57 {L
"Processor Power Efficiency Class", 1, 76, L
"0x%x", NULL
, NULL
, NULL
,
59 {L
"Reserved", 3, 77, L
"%x %x %x", Dump3Chars
, NULL
, NULL
, NULL
}
63 An ACPI_PARSER array describing the GICD Interrupt Controller Structure.
65 STATIC CONST ACPI_PARSER GicDParser
[] = {
66 {L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
67 {L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
68 {L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
70 {L
"GIC ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
71 {L
"Physical Base Address", 8, 8, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
72 {L
"System Vector Base", 4, 16, L
"0x%x", NULL
, NULL
,
73 ValidateGICDSystemVectorBase
, NULL
},
74 {L
"GIC Version", 1, 20, L
"%d", NULL
, NULL
, NULL
, NULL
},
75 {L
"Reserved", 3, 21, L
"%x %x %x", Dump3Chars
, NULL
, NULL
, NULL
}
79 An ACPI_PARSER array describing the MSI Frame Interrupt Controller Structure.
81 STATIC CONST ACPI_PARSER GicMSIFrameParser
[] = {
82 {L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
83 {L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
84 {L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
86 {L
"MSI Frame ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
87 {L
"Physical Base Address", 8, 8, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
88 {L
"Flags", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
90 {L
"SPI Count", 2, 20, L
"%d", NULL
, NULL
, NULL
, NULL
},
91 {L
"SPI Base", 2, 22, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
95 An ACPI_PARSER array describing the GICR Interrupt Controller Structure.
97 STATIC CONST ACPI_PARSER GicRParser
[] = {
98 {L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
99 {L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
100 {L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
102 {L
"Discovery Range Base Address", 8, 4, L
"0x%lx", NULL
, NULL
, NULL
,
104 {L
"Discovery Range Length", 4, 12, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
108 An ACPI_PARSER array describing the GIC ITS Interrupt Controller Structure.
110 STATIC CONST ACPI_PARSER GicITSParser
[] = {
111 {L
"Type", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
112 {L
"Length", 1, 1, L
"%d", NULL
, NULL
, NULL
, NULL
},
113 {L
"Reserved", 2, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
115 {L
"GIC ITS ID", 4, 4, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
116 {L
"Physical Base Address", 8, 8, L
"0x%lx", NULL
, NULL
, NULL
, NULL
},
117 {L
"Reserved", 4, 16, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
121 An ACPI_PARSER array describing the ACPI MADT Table.
123 STATIC CONST ACPI_PARSER MadtParser
[] = {
124 PARSE_ACPI_HEADER (&AcpiHdrInfo
),
125 {L
"Local Interrupt Controller Address", 4, 36, L
"0x%x", NULL
, NULL
, NULL
,
127 {L
"Flags", 4, 40, L
"0x%x", NULL
, NULL
, NULL
, NULL
}
131 An ACPI_PARSER array describing the MADT Interrupt Controller Structure Header Structure.
133 STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser
[] = {
134 {NULL
, 1, 0, NULL
, NULL
, (VOID
**)&MadtInterruptControllerType
, NULL
, NULL
},
135 {L
"Length", 1, 1, NULL
, NULL
, (VOID
**)&MadtInterruptControllerLength
, NULL
,
137 {L
"Reserved", 2, 2, NULL
, NULL
, NULL
, NULL
, NULL
}
141 This function validates the System Vector Base in the GICD.
143 @param [in] Ptr Pointer to the start of the field data.
144 @param [in] Context Pointer to context specific information e.g. this
145 could be a pointer to the ACPI table header.
150 ValidateGICDSystemVectorBase (
155 if (*(UINT32
*)Ptr
!= 0) {
156 IncrementErrorCount ();
158 L
"\nERROR: System Vector Base must be zero."
164 This function parses the ACPI MADT table.
165 When trace is enabled this function parses the MADT table and
166 traces the ACPI table fields.
168 This function currently parses the following Interrupt Controller
176 This function also performs validation of the ACPI table fields.
178 @param [in] Trace If TRUE, trace the ACPI fields.
179 @param [in] Ptr Pointer to the start of the buffer.
180 @param [in] AcpiTableLength Length of the ACPI table.
181 @param [in] AcpiTableRevision Revision of the ACPI table.
188 IN UINT32 AcpiTableLength
,
189 IN UINT8 AcpiTableRevision
193 UINT8
* InterruptContollerPtr
;
208 PARSER_PARAMS (MadtParser
)
210 InterruptContollerPtr
= Ptr
+ Offset
;
212 while (Offset
< AcpiTableLength
) {
213 // Parse Interrupt Controller Structure to obtain Length.
218 InterruptContollerPtr
,
219 2, // Length is 1 byte at offset 1
220 PARSER_PARAMS (MadtInterruptControllerHeaderParser
)
223 if (((Offset
+ (*MadtInterruptControllerLength
)) > AcpiTableLength
) ||
224 (*MadtInterruptControllerLength
< 4)) {
225 IncrementErrorCount ();
227 L
"ERROR: Invalid Interrupt Controller Length,"
228 L
" Type = %d, Length = %d\n",
229 *MadtInterruptControllerType
,
230 *MadtInterruptControllerLength
235 switch (*MadtInterruptControllerType
) {
236 case EFI_ACPI_6_2_GIC
: {
241 InterruptContollerPtr
,
242 *MadtInterruptControllerLength
,
243 PARSER_PARAMS (GicCParser
)
248 case EFI_ACPI_6_2_GICD
: {
249 if (++GICDCount
> 1) {
250 IncrementErrorCount ();
252 L
"ERROR: Only one GICD must be present,"
253 L
" GICDCount = %d\n",
261 InterruptContollerPtr
,
262 *MadtInterruptControllerLength
,
263 PARSER_PARAMS (GicDParser
)
268 case EFI_ACPI_6_2_GIC_MSI_FRAME
: {
273 InterruptContollerPtr
,
274 *MadtInterruptControllerLength
,
275 PARSER_PARAMS (GicMSIFrameParser
)
280 case EFI_ACPI_6_2_GICR
: {
285 InterruptContollerPtr
,
286 *MadtInterruptControllerLength
,
287 PARSER_PARAMS (GicRParser
)
292 case EFI_ACPI_6_2_GIC_ITS
: {
297 InterruptContollerPtr
,
298 *MadtInterruptControllerLength
,
299 PARSER_PARAMS (GicITSParser
)
305 IncrementErrorCount ();
307 L
"ERROR: Unknown Interrupt Controller Structure,"
308 L
" Type = %d, Length = %d\n",
309 *MadtInterruptControllerType
,
310 *MadtInterruptControllerLength
315 InterruptContollerPtr
+= *MadtInterruptControllerLength
;
316 Offset
+= *MadtInterruptControllerLength
;