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