]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Fadt/FadtParser.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Fadt / FadtParser.c
CommitLineData
a6eaba4d 1/** @file\r
ee4dc24f
RN
2 FADT table parser\r
3\r
54d33a53 4 Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.\r
40004ff9 5 Copyright (c) 2022, AMD Incorporated. All rights reserved.\r
56ba3746 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
ee4dc24f
RN
7\r
8 @par Reference(s):\r
d5cf0fba 9 - ACPI 6.3 Specification - January 2019\r
ee4dc24f
RN
10**/\r
11\r
12#include <IndustryStandard/Acpi.h>\r
13#include <Library/UefiLib.h>\r
14#include "AcpiParser.h"\r
15#include "AcpiTableParser.h"\r
d5cf0fba 16#include "AcpiView.h"\r
ee4dc24f
RN
17\r
18// Local variables\r
47d20b54
MK
19STATIC CONST UINT32 *DsdtAddress;\r
20STATIC CONST UINT64 *X_DsdtAddress;\r
21STATIC CONST UINT32 *Flags;\r
22STATIC CONST UINT32 *FirmwareCtrl;\r
23STATIC CONST UINT64 *X_FirmwareCtrl;\r
24STATIC CONST UINT8 *FadtMinorRevision;\r
25STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
ee4dc24f 26\r
a6eaba4d
DB
27/**\r
28 A macro defining the Hardware reduced ACPI flag\r
29**/\r
47d20b54 30#define HW_REDUCED_ACPI BIT20\r
ee4dc24f 31\r
d5cf0fba
SM
32/**\r
33 Offset to the FACS signature from the start of the FACS.\r
34**/\r
47d20b54 35#define FACS_SIGNATURE_OFFSET 0\r
d5cf0fba
SM
36\r
37/**\r
38 Offset to the FACS revision from the start of the FACS.\r
39**/\r
47d20b54 40#define FACS_VERSION_OFFSET 32\r
d5cf0fba
SM
41\r
42/**\r
43 Offset to the FACS length from the start of the FACS.\r
44**/\r
47d20b54 45#define FACS_LENGTH_OFFSET 4\r
d5cf0fba 46\r
a6eaba4d
DB
47/**\r
48 Get the ACPI XSDT header info.\r
49**/\r
b6e48ec6 50CONST ACPI_DESCRIPTION_HEADER_INFO *\r
ee4dc24f
RN
51EFIAPI\r
52GetAcpiXsdtHeaderInfo (\r
53 VOID\r
a6eaba4d 54 );\r
ee4dc24f 55\r
a6eaba4d
DB
56/**\r
57 This function validates the Firmware Control Field.\r
58\r
59 @param [in] Ptr Pointer to the start of the field data.\r
60 @param [in] Context Pointer to context specific information e.g. this\r
61 could be a pointer to the ACPI table header.\r
62**/\r
ee4dc24f
RN
63STATIC\r
64VOID\r
65EFIAPI\r
66ValidateFirmwareCtrl (\r
47d20b54
MK
67 IN UINT8 *Ptr,\r
68 IN VOID *Context\r
69 )\r
86da432a 70{\r
47d20b54
MK
71 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r
72 if (*(UINT32 *)Ptr != 0) {\r
86da432a
KK
73 IncrementErrorCount ();\r
74 Print (\r
75 L"\nERROR: Firmware Control must be zero for ARM platforms."\r
47d20b54 76 );\r
86da432a 77 }\r
47d20b54
MK
78\r
79 #endif\r
86da432a 80}\r
a6eaba4d
DB
81\r
82/**\r
83 This function validates the X_Firmware Control Field.\r
ee4dc24f 84\r
a6eaba4d
DB
85 @param [in] Ptr Pointer to the start of the field data.\r
86 @param [in] Context Pointer to context specific information e.g. this\r
87 could be a pointer to the ACPI table header.\r
88**/\r
ee4dc24f
RN
89STATIC\r
90VOID\r
91EFIAPI\r
92ValidateXFirmwareCtrl (\r
47d20b54
MK
93 IN UINT8 *Ptr,\r
94 IN VOID *Context\r
95 )\r
86da432a 96{\r
47d20b54
MK
97 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r
98 if (*(UINT64 *)Ptr != 0) {\r
86da432a
KK
99 IncrementErrorCount ();\r
100 Print (\r
101 L"\nERROR: X Firmware Control must be zero for ARM platforms."\r
47d20b54 102 );\r
86da432a 103 }\r
47d20b54
MK
104\r
105 #endif\r
86da432a 106}\r
ee4dc24f 107\r
a6eaba4d
DB
108/**\r
109 This function validates the flags.\r
110\r
111 @param [in] Ptr Pointer to the start of the field data.\r
112 @param [in] Context Pointer to context specific information e.g. this\r
113 could be a pointer to the ACPI table header.\r
114**/\r
ee4dc24f
RN
115STATIC\r
116VOID\r
117EFIAPI\r
118ValidateFlags (\r
47d20b54
MK
119 IN UINT8 *Ptr,\r
120 IN VOID *Context\r
121 )\r
86da432a 122{\r
47d20b54
MK
123 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r
124 if (((*(UINT32 *)Ptr) & HW_REDUCED_ACPI) == 0) {\r
86da432a
KK
125 IncrementErrorCount ();\r
126 Print (\r
127 L"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms."\r
47d20b54 128 );\r
86da432a 129 }\r
47d20b54
MK
130\r
131 #endif\r
86da432a 132}\r
ee4dc24f 133\r
40004ff9
ALA
134STATIC CONST ACPI_PARSER FadtFlagParser[] = {\r
135 { L"WBINVD", 1, 0, L"%d", NULL, NULL, NULL, NULL },\r
136 { L"WBINVD_FLUSH", 1, 1, L"%d", NULL, NULL, NULL, NULL },\r
137 { L"PROC_C1", 1, 2, L"%d", NULL, NULL, NULL, NULL },\r
138 { L"P_LVL2_UP", 1, 3, L"%d", NULL, NULL, NULL, NULL },\r
139 { L"PWR_BUTTON", 1, 4, L"%d", NULL, NULL, NULL, NULL },\r
140 { L"SLP_BUTTON", 1, 5, L"%d", NULL, NULL, NULL, NULL },\r
141 { L"FIX_RTC", 1, 6, L"%d", NULL, NULL, NULL, NULL },\r
142 { L"RTC_S4", 1, 7, L"%d", NULL, NULL, NULL, NULL },\r
143 { L"TMR_VAL_EXT", 1, 8, L"%d", NULL, NULL, NULL, NULL },\r
144 { L"DCK_CAP", 1, 9, L"%d", NULL, NULL, NULL, NULL },\r
145 { L"RESET_REG_SUP", 1, 10, L"%d", NULL, NULL, NULL, NULL },\r
146 { L"SEALED_CASE", 1, 11, L"%d", NULL, NULL, NULL, NULL },\r
147 { L"HEADLESS", 1, 12, L"%d", NULL, NULL, NULL, NULL },\r
148 { L"CPU_SW_SLP", 1, 13, L"%d", NULL, NULL, NULL, NULL },\r
149 { L"PCI_EXP_WAK", 1, 14, L"%d", NULL, NULL, NULL, NULL },\r
150 { L"USE_PLATFORM_CLOCK", 1, 15, L"%d", NULL, NULL, NULL, NULL },\r
151 { L"S4_RTC_STS_VALID", 1, 16, L"%d", NULL, NULL, NULL, NULL },\r
152 { L"REMOTE_POWER_ON_CAPABLE", 1, 17, L"%d", NULL, NULL, NULL, NULL },\r
153 { L"FORCE_APIC_CLUSTER_MODEL", 1, 18, L"%d", NULL, NULL, NULL, NULL },\r
154 { L"FORCE_APIC_PHYSICAL_DESTINATION_MODE", 1, 19, L"%d", NULL, NULL, NULL, NULL },\r
155 { L"HW_REDUCED_ACPI", 1, 20, L"%d", NULL, NULL, NULL, NULL },\r
156 { L"LOW_POWER_S0_IDLE_CAPABLE", 1, 21, L"%d", NULL, NULL, NULL, NULL },\r
157 { L"Reserved", 10, 22, L"%d", NULL, NULL, NULL, NULL }\r
158};\r
159\r
160/**\r
161 This function traces FADT Flags fields.\r
162 If no format string is specified the Format must be NULL.\r
163\r
164 @param [in] Format Optional format string for tracing the data.\r
165 @param [in] Ptr Pointer to the start of the buffer.\r
166**/\r
167VOID\r
168EFIAPI\r
169DumpFadtFlags (\r
170 IN CONST CHAR16 *Format OPTIONAL,\r
171 IN UINT8 *Ptr\r
172 )\r
173{\r
174 if (Format != NULL) {\r
175 Print (Format, *(UINT32 *)Ptr);\r
176 return;\r
177 }\r
178\r
179 Print (L"0x%X\n", *(UINT32 *)Ptr);\r
180 ParseAcpiBitFields (\r
181 TRUE,\r
182 2,\r
183 NULL,\r
184 Ptr,\r
185 4,\r
186 PARSER_PARAMS (FadtFlagParser)\r
187 );\r
188}\r
189\r
a6eaba4d
DB
190/**\r
191 An ACPI_PARSER array describing the ACPI FADT Table.\r
192**/\r
47d20b54 193STATIC CONST ACPI_PARSER FadtParser[] = {\r
ee4dc24f 194 PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
40004ff9 195 { L"FIRMWARE_CTRL", 4, 36, L"0x%x", NULL, (VOID **)&FirmwareCtrl,\r
47d20b54 196 ValidateFirmwareCtrl, NULL },\r
40004ff9
ALA
197 { L"DSDT", 4, 40, L"0x%x", NULL, (VOID **)&DsdtAddress, NULL, NULL },\r
198 { L"Reserved", 1, 44, L"%x", NULL, NULL, NULL, NULL },\r
199 { L"Preferred_PM_Profile", 1, 45, L"0x%x", NULL, NULL, NULL, NULL },\r
200 { L"SCI_INT", 2, 46, L"0x%x", NULL, NULL, NULL, NULL },\r
201 { L"SMI_CMD", 4, 48, L"0x%x", NULL, NULL, NULL, NULL },\r
202 { L"ACPI_ENABLE", 1, 52, L"0x%x", NULL, NULL, NULL, NULL },\r
203 { L"ACPI_DISABLE", 1, 53, L"0x%x", NULL, NULL, NULL, NULL },\r
204 { L"S4BIOS_REQ", 1, 54, L"0x%x", NULL, NULL, NULL, NULL },\r
205 { L"PSTATE_CNT", 1, 55, L"0x%x", NULL, NULL, NULL, NULL },\r
206 { L"PM1a_EVT_BLK", 4, 56, L"0x%x", NULL, NULL, NULL, NULL },\r
207 { L"PM1b_EVT_BLK", 4, 60, L"0x%x", NULL, NULL, NULL, NULL },\r
208 { L"PM1a_CNT_BLK", 4, 64, L"0x%x", NULL, NULL, NULL, NULL },\r
209 { L"PM1b_CNT_BLK", 4, 68, L"0x%x", NULL, NULL, NULL, NULL },\r
210 { L"PM2_CNT_BLK", 4, 72, L"0x%x", NULL, NULL, NULL, NULL },\r
211 { L"PM_TMR_BLK", 4, 76, L"0x%x", NULL, NULL, NULL, NULL },\r
212 { L"GPE0_BLK", 4, 80, L"0x%x", NULL, NULL, NULL, NULL },\r
213 { L"GPE1_BLK", 4, 84, L"0x%x", NULL, NULL, NULL, NULL },\r
214 { L"PM1_EVT_LEN", 1, 88, L"0x%x", NULL, NULL, NULL, NULL },\r
215 { L"PM1_CNT_LEN", 1, 89, L"0x%x", NULL, NULL, NULL, NULL },\r
216 { L"PM2_CNT_LEN", 1, 90, L"0x%x", NULL, NULL, NULL, NULL },\r
217 { L"PM_TMR_LEN", 1, 91, L"0x%x", NULL, NULL, NULL, NULL },\r
218 { L"GPE0_BLK_LEN", 1, 92, L"0x%x", NULL, NULL, NULL, NULL },\r
219 { L"GPE1_BLK_LEN", 1, 93, L"0x%x", NULL, NULL, NULL, NULL },\r
220 { L"GPE1_BASE", 1, 94, L"0x%x", NULL, NULL, NULL, NULL },\r
221 { L"CST_CNT", 1, 95, L"0x%x", NULL, NULL, NULL, NULL },\r
222 { L"P_LVL2_LAT", 2, 96, L"0x%x", NULL, NULL, NULL, NULL },\r
223 { L"P_LVL3_LAT", 2, 98, L"0x%x", NULL, NULL, NULL, NULL },\r
224 { L"FLUSH_SIZE", 2, 100, L"0x%x", NULL, NULL, NULL, NULL },\r
225 { L"FLUSH_STRIDE", 2, 102, L"0x%x", NULL, NULL, NULL, NULL },\r
226 { L"DUTY_OFFSET", 1, 104, L"0x%x", NULL, NULL, NULL, NULL },\r
227 { L"DUTY_WIDTH", 1, 105, L"0x%x", NULL, NULL, NULL, NULL },\r
228 { L"DAY_ALRM", 1, 106, L"0x%x", NULL, NULL, NULL, NULL },\r
229 { L"MON_ALRM", 1, 107, L"0x%x", NULL, NULL, NULL, NULL },\r
230 { L"CENTURY", 1, 108, L"0x%x", NULL, NULL, NULL, NULL },\r
231 { L"IAPC_BOOT_ARCH", 2, 109, L"0x%x", NULL, NULL, NULL, NULL },\r
232 { L"Reserved", 1, 111, L"0x%x", NULL, NULL, NULL, NULL },\r
233 { L"Flags", 4, 112, NULL, DumpFadtFlags, (VOID **)&Flags, ValidateFlags, NULL },\r
234 { L"RESET_REG", 12, 116, NULL, DumpGas, NULL, NULL, NULL },\r
235 { L"RESET_VALUE", 1, 128, L"0x%x", NULL, NULL, NULL, NULL },\r
236 { L"ARM_BOOT_ARCH", 2, 129, L"0x%x", NULL, NULL, NULL, NULL },\r
237 { L"FADT Minor Version", 1, 131, L"0x%x", NULL, (VOID **)&FadtMinorRevision,\r
47d20b54 238 NULL, NULL },\r
40004ff9 239 { L"X_FIRMWARE_CTRL", 8, 132, L"0x%lx", NULL, (VOID **)&X_FirmwareCtrl,\r
47d20b54 240 ValidateXFirmwareCtrl, NULL },\r
40004ff9
ALA
241 { L"X_DSDT", 8, 140, L"0x%lx", NULL, (VOID **)&X_DsdtAddress, NULL, NULL },\r
242 { L"X_PM1a_EVT_BLK", 12, 148, NULL, DumpGas, NULL, NULL, NULL },\r
243 { L"X_PM1b_EVT_BLK", 12, 160, NULL, DumpGas, NULL, NULL, NULL },\r
244 { L"X_PM1a_CNT_BLK", 12, 172, NULL, DumpGas, NULL, NULL, NULL },\r
245 { L"X_PM1b_CNT_BLK", 12, 184, NULL, DumpGas, NULL, NULL, NULL },\r
246 { L"X_PM2_CNT_BLK", 12, 196, NULL, DumpGas, NULL, NULL, NULL },\r
247 { L"X_PM_TMR_BLK", 12, 208, NULL, DumpGas, NULL, NULL, NULL },\r
248 { L"X_GPE0_BLK", 12, 220, NULL, DumpGas, NULL, NULL, NULL },\r
249 { L"X_GPE1_BLK", 12, 232, NULL, DumpGas, NULL, NULL, NULL },\r
250 { L"SLEEP_CONTROL_REG", 12, 244, NULL, DumpGas, NULL, NULL, NULL },\r
251 { L"SLEEP_STATUS_REG", 12, 256, NULL, DumpGas, NULL, NULL, NULL },\r
252 { L"Hypervisor VendorIdentity", 8, 268, L"%lx", NULL, NULL, NULL, NULL }\r
ee4dc24f
RN
253};\r
254\r
a6eaba4d
DB
255/**\r
256 This function parses the ACPI FADT table.\r
257 This function parses the FADT table and optionally traces the ACPI table fields.\r
ee4dc24f
RN
258\r
259 This function also performs validation of the ACPI table fields.\r
260\r
261 @param [in] Trace If TRUE, trace the ACPI fields.\r
262 @param [in] Ptr Pointer to the start of the buffer.\r
263 @param [in] AcpiTableLength Length of the ACPI table.\r
264 @param [in] AcpiTableRevision Revision of the ACPI table.\r
a6eaba4d 265**/\r
ee4dc24f
RN
266VOID\r
267EFIAPI\r
268ParseAcpiFadt (\r
47d20b54
MK
269 IN BOOLEAN Trace,\r
270 IN UINT8 *Ptr,\r
271 IN UINT32 AcpiTableLength,\r
272 IN UINT8 AcpiTableRevision\r
ee4dc24f
RN
273 )\r
274{\r
47d20b54
MK
275 EFI_STATUS Status;\r
276 UINT8 *DsdtPtr;\r
277 UINT8 *FirmwareCtrlPtr;\r
278 UINT32 FacsSignature;\r
279 UINT32 FacsLength;\r
280 UINT8 FacsRevision;\r
281 PARSE_ACPI_TABLE_PROC FacsParserProc;\r
ee4dc24f
RN
282\r
283 ParseAcpi (\r
284 Trace,\r
285 0,\r
286 "FADT",\r
287 Ptr,\r
288 AcpiTableLength,\r
289 PARSER_PARAMS (FadtParser)\r
290 );\r
291\r
292 if (Trace) {\r
54d33a53
KK
293 if (FadtMinorRevision != NULL) {\r
294 Print (L"\nSummary:\n");\r
295 PrintFieldName (2, L"FADT Version");\r
47d20b54 296 Print (L"%d.%d\n", *AcpiHdrInfo.Revision, *FadtMinorRevision);\r
54d33a53 297 }\r
ee4dc24f
RN
298\r
299 if (*GetAcpiXsdtHeaderInfo ()->OemTableId != *AcpiHdrInfo.OemTableId) {\r
300 IncrementErrorCount ();\r
301 Print (L"ERROR: OEM Table Id does not match with RSDT/XSDT.\n");\r
302 }\r
303 }\r
304\r
d5cf0fba
SM
305 // If X_FIRMWARE_CTRL is not zero then use X_FIRMWARE_CTRL and ignore\r
306 // FIRMWARE_CTRL, else use FIRMWARE_CTRL.\r
307 if ((X_FirmwareCtrl != NULL) && (*X_FirmwareCtrl != 0)) {\r
47d20b54 308 FirmwareCtrlPtr = (UINT8 *)(UINTN)(*X_FirmwareCtrl);\r
d5cf0fba 309 } else if ((FirmwareCtrl != NULL) && (*FirmwareCtrl != 0)) {\r
47d20b54 310 FirmwareCtrlPtr = (UINT8 *)(UINTN)(*FirmwareCtrl);\r
d5cf0fba
SM
311 } else {\r
312 FirmwareCtrlPtr = NULL;\r
313 // if HW_REDUCED_ACPI flag is not set, both FIRMWARE_CTRL and\r
314 // X_FIRMWARE_CTRL cannot be zero, and the FACS Table must be\r
315 // present.\r
316 if ((Trace) &&\r
317 (Flags != NULL) &&\r
47d20b54
MK
318 ((*Flags & EFI_ACPI_6_3_HW_REDUCED_ACPI) != EFI_ACPI_6_3_HW_REDUCED_ACPI))\r
319 {\r
d5cf0fba 320 IncrementErrorCount ();\r
47d20b54
MK
321 Print (\r
322 L"ERROR: No FACS table found, "\r
323 L"both X_FIRMWARE_CTRL and FIRMWARE_CTRL are zero.\n"\r
324 );\r
d5cf0fba
SM
325 }\r
326 }\r
327\r
328 if (FirmwareCtrlPtr != NULL) {\r
329 // The FACS table does not have a standard ACPI table header. Therefore,\r
330 // the signature, length and version needs to be initially parsed.\r
331 // The FACS signature is 4 bytes starting at offset 0.\r
47d20b54 332 FacsSignature = *(UINT32 *)(FirmwareCtrlPtr + FACS_SIGNATURE_OFFSET);\r
d5cf0fba
SM
333\r
334 // The FACS length is 4 bytes starting at offset 4.\r
47d20b54 335 FacsLength = *(UINT32 *)(FirmwareCtrlPtr + FACS_LENGTH_OFFSET);\r
d5cf0fba
SM
336\r
337 // The FACS version is 1 byte starting at offset 32.\r
47d20b54 338 FacsRevision = *(UINT8 *)(FirmwareCtrlPtr + FACS_VERSION_OFFSET);\r
d5cf0fba
SM
339\r
340 Trace = ProcessTableReportOptions (\r
341 FacsSignature,\r
342 FirmwareCtrlPtr,\r
343 FacsLength\r
344 );\r
345\r
346 Status = GetParser (FacsSignature, &FacsParserProc);\r
347 if (EFI_ERROR (Status)) {\r
348 Print (\r
349 L"ERROR: No registered parser found for FACS.\n"\r
350 );\r
351 return;\r
352 }\r
353\r
354 FacsParserProc (\r
355 Trace,\r
356 FirmwareCtrlPtr,\r
357 FacsLength,\r
358 FacsRevision\r
359 );\r
360 }\r
361\r
54d33a53
KK
362 // If X_DSDT is valid then use X_DSDT and ignore DSDT, else use DSDT.\r
363 if ((X_DsdtAddress != NULL) && (*X_DsdtAddress != 0)) {\r
47d20b54 364 DsdtPtr = (UINT8 *)(UINTN)(*X_DsdtAddress);\r
54d33a53 365 } else if ((DsdtAddress != NULL) && (*DsdtAddress != 0)) {\r
47d20b54 366 DsdtPtr = (UINT8 *)(UINTN)(*DsdtAddress);\r
ee4dc24f 367 } else {\r
54d33a53 368 // Both DSDT and X_DSDT cannot be invalid.\r
47d20b54 369 #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r
ee4dc24f
RN
370 if (Trace) {\r
371 // The DSDT Table is mandatory for ARM systems\r
372 // as the CPU information MUST be presented in\r
373 // the DSDT.\r
374 IncrementErrorCount ();\r
54d33a53 375 Print (L"ERROR: Both X_DSDT and DSDT are invalid.\n");\r
ee4dc24f 376 }\r
47d20b54
MK
377\r
378 #endif\r
ee4dc24f
RN
379 return;\r
380 }\r
381\r
382 ProcessAcpiTable (DsdtPtr);\r
383}\r