30cf3e14f7e776384d8c1c09d5acd29f7c7459b7
[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 = *(UINT32*)Ptr;\r
142   if (BlockTimerCount > 8) {\r
143     IncrementErrorCount ();\r
144     Print (\r
145       L"\nERROR: Timer Count = %d. Max Timer Count is 8.",\r
146       BlockTimerCount\r
147       );\r
148   }\r
149 }\r
150 \r
151 /**\r
152   This function parses the Platform GT Block.\r
153 \r
154   @param [in] Ptr     Pointer to the start of the GT Block data.\r
155   @param [in] Length  Length of the GT Block structure.\r
156 **/\r
157 STATIC\r
158 VOID\r
159 DumpGTBlock (\r
160   IN UINT8* Ptr,\r
161   IN UINT16 Length\r
162   )\r
163 {\r
164   UINT32 Index;\r
165   UINT32 Offset;\r
166   UINT16 GTBlockTimerLength;\r
167 \r
168   Offset = ParseAcpi (\r
169              TRUE,\r
170              2,\r
171              "GT Block",\r
172              Ptr,\r
173              Length,\r
174              PARSER_PARAMS (GtBlockParser)\r
175              );\r
176   GTBlockTimerLength = (*GtBlockLength - Offset) / (*GtBlockTimerCount);\r
177   Length -= Offset;\r
178 \r
179   if (*GtBlockTimerCount != 0) {\r
180     Ptr += (*GtBlockTimerOffset);\r
181     Index = 0;\r
182     while ((Index < (*GtBlockTimerCount)) && (Length >= GTBlockTimerLength)) {\r
183       Offset = ParseAcpi (\r
184                  TRUE,\r
185                  2,\r
186                  "GT Block Timer",\r
187                  Ptr,\r
188                  GTBlockTimerLength,\r
189                  PARSER_PARAMS (GtBlockTimerParser)\r
190                  );\r
191       // Increment by GT Block Timer structure size\r
192       Ptr += Offset;\r
193       Length -= Offset;\r
194       Index++;\r
195     }\r
196 \r
197     if (Length != 0) {\r
198       IncrementErrorCount ();\r
199       Print (\r
200         L"ERROR:GT Block Timer length mismatch. Unparsed %d bytes.\n",\r
201         Length\r
202         );\r
203     }\r
204   }\r
205 }\r
206 \r
207 /**\r
208   This function parses the Platform Watchdog timer.\r
209 \r
210   @param [in] Ptr     Pointer to the start of the watchdog timer data.\r
211   @param [in] Length  Length of the watchdog timer structure.\r
212 **/\r
213 STATIC\r
214 VOID\r
215 DumpWatchdogTimer (\r
216   IN UINT8* Ptr,\r
217   IN UINT16 Length\r
218   )\r
219 {\r
220   ParseAcpi (\r
221     TRUE,\r
222     2,\r
223     "SBSA Generic Watchdog",\r
224     Ptr,\r
225     Length,\r
226     PARSER_PARAMS (SBSAGenericWatchdogParser)\r
227     );\r
228 }\r
229 \r
230 /**\r
231   This function parses the ACPI GTDT table.\r
232   When trace is enabled this function parses the GTDT table and\r
233   traces the ACPI table fields.\r
234 \r
235   This function also parses the following platform timer structures:\r
236     - GT Block timer\r
237     - Watchdog timer\r
238 \r
239   This function also performs validation of the ACPI table fields.\r
240 \r
241   @param [in] Trace              If TRUE, trace the ACPI fields.\r
242   @param [in] Ptr                Pointer to the start of the buffer.\r
243   @param [in] AcpiTableLength    Length of the ACPI table.\r
244   @param [in] AcpiTableRevision  Revision of the ACPI table.\r
245 **/\r
246 VOID\r
247 EFIAPI\r
248 ParseAcpiGtdt (\r
249   IN BOOLEAN Trace,\r
250   IN UINT8*  Ptr,\r
251   IN UINT32  AcpiTableLength,\r
252   IN UINT8   AcpiTableRevision\r
253   )\r
254 {\r
255   UINT32 Index;\r
256   UINT8* TimerPtr;\r
257 \r
258   if (!Trace) {\r
259     return;\r
260   }\r
261 \r
262   ParseAcpi (\r
263     TRUE,\r
264     0,\r
265     "GTDT",\r
266     Ptr,\r
267     AcpiTableLength,\r
268     PARSER_PARAMS (GtdtParser)\r
269     );\r
270 \r
271   if (*GtdtPlatformTimerCount != 0) {\r
272     TimerPtr = Ptr + (*GtdtPlatformTimerOffset);\r
273     Index = 0;\r
274     do {\r
275       // Parse the Platform Timer Header\r
276       ParseAcpi (\r
277         FALSE,\r
278         0,\r
279         NULL,\r
280         TimerPtr,\r
281         4,  // GT Platform Timer structure header length.\r
282         PARSER_PARAMS (GtPlatformTimerHeaderParser)\r
283         );\r
284       switch (*PlatformTimerType) {\r
285         case EFI_ACPI_6_2_GTDT_GT_BLOCK:\r
286           DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
287           break;\r
288         case EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG:\r
289           DumpWatchdogTimer (TimerPtr, *PlatformTimerLength);\r
290           break;\r
291         default:\r
292           IncrementErrorCount ();\r
293           Print (\r
294             L"ERROR: INVALID Platform Timer Type = %d\n",\r
295             *PlatformTimerType\r
296             );\r
297           break;\r
298       } // switch\r
299       TimerPtr += (*PlatformTimerLength);\r
300       Index++;\r
301     } while (Index < *GtdtPlatformTimerCount);\r
302   }\r
303 }\r