]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/GtdtGenerator.c
DynamicTablesPkg: Remove redundant frame count check
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiGtdtLibArm / GtdtGenerator.c
CommitLineData
9c720258
SM
1/** @file\r
2 GTDT Table Generator\r
3\r
4 Copyright (c) 2017 - 2019, 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
e8015f2f 8 - ACPI 6.3 Specification - January 2019\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
44/** This macro expands to a function that retrieves the SBSA Generic\r
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
93 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
e8015f2f
PG
94 IN EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,\r
95 IN CONST UINT32 PlatformTimerCount,\r
96 IN CONST UINT32 AcpiTableRevision\r
9c720258
SM
97)\r
98{\r
99 EFI_STATUS Status;\r
100 CM_ARM_GENERIC_TIMER_INFO * GenericTimerInfo;\r
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
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
132 Gtdt->CntReadBasePhysicalAddress =\r
133 GenericTimerInfo->CounterReadBaseAddress;\r
134 Gtdt->PlatformTimerCount = PlatformTimerCount;\r
135 Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :\r
e8015f2f 136 sizeof (EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE);\r
9c720258 137\r
e8015f2f
PG
138 if (AcpiTableRevision > EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION) {\r
139 Gtdt->VirtualPL2TimerGSIV = GenericTimerInfo->VirtualPL2TimerGSIV;\r
140 Gtdt->VirtualPL2TimerFlags = GenericTimerInfo->VirtualPL2TimerFlags;\r
141 }\r
142\r
143 return Status;\r
9c720258
SM
144}\r
145\r
146/** Add the SBSA Generic Watchdog Timers to the GTDT table.\r
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
e8015f2f 157 IN EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,\r
9c720258
SM
158 IN CONST UINT32 WatchdogOffset,\r
159 IN CONST CM_ARM_GENERIC_WATCHDOG_INFO * WatchdogInfoList,\r
160 IN UINT32 WatchdogCount\r
161 )\r
162{\r
e8015f2f 163 EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE * Watchdog;\r
9c720258
SM
164\r
165 ASSERT (Gtdt != NULL);\r
166 ASSERT (WatchdogInfoList != NULL);\r
167\r
e8015f2f 168 Watchdog = (EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE *)\r
9c720258
SM
169 ((UINT8*)Gtdt + WatchdogOffset);\r
170\r
171 while (WatchdogCount-- != 0) {\r
172 // Add watchdog entry\r
173 DEBUG ((DEBUG_INFO, "GTDT: Watchdog = 0x%p\n", Watchdog));\r
e8015f2f 174 Watchdog->Type = EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG;\r
9c720258 175 Watchdog->Length =\r
e8015f2f 176 sizeof (EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE);\r
9c720258
SM
177 Watchdog->Reserved = EFI_ACPI_RESERVED_BYTE;\r
178 Watchdog->RefreshFramePhysicalAddress =\r
179 WatchdogInfoList->RefreshFrameAddress;\r
180 Watchdog->WatchdogControlFramePhysicalAddress =\r
181 WatchdogInfoList->ControlFrameAddress;\r
182 Watchdog->WatchdogTimerGSIV = WatchdogInfoList->TimerGSIV;\r
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
209 IN CONST VOID * Frame1,\r
210 IN CONST VOID * Frame2,\r
211 IN UINTN Index1,\r
212 IN UINTN Index2\r
213 )\r
214{\r
215 UINT8 FrameNumber1;\r
216 UINT8 FrameNumber2;\r
217\r
218 ASSERT ((Frame1 != NULL) && (Frame2 != NULL));\r
219\r
220 FrameNumber1 = ((CM_ARM_GTBLOCK_TIMER_FRAME_INFO*)Frame1)->FrameNumber;\r
221 FrameNumber2 = ((CM_ARM_GTBLOCK_TIMER_FRAME_INFO*)Frame2)->FrameNumber;\r
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
e8015f2f 252 IN EFI_ACPI_6_3_GTDT_GT_BLOCK_TIMER_STRUCTURE * GtBlockFrame,\r
9c720258
SM
253 IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO * GTBlockTimerFrameList,\r
254 IN UINT32 GTBlockFrameCount\r
255)\r
256{\r
ccc97f6d
KK
257 BOOLEAN IsFrameNumberDuplicated;\r
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
285 ));\r
286 return EFI_INVALID_PARAMETER;\r
287 }\r
288\r
9c720258
SM
289 GtBlockFrame->GTFrameNumber = GTBlockTimerFrameList->FrameNumber;\r
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
293\r
294 GtBlockFrame->CntBaseX = GTBlockTimerFrameList->PhysicalAddressCntBase;\r
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
303 GtBlockFrame->GTxVirtualTimerGSIV = GTBlockTimerFrameList->VirtualTimerGSIV;\r
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
311 return EFI_SUCCESS;\r
312}\r
313\r
314/** Add the GT Block Timers in the GTDT Table.\r
315\r
316 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
317 Protocol Interface.\r
318 @param [in] Gtdt Pointer to the GTDT Table.\r
319 @param [in] GTBlockOffset Offset of the GT Block\r
320 information in the GTDT Table.\r
321 @param [in] GTBlockInfo Pointer to the GT Block\r
322 Information List.\r
323 @param [in] BlockTimerCount Number of GT Block Timers.\r
324\r
325 @retval EFI_SUCCESS Table generated successfully.\r
326 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
327**/\r
328STATIC\r
329EFI_STATUS\r
330AddGTBlockList (\r
331 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
e8015f2f 332 IN EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE * CONST Gtdt,\r
9c720258
SM
333 IN CONST UINT32 GTBlockOffset,\r
334 IN CONST CM_ARM_GTBLOCK_INFO * GTBlockInfo,\r
335 IN UINT32 BlockTimerCount\r
336)\r
337{\r
338 EFI_STATUS Status;\r
e8015f2f
PG
339 EFI_ACPI_6_3_GTDT_GT_BLOCK_STRUCTURE * GTBlock;\r
340 EFI_ACPI_6_3_GTDT_GT_BLOCK_TIMER_STRUCTURE * GtBlockFrame;\r
9c720258
SM
341 CM_ARM_GTBLOCK_TIMER_FRAME_INFO * GTBlockTimerFrameList;\r
342 UINT32 GTBlockTimerFrameCount;\r
87847811 343 UINTN Length;\r
9c720258
SM
344\r
345 ASSERT (Gtdt != NULL);\r
346 ASSERT (GTBlockInfo != NULL);\r
347\r
e8015f2f 348 GTBlock = (EFI_ACPI_6_3_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)Gtdt +\r
9c720258
SM
349 GTBlockOffset);\r
350\r
351 while (BlockTimerCount-- != 0) {\r
352 DEBUG ((DEBUG_INFO, "GTDT: GTBlock = 0x%p\n", GTBlock));\r
353\r
354 Status = GetEArmObjGTBlockTimerFrameInfo (\r
355 CfgMgrProtocol,\r
356 GTBlockInfo->GTBlockTimerFrameToken,\r
357 &GTBlockTimerFrameList,\r
358 &GTBlockTimerFrameCount\r
359 );\r
360 if (EFI_ERROR (Status) ||\r
361 (GTBlockTimerFrameCount != GTBlockInfo->GTBlockTimerFrameCount)) {\r
362 DEBUG ((\r
363 DEBUG_ERROR,\r
364 "ERROR: GTDT: Failed to get Generic Timer Frames. Status = %r\n",\r
365 Status\r
366 ));\r
367 return Status;\r
368 }\r
369\r
87847811
SM
370 Length = sizeof (EFI_ACPI_6_3_GTDT_GT_BLOCK_STRUCTURE) +\r
371 (sizeof (EFI_ACPI_6_3_GTDT_GT_BLOCK_TIMER_STRUCTURE) *\r
372 GTBlockInfo->GTBlockTimerFrameCount);\r
9c720258 373\r
87847811
SM
374 // Check that the length of the GT block does not\r
375 // exceed MAX_UINT16\r
376 if (Length > MAX_UINT16) {\r
377 Status = EFI_INVALID_PARAMETER;\r
378 DEBUG ((\r
379 DEBUG_ERROR,\r
380 "ERROR: GTDT: Too many GT Frames. Count = %d. " \\r
381 "Maximum supported GT Block size exceeded. " \\r
382 "Status = %r\n",\r
383 GTBlockInfo->GTBlockTimerFrameCount,\r
384 Status\r
385 ));\r
386 return Status;\r
387 }\r
388\r
389 GTBlock->Type = EFI_ACPI_6_3_GTDT_GT_BLOCK;\r
390 GTBlock->Length = (UINT16)Length;\r
9c720258
SM
391 GTBlock->Reserved = EFI_ACPI_RESERVED_BYTE;\r
392 GTBlock->CntCtlBase = GTBlockInfo->GTBlockPhysicalAddress;\r
393 GTBlock->GTBlockTimerCount = GTBlockInfo->GTBlockTimerFrameCount;\r
394 GTBlock->GTBlockTimerOffset =\r
e8015f2f 395 sizeof (EFI_ACPI_6_3_GTDT_GT_BLOCK_STRUCTURE);\r
9c720258 396\r
e8015f2f 397 GtBlockFrame = (EFI_ACPI_6_3_GTDT_GT_BLOCK_TIMER_STRUCTURE*)\r
9c720258
SM
398 ((UINT8*)GTBlock + GTBlock->GTBlockTimerOffset);\r
399\r
400 // Add GT Block Timer frames\r
401 Status = AddGTBlockTimerFrames (\r
402 GtBlockFrame,\r
403 GTBlockTimerFrameList,\r
404 GTBlockTimerFrameCount\r
405 );\r
406 if (EFI_ERROR (Status)) {\r
407 DEBUG ((\r
408 DEBUG_ERROR,\r
409 "ERROR: GTDT: Failed to add Generic Timer Frames. Status = %r\n",\r
410 Status\r
411 ));\r
412 return Status;\r
413 }\r
414\r
415 // Next GTBlock\r
e8015f2f 416 GTBlock = (EFI_ACPI_6_3_GTDT_GT_BLOCK_STRUCTURE *)((UINT8*)GTBlock +\r
9c720258
SM
417 GTBlock->Length);\r
418 GTBlockInfo++;\r
419 }// for\r
420 return EFI_SUCCESS;\r
421}\r
422\r
423/** Construct the GTDT ACPI table.\r
424\r
425 Called by the Dynamic Table Manager, this function invokes the\r
426 Configuration Manager protocol interface to get the required hardware\r
427 information for generating the ACPI table.\r
428\r
429 If this function allocates any resources then they must be freed\r
430 in the FreeXXXXTableResources function.\r
431\r
432 @param [in] This Pointer to the table generator.\r
433 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
434 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
435 Protocol Interface.\r
436 @param [out] Table Pointer to the constructed ACPI Table.\r
437\r
438 @retval EFI_SUCCESS Table generated successfully.\r
439 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
440 @retval EFI_NOT_FOUND The required object was not found.\r
441 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
442 Manager is less than the Object size for the\r
443 requested object.\r
444 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
445**/\r
446STATIC\r
447EFI_STATUS\r
448EFIAPI\r
449BuildGtdtTable (\r
450 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
451 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
452 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
453 OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
454 )\r
455{\r
456 EFI_STATUS Status;\r
457 UINT32 TableSize;\r
458 UINT32 PlatformTimerCount;\r
459 UINT32 WatchdogCount;\r
460 UINT32 BlockTimerCount;\r
461 CM_ARM_GENERIC_WATCHDOG_INFO * WatchdogInfoList;\r
462 CM_ARM_GTBLOCK_INFO * GTBlockInfo;\r
e8015f2f 463 EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE * Gtdt;\r
9c720258
SM
464 UINT32 Idx;\r
465 UINT32 GTBlockOffset;\r
466 UINT32 WatchdogOffset;\r
467\r
468 ASSERT (This != NULL);\r
469 ASSERT (AcpiTableInfo != NULL);\r
470 ASSERT (CfgMgrProtocol != NULL);\r
471 ASSERT (Table != NULL);\r
472 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
473 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
474\r
475 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
476 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
477 DEBUG ((\r
478 DEBUG_ERROR,\r
479 "ERROR: GTDT: Requested table revision = %d, is not supported."\r
480 "Supported table revision: Minimum = %d, Maximum = %d\n",\r
481 AcpiTableInfo->AcpiTableRevision,\r
482 This->MinAcpiTableRevision,\r
483 This->AcpiTableRevision\r
484 ));\r
485 return EFI_INVALID_PARAMETER;\r
486 }\r
487\r
488 *Table = NULL;\r
489 Status = GetEArmObjPlatformGTBlockInfo (\r
490 CfgMgrProtocol,\r
491 CM_NULL_TOKEN,\r
492 &GTBlockInfo,\r
493 &BlockTimerCount\r
494 );\r
495 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
496 DEBUG ((\r
497 DEBUG_ERROR,\r
498 "ERROR: GTDT: Failed to Get Platform GT Block Information." \\r
499 " Status = %r\n",\r
500 Status\r
501 ));\r
502 goto error_handler;\r
503 }\r
504\r
505 Status = GetEArmObjPlatformGenericWatchdogInfo (\r
506 CfgMgrProtocol,\r
507 CM_NULL_TOKEN,\r
508 &WatchdogInfoList,\r
509 &WatchdogCount\r
510 );\r
511 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {\r
512 DEBUG ((\r
513 DEBUG_ERROR,\r
514 "ERROR: GTDT: Failed to Get Platform Generic Watchdog Information." \\r
515 " Status = %r\n",\r
516 Status\r
517 ));\r
518 goto error_handler;\r
519 }\r
520\r
521 DEBUG ((\r
522 DEBUG_INFO,\r
523 "GTDT: BlockTimerCount = %d, WatchdogCount = %d\n",\r
524 BlockTimerCount,\r
525 WatchdogCount\r
526 ));\r
527\r
528 // Calculate the GTDT Table Size\r
529 PlatformTimerCount = 0;\r
e8015f2f 530 TableSize = sizeof (EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE);\r
9c720258
SM
531 if (BlockTimerCount != 0) {\r
532 GTBlockOffset = TableSize;\r
533 PlatformTimerCount += BlockTimerCount;\r
e8015f2f 534 TableSize += (sizeof (EFI_ACPI_6_3_GTDT_GT_BLOCK_STRUCTURE) *\r
9c720258
SM
535 BlockTimerCount);\r
536\r
537 for (Idx = 0; Idx < BlockTimerCount; Idx++) {\r
538 if (GTBlockInfo[Idx].GTBlockTimerFrameCount > 8) {\r
539 Status = EFI_INVALID_PARAMETER;\r
540 DEBUG ((\r
541 DEBUG_ERROR,\r
542 "GTDT: GTBockFrameCount cannot be more than 8." \\r
543 " GTBockFrameCount = %d, Status = %r\n",\r
544 GTBlockInfo[Idx].GTBlockTimerFrameCount,\r
545 Status\r
546 ));\r
547 goto error_handler;\r
548 }\r
e8015f2f 549 TableSize += (sizeof (EFI_ACPI_6_3_GTDT_GT_BLOCK_TIMER_STRUCTURE) *\r
9c720258
SM
550 GTBlockInfo[Idx].GTBlockTimerFrameCount);\r
551 }\r
552\r
553 DEBUG ((\r
554 DEBUG_INFO,\r
555 "GTDT: GTBockOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",\r
556 GTBlockOffset,\r
557 PlatformTimerCount\r
558 ));\r
559 }\r
560\r
561 WatchdogOffset = 0;\r
562 if (WatchdogCount != 0) {\r
563 WatchdogOffset = TableSize;\r
564 PlatformTimerCount += WatchdogCount;\r
e8015f2f 565 TableSize += (sizeof (EFI_ACPI_6_3_GTDT_SBSA_GENERIC_WATCHDOG_STRUCTURE) *\r
9c720258
SM
566 WatchdogCount);\r
567 DEBUG ((\r
568 DEBUG_INFO,\r
569 "GTDT: WatchdogOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",\r
570 WatchdogOffset,\r
571 PlatformTimerCount\r
572 ));\r
573 }\r
574\r
575 *Table = (EFI_ACPI_DESCRIPTION_HEADER*)AllocateZeroPool (TableSize);\r
576 if (*Table == NULL) {\r
577 Status = EFI_OUT_OF_RESOURCES;\r
578 DEBUG ((\r
579 DEBUG_ERROR,\r
580 "ERROR: GTDT: Failed to allocate memory for GTDT Table, Size = %d," \\r
581 " Status = %r\n",\r
582 TableSize,\r
583 Status\r
584 ));\r
585 goto error_handler;\r
586 }\r
587\r
e8015f2f 588 Gtdt = (EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE*)*Table;\r
9c720258
SM
589 DEBUG ((\r
590 DEBUG_INFO,\r
591 "GTDT: Gtdt = 0x%p TableSize = 0x%x\n",\r
592 Gtdt,\r
593 TableSize\r
594 ));\r
595\r
596 Status = AddAcpiHeader (\r
597 CfgMgrProtocol,\r
598 This,\r
599 &Gtdt->Header,\r
e12bdeb1 600 AcpiTableInfo,\r
9c720258
SM
601 TableSize\r
602 );\r
603 if (EFI_ERROR (Status)) {\r
604 DEBUG ((\r
605 DEBUG_ERROR,\r
606 "ERROR: GTDT: Failed to add ACPI header. Status = %r\n",\r
607 Status\r
608 ));\r
609 goto error_handler;\r
610 }\r
611\r
612 Status = AddGenericTimerInfo (\r
613 CfgMgrProtocol,\r
614 Gtdt,\r
e8015f2f
PG
615 PlatformTimerCount,\r
616 AcpiTableInfo->AcpiTableRevision\r
9c720258
SM
617 );\r
618 if (EFI_ERROR (Status)) {\r
619 DEBUG ((\r
620 DEBUG_ERROR,\r
621 "ERROR: GTDT: Failed to add Generic Timer Info. Status = %r\n",\r
622 Status\r
623 ));\r
624 goto error_handler;\r
625 }\r
626\r
627 if (BlockTimerCount != 0) {\r
628 Status = AddGTBlockList (\r
629 CfgMgrProtocol,\r
630 Gtdt,\r
631 GTBlockOffset,\r
632 GTBlockInfo,\r
633 BlockTimerCount\r
634 );\r
635 if (EFI_ERROR (Status)) {\r
636 DEBUG ((\r
637 DEBUG_ERROR,\r
638 "ERROR: GTDT: Failed to add GT Block timers. Status = %r\n",\r
639 Status\r
640 ));\r
641 goto error_handler;\r
642 }\r
643 }\r
644\r
645 if (WatchdogCount != 0) {\r
646 AddGenericWatchdogList (\r
647 Gtdt,\r
648 WatchdogOffset,\r
649 WatchdogInfoList,\r
650 WatchdogCount\r
651 );\r
652 }\r
653\r
654 return Status;\r
655\r
656error_handler:\r
657 if (*Table != NULL) {\r
658 FreePool (*Table);\r
659 *Table = NULL;\r
660 }\r
661 return Status;\r
662}\r
663\r
664/** Free any resources allocated for constructing the GTDT.\r
665\r
666 @param [in] This Pointer to the table generator.\r
667 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
668 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
669 Protocol Interface.\r
670 @param [in, out] Table Pointer to the ACPI Table.\r
671\r
672 @retval EFI_SUCCESS The resources were freed successfully.\r
673 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
674**/\r
675STATIC\r
676EFI_STATUS\r
677FreeGtdtTableResources (\r
678 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
679 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
680 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
681 IN OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
682)\r
683{\r
684 ASSERT (This != NULL);\r
685 ASSERT (AcpiTableInfo != NULL);\r
686 ASSERT (CfgMgrProtocol != NULL);\r
687 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
688 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
689\r
690 if ((Table == NULL) || (*Table == NULL)) {\r
691 DEBUG ((DEBUG_ERROR, "ERROR: GTDT: Invalid Table Pointer\n"));\r
692 ASSERT ((Table != NULL) && (*Table != NULL));\r
693 return EFI_INVALID_PARAMETER;\r
694 }\r
695\r
696 FreePool (*Table);\r
697 *Table = NULL;\r
698 return EFI_SUCCESS;\r
699}\r
700\r
701/** This macro defines the GTDT Table Generator revision.\r
702*/\r
703#define GTDT_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
704\r
705/** The interface for the GTDT Table Generator.\r
706*/\r
707STATIC\r
708CONST\r
709ACPI_TABLE_GENERATOR GtdtGenerator = {\r
710 // Generator ID\r
711 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdGtdt),\r
712 // Generator Description\r
713 L"ACPI.STD.GTDT.GENERATOR",\r
714 // ACPI Table Signature\r
e8015f2f 715 EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,\r
9c720258 716 // ACPI Table Revision supported by this Generator\r
e8015f2f 717 EFI_ACPI_6_3_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,\r
9c720258
SM
718 // Minimum ACPI Table Revision supported by this Generator\r
719 EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,\r
720 // Creator ID\r
721 TABLE_GENERATOR_CREATOR_ID_ARM,\r
722 // Creator Revision\r
723 GTDT_GENERATOR_REVISION,\r
724 // Build Table function\r
725 BuildGtdtTable,\r
726 // Free Resource function\r
727 FreeGtdtTableResources,\r
728 // Extended build function not needed\r
729 NULL,\r
730 // Extended build function not implemented by the generator.\r
731 // Hence extended free resource function is not required.\r
732 NULL\r
733};\r
734\r
735/** Register the Generator with the ACPI Table Factory.\r
736\r
737 @param [in] ImageHandle The handle to the image.\r
738 @param [in] SystemTable Pointer to the System Table.\r
739\r
740 @retval EFI_SUCCESS The Generator is registered.\r
741 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
742 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
743 is already registered.\r
744**/\r
745EFI_STATUS\r
746EFIAPI\r
747AcpiGtdtLibConstructor (\r
43a0e08d
SM
748 IN EFI_HANDLE ImageHandle,\r
749 IN EFI_SYSTEM_TABLE * SystemTable\r
9c720258
SM
750 )\r
751{\r
752 EFI_STATUS Status;\r
753 Status = RegisterAcpiTableGenerator (&GtdtGenerator);\r
754 DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n", Status));\r
755 ASSERT_EFI_ERROR (Status);\r
756 return Status;\r
757}\r
758\r
759/** Deregister the Generator from the ACPI Table Factory.\r
760\r
761 @param [in] ImageHandle The handle to the image.\r
762 @param [in] SystemTable Pointer to the System Table.\r
763\r
764 @retval EFI_SUCCESS The Generator is deregistered.\r
765 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
766 @retval EFI_NOT_FOUND The Generator is not registered.\r
767**/\r
768EFI_STATUS\r
769EFIAPI\r
770AcpiGtdtLibDestructor (\r
43a0e08d
SM
771 IN EFI_HANDLE ImageHandle,\r
772 IN EFI_SYSTEM_TABLE * SystemTable\r
9c720258
SM
773 )\r
774{\r
775 EFI_STATUS Status;\r
776 Status = DeregisterAcpiTableGenerator (&GtdtGenerator);\r
777 DEBUG ((DEBUG_INFO, "GTDT: Deregister Generator. Status = %r\n", Status));\r
778 ASSERT_EFI_ERROR (Status);\r
779 return Status;\r
780}\r