]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c
ShellPkg: Apply uncrustify changes
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Fadt / FadtParser.c
1 /** @file
2 FADT 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 **/
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
78 #endif
79 }
80
81 /**
82 This function validates the X_Firmware Control Field.
83
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.
87 **/
88 STATIC
89 VOID
90 EFIAPI
91 ValidateXFirmwareCtrl (
92 IN UINT8 *Ptr,
93 IN VOID *Context
94 )
95 {
96 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
97 if (*(UINT64 *)Ptr != 0) {
98 IncrementErrorCount ();
99 Print (
100 L"\nERROR: X Firmware Control must be zero for ARM platforms."
101 );
102 }
103
104 #endif
105 }
106
107 /**
108 This function validates the flags.
109
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.
113 **/
114 STATIC
115 VOID
116 EFIAPI
117 ValidateFlags (
118 IN UINT8 *Ptr,
119 IN VOID *Context
120 )
121 {
122 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
123 if (((*(UINT32 *)Ptr) & HW_REDUCED_ACPI) == 0) {
124 IncrementErrorCount ();
125 Print (
126 L"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms."
127 );
128 }
129
130 #endif
131 }
132
133 /**
134 An ACPI_PARSER array describing the ACPI FADT Table.
135 **/
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,
181 NULL, NULL },
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 }
196 };
197
198 /**
199 This function parses the ACPI FADT table.
200 This function parses the FADT table and optionally traces the ACPI table fields.
201
202 This function also performs validation of the ACPI table fields.
203
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.
208 **/
209 VOID
210 EFIAPI
211 ParseAcpiFadt (
212 IN BOOLEAN Trace,
213 IN UINT8 *Ptr,
214 IN UINT32 AcpiTableLength,
215 IN UINT8 AcpiTableRevision
216 )
217 {
218 EFI_STATUS Status;
219 UINT8 *DsdtPtr;
220 UINT8 *FirmwareCtrlPtr;
221 UINT32 FacsSignature;
222 UINT32 FacsLength;
223 UINT8 FacsRevision;
224 PARSE_ACPI_TABLE_PROC FacsParserProc;
225
226 ParseAcpi (
227 Trace,
228 0,
229 "FADT",
230 Ptr,
231 AcpiTableLength,
232 PARSER_PARAMS (FadtParser)
233 );
234
235 if (Trace) {
236 if (FadtMinorRevision != NULL) {
237 Print (L"\nSummary:\n");
238 PrintFieldName (2, L"FADT Version");
239 Print (L"%d.%d\n", *AcpiHdrInfo.Revision, *FadtMinorRevision);
240 }
241
242 if (*GetAcpiXsdtHeaderInfo ()->OemTableId != *AcpiHdrInfo.OemTableId) {
243 IncrementErrorCount ();
244 Print (L"ERROR: OEM Table Id does not match with RSDT/XSDT.\n");
245 }
246 }
247
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);
254 } else {
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
258 // present.
259 if ((Trace) &&
260 (Flags != NULL) &&
261 ((*Flags & EFI_ACPI_6_3_HW_REDUCED_ACPI) != EFI_ACPI_6_3_HW_REDUCED_ACPI))
262 {
263 IncrementErrorCount ();
264 Print (
265 L"ERROR: No FACS table found, "
266 L"both X_FIRMWARE_CTRL and FIRMWARE_CTRL are zero.\n"
267 );
268 }
269 }
270
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);
276
277 // The FACS length is 4 bytes starting at offset 4.
278 FacsLength = *(UINT32 *)(FirmwareCtrlPtr + FACS_LENGTH_OFFSET);
279
280 // The FACS version is 1 byte starting at offset 32.
281 FacsRevision = *(UINT8 *)(FirmwareCtrlPtr + FACS_VERSION_OFFSET);
282
283 Trace = ProcessTableReportOptions (
284 FacsSignature,
285 FirmwareCtrlPtr,
286 FacsLength
287 );
288
289 Status = GetParser (FacsSignature, &FacsParserProc);
290 if (EFI_ERROR (Status)) {
291 Print (
292 L"ERROR: No registered parser found for FACS.\n"
293 );
294 return;
295 }
296
297 FacsParserProc (
298 Trace,
299 FirmwareCtrlPtr,
300 FacsLength,
301 FacsRevision
302 );
303 }
304
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);
310 } else {
311 // Both DSDT and X_DSDT cannot be invalid.
312 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
313 if (Trace) {
314 // The DSDT Table is mandatory for ARM systems
315 // as the CPU information MUST be presented in
316 // the DSDT.
317 IncrementErrorCount ();
318 Print (L"ERROR: Both X_DSDT and DSDT are invalid.\n");
319 }
320
321 #endif
322 return;
323 }
324
325 ProcessAcpiTable (DsdtPtr);
326 }