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