/** @file Copyright (c) 2017-2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @par Specification Reference: - Arm System Control and Management Interface - Platform Design Document (https://developer.arm.com/documentation/den0056/) **/ #include #include #include #include #include #include #include #include "ArmScmiBaseProtocolPrivate.h" #include "ArmScmiClockProtocolPrivate.h" #include "ArmScmiPerformanceProtocolPrivate.h" #include "ScmiDxe.h" #include "ScmiPrivate.h" STATIC CONST SCMI_PROTOCOL_ENTRY Protocols[] = { { ScmiProtocolIdBase, ScmiBaseProtocolInit }, { ScmiProtocolIdPerformance, ScmiPerformanceProtocolInit }, { ScmiProtocolIdClock, ScmiClockProtocolInit } }; /** ARM SCMI driver entry point function. This function installs the SCMI Base protocol and a list of other protocols is queried using the Base protocol. If protocol is supported, driver will call each protocol init function to install the protocol on the ImageHandle. @param[in] ImageHandle Handle to this EFI Image which will be used to install Base, Clock and Performance protocols. @param[in] SystemTable A pointer to boot time system table. @retval EFI_SUCCESS Driver initalized successfully. @retval EFI_UNSUPPORTED If SCMI base protocol version is not supported. @retval !(EFI_SUCCESS) Other errors. **/ EFI_STATUS EFIAPI ArmScmiDxeEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; SCMI_BASE_PROTOCOL *BaseProtocol; UINT32 Version; UINT32 Index; UINT32 NumProtocols; UINT32 ProtocolIndex; UINT8 *SupportedList; UINT32 SupportedListSize; // Every SCMI implementation must implement the base protocol. ASSERT (Protocols[0].Id == ScmiProtocolIdBase); Status = ScmiBaseProtocolInit (&ImageHandle); if (EFI_ERROR (Status)) { ASSERT (FALSE); return Status; } Status = gBS->LocateProtocol ( &gArmScmiBaseProtocolGuid, NULL, (VOID **)&BaseProtocol ); if (EFI_ERROR (Status)) { ASSERT (FALSE); return Status; } // Get SCMI Base protocol version. Status = BaseProtocol->GetVersion (BaseProtocol, &Version); if (EFI_ERROR (Status)) { ASSERT (FALSE); return Status; } // Accept any version between SCMI v1.0 and SCMI v2.0 if ((Version < BASE_PROTOCOL_VERSION_V1) || (Version > BASE_PROTOCOL_VERSION_V2)) { ASSERT (FALSE); return EFI_UNSUPPORTED; } // Apart from Base protocol, SCMI may implement various other protocols, // query total protocols implemented by the SCP firmware. NumProtocols = 0; Status = BaseProtocol->GetTotalProtocols (BaseProtocol, &NumProtocols); if (EFI_ERROR (Status)) { ASSERT (FALSE); return Status; } ASSERT (NumProtocols != 0); SupportedListSize = (NumProtocols * sizeof (*SupportedList)); Status = gBS->AllocatePool ( EfiBootServicesData, SupportedListSize, (VOID **)&SupportedList ); if (EFI_ERROR (Status)) { ASSERT (FALSE); return Status; } // Get the list of protocols supported by SCP firmware on the platform. Status = BaseProtocol->DiscoverListProtocols ( BaseProtocol, &SupportedListSize, SupportedList ); if (EFI_ERROR (Status)) { gBS->FreePool (SupportedList); ASSERT (FALSE); return Status; } // Install supported protocol on ImageHandle. for (ProtocolIndex = 1; ProtocolIndex < ARRAY_SIZE (Protocols); ProtocolIndex++) { for (Index = 0; Index < NumProtocols; Index++) { if (Protocols[ProtocolIndex].Id == SupportedList[Index]) { Status = Protocols[ProtocolIndex].InitFn (&ImageHandle); if (EFI_ERROR (Status)) { ASSERT_EFI_ERROR (Status); return Status; } break; } } } gBS->FreePool (SupportedList); return EFI_SUCCESS; }