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