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