ShellPkg/UefiShellAcpiViewCommandLib: Fix ECC issues
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Fadt / FadtParser.c
1 /** @file\r
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
28 /**\r
29   A macro defining the Hardware reduced ACPI flag\r
30 **/\r
31 #define HW_REDUCED_ACPI   BIT20\r
32 \r
33 /**\r
34   Get the ACPI XSDT header info.\r
35 **/\r
36 CONST ACPI_DESCRIPTION_HEADER_INFO* CONST\r
37 EFIAPI\r
38 GetAcpiXsdtHeaderInfo (\r
39   VOID\r
40   );\r
41 \r
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
49 STATIC\r
50 VOID\r
51 EFIAPI\r
52 ValidateFirmwareCtrl (\r
53   IN UINT8* Ptr,\r
54   IN VOID*  Context\r
55   );\r
56 \r
57 /**\r
58   This function validates the X_Firmware Control Field.\r
59 \r
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
64 STATIC\r
65 VOID\r
66 EFIAPI\r
67 ValidateXFirmwareCtrl (\r
68   IN UINT8* Ptr,\r
69   IN VOID*  Context\r
70   );\r
71 \r
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
79 STATIC\r
80 VOID\r
81 EFIAPI\r
82 ValidateFlags (\r
83   IN UINT8* Ptr,\r
84   IN VOID*  Context\r
85   );\r
86 \r
87 /**\r
88   An ACPI_PARSER array describing the ACPI FADT Table.\r
89 **/\r
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
151 /**\r
152   This function validates the Firmware Control Field.\r
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
157 **/\r
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
176 /**\r
177   This function validates the X_Firmware Control Field.\r
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
182 **/\r
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
201 /**\r
202   This function validates the flags.\r
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
207 **/\r
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
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
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
236 **/\r
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