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