]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
ShellPkg: Apply uncrustify changes
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Gtdt / GtdtParser.c
... / ...
CommitLineData
1/** @file\r
2 GTDT table parser\r
3\r
4 Copyright (c) 2016 - 2021, ARM Limited. All rights reserved.\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7 @par Reference(s):\r
8 - ACPI 6.4 Specification - January 2021\r
9 **/\r
10\r
11#include <IndustryStandard/Acpi.h>\r
12#include <Library/UefiLib.h>\r
13#include "AcpiParser.h"\r
14#include "AcpiTableParser.h"\r
15#include "AcpiViewConfig.h"\r
16\r
17// "The number of GT Block Timers must be less than or equal to 8"\r
18#define GT_BLOCK_TIMER_COUNT_MAX 8\r
19\r
20// Local variables\r
21STATIC CONST UINT32 *GtdtPlatformTimerCount;\r
22STATIC CONST UINT32 *GtdtPlatformTimerOffset;\r
23STATIC CONST UINT8 *PlatformTimerType;\r
24STATIC CONST UINT16 *PlatformTimerLength;\r
25STATIC CONST UINT32 *GtBlockTimerCount;\r
26STATIC CONST UINT32 *GtBlockTimerOffset;\r
27STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
28\r
29/**\r
30 This function validates the GT Block timer count.\r
31\r
32 @param [in] Ptr Pointer to the start of the field data.\r
33 @param [in] Context Pointer to context specific information e.g. this\r
34 could be a pointer to the ACPI table header.\r
35**/\r
36STATIC\r
37VOID\r
38EFIAPI\r
39ValidateGtBlockTimerCount (\r
40 IN UINT8 *Ptr,\r
41 IN VOID *Context\r
42 )\r
43{\r
44 UINT32 BlockTimerCount;\r
45\r
46 BlockTimerCount = *(UINT32 *)Ptr;\r
47\r
48 if (BlockTimerCount > GT_BLOCK_TIMER_COUNT_MAX) {\r
49 IncrementErrorCount ();\r
50 Print (\r
51 L"\nERROR: Timer Count = %d. Max Timer Count is %d.",\r
52 BlockTimerCount,\r
53 GT_BLOCK_TIMER_COUNT_MAX\r
54 );\r
55 }\r
56}\r
57\r
58/**\r
59 This function validates the GT Frame Number.\r
60\r
61 @param [in] Ptr Pointer to the start of the field data.\r
62 @param [in] Context Pointer to context specific information e.g. this\r
63 could be a pointer to the ACPI table header.\r
64**/\r
65STATIC\r
66VOID\r
67EFIAPI\r
68ValidateGtFrameNumber (\r
69 IN UINT8 *Ptr,\r
70 IN VOID *Context\r
71 )\r
72{\r
73 UINT8 FrameNumber;\r
74\r
75 FrameNumber = *(UINT8 *)Ptr;\r
76\r
77 if (FrameNumber >= GT_BLOCK_TIMER_COUNT_MAX) {\r
78 IncrementErrorCount ();\r
79 Print (\r
80 L"\nERROR: GT Frame Number = %d. GT Frame Number must be in range 0-%d.",\r
81 FrameNumber,\r
82 GT_BLOCK_TIMER_COUNT_MAX - 1\r
83 );\r
84 }\r
85}\r
86\r
87/**\r
88 An ACPI_PARSER array describing the ACPI GTDT Table.\r
89**/\r
90STATIC CONST ACPI_PARSER GtdtParser[] = {\r
91 PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
92 { L"CntControlBase Physical Address",8, 36, L"0x%lx", NULL, NULL,\r
93 NULL, NULL },\r
94 { L"Reserved", 4, 44, L"0x%x", NULL, NULL,NULL, NULL },\r
95 { L"Secure EL1 timer GSIV", 4, 48, L"0x%x", NULL, NULL,NULL, NULL },\r
96 { L"Secure EL1 timer FLAGS", 4, 52, L"0x%x", NULL, NULL,NULL, NULL },\r
97\r
98 { L"Non-Secure EL1 timer GSIV", 4, 56, L"0x%x", NULL, NULL,NULL, NULL },\r
99 { L"Non-Secure EL1 timer FLAGS", 4, 60, L"0x%x", NULL, NULL,NULL, NULL },\r
100\r
101 { L"Virtual timer GSIV", 4, 64, L"0x%x", NULL, NULL,NULL, NULL },\r
102 { L"Virtual timer FLAGS", 4, 68, L"0x%x", NULL, NULL,NULL, NULL },\r
103\r
104 { L"Non-Secure EL2 timer GSIV", 4, 72, L"0x%x", NULL, NULL,NULL, NULL },\r
105 { L"Non-Secure EL2 timer FLAGS", 4, 76, L"0x%x", NULL, NULL,NULL, NULL },\r
106\r
107 { L"CntReadBase Physical address", 8, 80, L"0x%lx", NULL, NULL,NULL, NULL },\r
108 { L"Platform Timer Count", 4, 88, L"%d", NULL,\r
109 (VOID **)&GtdtPlatformTimerCount, NULL, NULL },\r
110 { L"Platform Timer Offset", 4, 92, L"0x%x", NULL,\r
111 (VOID **)&GtdtPlatformTimerOffset,NULL, NULL },\r
112 { L"Virtual EL2 Timer GSIV", 4, 96, L"0x%x", NULL, NULL,NULL, NULL },\r
113 { L"Virtual EL2 Timer Flags", 4, 100, L"0x%x", NULL, NULL,NULL, NULL }\r
114};\r
115\r
116/**\r
117 An ACPI_PARSER array describing the Platform timer header.\r
118**/\r
119STATIC CONST ACPI_PARSER GtPlatformTimerHeaderParser[] = {\r
120 { L"Type", 1, 0, NULL, NULL, (VOID **)&PlatformTimerType, NULL, NULL },\r
121 { L"Length", 2, 1, NULL, NULL, (VOID **)&PlatformTimerLength, NULL, NULL },\r
122 { L"Reserved", 1, 3, NULL, NULL, NULL, NULL, NULL }\r
123};\r
124\r
125/**\r
126 An ACPI_PARSER array describing the Platform GT Block.\r
127**/\r
128STATIC CONST ACPI_PARSER GtBlockParser[] = {\r
129 { L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL },\r
130 { L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL },\r
131 { L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL },\r
132 { L"Physical address (CntCtlBase)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL },\r
133 { L"Timer Count", 4, 12, L"%d", NULL, (VOID **)&GtBlockTimerCount,\r
134 ValidateGtBlockTimerCount, NULL },\r
135 { L"Timer Offset", 4, 16, L"%d", NULL, (VOID **)&GtBlockTimerOffset, NULL,\r
136 NULL }\r
137};\r
138\r
139/**\r
140 An ACPI_PARSER array describing the GT Block timer.\r
141**/\r
142STATIC CONST ACPI_PARSER GtBlockTimerParser[] = {\r
143 { L"Frame Number", 1, 0, L"%d", NULL, NULL, ValidateGtFrameNumber, NULL },\r
144 { L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL },\r
145 { L"Physical address (CntBaseX)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL },\r
146 { L"Physical address (CntEL0BaseX)", 8, 12, L"0x%lx", NULL, NULL, NULL,\r
147 NULL },\r
148 { L"Physical Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },\r
149 { L"Physical Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL },\r
150 { L"Virtual Timer GSIV", 4, 28, L"0x%x", NULL, NULL, NULL, NULL },\r
151 { L"Virtual Timer Flags", 4, 32, L"0x%x", NULL, NULL, NULL, NULL },\r
152 { L"Common Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL }\r
153};\r
154\r
155/**\r
156 An ACPI_PARSER array describing the Platform Watchdog.\r
157**/\r
158STATIC CONST ACPI_PARSER ArmGenericWatchdogParser[] = {\r
159 { L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL },\r
160 { L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL },\r
161 { L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL },\r
162 { L"RefreshFrame Physical address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL },\r
163 { L"ControlFrame Physical address", 8, 12, L"0x%lx", NULL, NULL, NULL, NULL },\r
164 { L"Watchdog Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL },\r
165 { L"Watchdog Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL }\r
166};\r
167\r
168/**\r
169 This function parses the Platform GT Block.\r
170\r
171 @param [in] Ptr Pointer to the start of the GT Block data.\r
172 @param [in] Length Length of the GT Block structure.\r
173**/\r
174STATIC\r
175VOID\r
176DumpGTBlock (\r
177 IN UINT8 *Ptr,\r
178 IN UINT16 Length\r
179 )\r
180{\r
181 UINT32 Index;\r
182 UINT32 Offset;\r
183\r
184 ParseAcpi (\r
185 TRUE,\r
186 2,\r
187 "GT Block",\r
188 Ptr,\r
189 Length,\r
190 PARSER_PARAMS (GtBlockParser)\r
191 );\r
192\r
193 // Check if the values used to control the parsing logic have been\r
194 // successfully read.\r
195 if ((GtBlockTimerCount == NULL) ||\r
196 (GtBlockTimerOffset == NULL))\r
197 {\r
198 IncrementErrorCount ();\r
199 Print (\r
200 L"ERROR: Insufficient GT Block Structure length. Length = %d.\n",\r
201 Length\r
202 );\r
203 return;\r
204 }\r
205\r
206 Offset = *GtBlockTimerOffset;\r
207 Index = 0;\r
208\r
209 // Parse the specified number of GT Block Timer Structures or the GT Block\r
210 // Structure buffer length. Whichever is minimum.\r
211 while ((Index++ < *GtBlockTimerCount) &&\r
212 (Offset < Length))\r
213 {\r
214 Offset += ParseAcpi (\r
215 TRUE,\r
216 2,\r
217 "GT Block Timer",\r
218 Ptr + Offset,\r
219 Length - Offset,\r
220 PARSER_PARAMS (GtBlockTimerParser)\r
221 );\r
222 }\r
223}\r
224\r
225/**\r
226 This function parses the Platform Watchdog timer.\r
227\r
228 @param [in] Ptr Pointer to the start of the watchdog timer data.\r
229 @param [in] Length Length of the watchdog timer structure.\r
230**/\r
231STATIC\r
232VOID\r
233DumpWatchdogTimer (\r
234 IN UINT8 *Ptr,\r
235 IN UINT16 Length\r
236 )\r
237{\r
238 ParseAcpi (\r
239 TRUE,\r
240 2,\r
241 "Arm Generic Watchdog",\r
242 Ptr,\r
243 Length,\r
244 PARSER_PARAMS (ArmGenericWatchdogParser)\r
245 );\r
246}\r
247\r
248/**\r
249 This function parses the ACPI GTDT table.\r
250 When trace is enabled this function parses the GTDT table and\r
251 traces the ACPI table fields.\r
252\r
253 This function also parses the following platform timer structures:\r
254 - GT Block timer\r
255 - Watchdog timer\r
256\r
257 This function also performs validation of the ACPI table fields.\r
258\r
259 @param [in] Trace If TRUE, trace the ACPI fields.\r
260 @param [in] Ptr Pointer to the start of the buffer.\r
261 @param [in] AcpiTableLength Length of the ACPI table.\r
262 @param [in] AcpiTableRevision Revision of the ACPI table.\r
263**/\r
264VOID\r
265EFIAPI\r
266ParseAcpiGtdt (\r
267 IN BOOLEAN Trace,\r
268 IN UINT8 *Ptr,\r
269 IN UINT32 AcpiTableLength,\r
270 IN UINT8 AcpiTableRevision\r
271 )\r
272{\r
273 UINT32 Index;\r
274 UINT32 Offset;\r
275 UINT8 *TimerPtr;\r
276\r
277 if (!Trace) {\r
278 return;\r
279 }\r
280\r
281 ParseAcpi (\r
282 TRUE,\r
283 0,\r
284 "GTDT",\r
285 Ptr,\r
286 AcpiTableLength,\r
287 PARSER_PARAMS (GtdtParser)\r
288 );\r
289\r
290 // Check if the values used to control the parsing logic have been\r
291 // successfully read.\r
292 if ((GtdtPlatformTimerCount == NULL) ||\r
293 (GtdtPlatformTimerOffset == NULL))\r
294 {\r
295 IncrementErrorCount ();\r
296 Print (\r
297 L"ERROR: Insufficient table length. AcpiTableLength = %d.\n",\r
298 AcpiTableLength\r
299 );\r
300 return;\r
301 }\r
302\r
303 TimerPtr = Ptr + *GtdtPlatformTimerOffset;\r
304 Offset = *GtdtPlatformTimerOffset;\r
305 Index = 0;\r
306\r
307 // Parse the specified number of Platform Timer Structures or the GTDT\r
308 // buffer length. Whichever is minimum.\r
309 while ((Index++ < *GtdtPlatformTimerCount) &&\r
310 (Offset < AcpiTableLength))\r
311 {\r
312 // Parse the Platform Timer Header to obtain Length and Type\r
313 ParseAcpi (\r
314 FALSE,\r
315 0,\r
316 NULL,\r
317 TimerPtr,\r
318 AcpiTableLength - Offset,\r
319 PARSER_PARAMS (GtPlatformTimerHeaderParser)\r
320 );\r
321\r
322 // Check if the values used to control the parsing logic have been\r
323 // successfully read.\r
324 if ((PlatformTimerType == NULL) ||\r
325 (PlatformTimerLength == NULL))\r
326 {\r
327 IncrementErrorCount ();\r
328 Print (\r
329 L"ERROR: Insufficient remaining table buffer length to read the " \\r
330 L"Platform Timer Structure header. Length = %d.\n",\r
331 AcpiTableLength - Offset\r
332 );\r
333 return;\r
334 }\r
335\r
336 // Validate Platform Timer Structure length\r
337 if ((*PlatformTimerLength == 0) ||\r
338 ((Offset + (*PlatformTimerLength)) > AcpiTableLength))\r
339 {\r
340 IncrementErrorCount ();\r
341 Print (\r
342 L"ERROR: Invalid Platform Timer Structure length. " \\r
343 L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r
344 *PlatformTimerLength,\r
345 Offset,\r
346 AcpiTableLength\r
347 );\r
348 return;\r
349 }\r
350\r
351 switch (*PlatformTimerType) {\r
352 case EFI_ACPI_6_4_GTDT_GT_BLOCK:\r
353 DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
354 break;\r
355 case EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG:\r
356 DumpWatchdogTimer (TimerPtr, *PlatformTimerLength);\r
357 break;\r
358 default:\r
359 IncrementErrorCount ();\r
360 Print (\r
361 L"ERROR: Invalid Platform Timer Type = %d\n",\r
362 *PlatformTimerType\r
363 );\r
364 break;\r
365 } // switch\r
366\r
367 TimerPtr += *PlatformTimerLength;\r
368 Offset += *PlatformTimerLength;\r
369 } // while\r
370}\r