0ab460b02c9e062ac181e42e7e77f875a40c86dc
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Gtdt / GtdtParser.c
1 /** @file\r
2   GTDT 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* GtdtPlatformTimerCount;\r
24 STATIC CONST UINT32* GtdtPlatformTimerOffset;\r
25 STATIC CONST UINT8*  PlatformTimerType;\r
26 STATIC CONST UINT16* PlatformTimerLength;\r
27 STATIC CONST UINT32* GtBlockTimerCount;\r
28 STATIC CONST UINT32* GtBlockTimerOffset;\r
29 STATIC CONST UINT16* GtBlockLength;\r
30 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
31 \r
32 /**\r
33   This function validates the GT Block timer count.\r
34 \r
35   @param [in] Ptr     Pointer to the start of the field data.\r
36   @param [in] Context Pointer to context specific information e.g. this\r
37                       could be a pointer to the ACPI table header.\r
38 **/\r
39 STATIC\r
40 VOID\r
41 EFIAPI\r
42 ValidateGtBlockTimerCount (\r
43   IN UINT8* Ptr,\r
44   IN VOID*  Context\r
45   );\r
46 \r
47 /**\r
48   An ACPI_PARSER array describing the ACPI GTDT Table.\r
49 **/\r
50 STATIC CONST ACPI_PARSER GtdtParser[] = {\r
51   PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
52   {L"CntControlBase Physical Address", 8, 36, L"0x%lx", NULL, NULL,\r
53    NULL, NULL},\r
54   {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL},\r
55   {L"Secure EL1 timer GSIV", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},\r
56   {L"Secure EL1 timer FLAGS", 4, 52, L"0x%x", NULL, NULL, NULL, NULL},\r
57 \r
58   {L"Non-Secure EL1 timer GSIV", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},\r
59   {L"Non-Secure EL1 timer FLAGS", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},\r
60 \r
61   {L"Virtual timer GSIV", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},\r
62   {L"Virtual timer FLAGS", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},\r
63 \r
64   {L"Non-Secure EL2 timer GSIV", 4, 72, L"0x%x", NULL, NULL, NULL, NULL},\r
65   {L"Non-Secure EL2 timer FLAGS", 4, 76, L"0x%x", NULL, NULL, NULL, NULL},\r
66 \r
67   {L"CntReadBase Physical address", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL},\r
68   {L"Platform Timer Count", 4, 88, L"%d", NULL,\r
69    (VOID**)&GtdtPlatformTimerCount, NULL, NULL},\r
70   {L"Platform Timer Offset", 4, 92, L"0x%x", NULL,\r
71    (VOID**)&GtdtPlatformTimerOffset, NULL, NULL}\r
72 };\r
73 \r
74 /**\r
75   An ACPI_PARSER array describing the Platform timer header.\r
76 **/\r
77 STATIC CONST ACPI_PARSER GtPlatformTimerHeaderParser[] = {\r
78   {L"Type", 1, 0, NULL, NULL, (VOID**)&PlatformTimerType, NULL, NULL},\r
79   {L"Length", 2, 1, NULL, NULL, (VOID**)&PlatformTimerLength, NULL, NULL},\r
80   {L"Reserved", 1, 3, NULL, NULL, NULL, NULL, NULL}\r
81 };\r
82 \r
83 /**\r
84   An ACPI_PARSER array describing the Platform GT Block.\r
85 **/\r
86 STATIC CONST ACPI_PARSER GtBlockParser[] = {\r
87   {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
88   {L"Length", 2, 1, L"%d", NULL, (VOID**)&GtBlockLength, NULL, NULL},\r
89   {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL},\r
90   {L"Physical address (CntCtlBase)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},\r
91   {L"Timer Count", 4, 12, L"%d", NULL, (VOID**)&GtBlockTimerCount,\r
92    ValidateGtBlockTimerCount, NULL},\r
93   {L"Timer Offset", 4, 16, L"%d", NULL, (VOID**)&GtBlockTimerOffset, NULL,\r
94     NULL}\r
95 };\r
96 \r
97 /**\r
98   An ACPI_PARSER array describing the GT Block timer.\r
99 **/\r
100 STATIC CONST ACPI_PARSER GtBlockTimerParser[] = {\r
101   {L"Frame Number", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
102   {L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL},\r
103   {L"Physical address (CntBaseX)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},\r
104   {L"Physical address (CntEL0BaseX)", 8, 12, L"0x%lx", NULL, NULL, NULL,\r
105     NULL},\r
106   {L"Physical Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},\r
107   {L"Physical Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
108   {L"Virtual Timer GSIV", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},\r
109   {L"Virtual Timer Flags", 4, 32, L"0x%x", NULL, NULL, NULL, NULL},\r
110   {L"Common Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL}\r
111 };\r
112 \r
113 /**\r
114   An ACPI_PARSER array describing the Platform Watchdog.\r
115 **/\r
116 STATIC CONST ACPI_PARSER SBSAGenericWatchdogParser[] = {\r
117   {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
118   {L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL},\r
119   {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL},\r
120   {L"RefreshFrame Physical address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},\r
121   {L"ControlFrame Physical address", 8, 12, L"0x%lx", NULL, NULL, NULL, NULL},\r
122   {L"Watchdog Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},\r
123   {L"Watchdog Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL}\r
124 };\r
125 \r
126 /**\r
127   This function validates the GT Block timer count.\r
128 \r
129   @param [in] Ptr     Pointer to the start of the field data.\r
130   @param [in] Context Pointer to context specific information e.g. this\r
131                       could be a pointer to the ACPI table header.\r
132 **/\r
133 STATIC\r
134 VOID\r
135 EFIAPI\r
136 ValidateGtBlockTimerCount (\r
137   IN UINT8* Ptr,\r
138   IN VOID*  Context\r
139   )\r
140 {\r
141   UINT32 BlockTimerCount;\r
142 \r
143   BlockTimerCount = *(UINT32*)Ptr;\r
144 \r
145   if (BlockTimerCount > 8) {\r
146     IncrementErrorCount ();\r
147     Print (\r
148       L"\nERROR: Timer Count = %d. Max Timer Count is 8.",\r
149       BlockTimerCount\r
150       );\r
151   }\r
152 }\r
153 \r
154 /**\r
155   This function parses the Platform GT Block.\r
156 \r
157   @param [in] Ptr     Pointer to the start of the GT Block data.\r
158   @param [in] Length  Length of the GT Block structure.\r
159 **/\r
160 STATIC\r
161 VOID\r
162 DumpGTBlock (\r
163   IN UINT8* Ptr,\r
164   IN UINT32 Length\r
165   )\r
166 {\r
167   UINT32 Index;\r
168   UINT32 Offset;\r
169   UINT32 GTBlockTimerLength;\r
170 \r
171   Offset = ParseAcpi (\r
172              TRUE,\r
173              2,\r
174              "GT Block",\r
175              Ptr,\r
176              Length,\r
177              PARSER_PARAMS (GtBlockParser)\r
178              );\r
179   GTBlockTimerLength = (*GtBlockLength - Offset) / (*GtBlockTimerCount);\r
180   Length -= Offset;\r
181 \r
182   if (*GtBlockTimerCount != 0) {\r
183     Ptr += (*GtBlockTimerOffset);\r
184     Index = 0;\r
185     while ((Index < (*GtBlockTimerCount)) && (Length >= GTBlockTimerLength)) {\r
186       Offset = ParseAcpi (\r
187                  TRUE,\r
188                  2,\r
189                  "GT Block Timer",\r
190                  Ptr,\r
191                  GTBlockTimerLength,\r
192                  PARSER_PARAMS (GtBlockTimerParser)\r
193                  );\r
194       // Increment by GT Block Timer structure size\r
195       Ptr += Offset;\r
196       Length -= Offset;\r
197       Index++;\r
198     }\r
199 \r
200     if (Length != 0) {\r
201       IncrementErrorCount ();\r
202       Print (\r
203         L"ERROR:GT Block Timer length mismatch. Unparsed %d bytes.\n",\r
204         Length\r
205         );\r
206     }\r
207   }\r
208 }\r
209 \r
210 /**\r
211   This function parses the Platform Watchdog timer.\r
212 \r
213   @param [in] Ptr     Pointer to the start of the watchdog timer data.\r
214   @param [in] Length  Length of the watchdog timer structure.\r
215 **/\r
216 STATIC\r
217 VOID\r
218 DumpWatchdogTimer (\r
219   IN UINT8* Ptr,\r
220   IN UINT16 Length\r
221   )\r
222 {\r
223   ParseAcpi (\r
224     TRUE,\r
225     2,\r
226     "SBSA Generic Watchdog",\r
227     Ptr,\r
228     Length,\r
229     PARSER_PARAMS (SBSAGenericWatchdogParser)\r
230     );\r
231 }\r
232 \r
233 /**\r
234   This function parses the ACPI GTDT table.\r
235   When trace is enabled this function parses the GTDT table and\r
236   traces the ACPI table fields.\r
237 \r
238   This function also parses the following platform timer structures:\r
239     - GT Block timer\r
240     - Watchdog timer\r
241 \r
242   This function also performs validation of the ACPI table fields.\r
243 \r
244   @param [in] Trace              If TRUE, trace the ACPI fields.\r
245   @param [in] Ptr                Pointer to the start of the buffer.\r
246   @param [in] AcpiTableLength    Length of the ACPI table.\r
247   @param [in] AcpiTableRevision  Revision of the ACPI table.\r
248 **/\r
249 VOID\r
250 EFIAPI\r
251 ParseAcpiGtdt (\r
252   IN BOOLEAN Trace,\r
253   IN UINT8*  Ptr,\r
254   IN UINT32  AcpiTableLength,\r
255   IN UINT8   AcpiTableRevision\r
256   )\r
257 {\r
258   UINT32 Index;\r
259   UINT8* TimerPtr;\r
260 \r
261   if (!Trace) {\r
262     return;\r
263   }\r
264 \r
265   ParseAcpi (\r
266     TRUE,\r
267     0,\r
268     "GTDT",\r
269     Ptr,\r
270     AcpiTableLength,\r
271     PARSER_PARAMS (GtdtParser)\r
272     );\r
273 \r
274   if (*GtdtPlatformTimerCount != 0) {\r
275     TimerPtr = Ptr + (*GtdtPlatformTimerOffset);\r
276     Index = 0;\r
277     do {\r
278       // Parse the Platform Timer Header\r
279       ParseAcpi (\r
280         FALSE,\r
281         0,\r
282         NULL,\r
283         TimerPtr,\r
284         4,  // GT Platform Timer structure header length.\r
285         PARSER_PARAMS (GtPlatformTimerHeaderParser)\r
286         );\r
287       switch (*PlatformTimerType) {\r
288         case EFI_ACPI_6_2_GTDT_GT_BLOCK:\r
289           DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
290           break;\r
291         case EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG:\r
292           DumpWatchdogTimer (TimerPtr, *PlatformTimerLength);\r
293           break;\r
294         default:\r
295           IncrementErrorCount ();\r
296           Print (\r
297             L"ERROR: INVALID Platform Timer Type = %d\n",\r
298             *PlatformTimerType\r
299             );\r
300           break;\r
301       } // switch\r
302       TimerPtr += (*PlatformTimerLength);\r
303       Index++;\r
304     } while (Index < *GtdtPlatformTimerCount);\r
305   }\r
306 }\r