| /** @file | |
| Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR> | |
| 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 <Base.h> | |
| #include <Library/DebugLib.h> | |
| #include <Library/MemoryAllocationLib.h> | |
| #include <Library/UefiBootServicesTableLib.h> | |
| #include <Protocol/ArmScmiBaseProtocol.h> | |
| #include <Protocol/ArmScmiClockProtocol.h> | |
| #include <Protocol/ArmScmiPerformanceProtocol.h> | |
| #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; | |
| } |