4 Copyright (c) 2016 - 2019, 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."
81 This function validates the X_Firmware Control Field.
83 @param [in] Ptr Pointer to the start of the field data.
84 @param [in] Context Pointer to context specific information e.g. this
85 could be a pointer to the ACPI table header.
90 ValidateXFirmwareCtrl (
95 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
96 if (*(UINT64
*)Ptr
!= 0) {
97 IncrementErrorCount ();
99 L
"\nERROR: X Firmware Control must be zero for ARM platforms."
106 This function validates the flags.
108 @param [in] Ptr Pointer to the start of the field data.
109 @param [in] Context Pointer to context specific information e.g. this
110 could be a pointer to the ACPI table header.
120 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
121 if (((*(UINT32
*)Ptr
) & HW_REDUCED_ACPI
) == 0) {
122 IncrementErrorCount ();
124 L
"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms."
131 An ACPI_PARSER array describing the ACPI FADT Table.
133 STATIC CONST ACPI_PARSER FadtParser
[] = {
134 PARSE_ACPI_HEADER (&AcpiHdrInfo
),
135 {L
"FIRMWARE_CTRL", 4, 36, L
"0x%x", NULL
, (VOID
**)&FirmwareCtrl
,
136 ValidateFirmwareCtrl
, NULL
},
137 {L
"DSDT", 4, 40, L
"0x%x", NULL
, (VOID
**)&DsdtAddress
, NULL
, NULL
},
138 {L
"Reserved", 1, 44, L
"%x", NULL
, NULL
, NULL
, NULL
},
139 {L
"Preferred_PM_Profile", 1, 45, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
140 {L
"SCI_INT", 2, 46, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
141 {L
"SMI_CMD", 4, 48, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
142 {L
"ACPI_ENABLE", 1, 52, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
143 {L
"ACPI_DISABLE", 1, 53, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
144 {L
"S4BIOS_REQ", 1, 54, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
145 {L
"PSTATE_CNT", 1, 55, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
146 {L
"PM1a_EVT_BLK", 4, 56, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
147 {L
"PM1b_EVT_BLK", 4, 60, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
148 {L
"PM1a_CNT_BLK", 4, 64, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
149 {L
"PM1b_CNT_BLK", 4, 68, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
150 {L
"PM2_CNT_BLK", 4, 72, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
151 {L
"PM_TMR_BLK", 4, 76, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
152 {L
"GPE0_BLK", 4, 80, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
153 {L
"GPE1_BLK", 4, 84, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
154 {L
"PM1_EVT_LEN", 1, 88, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
155 {L
"PM1_CNT_LEN", 1, 89, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
156 {L
"PM2_CNT_LEN", 1, 90, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
157 {L
"PM_TMR_LEN", 1, 91, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
158 {L
"GPE0_BLK_LEN", 1, 92, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
159 {L
"GPE1_BLK_LEN", 1, 93, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
160 {L
"GPE1_BASE", 1, 94, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
161 {L
"CST_CNT", 1, 95, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
162 {L
"P_LVL2_LAT", 2, 96, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
163 {L
"P_LVL3_LAT", 2, 98, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
164 {L
"FLUSH_SIZE", 2, 100, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
165 {L
"FLUSH_STRIDE", 2, 102, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
166 {L
"DUTY_OFFSET", 1, 104, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
167 {L
"DUTY_WIDTH", 1, 105, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
168 {L
"DAY_ALRM", 1, 106, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
169 {L
"MON_ALRM", 1, 107, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
170 {L
"CENTURY", 1, 108, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
171 {L
"IAPC_BOOT_ARCH", 2, 109, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
172 {L
"Reserved", 1, 111, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
173 {L
"Flags", 4, 112, L
"0x%x", NULL
, (VOID
**)&Flags
, ValidateFlags
, NULL
},
174 {L
"RESET_REG", 12, 116, NULL
, DumpGas
, NULL
, NULL
, NULL
},
175 {L
"RESET_VALUE", 1, 128, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
176 {L
"ARM_BOOT_ARCH", 2, 129, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
177 {L
"FADT Minor Version", 1, 131, L
"0x%x", NULL
, (VOID
**)&FadtMinorRevision
,
179 {L
"X_FIRMWARE_CTRL", 8, 132, L
"0x%lx", NULL
, (VOID
**)&X_FirmwareCtrl
,
180 ValidateXFirmwareCtrl
, NULL
},
181 {L
"X_DSDT", 8, 140, L
"0x%lx", NULL
, (VOID
**)&X_DsdtAddress
, NULL
, NULL
},
182 {L
"X_PM1a_EVT_BLK", 12, 148, NULL
, DumpGas
, NULL
, NULL
, NULL
},
183 {L
"X_PM1b_EVT_BLK", 12, 160, NULL
, DumpGas
, NULL
, NULL
, NULL
},
184 {L
"X_PM1a_CNT_BLK", 12, 172, NULL
, DumpGas
, NULL
, NULL
, NULL
},
185 {L
"X_PM1b_CNT_BLK", 12, 184, NULL
, DumpGas
, NULL
, NULL
, NULL
},
186 {L
"X_PM2_CNT_BLK", 12, 196, NULL
, DumpGas
, NULL
, NULL
, NULL
},
187 {L
"X_PM_TMR_BLK", 12, 208, NULL
, DumpGas
, NULL
, NULL
, NULL
},
188 {L
"X_GPE0_BLK", 12, 220, NULL
, DumpGas
, NULL
, NULL
, NULL
},
189 {L
"X_GPE1_BLK", 12, 232, NULL
, DumpGas
, NULL
, NULL
, NULL
},
190 {L
"SLEEP_CONTROL_REG", 12, 244, NULL
, DumpGas
, NULL
, NULL
, NULL
},
191 {L
"SLEEP_STATUS_REG", 12, 256, NULL
, DumpGas
, NULL
, NULL
, NULL
},
192 {L
"Hypervisor VendorIdentity", 8, 268, L
"%lx", NULL
, NULL
, NULL
, NULL
}
196 This function parses the ACPI FADT table.
197 This function parses the FADT table and optionally traces the ACPI table fields.
199 This function also performs validation of the ACPI table fields.
201 @param [in] Trace If TRUE, trace the ACPI fields.
202 @param [in] Ptr Pointer to the start of the buffer.
203 @param [in] AcpiTableLength Length of the ACPI table.
204 @param [in] AcpiTableRevision Revision of the ACPI table.
211 IN UINT32 AcpiTableLength
,
212 IN UINT8 AcpiTableRevision
217 UINT8
* FirmwareCtrlPtr
;
218 UINT32 FacsSignature
;
221 PARSE_ACPI_TABLE_PROC FacsParserProc
;
229 PARSER_PARAMS (FadtParser
)
233 Print (L
"\nSummary:\n");
234 PrintFieldName (2, L
"FADT Version");
235 Print (L
"%d.%d\n", *AcpiHdrInfo
.Revision
, *FadtMinorRevision
);
237 if (*GetAcpiXsdtHeaderInfo ()->OemTableId
!= *AcpiHdrInfo
.OemTableId
) {
238 IncrementErrorCount ();
239 Print (L
"ERROR: OEM Table Id does not match with RSDT/XSDT.\n");
243 // If X_FIRMWARE_CTRL is not zero then use X_FIRMWARE_CTRL and ignore
244 // FIRMWARE_CTRL, else use FIRMWARE_CTRL.
245 if ((X_FirmwareCtrl
!= NULL
) && (*X_FirmwareCtrl
!= 0)) {
246 FirmwareCtrlPtr
= (UINT8
*)(UINTN
)(*X_FirmwareCtrl
);
247 } else if ((FirmwareCtrl
!= NULL
) && (*FirmwareCtrl
!= 0)) {
248 FirmwareCtrlPtr
= (UINT8
*)(UINTN
)(*FirmwareCtrl
);
250 FirmwareCtrlPtr
= NULL
;
251 // if HW_REDUCED_ACPI flag is not set, both FIRMWARE_CTRL and
252 // X_FIRMWARE_CTRL cannot be zero, and the FACS Table must be
256 ((*Flags
& EFI_ACPI_6_3_HW_REDUCED_ACPI
) != 0)) {
257 IncrementErrorCount ();
258 Print (L
"ERROR: No FACS table found, "
259 L
"both X_FIRMWARE_CTRL and FIRMWARE_CTRL are zero.\n");
263 if (FirmwareCtrlPtr
!= NULL
) {
264 // The FACS table does not have a standard ACPI table header. Therefore,
265 // the signature, length and version needs to be initially parsed.
266 // The FACS signature is 4 bytes starting at offset 0.
267 FacsSignature
= *(UINT32
*)(FirmwareCtrlPtr
+ FACS_SIGNATURE_OFFSET
);
269 // The FACS length is 4 bytes starting at offset 4.
270 FacsLength
= *(UINT32
*)(FirmwareCtrlPtr
+ FACS_LENGTH_OFFSET
);
272 // The FACS version is 1 byte starting at offset 32.
273 FacsRevision
= *(UINT8
*)(FirmwareCtrlPtr
+ FACS_VERSION_OFFSET
);
275 Trace
= ProcessTableReportOptions (
281 Status
= GetParser (FacsSignature
, &FacsParserProc
);
282 if (EFI_ERROR (Status
)) {
284 L
"ERROR: No registered parser found for FACS.\n"
297 // If X_DSDT is not zero then use X_DSDT and ignore DSDT,
299 if (*X_DsdtAddress
!= 0) {
300 DsdtPtr
= (UINT8
*)(UINTN
)(*X_DsdtAddress
);
301 } else if (*DsdtAddress
!= 0) {
302 DsdtPtr
= (UINT8
*)(UINTN
)(*DsdtAddress
);
304 // Both DSDT and X_DSDT cannot be zero.
305 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
307 // The DSDT Table is mandatory for ARM systems
308 // as the CPU information MUST be presented in
310 IncrementErrorCount ();
311 Print (L
"ERROR: Both X_DSDT and DSDT are NULL.\n");
317 ProcessAcpiTable (DsdtPtr
);