]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiGtdtLibArm / GtdtGenerator.c
CommitLineData
9c720258
SM
1/** @file\r
2 GTDT Table Generator\r
3\r
f09dbf20 4 Copyright (c) 2017 - 2021, ARM Limited. All rights reserved.\r
9cd9bdc6 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9c720258
SM
6\r
7 @par Reference(s):\r
f09dbf20 8 - ACPI 6.4 Specification - January 2021\r
9c720258
SM
9\r
10**/\r
11\r
12#include <Library/AcpiLib.h>\r
13#include <Library/DebugLib.h>\r
14#include <Library/MemoryAllocationLib.h>\r
15#include <Protocol/AcpiTable.h>\r
16\r
17// Module specific include files.\r
18#include <AcpiTableGenerator.h>\r
19#include <ConfigurationManagerObject.h>\r
20#include <ConfigurationManagerHelper.h>\r
21#include <Library/TableHelperLib.h>\r
22#include <Protocol/ConfigurationManagerProtocol.h>\r
23\r
24/** ARM standard GTDT Generator\r
25\r
26Requirements:\r
27 The following Configuration Manager Object(s) are required by\r
28 this Generator:\r
29 - EArmObjGenericTimerInfo\r
30 - EArmObjPlatformGenericWatchdogInfo (OPTIONAL)\r
31 - EArmObjPlatformGTBlockInfo (OPTIONAL)\r
32 - EArmObjGTBlockTimerFrameInfo (OPTIONAL)\r
33*/\r
34\r
35/** This macro expands to a function that retrieves the Generic\r
36 Timer Information from the Configuration Manager.\r
37*/\r
38GET_OBJECT_LIST (\r
39 EObjNameSpaceArm,\r
40 EArmObjGenericTimerInfo,\r
41 CM_ARM_GENERIC_TIMER_INFO\r
42 );\r
43\r
f09dbf20 44/** This macro expands to a function that retrieves the Arm Generic\r
9c720258
SM
45 Watchdog Timer Information from the Configuration Manager.\r
46*/\r
47GET_OBJECT_LIST (\r
48 EObjNameSpaceArm,\r
49 EArmObjPlatformGenericWatchdogInfo,\r
50 CM_ARM_GENERIC_WATCHDOG_INFO\r
51 );\r
52\r
53/** This macro expands to a function that retrieves the Platform Generic\r
54 Timer Block Information from the Configuration Manager.\r
55*/\r
56GET_OBJECT_LIST (\r
57 EObjNameSpaceArm,\r
58 EArmObjPlatformGTBlockInfo,\r
59 CM_ARM_GTBLOCK_INFO\r
60 );\r
61\r
62/** This macro expands to a function that retrieves the Generic\r
63 Timer Block Timer Frame Information from the Configuration Manager.\r
64*/\r
65GET_OBJECT_LIST (\r
66 EObjNameSpaceArm,\r
67 EArmObjGTBlockTimerFrameInfo,\r
68 CM_ARM_GTBLOCK_TIMER_FRAME_INFO\r
69 );\r
70\r
71/** Add the Generic Timer Information to the GTDT table.\r
72\r
73 Also update the Platform Timer offset information if the platform\r
74 implements platform timers.\r
75\r
76 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
77 Protocol Interface.\r
78 @param [in] Gtdt Pointer to the GTDT Table.\r
79 @param [in] PlatformTimerCount Platform timer count.\r
e8015f2f 80 @param [in] AcpiTableRevision Acpi Revision targeted by the platform.\r
9c720258
SM
81\r
82 @retval EFI_SUCCESS Success.\r
83 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
84 @retval EFI_NOT_FOUND The required object was not found.\r
85 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
86 Manager is less than the Object size for the\r
87 requested object.\r
88**/\r
89STATIC\r
90EFI_STATUS\r
91EFIAPI\r
92AddGenericTimerInfo (\r
731c67e1
MK
93 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
94 IN EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE *CONST Gtdt,\r
e8015f2f
PG
95 IN CONST UINT32 PlatformTimerCount,\r
96 IN CONST UINT32 AcpiTableRevision\r
731c67e1 97 )\r
9c720258 98{\r
731c67e1
MK
99 EFI_STATUS Status;\r
100 CM_ARM_GENERIC_TIMER_INFO *GenericTimerInfo;\r
9c720258
SM
101\r
102 ASSERT (CfgMgrProtocol != NULL);\r
103 ASSERT (Gtdt != NULL);\r
104\r
105 Status = GetEArmObjGenericTimerInfo (\r
106 CfgMgrProtocol,\r
107 CM_NULL_TOKEN,\r
108 &GenericTimerInfo,\r
109 NULL\r
110 );\r
111\r
112 if (EFI_ERROR (Status)) {\r
113 DEBUG ((\r
114 DEBUG_ERROR,\r
115 "ERROR: GTDT: Failed to get GenericTimerInfo. Status = %r\n",\r
116 Status\r
117 ));\r
118 return Status;\r
119 }\r
120\r
121 Gtdt->CntControlBasePhysicalAddress =\r
122 GenericTimerInfo->CounterControlBaseAddress;\r
731c67e1
MK
123 Gtdt->Reserved = EFI_ACPI_RESERVED_DWORD;\r
124 Gtdt->SecurePL1TimerGSIV = GenericTimerInfo->SecurePL1TimerGSIV;\r
125 Gtdt->SecurePL1TimerFlags = GenericTimerInfo->SecurePL1TimerFlags;\r
126 Gtdt->NonSecurePL1TimerGSIV = GenericTimerInfo->NonSecurePL1TimerGSIV;\r
127 Gtdt->NonSecurePL1TimerFlags = GenericTimerInfo->NonSecurePL1TimerFlags;\r
128 Gtdt->VirtualTimerGSIV = GenericTimerInfo->VirtualTimerGSIV;\r
129 Gtdt->VirtualTimerFlags = GenericTimerInfo->VirtualTimerFlags;\r
130 Gtdt->NonSecurePL2TimerGSIV = GenericTimerInfo->NonSecurePL2TimerGSIV;\r
131 Gtdt->NonSecurePL2TimerFlags = GenericTimerInfo->NonSecurePL2TimerFlags;\r
9c720258
SM
132 Gtdt->CntReadBasePhysicalAddress =\r
133 GenericTimerInfo->CounterReadBaseAddress;\r
731c67e1 134 Gtdt->PlatformTimerCount = PlatformTimerCount;\r
9c720258 135 Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :\r
731c67e1 136 sizeof (EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE);\r
9c720258 137\r
e8015f2f 138 if (AcpiTableRevision > EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION) {\r
731c67e1 139 Gtdt->VirtualPL2TimerGSIV = GenericTimerInfo->VirtualPL2TimerGSIV;\r
e8015f2f
PG
140 Gtdt->VirtualPL2TimerFlags = GenericTimerInfo->VirtualPL2TimerFlags;\r
141 }\r
142\r
143 return Status;\r
9c720258
SM
144}\r
145\r
f09dbf20 146/** Add the Arm Generic Watchdog Timers to the GTDT table.\r
9c720258
SM
147\r
148 @param [in] Gtdt Pointer to the GTDT Table.\r
149 @param [in] WatchdogOffset Offset to the watchdog information in the\r
150 GTDT Table.\r
151 @param [in] WatchdogInfoList Pointer to the watchdog information list.\r
152 @param [in] WatchdogCount Platform timer count.\r
153**/\r
154STATIC\r
155VOID\r
156AddGenericWatchdogList (\r
731c67e1 157 IN EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE *CONST Gtdt,\r
9c720258 158 IN CONST UINT32 WatchdogOffset,\r
731c67e1 159 IN CONST CM_ARM_GENERIC_WATCHDOG_INFO *WatchdogInfoList,\r
9c720258
SM
160 IN UINT32 WatchdogCount\r
161 )\r
162{\r
731c67e1 163 EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG_STRUCTURE *Watchdog;\r
9c720258
SM
164\r
165 ASSERT (Gtdt != NULL);\r
166 ASSERT (WatchdogInfoList != NULL);\r
167\r
f09dbf20 168 Watchdog = (EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG_STRUCTURE *)\r
731c67e1 169 ((UINT8 *)Gtdt + WatchdogOffset);\r
9c720258
SM
170\r
171 while (WatchdogCount-- != 0) {\r
172 // Add watchdog entry\r
173 DEBUG ((DEBUG_INFO, "GTDT: Watchdog = 0x%p\n", Watchdog));\r
731c67e1 174 Watchdog->Type = EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG;\r
9c720258 175 Watchdog->Length =\r
f09dbf20 176 sizeof (EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG_STRUCTURE);\r
731c67e1 177 Watchdog->Reserved = EFI_ACPI_RESERVED_BYTE;\r
9c720258
SM
178 Watchdog->RefreshFramePhysicalAddress =\r
179 WatchdogInfoList->RefreshFrameAddress;\r
180 Watchdog->WatchdogControlFramePhysicalAddress =\r
181 WatchdogInfoList->ControlFrameAddress;\r
731c67e1 182 Watchdog->WatchdogTimerGSIV = WatchdogInfoList->TimerGSIV;\r
9c720258
SM
183 Watchdog->WatchdogTimerFlags = WatchdogInfoList->Flags;\r
184 Watchdog++;\r
185 WatchdogInfoList++;\r
186 } // for\r
187}\r
188\r
ccc97f6d
KK
189/**\r
190 Function to test if two Generic Timer Block Frame Info structures have the\r
191 same frame number.\r
192\r
193 @param [in] Frame1 Pointer to the first GT Block Frame Info\r
194 structure.\r
195 @param [in] Frame2 Pointer to the second GT Block Frame Info\r
196 structure.\r
197 @param [in] Index1 Index of Frame1 in the shared GT Block Frame\r
198 Information List.\r
199 @param [in] Index2 Index of Frame2 in the shared GT Block Frame\r
200 Information List.\r
201\r
202 @retval TRUE Frame1 and Frame2 have the same frame number.\r
203 @return FALSE Frame1 and Frame2 have different frame numbers.\r
204\r
205**/\r
206BOOLEAN\r
207EFIAPI\r
208IsGtFrameNumberEqual (\r
731c67e1
MK
209 IN CONST VOID *Frame1,\r
210 IN CONST VOID *Frame2,\r
211 IN UINTN Index1,\r
212 IN UINTN Index2\r
ccc97f6d
KK
213 )\r
214{\r
731c67e1
MK
215 UINT8 FrameNumber1;\r
216 UINT8 FrameNumber2;\r
ccc97f6d
KK
217\r
218 ASSERT ((Frame1 != NULL) && (Frame2 != NULL));\r
219\r
731c67e1
MK
220 FrameNumber1 = ((CM_ARM_GTBLOCK_TIMER_FRAME_INFO *)Frame1)->FrameNumber;\r
221 FrameNumber2 = ((CM_ARM_GTBLOCK_TIMER_FRAME_INFO *)Frame2)->FrameNumber;\r
ccc97f6d
KK
222\r
223 if (FrameNumber1 == FrameNumber2) {\r
224 DEBUG ((\r
225 DEBUG_ERROR,\r
226 "ERROR: GTDT: GT Block Frame Info Structures %d and %d have the same " \\r
227 "frame number: 0x%x.\n",\r
228 Index1,\r
229 Index2,\r
230 FrameNumber1\r
231 ));\r
232 return TRUE;\r
233 }\r
234\r
235 return FALSE;\r
236}\r
237\r
9c720258
SM
238/** Update the GT Block Timer Frame lists in the GTDT Table.\r
239\r
240 @param [in] GtBlockFrame Pointer to the GT Block Frames\r
241 list to be updated.\r
242 @param [in] GTBlockTimerFrameList Pointer to the GT Block Frame\r
243 Information List.\r
244 @param [in] GTBlockFrameCount Number of GT Block Frames.\r
245\r
ccc97f6d
KK
246 @retval EFI_SUCCESS Table generated successfully.\r
247 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
9c720258
SM
248**/\r
249STATIC\r
250EFI_STATUS\r
251AddGTBlockTimerFrames (\r
731c67e1
MK
252 IN EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE *GtBlockFrame,\r
253 IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO *GTBlockTimerFrameList,\r
254 IN UINT32 GTBlockFrameCount\r
255 )\r
9c720258 256{\r
731c67e1 257 BOOLEAN IsFrameNumberDuplicated;\r
ccc97f6d 258\r
9c720258
SM
259 ASSERT (GtBlockFrame != NULL);\r
260 ASSERT (GTBlockTimerFrameList != NULL);\r
261\r
ccc97f6d
KK
262 IsFrameNumberDuplicated = FindDuplicateValue (\r
263 GTBlockTimerFrameList,\r
264 GTBlockFrameCount,\r
265 sizeof (CM_ARM_GTBLOCK_TIMER_FRAME_INFO),\r
266 IsGtFrameNumberEqual\r
267 );\r
268 // Duplicate entry was found so timer frame numbers provided are invalid\r
269 if (IsFrameNumberDuplicated) {\r
270 return EFI_INVALID_PARAMETER;\r
271 }\r
272\r
9c720258
SM
273 while (GTBlockFrameCount-- != 0) {\r
274 DEBUG ((\r
275 DEBUG_INFO,\r
276 "GTDT: GtBlockFrame = 0x%p\n",\r
277 GtBlockFrame\r
278 ));\r
279\r
75bf10a6
KK
280 if (GTBlockTimerFrameList->FrameNumber >= 8) {\r
281 DEBUG ((\r
282 DEBUG_ERROR,\r
283 "ERROR: GTDT: Frame number %d is not in the range 0-7\n",\r
284 GTBlockTimerFrameList->FrameNumber\r
731c67e1 285 ));\r
75bf10a6
KK
286 return EFI_INVALID_PARAMETER;\r
287 }\r
288\r
9c720258 289 GtBlockFrame->GTFrameNumber = GTBlockTimerFrameList->FrameNumber;\r
731c67e1
MK
290 GtBlockFrame->Reserved[0] = EFI_ACPI_RESERVED_BYTE;\r
291 GtBlockFrame->Reserved[1] = EFI_ACPI_RESERVED_BYTE;\r
292 GtBlockFrame->Reserved[2] = EFI_ACPI_RESERVED_BYTE;\r
9c720258 293\r
731c67e1 294 GtBlockFrame->CntBaseX = GTBlockTimerFrameList->PhysicalAddressCntBase;\r
9c720258
SM
295 GtBlockFrame->CntEL0BaseX =\r
296 GTBlockTimerFrameList->PhysicalAddressCntEL0Base;\r
297\r
298 GtBlockFrame->GTxPhysicalTimerGSIV =\r
299 GTBlockTimerFrameList->PhysicalTimerGSIV;\r
300 GtBlockFrame->GTxPhysicalTimerFlags =\r
301 GTBlockTimerFrameList->PhysicalTimerFlags;\r
302\r
731c67e1 303 GtBlockFrame->GTxVirtualTimerGSIV = GTBlockTimerFrameList->VirtualTimerGSIV;\r
9c720258
SM
304 GtBlockFrame->GTxVirtualTimerFlags =\r
305 GTBlockTimerFrameList->VirtualTimerFlags;\r
306\r
307 GtBlockFrame->GTxCommonFlags = GTBlockTimerFrameList->CommonFlags;\r
308 GtBlockFrame++;\r
309 GTBlockTimerFrameList++;\r
310 } // for\r
731c67e1 311\r
9c720258
SM
312 return EFI_SUCCESS;\r
313}\r
314\r
315/** Add the GT Block Timers in the GTDT Table.\r
316\r
317 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
318 Protocol Interface.\r
319 @param [in] Gtdt Pointer to the GTDT Table.\r
320 @param [in] GTBlockOffset Offset of the GT Block\r
321 information in the GTDT Table.\r
322 @param [in] GTBlockInfo Pointer to the GT Block\r
323 Information List.\r
324 @param [in] BlockTimerCount Number of GT Block Timers.\r
325\r
326 @retval EFI_SUCCESS Table generated successfully.\r
327 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
328**/\r
329STATIC\r
330EFI_STATUS\r
331AddGTBlockList (\r
731c67e1
MK
332 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
333 IN EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE *CONST Gtdt,\r
9c720258 334 IN CONST UINT32 GTBlockOffset,\r
731c67e1 335 IN CONST CM_ARM_GTBLOCK_INFO *GTBlockInfo,\r
9c720258 336 IN UINT32 BlockTimerCount\r
731c67e1 337 )\r
9c720258 338{\r
731c67e1
MK
339 EFI_STATUS Status;\r
340 EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE *GTBlock;\r
341 EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE *GtBlockFrame;\r
342 CM_ARM_GTBLOCK_TIMER_FRAME_INFO *GTBlockTimerFrameList;\r
343 UINT32 GTBlockTimerFrameCount;\r
344 UINTN Length;\r
9c720258
SM
345\r
346 ASSERT (Gtdt != NULL);\r
347 ASSERT (GTBlockInfo != NULL);\r
348\r
731c67e1
MK
349 GTBlock = (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE *)((UINT8 *)Gtdt +\r
350 GTBlockOffset);\r
9c720258
SM
351\r
352 while (BlockTimerCount-- != 0) {\r
353 DEBUG ((DEBUG_INFO, "GTDT: GTBlock = 0x%p\n", GTBlock));\r
354\r
355 Status = GetEArmObjGTBlockTimerFrameInfo (\r
356 CfgMgrProtocol,\r
357 GTBlockInfo->GTBlockTimerFrameToken,\r
358 &GTBlockTimerFrameList,\r
359 &GTBlockTimerFrameCount\r
360 );\r
361 if (EFI_ERROR (Status) ||\r
731c67e1
MK
362 (GTBlockTimerFrameCount != GTBlockInfo->GTBlockTimerFrameCount))\r
363 {\r
9c720258
SM
364 DEBUG ((\r
365 DEBUG_ERROR,\r
366 "ERROR: GTDT: Failed to get Generic Timer Frames. Status = %r\n",\r
367 Status\r
368 ));\r
369 return Status;\r
370 }\r
371\r
f09dbf20 372 Length = sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE) +\r
731c67e1
MK
373 (sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE) *\r
374 GTBlockInfo->GTBlockTimerFrameCount);\r
9c720258 375\r
87847811
SM
376 // Check that the length of the GT block does not\r
377 // exceed MAX_UINT16\r
378 if (Length > MAX_UINT16) {\r
379 Status = EFI_INVALID_PARAMETER;\r
380 DEBUG ((\r
381 DEBUG_ERROR,\r
382 "ERROR: GTDT: Too many GT Frames. Count = %d. " \\r
383 "Maximum supported GT Block size exceeded. " \\r
384 "Status = %r\n",\r
385 GTBlockInfo->GTBlockTimerFrameCount,\r
386 Status\r
387 ));\r
388 return Status;\r
389 }\r
390\r
731c67e1
MK
391 GTBlock->Type = EFI_ACPI_6_4_GTDT_GT_BLOCK;\r
392 GTBlock->Length = (UINT16)Length;\r
393 GTBlock->Reserved = EFI_ACPI_RESERVED_BYTE;\r
394 GTBlock->CntCtlBase = GTBlockInfo->GTBlockPhysicalAddress;\r
395 GTBlock->GTBlockTimerCount = GTBlockInfo->GTBlockTimerFrameCount;\r
9c720258 396 GTBlock->GTBlockTimerOffset =\r
f09dbf20 397 sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE);\r
9c720258 398\r
731c67e1
MK
399 GtBlockFrame = (EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE *)\r
400 ((UINT8 *)GTBlock + GTBlock->GTBlockTimerOffset);\r
9c720258
SM
401\r
402 // Add GT Block Timer frames\r
403 Status = AddGTBlockTimerFrames (\r
404 GtBlockFrame,\r
405 GTBlockTimerFrameList,\r
406 GTBlockTimerFrameCount\r
407 );\r
408 if (EFI_ERROR (Status)) {\r
409 DEBUG ((\r
410 DEBUG_ERROR,\r
411 "ERROR: GTDT: Failed to add Generic Timer Frames. Status = %r\n",\r
412 Status\r
413 ));\r
414 return Status;\r
415 }\r
416\r
417 // Next GTBlock\r
731c67e1
MK
418 GTBlock = (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE *)((UINT8 *)GTBlock +\r
419 GTBlock->Length);\r
9c720258
SM
420 GTBlockInfo++;\r
421 }// for\r
731c67e1 422\r
9c720258
SM
423 return EFI_SUCCESS;\r
424}\r
425\r
426/** Construct the GTDT ACPI table.\r
427\r
428 Called by the Dynamic Table Manager, this function invokes the\r
429 Configuration Manager protocol interface to get the required hardware\r
430 information for generating the ACPI table.\r
431\r
432 If this function allocates any resources then they must be freed\r
433 in the FreeXXXXTableResources function.\r
434\r
435 @param [in] This Pointer to the table generator.\r
436 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
437 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
438 Protocol Interface.\r
439 @param [out] Table Pointer to the constructed ACPI Table.\r
440\r
441 @retval EFI_SUCCESS Table generated successfully.\r
442 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
443 @retval EFI_NOT_FOUND The required object was not found.\r
444 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
445 Manager is less than the Object size for the\r
446 requested object.\r
447 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
448**/\r
449STATIC\r
450EFI_STATUS\r
451EFIAPI\r
452BuildGtdtTable (\r
731c67e1
MK
453 IN CONST ACPI_TABLE_GENERATOR *CONST This,\r
454 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
455 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
456 OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table\r
9c720258
SM
457 )\r
458{\r
731c67e1
MK
459 EFI_STATUS Status;\r
460 UINT32 TableSize;\r
461 UINT32 PlatformTimerCount;\r
462 UINT32 WatchdogCount;\r
463 UINT32 BlockTimerCount;\r
464 CM_ARM_GENERIC_WATCHDOG_INFO *WatchdogInfoList;\r
465 CM_ARM_GTBLOCK_INFO *GTBlockInfo;\r
466 EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE *Gtdt;\r
467 UINT32 Idx;\r
468 UINT32 GTBlockOffset;\r
469 UINT32 WatchdogOffset;\r
9c720258
SM
470\r
471 ASSERT (This != NULL);\r
472 ASSERT (AcpiTableInfo != NULL);\r
473 ASSERT (CfgMgrProtocol != NULL);\r
474 ASSERT (Table != NULL);\r
475 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
476 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
477\r
478 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
731c67e1
MK
479 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))\r
480 {\r
9c720258
SM
481 DEBUG ((\r
482 DEBUG_ERROR,\r
483 "ERROR: GTDT: Requested table revision = %d, is not supported."\r
484 "Supported table revision: Minimum = %d, Maximum = %d\n",\r
485 AcpiTableInfo->AcpiTableRevision,\r
486 This->MinAcpiTableRevision,\r
487 This->AcpiTableRevision\r
488 ));\r
489 return EFI_INVALID_PARAMETER;\r
490 }\r
491\r
492 *Table = NULL;\r
493 Status = GetEArmObjPlatformGTBlockInfo (\r
494 CfgMgrProtocol,\r
495 CM_NULL_TOKEN,\r
496 &GTBlockInfo,\r
497 &BlockTimerCount\r
498 );\r
499 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
500 DEBUG ((\r
501 DEBUG_ERROR,\r
502 "ERROR: GTDT: Failed to Get Platform GT Block Information." \\r
503 " Status = %r\n",\r
504 Status\r
505 ));\r
506 goto error_handler;\r
507 }\r
508\r
509 Status = GetEArmObjPlatformGenericWatchdogInfo (\r
510 CfgMgrProtocol,\r
511 CM_NULL_TOKEN,\r
512 &WatchdogInfoList,\r
513 &WatchdogCount\r
514 );\r
515 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
516 DEBUG ((\r
517 DEBUG_ERROR,\r
518 "ERROR: GTDT: Failed to Get Platform Generic Watchdog Information." \\r
519 " Status = %r\n",\r
520 Status\r
521 ));\r
522 goto error_handler;\r
523 }\r
524\r
525 DEBUG ((\r
526 DEBUG_INFO,\r
527 "GTDT: BlockTimerCount = %d, WatchdogCount = %d\n",\r
528 BlockTimerCount,\r
529 WatchdogCount\r
530 ));\r
531\r
532 // Calculate the GTDT Table Size\r
533 PlatformTimerCount = 0;\r
731c67e1 534 TableSize = sizeof (EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE);\r
9c720258 535 if (BlockTimerCount != 0) {\r
731c67e1 536 GTBlockOffset = TableSize;\r
9c720258 537 PlatformTimerCount += BlockTimerCount;\r
731c67e1
MK
538 TableSize += (sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE) *\r
539 BlockTimerCount);\r
9c720258
SM
540\r
541 for (Idx = 0; Idx < BlockTimerCount; Idx++) {\r
542 if (GTBlockInfo[Idx].GTBlockTimerFrameCount > 8) {\r
543 Status = EFI_INVALID_PARAMETER;\r
544 DEBUG ((\r
545 DEBUG_ERROR,\r
546 "GTDT: GTBockFrameCount cannot be more than 8." \\r
547 " GTBockFrameCount = %d, Status = %r\n",\r
548 GTBlockInfo[Idx].GTBlockTimerFrameCount,\r
549 Status\r
550 ));\r
551 goto error_handler;\r
552 }\r
731c67e1 553\r
f09dbf20 554 TableSize += (sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE) *\r
731c67e1 555 GTBlockInfo[Idx].GTBlockTimerFrameCount);\r
9c720258
SM
556 }\r
557\r
558 DEBUG ((\r
559 DEBUG_INFO,\r
560 "GTDT: GTBockOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",\r
561 GTBlockOffset,\r
562 PlatformTimerCount\r
563 ));\r
564 }\r
565\r
566 WatchdogOffset = 0;\r
567 if (WatchdogCount != 0) {\r
731c67e1 568 WatchdogOffset = TableSize;\r
9c720258 569 PlatformTimerCount += WatchdogCount;\r
731c67e1
MK
570 TableSize += (sizeof (EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG_STRUCTURE) *\r
571 WatchdogCount);\r
9c720258
SM
572 DEBUG ((\r
573 DEBUG_INFO,\r
574 "GTDT: WatchdogOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",\r
575 WatchdogOffset,\r
576 PlatformTimerCount\r
577 ));\r
578 }\r
579\r
731c67e1 580 *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);\r
9c720258
SM
581 if (*Table == NULL) {\r
582 Status = EFI_OUT_OF_RESOURCES;\r
583 DEBUG ((\r
584 DEBUG_ERROR,\r
585 "ERROR: GTDT: Failed to allocate memory for GTDT Table, Size = %d," \\r
586 " Status = %r\n",\r
587 TableSize,\r
588 Status\r
589 ));\r
590 goto error_handler;\r
591 }\r
592\r
731c67e1 593 Gtdt = (EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE *)*Table;\r
9c720258
SM
594 DEBUG ((\r
595 DEBUG_INFO,\r
596 "GTDT: Gtdt = 0x%p TableSize = 0x%x\n",\r
597 Gtdt,\r
598 TableSize\r
599 ));\r
600\r
601 Status = AddAcpiHeader (\r
602 CfgMgrProtocol,\r
603 This,\r
604 &Gtdt->Header,\r
e12bdeb1 605 AcpiTableInfo,\r
9c720258
SM
606 TableSize\r
607 );\r
608 if (EFI_ERROR (Status)) {\r
609 DEBUG ((\r
610 DEBUG_ERROR,\r
611 "ERROR: GTDT: Failed to add ACPI header. Status = %r\n",\r
612 Status\r
613 ));\r
614 goto error_handler;\r
615 }\r
616\r
617 Status = AddGenericTimerInfo (\r
618 CfgMgrProtocol,\r
619 Gtdt,\r
e8015f2f
PG
620 PlatformTimerCount,\r
621 AcpiTableInfo->AcpiTableRevision\r
9c720258
SM
622 );\r
623 if (EFI_ERROR (Status)) {\r
624 DEBUG ((\r
625 DEBUG_ERROR,\r
626 "ERROR: GTDT: Failed to add Generic Timer Info. Status = %r\n",\r
627 Status\r
628 ));\r
629 goto error_handler;\r
630 }\r
631\r
632 if (BlockTimerCount != 0) {\r
633 Status = AddGTBlockList (\r
634 CfgMgrProtocol,\r
635 Gtdt,\r
636 GTBlockOffset,\r
637 GTBlockInfo,\r
638 BlockTimerCount\r
639 );\r
640 if (EFI_ERROR (Status)) {\r
641 DEBUG ((\r
642 DEBUG_ERROR,\r
643 "ERROR: GTDT: Failed to add GT Block timers. Status = %r\n",\r
644 Status\r
645 ));\r
646 goto error_handler;\r
647 }\r
648 }\r
649\r
650 if (WatchdogCount != 0) {\r
651 AddGenericWatchdogList (\r
652 Gtdt,\r
653 WatchdogOffset,\r
654 WatchdogInfoList,\r
655 WatchdogCount\r
656 );\r
657 }\r
658\r
659 return Status;\r
660\r
661error_handler:\r
662 if (*Table != NULL) {\r
663 FreePool (*Table);\r
664 *Table = NULL;\r
665 }\r
731c67e1 666\r
9c720258
SM
667 return Status;\r
668}\r
669\r
670/** Free any resources allocated for constructing the GTDT.\r
671\r
672 @param [in] This Pointer to the table generator.\r
673 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
674 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
675 Protocol Interface.\r
676 @param [in, out] Table Pointer to the ACPI Table.\r
677\r
678 @retval EFI_SUCCESS The resources were freed successfully.\r
679 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
680**/\r
681STATIC\r
682EFI_STATUS\r
683FreeGtdtTableResources (\r
731c67e1
MK
684 IN CONST ACPI_TABLE_GENERATOR *CONST This,\r
685 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
686 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
687 IN OUT EFI_ACPI_DESCRIPTION_HEADER **CONST Table\r
688 )\r
9c720258
SM
689{\r
690 ASSERT (This != NULL);\r
691 ASSERT (AcpiTableInfo != NULL);\r
692 ASSERT (CfgMgrProtocol != NULL);\r
693 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
694 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
695\r
696 if ((Table == NULL) || (*Table == NULL)) {\r
697 DEBUG ((DEBUG_ERROR, "ERROR: GTDT: Invalid Table Pointer\n"));\r
698 ASSERT ((Table != NULL) && (*Table != NULL));\r
699 return EFI_INVALID_PARAMETER;\r
700 }\r
701\r
702 FreePool (*Table);\r
703 *Table = NULL;\r
704 return EFI_SUCCESS;\r
705}\r
706\r
707/** This macro defines the GTDT Table Generator revision.\r
708*/\r
731c67e1 709#define GTDT_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
9c720258
SM
710\r
711/** The interface for the GTDT Table Generator.\r
712*/\r
713STATIC\r
714CONST\r
731c67e1 715ACPI_TABLE_GENERATOR GtdtGenerator = {\r
9c720258
SM
716 // Generator ID\r
717 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdGtdt),\r
718 // Generator Description\r
719 L"ACPI.STD.GTDT.GENERATOR",\r
720 // ACPI Table Signature\r
f09dbf20 721 EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,\r
9c720258 722 // ACPI Table Revision supported by this Generator\r
f09dbf20 723 EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,\r
9c720258
SM
724 // Minimum ACPI Table Revision supported by this Generator\r
725 EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,\r
726 // Creator ID\r
727 TABLE_GENERATOR_CREATOR_ID_ARM,\r
728 // Creator Revision\r
729 GTDT_GENERATOR_REVISION,\r
730 // Build Table function\r
731 BuildGtdtTable,\r
732 // Free Resource function\r
733 FreeGtdtTableResources,\r
734 // Extended build function not needed\r
735 NULL,\r
736 // Extended build function not implemented by the generator.\r
737 // Hence extended free resource function is not required.\r
738 NULL\r
739};\r
740\r
741/** Register the Generator with the ACPI Table Factory.\r
742\r
743 @param [in] ImageHandle The handle to the image.\r
744 @param [in] SystemTable Pointer to the System Table.\r
745\r
746 @retval EFI_SUCCESS The Generator is registered.\r
747 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
748 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
749 is already registered.\r
750**/\r
751EFI_STATUS\r
752EFIAPI\r
753AcpiGtdtLibConstructor (\r
731c67e1
MK
754 IN EFI_HANDLE ImageHandle,\r
755 IN EFI_SYSTEM_TABLE *SystemTable\r
9c720258
SM
756 )\r
757{\r
758 EFI_STATUS Status;\r
731c67e1 759\r
9c720258
SM
760 Status = RegisterAcpiTableGenerator (&GtdtGenerator);\r
761 DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n", Status));\r
762 ASSERT_EFI_ERROR (Status);\r
763 return Status;\r
764}\r
765\r
766/** Deregister the Generator from the ACPI Table Factory.\r
767\r
768 @param [in] ImageHandle The handle to the image.\r
769 @param [in] SystemTable Pointer to the System Table.\r
770\r
771 @retval EFI_SUCCESS The Generator is deregistered.\r
772 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
773 @retval EFI_NOT_FOUND The Generator is not registered.\r
774**/\r
775EFI_STATUS\r
776EFIAPI\r
777AcpiGtdtLibDestructor (\r
731c67e1
MK
778 IN EFI_HANDLE ImageHandle,\r
779 IN EFI_SYSTEM_TABLE *SystemTable\r
9c720258
SM
780 )\r
781{\r
782 EFI_STATUS Status;\r
731c67e1 783\r
9c720258
SM
784 Status = DeregisterAcpiTableGenerator (&GtdtGenerator);\r
785 DEBUG ((DEBUG_INFO, "GTDT: Deregister Generator. Status = %r\n", Status));\r
786 ASSERT_EFI_ERROR (Status);\r
787 return Status;\r
788}\r