REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the DynamicTablesPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
		
			
				
	
	
		
			789 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			789 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   GTDT Table Generator
 | |
| 
 | |
|   Copyright (c) 2017 - 2021, ARM Limited. All rights reserved.
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
|   @par Reference(s):
 | |
|   - ACPI 6.4 Specification - January 2021
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include <Library/AcpiLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Protocol/AcpiTable.h>
 | |
| 
 | |
| // Module specific include files.
 | |
| #include <AcpiTableGenerator.h>
 | |
| #include <ConfigurationManagerObject.h>
 | |
| #include <ConfigurationManagerHelper.h>
 | |
| #include <Library/TableHelperLib.h>
 | |
| #include <Protocol/ConfigurationManagerProtocol.h>
 | |
| 
 | |
| /** ARM standard GTDT Generator
 | |
| 
 | |
| Requirements:
 | |
|   The following Configuration Manager Object(s) are required by
 | |
|   this Generator:
 | |
|   - EArmObjGenericTimerInfo
 | |
|   - EArmObjPlatformGenericWatchdogInfo (OPTIONAL)
 | |
|   - EArmObjPlatformGTBlockInfo (OPTIONAL)
 | |
|   - EArmObjGTBlockTimerFrameInfo (OPTIONAL)
 | |
| */
 | |
| 
 | |
| /** This macro expands to a function that retrieves the Generic
 | |
|     Timer Information from the Configuration Manager.
 | |
| */
 | |
| GET_OBJECT_LIST (
 | |
|   EObjNameSpaceArm,
 | |
|   EArmObjGenericTimerInfo,
 | |
|   CM_ARM_GENERIC_TIMER_INFO
 | |
|   );
 | |
| 
 | |
| /** This macro expands to a function that retrieves the Arm Generic
 | |
|     Watchdog Timer Information from the Configuration Manager.
 | |
| */
 | |
| GET_OBJECT_LIST (
 | |
|   EObjNameSpaceArm,
 | |
|   EArmObjPlatformGenericWatchdogInfo,
 | |
|   CM_ARM_GENERIC_WATCHDOG_INFO
 | |
|   );
 | |
| 
 | |
| /** This macro expands to a function that retrieves the Platform Generic
 | |
|     Timer Block Information from the Configuration Manager.
 | |
| */
 | |
| GET_OBJECT_LIST (
 | |
|   EObjNameSpaceArm,
 | |
|   EArmObjPlatformGTBlockInfo,
 | |
|   CM_ARM_GTBLOCK_INFO
 | |
|   );
 | |
| 
 | |
| /** This macro expands to a function that retrieves the Generic
 | |
|   Timer Block Timer Frame Information from the Configuration Manager.
 | |
| */
 | |
| GET_OBJECT_LIST (
 | |
|   EObjNameSpaceArm,
 | |
|   EArmObjGTBlockTimerFrameInfo,
 | |
|   CM_ARM_GTBLOCK_TIMER_FRAME_INFO
 | |
|   );
 | |
| 
 | |
| /** Add the Generic Timer Information to the GTDT table.
 | |
| 
 | |
|   Also update the Platform Timer offset information if the platform
 | |
|   implements platform timers.
 | |
| 
 | |
|   @param [in]  CfgMgrProtocol     Pointer to the Configuration Manager
 | |
|                                   Protocol Interface.
 | |
|   @param [in]  Gtdt               Pointer to the GTDT Table.
 | |
|   @param [in]  PlatformTimerCount Platform timer count.
 | |
|   @param [in]  AcpiTableRevision  Acpi Revision targeted by the platform.
 | |
| 
 | |
|   @retval EFI_SUCCESS           Success.
 | |
|   @retval EFI_INVALID_PARAMETER A parameter is invalid.
 | |
|   @retval EFI_NOT_FOUND         The required object was not found.
 | |
|   @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
 | |
|                                 Manager is less than the Object size for the
 | |
|                                 requested object.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| AddGenericTimerInfo (
 | |
|   IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL         *CONST  CfgMgrProtocol,
 | |
|   IN        EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE *CONST  Gtdt,
 | |
|   IN  CONST UINT32                                               PlatformTimerCount,
 | |
|   IN  CONST UINT32                                               AcpiTableRevision
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                 Status;
 | |
|   CM_ARM_GENERIC_TIMER_INFO  *GenericTimerInfo;
 | |
| 
 | |
|   ASSERT (CfgMgrProtocol != NULL);
 | |
|   ASSERT (Gtdt != NULL);
 | |
| 
 | |
|   Status = GetEArmObjGenericTimerInfo (
 | |
|              CfgMgrProtocol,
 | |
|              CM_NULL_TOKEN,
 | |
|              &GenericTimerInfo,
 | |
|              NULL
 | |
|              );
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: GTDT: Failed to get GenericTimerInfo. Status = %r\n",
 | |
|       Status
 | |
|       ));
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Gtdt->CntControlBasePhysicalAddress =
 | |
|     GenericTimerInfo->CounterControlBaseAddress;
 | |
|   Gtdt->Reserved                   = EFI_ACPI_RESERVED_DWORD;
 | |
|   Gtdt->SecurePL1TimerGSIV         = GenericTimerInfo->SecurePL1TimerGSIV;
 | |
|   Gtdt->SecurePL1TimerFlags        = GenericTimerInfo->SecurePL1TimerFlags;
 | |
|   Gtdt->NonSecurePL1TimerGSIV      = GenericTimerInfo->NonSecurePL1TimerGSIV;
 | |
|   Gtdt->NonSecurePL1TimerFlags     = GenericTimerInfo->NonSecurePL1TimerFlags;
 | |
|   Gtdt->VirtualTimerGSIV           = GenericTimerInfo->VirtualTimerGSIV;
 | |
|   Gtdt->VirtualTimerFlags          = GenericTimerInfo->VirtualTimerFlags;
 | |
|   Gtdt->NonSecurePL2TimerGSIV      = GenericTimerInfo->NonSecurePL2TimerGSIV;
 | |
|   Gtdt->NonSecurePL2TimerFlags     = GenericTimerInfo->NonSecurePL2TimerFlags;
 | |
|   Gtdt->CntReadBasePhysicalAddress =
 | |
|     GenericTimerInfo->CounterReadBaseAddress;
 | |
|   Gtdt->PlatformTimerCount  = PlatformTimerCount;
 | |
|   Gtdt->PlatformTimerOffset = (PlatformTimerCount == 0) ? 0 :
 | |
|                               sizeof (EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE);
 | |
| 
 | |
|   if (AcpiTableRevision > EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION) {
 | |
|     Gtdt->VirtualPL2TimerGSIV  = GenericTimerInfo->VirtualPL2TimerGSIV;
 | |
|     Gtdt->VirtualPL2TimerFlags = GenericTimerInfo->VirtualPL2TimerFlags;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /** Add the Arm Generic Watchdog Timers to the GTDT table.
 | |
| 
 | |
|   @param [in]  Gtdt             Pointer to the GTDT Table.
 | |
|   @param [in]  WatchdogOffset   Offset to the watchdog information in the
 | |
|                                 GTDT Table.
 | |
|   @param [in]  WatchdogInfoList Pointer to the watchdog information list.
 | |
|   @param [in]  WatchdogCount    Platform timer count.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| AddGenericWatchdogList (
 | |
|   IN EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE  *CONST  Gtdt,
 | |
|   IN CONST UINT32                                          WatchdogOffset,
 | |
|   IN CONST CM_ARM_GENERIC_WATCHDOG_INFO                    *WatchdogInfoList,
 | |
|   IN       UINT32                                          WatchdogCount
 | |
|   )
 | |
| {
 | |
|   EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG_STRUCTURE  *Watchdog;
 | |
| 
 | |
|   ASSERT (Gtdt != NULL);
 | |
|   ASSERT (WatchdogInfoList != NULL);
 | |
| 
 | |
|   Watchdog = (EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG_STRUCTURE *)
 | |
|              ((UINT8 *)Gtdt + WatchdogOffset);
 | |
| 
 | |
|   while (WatchdogCount-- != 0) {
 | |
|     // Add watchdog entry
 | |
|     DEBUG ((DEBUG_INFO, "GTDT: Watchdog = 0x%p\n", Watchdog));
 | |
|     Watchdog->Type   = EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG;
 | |
|     Watchdog->Length =
 | |
|       sizeof (EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG_STRUCTURE);
 | |
|     Watchdog->Reserved                    = EFI_ACPI_RESERVED_BYTE;
 | |
|     Watchdog->RefreshFramePhysicalAddress =
 | |
|       WatchdogInfoList->RefreshFrameAddress;
 | |
|     Watchdog->WatchdogControlFramePhysicalAddress =
 | |
|       WatchdogInfoList->ControlFrameAddress;
 | |
|     Watchdog->WatchdogTimerGSIV  = WatchdogInfoList->TimerGSIV;
 | |
|     Watchdog->WatchdogTimerFlags = WatchdogInfoList->Flags;
 | |
|     Watchdog++;
 | |
|     WatchdogInfoList++;
 | |
|   } // for
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Function to test if two Generic Timer Block Frame Info structures have the
 | |
|   same frame number.
 | |
| 
 | |
|   @param [in]  Frame1           Pointer to the first GT Block Frame Info
 | |
|                                 structure.
 | |
|   @param [in]  Frame2           Pointer to the second GT Block Frame Info
 | |
|                                 structure.
 | |
|   @param [in]  Index1           Index of Frame1 in the shared GT Block Frame
 | |
|                                 Information List.
 | |
|   @param [in]  Index2           Index of Frame2 in the shared GT Block Frame
 | |
|                                 Information List.
 | |
| 
 | |
|   @retval TRUE                  Frame1 and Frame2 have the same frame number.
 | |
|   @return FALSE                 Frame1 and Frame2 have different frame numbers.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| EFIAPI
 | |
| IsGtFrameNumberEqual (
 | |
|   IN  CONST VOID   *Frame1,
 | |
|   IN  CONST VOID   *Frame2,
 | |
|   IN        UINTN  Index1,
 | |
|   IN        UINTN  Index2
 | |
|   )
 | |
| {
 | |
|   UINT8  FrameNumber1;
 | |
|   UINT8  FrameNumber2;
 | |
| 
 | |
|   ASSERT ((Frame1 != NULL) && (Frame2 != NULL));
 | |
| 
 | |
|   FrameNumber1 = ((CM_ARM_GTBLOCK_TIMER_FRAME_INFO *)Frame1)->FrameNumber;
 | |
|   FrameNumber2 = ((CM_ARM_GTBLOCK_TIMER_FRAME_INFO *)Frame2)->FrameNumber;
 | |
| 
 | |
|   if (FrameNumber1 == FrameNumber2) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: GTDT: GT Block Frame Info Structures %d and %d have the same " \
 | |
|       "frame number: 0x%x.\n",
 | |
|       Index1,
 | |
|       Index2,
 | |
|       FrameNumber1
 | |
|       ));
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| /** Update the GT Block Timer Frame lists in the GTDT Table.
 | |
| 
 | |
|   @param [in]  GtBlockFrame           Pointer to the GT Block Frames
 | |
|                                       list to be updated.
 | |
|   @param [in]  GTBlockTimerFrameList  Pointer to the GT Block Frame
 | |
|                                       Information List.
 | |
|   @param [in]  GTBlockFrameCount      Number of GT Block Frames.
 | |
| 
 | |
|   @retval EFI_SUCCESS                 Table generated successfully.
 | |
|   @retval EFI_INVALID_PARAMETER       A parameter is invalid.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| AddGTBlockTimerFrames (
 | |
|   IN       EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE  *GtBlockFrame,
 | |
|   IN CONST CM_ARM_GTBLOCK_TIMER_FRAME_INFO             *GTBlockTimerFrameList,
 | |
|   IN       UINT32                                      GTBlockFrameCount
 | |
|   )
 | |
| {
 | |
|   BOOLEAN  IsFrameNumberDuplicated;
 | |
| 
 | |
|   ASSERT (GtBlockFrame != NULL);
 | |
|   ASSERT (GTBlockTimerFrameList != NULL);
 | |
| 
 | |
|   IsFrameNumberDuplicated = FindDuplicateValue (
 | |
|                               GTBlockTimerFrameList,
 | |
|                               GTBlockFrameCount,
 | |
|                               sizeof (CM_ARM_GTBLOCK_TIMER_FRAME_INFO),
 | |
|                               IsGtFrameNumberEqual
 | |
|                               );
 | |
|   // Duplicate entry was found so timer frame numbers provided are invalid
 | |
|   if (IsFrameNumberDuplicated) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   while (GTBlockFrameCount-- != 0) {
 | |
|     DEBUG ((
 | |
|       DEBUG_INFO,
 | |
|       "GTDT: GtBlockFrame = 0x%p\n",
 | |
|       GtBlockFrame
 | |
|       ));
 | |
| 
 | |
|     if (GTBlockTimerFrameList->FrameNumber >= 8) {
 | |
|       DEBUG ((
 | |
|         DEBUG_ERROR,
 | |
|         "ERROR: GTDT: Frame number %d is not in the range 0-7\n",
 | |
|         GTBlockTimerFrameList->FrameNumber
 | |
|         ));
 | |
|       return EFI_INVALID_PARAMETER;
 | |
|     }
 | |
| 
 | |
|     GtBlockFrame->GTFrameNumber = GTBlockTimerFrameList->FrameNumber;
 | |
|     GtBlockFrame->Reserved[0]   = EFI_ACPI_RESERVED_BYTE;
 | |
|     GtBlockFrame->Reserved[1]   = EFI_ACPI_RESERVED_BYTE;
 | |
|     GtBlockFrame->Reserved[2]   = EFI_ACPI_RESERVED_BYTE;
 | |
| 
 | |
|     GtBlockFrame->CntBaseX    = GTBlockTimerFrameList->PhysicalAddressCntBase;
 | |
|     GtBlockFrame->CntEL0BaseX =
 | |
|       GTBlockTimerFrameList->PhysicalAddressCntEL0Base;
 | |
| 
 | |
|     GtBlockFrame->GTxPhysicalTimerGSIV =
 | |
|       GTBlockTimerFrameList->PhysicalTimerGSIV;
 | |
|     GtBlockFrame->GTxPhysicalTimerFlags =
 | |
|       GTBlockTimerFrameList->PhysicalTimerFlags;
 | |
| 
 | |
|     GtBlockFrame->GTxVirtualTimerGSIV  = GTBlockTimerFrameList->VirtualTimerGSIV;
 | |
|     GtBlockFrame->GTxVirtualTimerFlags =
 | |
|       GTBlockTimerFrameList->VirtualTimerFlags;
 | |
| 
 | |
|     GtBlockFrame->GTxCommonFlags = GTBlockTimerFrameList->CommonFlags;
 | |
|     GtBlockFrame++;
 | |
|     GTBlockTimerFrameList++;
 | |
|   } // for
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /** Add the GT Block Timers in the GTDT Table.
 | |
| 
 | |
|   @param [in]  CfgMgrProtocol   Pointer to the Configuration Manager
 | |
|                                 Protocol Interface.
 | |
|   @param [in]  Gtdt             Pointer to the GTDT Table.
 | |
|   @param [in]  GTBlockOffset    Offset of the GT Block
 | |
|                                 information in the GTDT Table.
 | |
|   @param [in]  GTBlockInfo      Pointer to the GT Block
 | |
|                                 Information List.
 | |
|   @param [in]  BlockTimerCount  Number of GT Block Timers.
 | |
| 
 | |
|   @retval EFI_SUCCESS           Table generated successfully.
 | |
|   @retval EFI_INVALID_PARAMETER A parameter is invalid.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| AddGTBlockList (
 | |
|   IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL     *CONST  CfgMgrProtocol,
 | |
|   IN EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE    *CONST  Gtdt,
 | |
|   IN CONST UINT32                                            GTBlockOffset,
 | |
|   IN CONST CM_ARM_GTBLOCK_INFO                               *GTBlockInfo,
 | |
|   IN       UINT32                                            BlockTimerCount
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                                  Status;
 | |
|   EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE        *GTBlock;
 | |
|   EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE  *GtBlockFrame;
 | |
|   CM_ARM_GTBLOCK_TIMER_FRAME_INFO             *GTBlockTimerFrameList;
 | |
|   UINT32                                      GTBlockTimerFrameCount;
 | |
|   UINTN                                       Length;
 | |
| 
 | |
|   ASSERT (Gtdt != NULL);
 | |
|   ASSERT (GTBlockInfo != NULL);
 | |
| 
 | |
|   GTBlock = (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE *)((UINT8 *)Gtdt +
 | |
|                                                      GTBlockOffset);
 | |
| 
 | |
|   while (BlockTimerCount-- != 0) {
 | |
|     DEBUG ((DEBUG_INFO, "GTDT: GTBlock = 0x%p\n", GTBlock));
 | |
| 
 | |
|     Status = GetEArmObjGTBlockTimerFrameInfo (
 | |
|                CfgMgrProtocol,
 | |
|                GTBlockInfo->GTBlockTimerFrameToken,
 | |
|                >BlockTimerFrameList,
 | |
|                >BlockTimerFrameCount
 | |
|                );
 | |
|     if (EFI_ERROR (Status) ||
 | |
|         (GTBlockTimerFrameCount != GTBlockInfo->GTBlockTimerFrameCount))
 | |
|     {
 | |
|       DEBUG ((
 | |
|         DEBUG_ERROR,
 | |
|         "ERROR: GTDT: Failed to get Generic Timer Frames. Status = %r\n",
 | |
|         Status
 | |
|         ));
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     Length = sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE) +
 | |
|              (sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
 | |
|               GTBlockInfo->GTBlockTimerFrameCount);
 | |
| 
 | |
|     // Check that the length of the GT block does not
 | |
|     // exceed MAX_UINT16
 | |
|     if (Length > MAX_UINT16) {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       DEBUG ((
 | |
|         DEBUG_ERROR,
 | |
|         "ERROR: GTDT: Too many GT Frames. Count = %d. " \
 | |
|         "Maximum supported GT Block size exceeded. " \
 | |
|         "Status = %r\n",
 | |
|         GTBlockInfo->GTBlockTimerFrameCount,
 | |
|         Status
 | |
|         ));
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     GTBlock->Type               = EFI_ACPI_6_4_GTDT_GT_BLOCK;
 | |
|     GTBlock->Length             = (UINT16)Length;
 | |
|     GTBlock->Reserved           = EFI_ACPI_RESERVED_BYTE;
 | |
|     GTBlock->CntCtlBase         = GTBlockInfo->GTBlockPhysicalAddress;
 | |
|     GTBlock->GTBlockTimerCount  = GTBlockInfo->GTBlockTimerFrameCount;
 | |
|     GTBlock->GTBlockTimerOffset =
 | |
|       sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE);
 | |
| 
 | |
|     GtBlockFrame = (EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE *)
 | |
|                    ((UINT8 *)GTBlock + GTBlock->GTBlockTimerOffset);
 | |
| 
 | |
|     // Add GT Block Timer frames
 | |
|     Status = AddGTBlockTimerFrames (
 | |
|                GtBlockFrame,
 | |
|                GTBlockTimerFrameList,
 | |
|                GTBlockTimerFrameCount
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((
 | |
|         DEBUG_ERROR,
 | |
|         "ERROR: GTDT: Failed to add Generic Timer Frames. Status = %r\n",
 | |
|         Status
 | |
|         ));
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     // Next GTBlock
 | |
|     GTBlock = (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE *)((UINT8 *)GTBlock +
 | |
|                                                        GTBlock->Length);
 | |
|     GTBlockInfo++;
 | |
|   }// for
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /** Construct the GTDT ACPI table.
 | |
| 
 | |
|   Called by the Dynamic Table Manager, this function invokes the
 | |
|   Configuration Manager protocol interface to get the required hardware
 | |
|   information for generating the ACPI table.
 | |
| 
 | |
|   If this function allocates any resources then they must be freed
 | |
|   in the FreeXXXXTableResources function.
 | |
| 
 | |
|   @param [in]  This           Pointer to the table generator.
 | |
|   @param [in]  AcpiTableInfo  Pointer to the ACPI Table Info.
 | |
|   @param [in]  CfgMgrProtocol Pointer to the Configuration Manager
 | |
|                               Protocol Interface.
 | |
|   @param [out] Table          Pointer to the constructed ACPI Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS           Table generated successfully.
 | |
|   @retval EFI_INVALID_PARAMETER A parameter is invalid.
 | |
|   @retval EFI_NOT_FOUND         The required object was not found.
 | |
|   @retval EFI_BAD_BUFFER_SIZE   The size returned by the Configuration
 | |
|                                 Manager is less than the Object size for the
 | |
|                                 requested object.
 | |
|   @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| BuildGtdtTable (
 | |
|   IN  CONST ACPI_TABLE_GENERATOR                  *CONST  This,
 | |
|   IN  CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo,
 | |
|   IN  CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
 | |
|   OUT       EFI_ACPI_DESCRIPTION_HEADER          **CONST  Table
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                                    Status;
 | |
|   UINT32                                        TableSize;
 | |
|   UINT32                                        PlatformTimerCount;
 | |
|   UINT32                                        WatchdogCount;
 | |
|   UINT32                                        BlockTimerCount;
 | |
|   CM_ARM_GENERIC_WATCHDOG_INFO                  *WatchdogInfoList;
 | |
|   CM_ARM_GTBLOCK_INFO                           *GTBlockInfo;
 | |
|   EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE  *Gtdt;
 | |
|   UINT32                                        Idx;
 | |
|   UINT32                                        GTBlockOffset;
 | |
|   UINT32                                        WatchdogOffset;
 | |
| 
 | |
|   ASSERT (This != NULL);
 | |
|   ASSERT (AcpiTableInfo != NULL);
 | |
|   ASSERT (CfgMgrProtocol != NULL);
 | |
|   ASSERT (Table != NULL);
 | |
|   ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
 | |
|   ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
 | |
| 
 | |
|   if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
 | |
|       (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
 | |
|   {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: GTDT: Requested table revision = %d, is not supported."
 | |
|       "Supported table revision: Minimum = %d, Maximum = %d\n",
 | |
|       AcpiTableInfo->AcpiTableRevision,
 | |
|       This->MinAcpiTableRevision,
 | |
|       This->AcpiTableRevision
 | |
|       ));
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   *Table = NULL;
 | |
|   Status = GetEArmObjPlatformGTBlockInfo (
 | |
|              CfgMgrProtocol,
 | |
|              CM_NULL_TOKEN,
 | |
|              >BlockInfo,
 | |
|              &BlockTimerCount
 | |
|              );
 | |
|   if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: GTDT: Failed to Get Platform GT Block Information." \
 | |
|       " Status = %r\n",
 | |
|       Status
 | |
|       ));
 | |
|     goto error_handler;
 | |
|   }
 | |
| 
 | |
|   Status = GetEArmObjPlatformGenericWatchdogInfo (
 | |
|              CfgMgrProtocol,
 | |
|              CM_NULL_TOKEN,
 | |
|              &WatchdogInfoList,
 | |
|              &WatchdogCount
 | |
|              );
 | |
|   if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: GTDT: Failed to Get Platform Generic Watchdog Information." \
 | |
|       " Status = %r\n",
 | |
|       Status
 | |
|       ));
 | |
|     goto error_handler;
 | |
|   }
 | |
| 
 | |
|   DEBUG ((
 | |
|     DEBUG_INFO,
 | |
|     "GTDT: BlockTimerCount = %d, WatchdogCount = %d\n",
 | |
|     BlockTimerCount,
 | |
|     WatchdogCount
 | |
|     ));
 | |
| 
 | |
|   // Calculate the GTDT Table Size
 | |
|   PlatformTimerCount = 0;
 | |
|   TableSize          = sizeof (EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE);
 | |
|   if (BlockTimerCount != 0) {
 | |
|     GTBlockOffset       = TableSize;
 | |
|     PlatformTimerCount += BlockTimerCount;
 | |
|     TableSize          += (sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_STRUCTURE) *
 | |
|                            BlockTimerCount);
 | |
| 
 | |
|     for (Idx = 0; Idx < BlockTimerCount; Idx++) {
 | |
|       if (GTBlockInfo[Idx].GTBlockTimerFrameCount > 8) {
 | |
|         Status = EFI_INVALID_PARAMETER;
 | |
|         DEBUG ((
 | |
|           DEBUG_ERROR,
 | |
|           "GTDT: GTBockFrameCount cannot be more than 8." \
 | |
|           " GTBockFrameCount = %d, Status = %r\n",
 | |
|           GTBlockInfo[Idx].GTBlockTimerFrameCount,
 | |
|           Status
 | |
|           ));
 | |
|         goto error_handler;
 | |
|       }
 | |
| 
 | |
|       TableSize += (sizeof (EFI_ACPI_6_4_GTDT_GT_BLOCK_TIMER_STRUCTURE) *
 | |
|                     GTBlockInfo[Idx].GTBlockTimerFrameCount);
 | |
|     }
 | |
| 
 | |
|     DEBUG ((
 | |
|       DEBUG_INFO,
 | |
|       "GTDT: GTBockOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
 | |
|       GTBlockOffset,
 | |
|       PlatformTimerCount
 | |
|       ));
 | |
|   }
 | |
| 
 | |
|   WatchdogOffset = 0;
 | |
|   if (WatchdogCount != 0) {
 | |
|     WatchdogOffset      = TableSize;
 | |
|     PlatformTimerCount += WatchdogCount;
 | |
|     TableSize          += (sizeof (EFI_ACPI_6_4_GTDT_ARM_GENERIC_WATCHDOG_STRUCTURE) *
 | |
|                            WatchdogCount);
 | |
|     DEBUG ((
 | |
|       DEBUG_INFO,
 | |
|       "GTDT: WatchdogOffset = 0x%x, PLATFORM_TIMER_COUNT = %d\n",
 | |
|       WatchdogOffset,
 | |
|       PlatformTimerCount
 | |
|       ));
 | |
|   }
 | |
| 
 | |
|   *Table = (EFI_ACPI_DESCRIPTION_HEADER *)AllocateZeroPool (TableSize);
 | |
|   if (*Table == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: GTDT: Failed to allocate memory for GTDT Table, Size = %d," \
 | |
|       " Status = %r\n",
 | |
|       TableSize,
 | |
|       Status
 | |
|       ));
 | |
|     goto error_handler;
 | |
|   }
 | |
| 
 | |
|   Gtdt = (EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE *)*Table;
 | |
|   DEBUG ((
 | |
|     DEBUG_INFO,
 | |
|     "GTDT: Gtdt = 0x%p TableSize = 0x%x\n",
 | |
|     Gtdt,
 | |
|     TableSize
 | |
|     ));
 | |
| 
 | |
|   Status = AddAcpiHeader (
 | |
|              CfgMgrProtocol,
 | |
|              This,
 | |
|              &Gtdt->Header,
 | |
|              AcpiTableInfo,
 | |
|              TableSize
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: GTDT: Failed to add ACPI header. Status = %r\n",
 | |
|       Status
 | |
|       ));
 | |
|     goto error_handler;
 | |
|   }
 | |
| 
 | |
|   Status = AddGenericTimerInfo (
 | |
|              CfgMgrProtocol,
 | |
|              Gtdt,
 | |
|              PlatformTimerCount,
 | |
|              AcpiTableInfo->AcpiTableRevision
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "ERROR: GTDT: Failed to add Generic Timer Info. Status = %r\n",
 | |
|       Status
 | |
|       ));
 | |
|     goto error_handler;
 | |
|   }
 | |
| 
 | |
|   if (BlockTimerCount != 0) {
 | |
|     Status = AddGTBlockList (
 | |
|                CfgMgrProtocol,
 | |
|                Gtdt,
 | |
|                GTBlockOffset,
 | |
|                GTBlockInfo,
 | |
|                BlockTimerCount
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       DEBUG ((
 | |
|         DEBUG_ERROR,
 | |
|         "ERROR: GTDT: Failed to add GT Block timers. Status = %r\n",
 | |
|         Status
 | |
|         ));
 | |
|       goto error_handler;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (WatchdogCount != 0) {
 | |
|     AddGenericWatchdogList (
 | |
|       Gtdt,
 | |
|       WatchdogOffset,
 | |
|       WatchdogInfoList,
 | |
|       WatchdogCount
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| 
 | |
| error_handler:
 | |
|   if (*Table != NULL) {
 | |
|     FreePool (*Table);
 | |
|     *Table = NULL;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /** Free any resources allocated for constructing the GTDT.
 | |
| 
 | |
|   @param [in]      This           Pointer to the table generator.
 | |
|   @param [in]      AcpiTableInfo  Pointer to the ACPI Table Info.
 | |
|   @param [in]      CfgMgrProtocol Pointer to the Configuration Manager
 | |
|                                   Protocol Interface.
 | |
|   @param [in, out] Table          Pointer to the ACPI Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The resources were freed successfully.
 | |
|   @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| FreeGtdtTableResources (
 | |
|   IN      CONST ACPI_TABLE_GENERATOR                  *CONST  This,
 | |
|   IN      CONST CM_STD_OBJ_ACPI_TABLE_INFO            *CONST  AcpiTableInfo,
 | |
|   IN      CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL  *CONST  CfgMgrProtocol,
 | |
|   IN OUT        EFI_ACPI_DESCRIPTION_HEADER          **CONST  Table
 | |
|   )
 | |
| {
 | |
|   ASSERT (This != NULL);
 | |
|   ASSERT (AcpiTableInfo != NULL);
 | |
|   ASSERT (CfgMgrProtocol != NULL);
 | |
|   ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
 | |
|   ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
 | |
| 
 | |
|   if ((Table == NULL) || (*Table == NULL)) {
 | |
|     DEBUG ((DEBUG_ERROR, "ERROR: GTDT: Invalid Table Pointer\n"));
 | |
|     ASSERT ((Table != NULL) && (*Table != NULL));
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   FreePool (*Table);
 | |
|   *Table = NULL;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /** This macro defines the GTDT Table Generator revision.
 | |
| */
 | |
| #define GTDT_GENERATOR_REVISION  CREATE_REVISION (1, 0)
 | |
| 
 | |
| /** The interface for the GTDT Table Generator.
 | |
| */
 | |
| STATIC
 | |
| CONST
 | |
| ACPI_TABLE_GENERATOR  GtdtGenerator = {
 | |
|   // Generator ID
 | |
|   CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdGtdt),
 | |
|   // Generator Description
 | |
|   L"ACPI.STD.GTDT.GENERATOR",
 | |
|   // ACPI Table Signature
 | |
|   EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE,
 | |
|   // ACPI Table Revision supported by this Generator
 | |
|   EFI_ACPI_6_4_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,
 | |
|   // Minimum ACPI Table Revision supported by this Generator
 | |
|   EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_REVISION,
 | |
|   // Creator ID
 | |
|   TABLE_GENERATOR_CREATOR_ID_ARM,
 | |
|   // Creator Revision
 | |
|   GTDT_GENERATOR_REVISION,
 | |
|   // Build Table function
 | |
|   BuildGtdtTable,
 | |
|   // Free Resource function
 | |
|   FreeGtdtTableResources,
 | |
|   // Extended build function not needed
 | |
|   NULL,
 | |
|   // Extended build function not implemented by the generator.
 | |
|   // Hence extended free resource function is not required.
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| /** Register the Generator with the ACPI Table Factory.
 | |
| 
 | |
|   @param [in]  ImageHandle  The handle to the image.
 | |
|   @param [in]  SystemTable  Pointer to the System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The Generator is registered.
 | |
|   @retval EFI_INVALID_PARAMETER A parameter is invalid.
 | |
|   @retval EFI_ALREADY_STARTED   The Generator for the Table ID
 | |
|                                 is already registered.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| AcpiGtdtLibConstructor (
 | |
|   IN  EFI_HANDLE        ImageHandle,
 | |
|   IN  EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = RegisterAcpiTableGenerator (&GtdtGenerator);
 | |
|   DEBUG ((DEBUG_INFO, "GTDT: Register Generator. Status = %r\n", Status));
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /** Deregister the Generator from the ACPI Table Factory.
 | |
| 
 | |
|   @param [in]  ImageHandle  The handle to the image.
 | |
|   @param [in]  SystemTable  Pointer to the System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS           The Generator is deregistered.
 | |
|   @retval EFI_INVALID_PARAMETER A parameter is invalid.
 | |
|   @retval EFI_NOT_FOUND         The Generator is not registered.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| AcpiGtdtLibDestructor (
 | |
|   IN  EFI_HANDLE        ImageHandle,
 | |
|   IN  EFI_SYSTEM_TABLE  *SystemTable
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = DeregisterAcpiTableGenerator (&GtdtGenerator);
 | |
|   DEBUG ((DEBUG_INFO, "GTDT: Deregister Generator. Status = %r\n", Status));
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
|   return Status;
 | |
| }
 |