]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
ShellPkg: Update Acpiview GTDT parser to ACPI 6.4
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Gtdt / GtdtParser.c
CommitLineData
a6eaba4d 1/** @file\r
ee4dc24f
RN
2 GTDT table parser\r
3\r
942c9bd3 4 Copyright (c) 2016 - 2021, ARM Limited. All rights reserved.\r
56ba3746 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
ee4dc24f
RN
6\r
7 @par Reference(s):\r
942c9bd3 8 - ACPI 6.4 Specification - January 2021\r
ee4dc24f
RN
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
e18ac66d 15#include "AcpiViewConfig.h"\r
ee4dc24f 16\r
2a219e19
KK
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
ee4dc24f
RN
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
ee4dc24f
RN
27STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
28\r
a6eaba4d
DB
29/**\r
30 This function validates the GT Block timer count.\r
ee4dc24f
RN
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
a6eaba4d 35**/\r
ee4dc24f
RN
36STATIC\r
37VOID\r
38EFIAPI\r
39ValidateGtBlockTimerCount (\r
40 IN UINT8* Ptr,\r
41 IN VOID* Context\r
2a219e19
KK
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
ee4dc24f 57\r
8da8daaf
KK
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
2a219e19
KK
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
8da8daaf 86\r
a6eaba4d
DB
87/**\r
88 An ACPI_PARSER array describing the ACPI GTDT Table.\r
89**/\r
ee4dc24f
RN
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
98f98eb4
PG
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
ee4dc24f
RN
114};\r
115\r
a6eaba4d
DB
116/**\r
117 An ACPI_PARSER array describing the Platform timer header.\r
118**/\r
ee4dc24f
RN
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
a6eaba4d
DB
125/**\r
126 An ACPI_PARSER array describing the Platform GT Block.\r
127**/\r
ee4dc24f
RN
128STATIC CONST ACPI_PARSER GtBlockParser[] = {\r
129 {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
1d12f0e6 130 {L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL},\r
ee4dc24f
RN
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
a6eaba4d
DB
139/**\r
140 An ACPI_PARSER array describing the GT Block timer.\r
141**/\r
ee4dc24f 142STATIC CONST ACPI_PARSER GtBlockTimerParser[] = {\r
8da8daaf 143 {L"Frame Number", 1, 0, L"%d", NULL, NULL, ValidateGtFrameNumber, NULL},\r
ee4dc24f
RN
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
a6eaba4d
DB
155/**\r
156 An ACPI_PARSER array describing the Platform Watchdog.\r
157**/\r
942c9bd3 158STATIC CONST ACPI_PARSER ArmGenericWatchdogParser[] = {\r
ee4dc24f
RN
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
a6eaba4d
DB
168/**\r
169 This function parses the Platform GT Block.\r
ee4dc24f 170\r
1d12f0e6
KK
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
a6eaba4d 173**/\r
ee4dc24f
RN
174STATIC\r
175VOID\r
176DumpGTBlock (\r
177 IN UINT8* Ptr,\r
1d12f0e6 178 IN UINT16 Length\r
ee4dc24f
RN
179 )\r
180{\r
181 UINT32 Index;\r
182 UINT32 Offset;\r
ee4dc24f 183\r
1d12f0e6
KK
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
214bc6e2
KK
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 IncrementErrorCount ();\r
198 Print (\r
199 L"ERROR: Insufficient GT Block Structure length. Length = %d.\n",\r
200 Length\r
201 );\r
202 return;\r
203 }\r
204\r
1d12f0e6
KK
205 Offset = *GtBlockTimerOffset;\r
206 Index = 0;\r
207\r
208 // Parse the specified number of GT Block Timer Structures or the GT Block\r
209 // Structure buffer length. Whichever is minimum.\r
210 while ((Index++ < *GtBlockTimerCount) &&\r
211 (Offset < Length)) {\r
212 Offset += ParseAcpi (\r
213 TRUE,\r
214 2,\r
215 "GT Block Timer",\r
216 Ptr + Offset,\r
217 Length - Offset,\r
218 PARSER_PARAMS (GtBlockTimerParser)\r
219 );\r
ee4dc24f
RN
220 }\r
221}\r
222\r
a6eaba4d
DB
223/**\r
224 This function parses the Platform Watchdog timer.\r
ee4dc24f
RN
225\r
226 @param [in] Ptr Pointer to the start of the watchdog timer data.\r
227 @param [in] Length Length of the watchdog timer structure.\r
a6eaba4d 228**/\r
ee4dc24f
RN
229STATIC\r
230VOID\r
231DumpWatchdogTimer (\r
232 IN UINT8* Ptr,\r
233 IN UINT16 Length\r
234 )\r
235{\r
236 ParseAcpi (\r
237 TRUE,\r
238 2,\r
942c9bd3 239 "Arm Generic Watchdog",\r
ee4dc24f
RN
240 Ptr,\r
241 Length,\r
942c9bd3 242 PARSER_PARAMS (ArmGenericWatchdogParser)\r
ee4dc24f
RN
243 );\r
244}\r
245\r
a6eaba4d
DB
246/**\r
247 This function parses the ACPI GTDT table.\r
ee4dc24f
RN
248 When trace is enabled this function parses the GTDT table and\r
249 traces the ACPI table fields.\r
250\r
251 This function also parses the following platform timer structures:\r
252 - GT Block timer\r
253 - Watchdog timer\r
254\r
255 This function also performs validation of the ACPI table fields.\r
256\r
257 @param [in] Trace If TRUE, trace the ACPI fields.\r
258 @param [in] Ptr Pointer to the start of the buffer.\r
259 @param [in] AcpiTableLength Length of the ACPI table.\r
260 @param [in] AcpiTableRevision Revision of the ACPI table.\r
a6eaba4d 261**/\r
ee4dc24f
RN
262VOID\r
263EFIAPI\r
264ParseAcpiGtdt (\r
265 IN BOOLEAN Trace,\r
266 IN UINT8* Ptr,\r
267 IN UINT32 AcpiTableLength,\r
268 IN UINT8 AcpiTableRevision\r
269 )\r
270{\r
271 UINT32 Index;\r
1d12f0e6 272 UINT32 Offset;\r
ee4dc24f
RN
273 UINT8* TimerPtr;\r
274\r
275 if (!Trace) {\r
276 return;\r
277 }\r
278\r
279 ParseAcpi (\r
280 TRUE,\r
281 0,\r
282 "GTDT",\r
283 Ptr,\r
284 AcpiTableLength,\r
285 PARSER_PARAMS (GtdtParser)\r
286 );\r
287\r
214bc6e2
KK
288 // Check if the values used to control the parsing logic have been\r
289 // successfully read.\r
290 if ((GtdtPlatformTimerCount == NULL) ||\r
291 (GtdtPlatformTimerOffset == NULL)) {\r
292 IncrementErrorCount ();\r
293 Print (\r
294 L"ERROR: Insufficient table length. AcpiTableLength = %d.\n",\r
295 AcpiTableLength\r
296 );\r
297 return;\r
298 }\r
299\r
1d12f0e6
KK
300 TimerPtr = Ptr + *GtdtPlatformTimerOffset;\r
301 Offset = *GtdtPlatformTimerOffset;\r
302 Index = 0;\r
303\r
304 // Parse the specified number of Platform Timer Structures or the GTDT\r
305 // buffer length. Whichever is minimum.\r
306 while ((Index++ < *GtdtPlatformTimerCount) &&\r
307 (Offset < AcpiTableLength)) {\r
308 // Parse the Platform Timer Header to obtain Length and Type\r
309 ParseAcpi (\r
310 FALSE,\r
311 0,\r
312 NULL,\r
313 TimerPtr,\r
314 AcpiTableLength - Offset,\r
315 PARSER_PARAMS (GtPlatformTimerHeaderParser)\r
316 );\r
317\r
214bc6e2
KK
318 // Check if the values used to control the parsing logic have been\r
319 // successfully read.\r
320 if ((PlatformTimerType == NULL) ||\r
321 (PlatformTimerLength == NULL)) {\r
322 IncrementErrorCount ();\r
323 Print (\r
324 L"ERROR: Insufficient remaining table buffer length to read the " \\r
325 L"Platform Timer Structure header. Length = %d.\n",\r
326 AcpiTableLength - Offset\r
327 );\r
328 return;\r
329 }\r
330\r
b8504826
KK
331 // Validate Platform Timer Structure length\r
332 if ((*PlatformTimerLength == 0) ||\r
333 ((Offset + (*PlatformTimerLength)) > AcpiTableLength)) {\r
1d12f0e6
KK
334 IncrementErrorCount ();\r
335 Print (\r
336 L"ERROR: Invalid Platform Timer Structure length. " \\r
b8504826 337 L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r
1d12f0e6 338 *PlatformTimerLength,\r
b8504826
KK
339 Offset,\r
340 AcpiTableLength\r
ee4dc24f 341 );\r
1d12f0e6
KK
342 return;\r
343 }\r
344\r
345 switch (*PlatformTimerType) {\r
942c9bd3 346 case EFI_ACPI_6_4_GTDT_GT_BLOCK:\r
1d12f0e6
KK
347 DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
348 break;\r
942c9bd3 349 case EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG:\r
1d12f0e6
KK
350 DumpWatchdogTimer (TimerPtr, *PlatformTimerLength);\r
351 break;\r
352 default:\r
353 IncrementErrorCount ();\r
354 Print (\r
355 L"ERROR: Invalid Platform Timer Type = %d\n",\r
356 *PlatformTimerType\r
357 );\r
358 break;\r
359 } // switch\r
360\r
361 TimerPtr += *PlatformTimerLength;\r
362 Offset += *PlatformTimerLength;\r
363 } // while\r
ee4dc24f 364}\r