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