]>
Commit | Line | Data |
---|---|---|
a6eaba4d | 1 | /** @file\r |
ee4dc24f RN |
2 | FADT table parser\r |
3 | \r | |
4 | Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.\r | |
5 | This program and the accompanying materials\r | |
6 | are licensed and made available under the terms and conditions of the BSD License\r | |
7 | which accompanies this distribution. The full text of the license may be found at\r | |
8 | http://opensource.org/licenses/bsd-license.php\r | |
9 | \r | |
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
12 | \r | |
13 | @par Reference(s):\r | |
14 | - ACPI 6.2 Specification - Errata A, September 2017\r | |
15 | **/\r | |
16 | \r | |
17 | #include <IndustryStandard/Acpi.h>\r | |
18 | #include <Library/UefiLib.h>\r | |
19 | #include "AcpiParser.h"\r | |
20 | #include "AcpiTableParser.h"\r | |
21 | \r | |
22 | // Local variables\r | |
23 | STATIC CONST UINT32* DsdtAddress;\r | |
24 | STATIC CONST UINT64* X_DsdtAddress;\r | |
25 | STATIC CONST UINT8* FadtMinorRevision;\r | |
26 | STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r | |
27 | \r | |
a6eaba4d DB |
28 | /**\r |
29 | A macro defining the Hardware reduced ACPI flag\r | |
30 | **/\r | |
ee4dc24f RN |
31 | #define HW_REDUCED_ACPI BIT20\r |
32 | \r | |
a6eaba4d DB |
33 | /**\r |
34 | Get the ACPI XSDT header info.\r | |
35 | **/\r | |
ee4dc24f RN |
36 | CONST ACPI_DESCRIPTION_HEADER_INFO* CONST\r |
37 | EFIAPI\r | |
38 | GetAcpiXsdtHeaderInfo (\r | |
39 | VOID\r | |
a6eaba4d | 40 | );\r |
ee4dc24f | 41 | \r |
a6eaba4d DB |
42 | /**\r |
43 | This function validates the Firmware Control Field.\r | |
44 | \r | |
45 | @param [in] Ptr Pointer to the start of the field data.\r | |
46 | @param [in] Context Pointer to context specific information e.g. this\r | |
47 | could be a pointer to the ACPI table header.\r | |
48 | **/\r | |
ee4dc24f RN |
49 | STATIC\r |
50 | VOID\r | |
51 | EFIAPI\r | |
52 | ValidateFirmwareCtrl (\r | |
53 | IN UINT8* Ptr,\r | |
54 | IN VOID* Context\r | |
a6eaba4d DB |
55 | );\r |
56 | \r | |
57 | /**\r | |
58 | This function validates the X_Firmware Control Field.\r | |
ee4dc24f | 59 | \r |
a6eaba4d DB |
60 | @param [in] Ptr Pointer to the start of the field data.\r |
61 | @param [in] Context Pointer to context specific information e.g. this\r | |
62 | could be a pointer to the ACPI table header.\r | |
63 | **/\r | |
ee4dc24f RN |
64 | STATIC\r |
65 | VOID\r | |
66 | EFIAPI\r | |
67 | ValidateXFirmwareCtrl (\r | |
68 | IN UINT8* Ptr,\r | |
69 | IN VOID* Context\r | |
a6eaba4d | 70 | );\r |
ee4dc24f | 71 | \r |
a6eaba4d DB |
72 | /**\r |
73 | This function validates the flags.\r | |
74 | \r | |
75 | @param [in] Ptr Pointer to the start of the field data.\r | |
76 | @param [in] Context Pointer to context specific information e.g. this\r | |
77 | could be a pointer to the ACPI table header.\r | |
78 | **/\r | |
ee4dc24f RN |
79 | STATIC\r |
80 | VOID\r | |
81 | EFIAPI\r | |
82 | ValidateFlags (\r | |
83 | IN UINT8* Ptr,\r | |
84 | IN VOID* Context\r | |
a6eaba4d | 85 | );\r |
ee4dc24f | 86 | \r |
a6eaba4d DB |
87 | /**\r |
88 | An ACPI_PARSER array describing the ACPI FADT Table.\r | |
89 | **/\r | |
ee4dc24f RN |
90 | STATIC CONST ACPI_PARSER FadtParser[] = {\r |
91 | PARSE_ACPI_HEADER (&AcpiHdrInfo),\r | |
92 | {L"FIRMWARE_CTRL", 4, 36, L"0x%x", NULL, NULL, ValidateFirmwareCtrl, NULL},\r | |
93 | {L"DSDT", 4, 40, L"0x%x", NULL, (VOID**)&DsdtAddress, NULL, NULL},\r | |
94 | {L"Reserved", 1, 44, L"%x", NULL, NULL, NULL, NULL},\r | |
95 | {L"Preferred_PM_Profile", 1, 45, L"0x%x", NULL, NULL, NULL, NULL},\r | |
96 | {L"SCI_INT", 2, 46, L"0x%x", NULL, NULL, NULL, NULL},\r | |
97 | {L"SMI_CMD", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},\r | |
98 | {L"ACPI_ENABLE", 1, 52, L"0x%x", NULL, NULL, NULL, NULL},\r | |
99 | {L"ACPI_DISABLE", 1, 53, L"0x%x", NULL, NULL, NULL, NULL},\r | |
100 | {L"S4BIOS_REQ", 1, 54, L"0x%x", NULL, NULL, NULL, NULL},\r | |
101 | {L"PSTATE_CNT", 1, 55, L"0x%x", NULL, NULL, NULL, NULL},\r | |
102 | {L"PM1a_EVT_BLK", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},\r | |
103 | {L"PM1b_EVT_BLK", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},\r | |
104 | {L"PM1a_CNT_BLK", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},\r | |
105 | {L"PM1b_CNT_BLK", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},\r | |
106 | {L"PM2_CNT_BLK", 4, 72, L"0x%x", NULL, NULL, NULL, NULL},\r | |
107 | {L"PM_TMR_BLK", 4, 76, L"0x%x", NULL, NULL, NULL, NULL},\r | |
108 | {L"GPE0_BLK", 4, 80, L"0x%x", NULL, NULL, NULL, NULL},\r | |
109 | {L"GPE1_BLK", 4, 84, L"0x%x", NULL, NULL, NULL, NULL},\r | |
110 | {L"PM1_EVT_LEN", 1, 88, L"0x%x", NULL, NULL, NULL, NULL},\r | |
111 | {L"PM1_CNT_LEN", 1, 89, L"0x%x", NULL, NULL, NULL, NULL},\r | |
112 | {L"PM2_CNT_LEN", 1, 90, L"0x%x", NULL, NULL, NULL, NULL},\r | |
113 | {L"PM_TMR_LEN", 1, 91, L"0x%x", NULL, NULL, NULL, NULL},\r | |
114 | {L"GPE0_BLK_LEN", 1, 92, L"0x%x", NULL, NULL, NULL, NULL},\r | |
115 | {L"GPE1_BLK_LEN", 1, 93, L"0x%x", NULL, NULL, NULL, NULL},\r | |
116 | {L"GPE1_BASE", 1, 94, L"0x%x", NULL, NULL, NULL, NULL},\r | |
117 | {L"CST_CNT", 1, 95, L"0x%x", NULL, NULL, NULL, NULL},\r | |
118 | {L"P_LVL2_LAT", 2, 96, L"0x%x", NULL, NULL, NULL, NULL},\r | |
119 | {L"P_LVL3_LAT", 2, 98, L"0x%x", NULL, NULL, NULL, NULL},\r | |
120 | {L"FLUSH_SIZE", 2, 100, L"0x%x", NULL, NULL, NULL, NULL},\r | |
121 | {L"FLUSH_STRIDE", 2, 102, L"0x%x", NULL, NULL, NULL, NULL},\r | |
122 | {L"DUTY_OFFSET", 1, 104, L"0x%x", NULL, NULL, NULL, NULL},\r | |
123 | {L"DUTY_WIDTH", 1, 105, L"0x%x", NULL, NULL, NULL, NULL},\r | |
124 | {L"DAY_ALRM", 1, 106, L"0x%x", NULL, NULL, NULL, NULL},\r | |
125 | {L"MON_ALRM", 1, 107, L"0x%x", NULL, NULL, NULL, NULL},\r | |
126 | {L"CENTURY", 1, 108, L"0x%x", NULL, NULL, NULL, NULL},\r | |
127 | {L"IAPC_BOOT_ARCH", 2, 109, L"0x%x", NULL, NULL, NULL, NULL},\r | |
128 | {L"Reserved", 1, 111, L"0x%x", NULL, NULL, NULL, NULL},\r | |
129 | {L"Flags", 4, 112, L"0x%x", NULL, NULL, ValidateFlags, NULL},\r | |
130 | {L"RESET_REG", 12, 116, NULL, DumpGas, NULL, NULL, NULL},\r | |
131 | {L"RESET_VALUE", 1, 128, L"0x%x", NULL, NULL, NULL, NULL},\r | |
132 | {L"ARM_BOOT_ARCH", 2, 129, L"0x%x", NULL, NULL, NULL, NULL},\r | |
133 | {L"FADT Minor Version", 1, 131, L"0x%x", NULL, (VOID**)&FadtMinorRevision,\r | |
134 | NULL, NULL},\r | |
135 | {L"X_FIRMWARE_CTRL", 8, 132, L"0x%lx", NULL, NULL,\r | |
136 | ValidateXFirmwareCtrl, NULL},\r | |
137 | {L"X_DSDT", 8, 140, L"0x%lx", NULL, (VOID**)&X_DsdtAddress, NULL, NULL},\r | |
138 | {L"X_PM1a_EVT_BLK", 12, 148, NULL, DumpGas, NULL, NULL, NULL},\r | |
139 | {L"X_PM1b_EVT_BLK", 12, 160, NULL, DumpGas, NULL, NULL, NULL},\r | |
140 | {L"X_PM1a_CNT_BLK", 12, 172, NULL, DumpGas, NULL, NULL, NULL},\r | |
141 | {L"X_PM1b_CNT_BLK", 12, 184, NULL, DumpGas, NULL, NULL, NULL},\r | |
142 | {L"X_PM2_CNT_BLK", 12, 196, NULL, DumpGas, NULL, NULL, NULL},\r | |
143 | {L"X_PM_TMR_BLK", 12, 208, NULL, DumpGas, NULL, NULL, NULL},\r | |
144 | {L"X_GPE0_BLK", 12, 220, NULL, DumpGas, NULL, NULL, NULL},\r | |
145 | {L"X_GPE1_BLK", 12, 232, NULL, DumpGas, NULL, NULL, NULL},\r | |
146 | {L"SLEEP_CONTROL_REG", 12, 244, NULL, DumpGas, NULL, NULL, NULL},\r | |
147 | {L"SLEEP_STATUS_REG", 12, 256, NULL, DumpGas, NULL, NULL, NULL},\r | |
148 | {L"Hypervisor VendorIdentity", 8, 268, L"%lx", NULL, NULL, NULL, NULL}\r | |
149 | };\r | |
150 | \r | |
a6eaba4d DB |
151 | /**\r |
152 | This function validates the Firmware Control Field.\r | |
ee4dc24f RN |
153 | \r |
154 | @param [in] Ptr Pointer to the start of the field data.\r | |
155 | @param [in] Context Pointer to context specific information e.g. this\r | |
156 | could be a pointer to the ACPI table header.\r | |
a6eaba4d | 157 | **/\r |
ee4dc24f RN |
158 | STATIC\r |
159 | VOID\r | |
160 | EFIAPI\r | |
161 | ValidateFirmwareCtrl (\r | |
162 | IN UINT8* Ptr,\r | |
163 | IN VOID* Context\r | |
164 | )\r | |
165 | {\r | |
166 | #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r | |
167 | if (*(UINT32*)Ptr != 0) {\r | |
168 | IncrementErrorCount ();\r | |
169 | Print (\r | |
170 | L"\nERROR: Firmware Control must be zero for ARM platforms."\r | |
171 | );\r | |
172 | }\r | |
173 | #endif\r | |
174 | }\r | |
175 | \r | |
a6eaba4d DB |
176 | /**\r |
177 | This function validates the X_Firmware Control Field.\r | |
ee4dc24f RN |
178 | \r |
179 | @param [in] Ptr Pointer to the start of the field data.\r | |
180 | @param [in] Context Pointer to context specific information e.g. this\r | |
181 | could be a pointer to the ACPI table header.\r | |
a6eaba4d | 182 | **/\r |
ee4dc24f RN |
183 | STATIC\r |
184 | VOID\r | |
185 | EFIAPI\r | |
186 | ValidateXFirmwareCtrl (\r | |
187 | IN UINT8* Ptr,\r | |
188 | IN VOID* Context\r | |
189 | )\r | |
190 | {\r | |
191 | #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r | |
192 | if (*(UINT64*)Ptr != 0) {\r | |
193 | IncrementErrorCount ();\r | |
194 | Print (\r | |
195 | L"\nERROR: X Firmware Control must be zero for ARM platforms."\r | |
196 | );\r | |
197 | }\r | |
198 | #endif\r | |
199 | }\r | |
200 | \r | |
a6eaba4d DB |
201 | /**\r |
202 | This function validates the flags.\r | |
ee4dc24f RN |
203 | \r |
204 | @param [in] Ptr Pointer to the start of the field data.\r | |
205 | @param [in] Context Pointer to context specific information e.g. this\r | |
206 | could be a pointer to the ACPI table header.\r | |
a6eaba4d | 207 | **/\r |
ee4dc24f RN |
208 | STATIC\r |
209 | VOID\r | |
210 | EFIAPI\r | |
211 | ValidateFlags (\r | |
212 | IN UINT8* Ptr,\r | |
213 | IN VOID* Context\r | |
214 | )\r | |
215 | {\r | |
216 | #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r | |
217 | if (((*(UINT32*)Ptr) & HW_REDUCED_ACPI) == 0) {\r | |
218 | IncrementErrorCount ();\r | |
219 | Print (\r | |
220 | L"\nERROR: HW_REDUCED_ACPI flag must be set for ARM platforms."\r | |
221 | );\r | |
222 | }\r | |
223 | #endif\r | |
224 | }\r | |
225 | \r | |
a6eaba4d DB |
226 | /**\r |
227 | This function parses the ACPI FADT table.\r | |
228 | This function parses the FADT table and optionally traces the ACPI table fields.\r | |
ee4dc24f RN |
229 | \r |
230 | This function also performs validation of the ACPI table fields.\r | |
231 | \r | |
232 | @param [in] Trace If TRUE, trace the ACPI fields.\r | |
233 | @param [in] Ptr Pointer to the start of the buffer.\r | |
234 | @param [in] AcpiTableLength Length of the ACPI table.\r | |
235 | @param [in] AcpiTableRevision Revision of the ACPI table.\r | |
a6eaba4d | 236 | **/\r |
ee4dc24f RN |
237 | VOID\r |
238 | EFIAPI\r | |
239 | ParseAcpiFadt (\r | |
240 | IN BOOLEAN Trace,\r | |
241 | IN UINT8* Ptr,\r | |
242 | IN UINT32 AcpiTableLength,\r | |
243 | IN UINT8 AcpiTableRevision\r | |
244 | )\r | |
245 | {\r | |
246 | UINT8* DsdtPtr;\r | |
247 | \r | |
248 | ParseAcpi (\r | |
249 | Trace,\r | |
250 | 0,\r | |
251 | "FADT",\r | |
252 | Ptr,\r | |
253 | AcpiTableLength,\r | |
254 | PARSER_PARAMS (FadtParser)\r | |
255 | );\r | |
256 | \r | |
257 | if (Trace) {\r | |
258 | Print (L"\nSummary:\n");\r | |
259 | PrintFieldName (2, L"FADT Version");\r | |
260 | Print (L"%d.%d\n", *AcpiHdrInfo.Revision, *FadtMinorRevision);\r | |
261 | \r | |
262 | if (*GetAcpiXsdtHeaderInfo ()->OemTableId != *AcpiHdrInfo.OemTableId) {\r | |
263 | IncrementErrorCount ();\r | |
264 | Print (L"ERROR: OEM Table Id does not match with RSDT/XSDT.\n");\r | |
265 | }\r | |
266 | }\r | |
267 | \r | |
268 | // If X_DSDT is not zero then use X_DSDT and ignore DSDT,\r | |
269 | // else use DSDT.\r | |
270 | if (*X_DsdtAddress != 0) {\r | |
271 | DsdtPtr = (UINT8*)(UINTN)(*X_DsdtAddress);\r | |
272 | } else if (*DsdtAddress != 0) {\r | |
273 | DsdtPtr = (UINT8*)(UINTN)(*DsdtAddress);\r | |
274 | } else {\r | |
275 | // Both DSDT and X_DSDT cannot be zero.\r | |
276 | #if defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)\r | |
277 | if (Trace) {\r | |
278 | // The DSDT Table is mandatory for ARM systems\r | |
279 | // as the CPU information MUST be presented in\r | |
280 | // the DSDT.\r | |
281 | IncrementErrorCount ();\r | |
282 | Print (L"ERROR: Both X_DSDT and DSDT are NULL.\n");\r | |
283 | }\r | |
284 | #endif\r | |
285 | return;\r | |
286 | }\r | |
287 | \r | |
288 | ProcessAcpiTable (DsdtPtr);\r | |
289 | }\r |