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