]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c
5b8cc174f16afb3d4feb6a518952e60c6564ee34
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Fadt / FadtParser.c
1 /** @file
2 FADT table parser
3
4 Copyright (c) 2016 - 2019, 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 **/
10
11 #include <IndustryStandard/Acpi.h>
12 #include <Library/UefiLib.h>
13 #include "AcpiParser.h"
14 #include "AcpiTableParser.h"
15 #include "AcpiView.h"
16
17 // Local variables
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;
25
26 /**
27 A macro defining the Hardware reduced ACPI flag
28 **/
29 #define HW_REDUCED_ACPI BIT20
30
31 /**
32 Offset to the FACS signature from the start of the FACS.
33 **/
34 #define FACS_SIGNATURE_OFFSET 0
35
36 /**
37 Offset to the FACS revision from the start of the FACS.
38 **/
39 #define FACS_VERSION_OFFSET 32
40
41 /**
42 Offset to the FACS length from the start of the FACS.
43 **/
44 #define FACS_LENGTH_OFFSET 4
45
46 /**
47 Get the ACPI XSDT header info.
48 **/
49 CONST ACPI_DESCRIPTION_HEADER_INFO *
50 EFIAPI
51 GetAcpiXsdtHeaderInfo (
52 VOID
53 );
54
55 /**
56 This function validates the Firmware Control Field.
57
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.
61 **/
62 STATIC
63 VOID
64 EFIAPI
65 ValidateFirmwareCtrl (
66 IN UINT8* Ptr,
67 IN VOID* Context
68 )
69 {
70 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
71 if (*(UINT32*)Ptr != 0) {
72 IncrementErrorCount ();
73 Print (
74 L"\nERROR: Firmware Control must be zero for ARM platforms."
75 );
76 }
77 #endif
78 }
79
80 /**
81 This function validates the X_Firmware Control Field.
82
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.
86 **/
87 STATIC
88 VOID
89 EFIAPI
90 ValidateXFirmwareCtrl (
91 IN UINT8* Ptr,
92 IN VOID* Context
93 )
94 {
95 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
96 if (*(UINT64*)Ptr != 0) {
97 IncrementErrorCount ();
98 Print (
99 L"\nERROR: X Firmware Control must be zero for ARM platforms."
100 );
101 }
102 #endif
103 }
104
105 /**
106 This function validates the flags.
107
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.
111 **/
112 STATIC
113 VOID
114 EFIAPI
115 ValidateFlags (
116 IN UINT8* Ptr,
117 IN VOID* Context
118 )
119 {
120 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
121 if (((*(UINT32*)Ptr) & HW_REDUCED_ACPI) == 0) {
122 IncrementErrorCount ();
123 Print (
124 L"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms."
125 );
126 }
127 #endif
128 }
129
130 /**
131 An ACPI_PARSER array describing the ACPI FADT Table.
132 **/
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,
178 NULL, NULL},
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}
193 };
194
195 /**
196 This function parses the ACPI FADT table.
197 This function parses the FADT table and optionally traces the ACPI table fields.
198
199 This function also performs validation of the ACPI table fields.
200
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.
205 **/
206 VOID
207 EFIAPI
208 ParseAcpiFadt (
209 IN BOOLEAN Trace,
210 IN UINT8* Ptr,
211 IN UINT32 AcpiTableLength,
212 IN UINT8 AcpiTableRevision
213 )
214 {
215 EFI_STATUS Status;
216 UINT8* DsdtPtr;
217 UINT8* FirmwareCtrlPtr;
218 UINT32 FacsSignature;
219 UINT32 FacsLength;
220 UINT8 FacsRevision;
221 PARSE_ACPI_TABLE_PROC FacsParserProc;
222
223 ParseAcpi (
224 Trace,
225 0,
226 "FADT",
227 Ptr,
228 AcpiTableLength,
229 PARSER_PARAMS (FadtParser)
230 );
231
232 if (Trace) {
233 Print (L"\nSummary:\n");
234 PrintFieldName (2, L"FADT Version");
235 Print (L"%d.%d\n", *AcpiHdrInfo.Revision, *FadtMinorRevision);
236
237 if (*GetAcpiXsdtHeaderInfo ()->OemTableId != *AcpiHdrInfo.OemTableId) {
238 IncrementErrorCount ();
239 Print (L"ERROR: OEM Table Id does not match with RSDT/XSDT.\n");
240 }
241 }
242
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);
249 } else {
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
253 // present.
254 if ((Trace) &&
255 (Flags != NULL) &&
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");
260 }
261 }
262
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);
268
269 // The FACS length is 4 bytes starting at offset 4.
270 FacsLength = *(UINT32*)(FirmwareCtrlPtr + FACS_LENGTH_OFFSET);
271
272 // The FACS version is 1 byte starting at offset 32.
273 FacsRevision = *(UINT8*)(FirmwareCtrlPtr + FACS_VERSION_OFFSET);
274
275 Trace = ProcessTableReportOptions (
276 FacsSignature,
277 FirmwareCtrlPtr,
278 FacsLength
279 );
280
281 Status = GetParser (FacsSignature, &FacsParserProc);
282 if (EFI_ERROR (Status)) {
283 Print (
284 L"ERROR: No registered parser found for FACS.\n"
285 );
286 return;
287 }
288
289 FacsParserProc (
290 Trace,
291 FirmwareCtrlPtr,
292 FacsLength,
293 FacsRevision
294 );
295 }
296
297 // If X_DSDT is not zero then use X_DSDT and ignore DSDT,
298 // else use DSDT.
299 if (*X_DsdtAddress != 0) {
300 DsdtPtr = (UINT8*)(UINTN)(*X_DsdtAddress);
301 } else if (*DsdtAddress != 0) {
302 DsdtPtr = (UINT8*)(UINTN)(*DsdtAddress);
303 } else {
304 // Both DSDT and X_DSDT cannot be zero.
305 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
306 if (Trace) {
307 // The DSDT Table is mandatory for ARM systems
308 // as the CPU information MUST be presented in
309 // the DSDT.
310 IncrementErrorCount ();
311 Print (L"ERROR: Both X_DSDT and DSDT are NULL.\n");
312 }
313 #endif
314 return;
315 }
316
317 ProcessAcpiTable (DsdtPtr);
318 }