]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 17// "The number of GT Block Timers must be less than or equal to 8"\r
47d20b54 18#define GT_BLOCK_TIMER_COUNT_MAX 8\r
2a219e19 19\r
ee4dc24f 20// Local variables\r
47d20b54
MK
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
ee4dc24f 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
47d20b54
MK
40 IN UINT8 *Ptr,\r
41 IN VOID *Context\r
2a219e19
KK
42 )\r
43{\r
47d20b54 44 UINT32 BlockTimerCount;\r
2a219e19 45\r
47d20b54 46 BlockTimerCount = *(UINT32 *)Ptr;\r
2a219e19
KK
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
47d20b54
MK
69 IN UINT8 *Ptr,\r
70 IN VOID *Context\r
2a219e19
KK
71 )\r
72{\r
47d20b54 73 UINT8 FrameNumber;\r
2a219e19 74\r
47d20b54 75 FrameNumber = *(UINT8 *)Ptr;\r
2a219e19
KK
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
47d20b54 90STATIC CONST ACPI_PARSER GtdtParser[] = {\r
ee4dc24f 91 PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
47d20b54
MK
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
ee4dc24f
RN
114};\r
115\r
a6eaba4d
DB
116/**\r
117 An ACPI_PARSER array describing the Platform timer header.\r
118**/\r
47d20b54
MK
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
ee4dc24f
RN
123};\r
124\r
a6eaba4d
DB
125/**\r
126 An ACPI_PARSER array describing the Platform GT Block.\r
127**/\r
47d20b54
MK
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
ee4dc24f
RN
137};\r
138\r
a6eaba4d
DB
139/**\r
140 An ACPI_PARSER array describing the GT Block timer.\r
141**/\r
47d20b54
MK
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
ee4dc24f
RN
153};\r
154\r
a6eaba4d
DB
155/**\r
156 An ACPI_PARSER array describing the Platform Watchdog.\r
157**/\r
47d20b54
MK
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
ee4dc24f
RN
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
47d20b54
MK
177 IN UINT8 *Ptr,\r
178 IN UINT16 Length\r
ee4dc24f
RN
179 )\r
180{\r
47d20b54
MK
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
47d20b54
MK
196 (GtBlockTimerOffset == NULL))\r
197 {\r
214bc6e2
KK
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
1d12f0e6 206 Offset = *GtBlockTimerOffset;\r
47d20b54 207 Index = 0;\r
1d12f0e6
KK
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
47d20b54
MK
212 (Offset < Length))\r
213 {\r
1d12f0e6
KK
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
ee4dc24f
RN
222 }\r
223}\r
224\r
a6eaba4d
DB
225/**\r
226 This function parses the Platform Watchdog timer.\r
ee4dc24f
RN
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
a6eaba4d 230**/\r
ee4dc24f
RN
231STATIC\r
232VOID\r
233DumpWatchdogTimer (\r
47d20b54
MK
234 IN UINT8 *Ptr,\r
235 IN UINT16 Length\r
ee4dc24f
RN
236 )\r
237{\r
238 ParseAcpi (\r
239 TRUE,\r
240 2,\r
942c9bd3 241 "Arm Generic Watchdog",\r
ee4dc24f
RN
242 Ptr,\r
243 Length,\r
942c9bd3 244 PARSER_PARAMS (ArmGenericWatchdogParser)\r
ee4dc24f
RN
245 );\r
246}\r
247\r
a6eaba4d
DB
248/**\r
249 This function parses the ACPI GTDT table.\r
ee4dc24f
RN
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
a6eaba4d 263**/\r
ee4dc24f
RN
264VOID\r
265EFIAPI\r
266ParseAcpiGtdt (\r
47d20b54
MK
267 IN BOOLEAN Trace,\r
268 IN UINT8 *Ptr,\r
269 IN UINT32 AcpiTableLength,\r
270 IN UINT8 AcpiTableRevision\r
ee4dc24f
RN
271 )\r
272{\r
47d20b54
MK
273 UINT32 Index;\r
274 UINT32 Offset;\r
275 UINT8 *TimerPtr;\r
ee4dc24f
RN
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
214bc6e2
KK
290 // Check if the values used to control the parsing logic have been\r
291 // successfully read.\r
292 if ((GtdtPlatformTimerCount == NULL) ||\r
47d20b54
MK
293 (GtdtPlatformTimerOffset == NULL))\r
294 {\r
214bc6e2
KK
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
1d12f0e6 303 TimerPtr = Ptr + *GtdtPlatformTimerOffset;\r
47d20b54
MK
304 Offset = *GtdtPlatformTimerOffset;\r
305 Index = 0;\r
1d12f0e6
KK
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
47d20b54
MK
310 (Offset < AcpiTableLength))\r
311 {\r
1d12f0e6
KK
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
214bc6e2
KK
322 // Check if the values used to control the parsing logic have been\r
323 // successfully read.\r
324 if ((PlatformTimerType == NULL) ||\r
47d20b54
MK
325 (PlatformTimerLength == NULL))\r
326 {\r
214bc6e2
KK
327 IncrementErrorCount ();\r
328 Print (\r
329 L"ERROR: Insufficient remaining table buffer length to read the " \\r
47d20b54 330 L"Platform Timer Structure header. Length = %d.\n",\r
214bc6e2
KK
331 AcpiTableLength - Offset\r
332 );\r
333 return;\r
334 }\r
335\r
b8504826
KK
336 // Validate Platform Timer Structure length\r
337 if ((*PlatformTimerLength == 0) ||\r
47d20b54
MK
338 ((Offset + (*PlatformTimerLength)) > AcpiTableLength))\r
339 {\r
1d12f0e6
KK
340 IncrementErrorCount ();\r
341 Print (\r
342 L"ERROR: Invalid Platform Timer Structure length. " \\r
47d20b54 343 L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",\r
1d12f0e6 344 *PlatformTimerLength,\r
b8504826
KK
345 Offset,\r
346 AcpiTableLength\r
ee4dc24f 347 );\r
1d12f0e6
KK
348 return;\r
349 }\r
350\r
351 switch (*PlatformTimerType) {\r
942c9bd3 352 case EFI_ACPI_6_4_GTDT_GT_BLOCK:\r
1d12f0e6
KK
353 DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
354 break;\r
942c9bd3 355 case EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG:\r
1d12f0e6
KK
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
47d20b54 368 Offset += *PlatformTimerLength;\r
1d12f0e6 369 } // while\r
ee4dc24f 370}\r