4 Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - ACPI 6.3 Specification - January 2019
11 #include <IndustryStandard/Acpi.h>
12 #include <Library/UefiLib.h>
13 #include "AcpiParser.h"
14 #include "AcpiTableParser.h"
18 STATIC CONST UINT32
*DsdtAddress
;
19 STATIC CONST UINT64
*X_DsdtAddress
;
20 STATIC CONST UINT32
*Flags
;
21 STATIC CONST UINT32
*FirmwareCtrl
;
22 STATIC CONST UINT64
*X_FirmwareCtrl
;
23 STATIC CONST UINT8
*FadtMinorRevision
;
24 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
27 A macro defining the Hardware reduced ACPI flag
29 #define HW_REDUCED_ACPI BIT20
32 Offset to the FACS signature from the start of the FACS.
34 #define FACS_SIGNATURE_OFFSET 0
37 Offset to the FACS revision from the start of the FACS.
39 #define FACS_VERSION_OFFSET 32
42 Offset to the FACS length from the start of the FACS.
44 #define FACS_LENGTH_OFFSET 4
47 Get the ACPI XSDT header info.
49 CONST ACPI_DESCRIPTION_HEADER_INFO
*
51 GetAcpiXsdtHeaderInfo (
56 This function validates the Firmware Control Field.
58 @param [in] Ptr Pointer to the start of the field data.
59 @param [in] Context Pointer to context specific information e.g. this
60 could be a pointer to the ACPI table header.
65 ValidateFirmwareCtrl (
70 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
71 if (*(UINT32
*)Ptr
!= 0) {
72 IncrementErrorCount ();
74 L
"\nERROR: Firmware Control must be zero for ARM platforms."
82 This function validates the X_Firmware Control Field.
84 @param [in] Ptr Pointer to the start of the field data.
85 @param [in] Context Pointer to context specific information e.g. this
86 could be a pointer to the ACPI table header.
91 ValidateXFirmwareCtrl (
96 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
97 if (*(UINT64
*)Ptr
!= 0) {
98 IncrementErrorCount ();
100 L
"\nERROR: X Firmware Control must be zero for ARM platforms."
108 This function validates the flags.
110 @param [in] Ptr Pointer to the start of the field data.
111 @param [in] Context Pointer to context specific information e.g. this
112 could be a pointer to the ACPI table header.
122 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
123 if (((*(UINT32
*)Ptr
) & HW_REDUCED_ACPI
) == 0) {
124 IncrementErrorCount ();
126 L
"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms."
134 An ACPI_PARSER array describing the ACPI FADT Table.
136 STATIC CONST ACPI_PARSER FadtParser
[] = {
137 PARSE_ACPI_HEADER (&AcpiHdrInfo
),
138 { L
"FIRMWARE_CTRL", 4, 36, L
"0x%x", NULL
, (VOID
**)&FirmwareCtrl
,
139 ValidateFirmwareCtrl
, NULL
},
140 { L
"DSDT", 4, 40, L
"0x%x", NULL
, (VOID
**)&DsdtAddress
, NULL
, NULL
},
141 { L
"Reserved", 1, 44, L
"%x", NULL
, NULL
, NULL
, NULL
},
142 { L
"Preferred_PM_Profile", 1, 45, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
143 { L
"SCI_INT", 2, 46, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
144 { L
"SMI_CMD", 4, 48, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
145 { L
"ACPI_ENABLE", 1, 52, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
146 { L
"ACPI_DISABLE", 1, 53, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
147 { L
"S4BIOS_REQ", 1, 54, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
148 { L
"PSTATE_CNT", 1, 55, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
149 { L
"PM1a_EVT_BLK", 4, 56, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
150 { L
"PM1b_EVT_BLK", 4, 60, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
151 { L
"PM1a_CNT_BLK", 4, 64, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
152 { L
"PM1b_CNT_BLK", 4, 68, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
153 { L
"PM2_CNT_BLK", 4, 72, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
154 { L
"PM_TMR_BLK", 4, 76, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
155 { L
"GPE0_BLK", 4, 80, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
156 { L
"GPE1_BLK", 4, 84, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
157 { L
"PM1_EVT_LEN", 1, 88, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
158 { L
"PM1_CNT_LEN", 1, 89, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
159 { L
"PM2_CNT_LEN", 1, 90, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
160 { L
"PM_TMR_LEN", 1, 91, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
161 { L
"GPE0_BLK_LEN", 1, 92, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
162 { L
"GPE1_BLK_LEN", 1, 93, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
163 { L
"GPE1_BASE", 1, 94, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
164 { L
"CST_CNT", 1, 95, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
165 { L
"P_LVL2_LAT", 2, 96, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
166 { L
"P_LVL3_LAT", 2, 98, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
167 { L
"FLUSH_SIZE", 2, 100, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
168 { L
"FLUSH_STRIDE", 2, 102, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
169 { L
"DUTY_OFFSET", 1, 104, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
170 { L
"DUTY_WIDTH", 1, 105, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
171 { L
"DAY_ALRM", 1, 106, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
172 { L
"MON_ALRM", 1, 107, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
173 { L
"CENTURY", 1, 108, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
174 { L
"IAPC_BOOT_ARCH", 2, 109, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
175 { L
"Reserved", 1, 111, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
176 { L
"Flags", 4, 112, L
"0x%x", NULL
, (VOID
**)&Flags
, ValidateFlags
, NULL
},
177 { L
"RESET_REG", 12, 116, NULL
, DumpGas
, NULL
, NULL
, NULL
},
178 { L
"RESET_VALUE", 1, 128, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
179 { L
"ARM_BOOT_ARCH", 2, 129, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
180 { L
"FADT Minor Version", 1, 131, L
"0x%x", NULL
, (VOID
**)&FadtMinorRevision
,
182 { L
"X_FIRMWARE_CTRL", 8, 132, L
"0x%lx", NULL
, (VOID
**)&X_FirmwareCtrl
,
183 ValidateXFirmwareCtrl
, NULL
},
184 { L
"X_DSDT", 8, 140, L
"0x%lx", NULL
, (VOID
**)&X_DsdtAddress
, NULL
, NULL
},
185 { L
"X_PM1a_EVT_BLK", 12, 148, NULL
, DumpGas
, NULL
, NULL
, NULL
},
186 { L
"X_PM1b_EVT_BLK", 12, 160, NULL
, DumpGas
, NULL
, NULL
, NULL
},
187 { L
"X_PM1a_CNT_BLK", 12, 172, NULL
, DumpGas
, NULL
, NULL
, NULL
},
188 { L
"X_PM1b_CNT_BLK", 12, 184, NULL
, DumpGas
, NULL
, NULL
, NULL
},
189 { L
"X_PM2_CNT_BLK", 12, 196, NULL
, DumpGas
, NULL
, NULL
, NULL
},
190 { L
"X_PM_TMR_BLK", 12, 208, NULL
, DumpGas
, NULL
, NULL
, NULL
},
191 { L
"X_GPE0_BLK", 12, 220, NULL
, DumpGas
, NULL
, NULL
, NULL
},
192 { L
"X_GPE1_BLK", 12, 232, NULL
, DumpGas
, NULL
, NULL
, NULL
},
193 { L
"SLEEP_CONTROL_REG", 12, 244, NULL
, DumpGas
, NULL
, NULL
, NULL
},
194 { L
"SLEEP_STATUS_REG", 12, 256, NULL
, DumpGas
, NULL
, NULL
, NULL
},
195 { L
"Hypervisor VendorIdentity", 8, 268, L
"%lx", NULL
, NULL
, NULL
, NULL
}
199 This function parses the ACPI FADT table.
200 This function parses the FADT table and optionally traces the ACPI table fields.
202 This function also performs validation of the ACPI table fields.
204 @param [in] Trace If TRUE, trace the ACPI fields.
205 @param [in] Ptr Pointer to the start of the buffer.
206 @param [in] AcpiTableLength Length of the ACPI table.
207 @param [in] AcpiTableRevision Revision of the ACPI table.
214 IN UINT32 AcpiTableLength
,
215 IN UINT8 AcpiTableRevision
220 UINT8
*FirmwareCtrlPtr
;
221 UINT32 FacsSignature
;
224 PARSE_ACPI_TABLE_PROC FacsParserProc
;
232 PARSER_PARAMS (FadtParser
)
236 if (FadtMinorRevision
!= NULL
) {
237 Print (L
"\nSummary:\n");
238 PrintFieldName (2, L
"FADT Version");
239 Print (L
"%d.%d\n", *AcpiHdrInfo
.Revision
, *FadtMinorRevision
);
242 if (*GetAcpiXsdtHeaderInfo ()->OemTableId
!= *AcpiHdrInfo
.OemTableId
) {
243 IncrementErrorCount ();
244 Print (L
"ERROR: OEM Table Id does not match with RSDT/XSDT.\n");
248 // If X_FIRMWARE_CTRL is not zero then use X_FIRMWARE_CTRL and ignore
249 // FIRMWARE_CTRL, else use FIRMWARE_CTRL.
250 if ((X_FirmwareCtrl
!= NULL
) && (*X_FirmwareCtrl
!= 0)) {
251 FirmwareCtrlPtr
= (UINT8
*)(UINTN
)(*X_FirmwareCtrl
);
252 } else if ((FirmwareCtrl
!= NULL
) && (*FirmwareCtrl
!= 0)) {
253 FirmwareCtrlPtr
= (UINT8
*)(UINTN
)(*FirmwareCtrl
);
255 FirmwareCtrlPtr
= NULL
;
256 // if HW_REDUCED_ACPI flag is not set, both FIRMWARE_CTRL and
257 // X_FIRMWARE_CTRL cannot be zero, and the FACS Table must be
261 ((*Flags
& EFI_ACPI_6_3_HW_REDUCED_ACPI
) != EFI_ACPI_6_3_HW_REDUCED_ACPI
))
263 IncrementErrorCount ();
265 L
"ERROR: No FACS table found, "
266 L
"both X_FIRMWARE_CTRL and FIRMWARE_CTRL are zero.\n"
271 if (FirmwareCtrlPtr
!= NULL
) {
272 // The FACS table does not have a standard ACPI table header. Therefore,
273 // the signature, length and version needs to be initially parsed.
274 // The FACS signature is 4 bytes starting at offset 0.
275 FacsSignature
= *(UINT32
*)(FirmwareCtrlPtr
+ FACS_SIGNATURE_OFFSET
);
277 // The FACS length is 4 bytes starting at offset 4.
278 FacsLength
= *(UINT32
*)(FirmwareCtrlPtr
+ FACS_LENGTH_OFFSET
);
280 // The FACS version is 1 byte starting at offset 32.
281 FacsRevision
= *(UINT8
*)(FirmwareCtrlPtr
+ FACS_VERSION_OFFSET
);
283 Trace
= ProcessTableReportOptions (
289 Status
= GetParser (FacsSignature
, &FacsParserProc
);
290 if (EFI_ERROR (Status
)) {
292 L
"ERROR: No registered parser found for FACS.\n"
305 // If X_DSDT is valid then use X_DSDT and ignore DSDT, else use DSDT.
306 if ((X_DsdtAddress
!= NULL
) && (*X_DsdtAddress
!= 0)) {
307 DsdtPtr
= (UINT8
*)(UINTN
)(*X_DsdtAddress
);
308 } else if ((DsdtAddress
!= NULL
) && (*DsdtAddress
!= 0)) {
309 DsdtPtr
= (UINT8
*)(UINTN
)(*DsdtAddress
);
311 // Both DSDT and X_DSDT cannot be invalid.
312 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
314 // The DSDT Table is mandatory for ARM systems
315 // as the CPU information MUST be presented in
317 IncrementErrorCount ();
318 Print (L
"ERROR: Both X_DSDT and DSDT are invalid.\n");
325 ProcessAcpiTable (DsdtPtr
);