/** @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; | |
} |