1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
/** @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;
}
|