]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
ShellPkg: Add acpiview tool to dump ACPI tables
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / Parsers / Gtdt / GtdtParser.c
CommitLineData
ee4dc24f
RN
1/**\r
2 GTDT table parser\r
3\r
4 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13 @par Reference(s):\r
14 - ACPI 6.2 Specification - Errata A, September 2017\r
15 **/\r
16\r
17#include <IndustryStandard/Acpi.h>\r
18#include <Library/UefiLib.h>\r
19#include "AcpiParser.h"\r
20#include "AcpiTableParser.h"\r
21\r
22// Local variables\r
23STATIC CONST UINT32* GtdtPlatformTimerCount;\r
24STATIC CONST UINT32* GtdtPlatformTimerOffset;\r
25STATIC CONST UINT8* PlatformTimerType;\r
26STATIC CONST UINT16* PlatformTimerLength;\r
27STATIC CONST UINT32* GtBlockTimerCount;\r
28STATIC CONST UINT32* GtBlockTimerOffset;\r
29STATIC CONST UINT16* GtBlockLength;\r
30STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
31\r
32/** This function validates the GT Block timer count.\r
33\r
34 @param [in] Ptr Pointer to the start of the field data.\r
35 @param [in] Context Pointer to context specific information e.g. this\r
36 could be a pointer to the ACPI table header.\r
37*/\r
38STATIC\r
39VOID\r
40EFIAPI\r
41ValidateGtBlockTimerCount (\r
42 IN UINT8* Ptr,\r
43 IN VOID* Context\r
44 );\r
45\r
46/** An ACPI_PARSER array describing the ACPI GTDT Table.\r
47*/\r
48STATIC CONST ACPI_PARSER GtdtParser[] = {\r
49 PARSE_ACPI_HEADER (&AcpiHdrInfo),\r
50 {L"CntControlBase Physical Address", 8, 36, L"0x%lx", NULL, NULL,\r
51 NULL, NULL},\r
52 {L"Reserved", 4, 44, L"0x%x", NULL, NULL, NULL, NULL},\r
53 {L"Secure EL1 timer GSIV", 4, 48, L"0x%x", NULL, NULL, NULL, NULL},\r
54 {L"Secure EL1 timer FLAGS", 4, 52, L"0x%x", NULL, NULL, NULL, NULL},\r
55\r
56 {L"Non-Secure EL1 timer GSIV", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},\r
57 {L"Non-Secure EL1 timer FLAGS", 4, 60, L"0x%x", NULL, NULL, NULL, NULL},\r
58\r
59 {L"Virtual timer GSIV", 4, 64, L"0x%x", NULL, NULL, NULL, NULL},\r
60 {L"Virtual timer FLAGS", 4, 68, L"0x%x", NULL, NULL, NULL, NULL},\r
61\r
62 {L"Non-Secure EL2 timer GSIV", 4, 72, L"0x%x", NULL, NULL, NULL, NULL},\r
63 {L"Non-Secure EL2 timer FLAGS", 4, 76, L"0x%x", NULL, NULL, NULL, NULL},\r
64\r
65 {L"CntReadBase Physical address", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL},\r
66 {L"Platform Timer Count", 4, 88, L"%d", NULL,\r
67 (VOID**)&GtdtPlatformTimerCount, NULL, NULL},\r
68 {L"Platform Timer Offset", 4, 92, L"0x%x", NULL,\r
69 (VOID**)&GtdtPlatformTimerOffset, NULL, NULL}\r
70};\r
71\r
72/** An ACPI_PARSER array describing the Platform timer header.\r
73*/\r
74STATIC CONST ACPI_PARSER GtPlatformTimerHeaderParser[] = {\r
75 {L"Type", 1, 0, NULL, NULL, (VOID**)&PlatformTimerType, NULL, NULL},\r
76 {L"Length", 2, 1, NULL, NULL, (VOID**)&PlatformTimerLength, NULL, NULL},\r
77 {L"Reserved", 1, 3, NULL, NULL, NULL, NULL, NULL}\r
78};\r
79\r
80/** An ACPI_PARSER array describing the Platform GT Block.\r
81*/\r
82STATIC CONST ACPI_PARSER GtBlockParser[] = {\r
83 {L"Type", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
84 {L"Length", 2, 1, L"%d", NULL, (VOID**)&GtBlockLength, NULL, NULL},\r
85 {L"Reserved", 1, 3, L"%x", NULL, NULL, NULL, NULL},\r
86 {L"Physical address (CntCtlBase)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},\r
87 {L"Timer Count", 4, 12, L"%d", NULL, (VOID**)&GtBlockTimerCount,\r
88 ValidateGtBlockTimerCount, NULL},\r
89 {L"Timer Offset", 4, 16, L"%d", NULL, (VOID**)&GtBlockTimerOffset, NULL,\r
90 NULL}\r
91};\r
92\r
93/** An ACPI_PARSER array describing the GT Block timer.\r
94*/\r
95STATIC CONST ACPI_PARSER GtBlockTimerParser[] = {\r
96 {L"Frame Number", 1, 0, L"%d", NULL, NULL, NULL, NULL},\r
97 {L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL},\r
98 {L"Physical address (CntBaseX)", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL},\r
99 {L"Physical address (CntEL0BaseX)", 8, 12, L"0x%lx", NULL, NULL, NULL,\r
100 NULL},\r
101 {L"Physical Timer GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},\r
102 {L"Physical Timer Flags", 4, 24, L"0x%x", NULL, NULL, NULL, NULL},\r
103 {L"Virtual Timer GSIV", 4, 28, L"0x%x", NULL, NULL, NULL, NULL},\r
104 {L"Virtual Timer Flags", 4, 32, L"0x%x", NULL, NULL, NULL, NULL},\r
105 {L"Common Flags", 4, 36, L"0x%x", NULL, NULL, NULL, NULL}\r
106};\r
107\r
108/** An ACPI_PARSER array describing the Platform Watchdog.\r
109*/\r
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
120/** This function validates the GT Block timer count.\r
121\r
122 @param [in] Ptr Pointer to the start of the field data.\r
123 @param [in] Context Pointer to context specific information e.g. this\r
124 could be a pointer to the ACPI table header.\r
125*/\r
126STATIC\r
127VOID\r
128EFIAPI\r
129ValidateGtBlockTimerCount (\r
130 IN UINT8* Ptr,\r
131 IN VOID* Context\r
132 )\r
133{\r
134 UINT32 BlockTimerCount = *(UINT32*)Ptr;\r
135 if (BlockTimerCount > 8) {\r
136 IncrementErrorCount ();\r
137 Print (\r
138 L"\nERROR: Timer Count = %d. Max Timer Count is 8.",\r
139 BlockTimerCount\r
140 );\r
141 }\r
142}\r
143\r
144/** This function parses the Platform GT Block.\r
145\r
146 @param [in] Ptr Pointer to the start of the GT Block data.\r
147 @param [in] Length Length of the GT Block structure.\r
148*/\r
149STATIC\r
150VOID\r
151DumpGTBlock (\r
152 IN UINT8* Ptr,\r
153 IN UINT16 Length\r
154 )\r
155{\r
156 UINT32 Index;\r
157 UINT32 Offset;\r
158 UINT16 GTBlockTimerLength;\r
159\r
160 Offset = ParseAcpi (\r
161 TRUE,\r
162 2,\r
163 "GT Block",\r
164 Ptr,\r
165 Length,\r
166 PARSER_PARAMS (GtBlockParser)\r
167 );\r
168 GTBlockTimerLength = (*GtBlockLength - Offset) / (*GtBlockTimerCount);\r
169 Length -= Offset;\r
170\r
171 if (*GtBlockTimerCount != 0) {\r
172 Ptr += (*GtBlockTimerOffset);\r
173 Index = 0;\r
174 while ((Index < (*GtBlockTimerCount)) && (Length >= GTBlockTimerLength)) {\r
175 Offset = ParseAcpi (\r
176 TRUE,\r
177 2,\r
178 "GT Block Timer",\r
179 Ptr,\r
180 GTBlockTimerLength,\r
181 PARSER_PARAMS (GtBlockTimerParser)\r
182 );\r
183 // Increment by GT Block Timer structure size\r
184 Ptr += Offset;\r
185 Length -= Offset;\r
186 Index++;\r
187 }\r
188\r
189 if (Length != 0) {\r
190 IncrementErrorCount ();\r
191 Print (\r
192 L"ERROR:GT Block Timer length mismatch. Unparsed %d bytes.\n",\r
193 Length\r
194 );\r
195 }\r
196 }\r
197}\r
198\r
199/** This function parses the Platform Watchdog timer.\r
200\r
201 @param [in] Ptr Pointer to the start of the watchdog timer data.\r
202 @param [in] Length Length of the watchdog timer structure.\r
203*/\r
204STATIC\r
205VOID\r
206DumpWatchdogTimer (\r
207 IN UINT8* Ptr,\r
208 IN UINT16 Length\r
209 )\r
210{\r
211 ParseAcpi (\r
212 TRUE,\r
213 2,\r
214 "SBSA Generic Watchdog",\r
215 Ptr,\r
216 Length,\r
217 PARSER_PARAMS (SBSAGenericWatchdogParser)\r
218 );\r
219}\r
220\r
221/** This function parses the ACPI GTDT table.\r
222 When trace is enabled this function parses the GTDT table and\r
223 traces the ACPI table fields.\r
224\r
225 This function also parses the following platform timer structures:\r
226 - GT Block timer\r
227 - Watchdog timer\r
228\r
229 This function also performs validation of the ACPI table fields.\r
230\r
231 @param [in] Trace If TRUE, trace the ACPI fields.\r
232 @param [in] Ptr Pointer to the start of the buffer.\r
233 @param [in] AcpiTableLength Length of the ACPI table.\r
234 @param [in] AcpiTableRevision Revision of the ACPI table.\r
235*/\r
236VOID\r
237EFIAPI\r
238ParseAcpiGtdt (\r
239 IN BOOLEAN Trace,\r
240 IN UINT8* Ptr,\r
241 IN UINT32 AcpiTableLength,\r
242 IN UINT8 AcpiTableRevision\r
243 )\r
244{\r
245 UINT32 Index;\r
246 UINT8* TimerPtr;\r
247\r
248 if (!Trace) {\r
249 return;\r
250 }\r
251\r
252 ParseAcpi (\r
253 TRUE,\r
254 0,\r
255 "GTDT",\r
256 Ptr,\r
257 AcpiTableLength,\r
258 PARSER_PARAMS (GtdtParser)\r
259 );\r
260\r
261 if (*GtdtPlatformTimerCount != 0) {\r
262 TimerPtr = Ptr + (*GtdtPlatformTimerOffset);\r
263 Index = 0;\r
264 do {\r
265 // Parse the Platform Timer Header\r
266 ParseAcpi (\r
267 FALSE,\r
268 0,\r
269 NULL,\r
270 TimerPtr,\r
271 4, // GT Platform Timer structure header length.\r
272 PARSER_PARAMS (GtPlatformTimerHeaderParser)\r
273 );\r
274 switch (*PlatformTimerType) {\r
275 case EFI_ACPI_6_2_GTDT_GT_BLOCK:\r
276 DumpGTBlock (TimerPtr, *PlatformTimerLength);\r
277 break;\r
278 case EFI_ACPI_6_2_GTDT_SBSA_GENERIC_WATCHDOG:\r
279 DumpWatchdogTimer (TimerPtr, *PlatformTimerLength);\r
280 break;\r
281 default:\r
282 IncrementErrorCount ();\r
283 Print (\r
284 L"ERROR: INVALID Platform Timer Type = %d\n",\r
285 *PlatformTimerType\r
286 );\r
287 break;\r
288 } // switch\r
289 TimerPtr += (*PlatformTimerLength);\r
290 Index++;\r
291 } while (Index < *GtdtPlatformTimerCount);\r
292 }\r
293}\r