1 /** @file
2
3 Copyright (c) 2017-2018, Arm Limited. All rights reserved.
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 System Control and Management Interface V1.0
8 http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
9 DEN0056A_System_Control_and_Management_Interface.pdf
10 **/
11
12 #include <Library/BaseLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/UefiBootServicesTableLib.h>
15 #include <Protocol/ArmScmiBaseProtocol.h>
16
17 #include "ArmScmiBaseProtocolPrivate.h"
18 #include "ScmiPrivate.h"
19
20 /** Return version of the Base protocol supported by SCP firmware.
21
22 @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
23
24 @param[out] Version Version of the supported SCMI Base protocol.
25
26 @retval EFI_SUCCESS The version of the protocol is returned.
27 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
28 @retval !(EFI_SUCCESS) Other errors.
29 **/
30 STATIC
31 EFI_STATUS
BaseGetVersion(IN SCMI_BASE_PROTOCOL * This,OUT UINT32 * Version)32 BaseGetVersion (
33 IN SCMI_BASE_PROTOCOL *This,
34 OUT UINT32 *Version
35 )
36 {
37 return ScmiGetProtocolVersion (SCMI_PROTOCOL_ID_BASE, Version);
38 }
39
40 /** Return total number of SCMI protocols supported by the SCP firmware.
41
42 @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
43
44 @param[out] TotalProtocols Total number of SCMI protocols supported.
45
46 @retval EFI_SUCCESS Total number of protocols supported are returned.
47 @retval EFI_DEVICE_ERROR SCP returns a SCMI error.
48 @retval !(EFI_SUCCESS) Other errors.
49 **/
50 STATIC
51 EFI_STATUS
BaseGetTotalProtocols(IN SCMI_BASE_PROTOCOL * This,OUT UINT32 * TotalProtocols)52 BaseGetTotalProtocols (
53 IN SCMI_BASE_PROTOCOL *This,
54 OUT UINT32 *TotalProtocols
55 )
56 {
57 EFI_STATUS Status;
58 UINT32 *ReturnValues;
59
60 Status = ScmiGetProtocolAttributes (SCMI_PROTOCOL_ID_BASE, &ReturnValues);
61 if (EFI_ERROR (Status)) {
62 return Status;
63 }
64
65 *TotalProtocols = SCMI_TOTAL_PROTOCOLS (ReturnValues[0]);
66
67 return EFI_SUCCESS;
68 }
69
70 /** Common function which returns vendor details.
71
72 @param[in] MessageId SCMI_MESSAGE_ID_BASE_DISCOVER_VENDOR
73 OR
74 SCMI_MESSAGE_ID_BASE_DISCOVER_SUB_VENDOR
75
76 @param[out] VendorIdentifier ASCII name of the vendor/subvendor.
77
78 @retval EFI_SUCCESS VendorIdentifier is returned.
79 @retval EFI_DEVICE_ERROR SCP returns an SCMI error.
80 @retval !(EFI_SUCCESS) Other errors.
81 **/
82 STATIC
83 EFI_STATUS
BaseDiscoverVendorDetails(IN SCMI_MESSAGE_ID_BASE MessageId,OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN])84 BaseDiscoverVendorDetails (
85 IN SCMI_MESSAGE_ID_BASE MessageId,
86 OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN]
87 )
88 {
89 EFI_STATUS Status;
90 UINT32 *ReturnValues;
91 SCMI_COMMAND Cmd;
92 UINT32 PayloadLength;
93
94 Cmd.ProtocolId = SCMI_PROTOCOL_ID_BASE;
95 Cmd.MessageId = MessageId;
96
97 PayloadLength = 0;
98
99 Status = ScmiCommandExecute (
100 &Cmd,
101 &PayloadLength,
102 &ReturnValues
103 );
104 if (EFI_ERROR (Status)) {
105 return Status;
106 }
107
108 AsciiStrCpyS (
109 (CHAR8*)VendorIdentifier,
110 SCMI_MAX_STR_LEN,
111 (CONST CHAR8*)ReturnValues
112 );
113
114 return EFI_SUCCESS;
115 }
116
117 /** Return vendor name.
118
119 @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
120
121 @param[out] VendorIdentifier Null terminated ASCII string of up to
122 16 bytes with a vendor name.
123
124 @retval EFI_SUCCESS VendorIdentifier is returned.
125 @retval EFI_DEVICE_ERROR SCP returns a SCMI error.
126 @retval !(EFI_SUCCESS) Other errors.
127 **/
128 STATIC
129 EFI_STATUS
BaseDiscoverVendor(IN SCMI_BASE_PROTOCOL * This,OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN])130 BaseDiscoverVendor (
131 IN SCMI_BASE_PROTOCOL *This,
132 OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN]
133 )
134 {
135 return BaseDiscoverVendorDetails (
136 SCMI_MESSAGE_ID_BASE_DISCOVER_VENDOR,
137 VendorIdentifier
138 );
139 }
140
141 /** Return sub vendor name.
142
143 @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
144
145 @param[out] VendorIdentifier Null terminated ASCII string of up to
146 16 bytes with a sub vendor name.
147
148 @retval EFI_SUCCESS VendorIdentifier is returned.
149 @retval EFI_DEVICE_ERROR SCP returns a SCMI error.
150 @retval !(EFI_SUCCESS) Other errors.
151 **/
152 EFI_STATUS
BaseDiscoverSubVendor(IN SCMI_BASE_PROTOCOL * This,OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN])153 BaseDiscoverSubVendor (
154 IN SCMI_BASE_PROTOCOL *This,
155 OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN]
156 )
157 {
158 return BaseDiscoverVendorDetails (
159 SCMI_MESSAGE_ID_BASE_DISCOVER_SUB_VENDOR,
160 VendorIdentifier
161 );
162 }
163
164 /** Return implementation version.
165
166 @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
167
168 @param[out] ImplementationVersion Vendor specific implementation version.
169
170 @retval EFI_SUCCESS Implementation version is returned.
171 @retval EFI_DEVICE_ERROR SCP returns a SCMI error.
172 @retval !(EFI_SUCCESS) Other errors.
173 **/
174 STATIC
175 EFI_STATUS
BaseDiscoverImplVersion(IN SCMI_BASE_PROTOCOL * This,OUT UINT32 * ImplementationVersion)176 BaseDiscoverImplVersion (
177 IN SCMI_BASE_PROTOCOL *This,
178 OUT UINT32 *ImplementationVersion
179 )
180 {
181 EFI_STATUS Status;
182 UINT32 *ReturnValues;
183 SCMI_COMMAND Cmd;
184 UINT32 PayloadLength;
185
186 Cmd.ProtocolId = SCMI_PROTOCOL_ID_BASE;
187 Cmd.MessageId = SCMI_MESSAGE_ID_BASE_DISCOVER_IMPLEMENTATION_VERSION;
188
189 PayloadLength = 0;
190
191 Status = ScmiCommandExecute (
192 &Cmd,
193 &PayloadLength,
194 &ReturnValues
195 );
196 if (EFI_ERROR (Status)) {
197 return Status;
198 }
199
200 *ImplementationVersion = ReturnValues[0];
201
202 return EFI_SUCCESS;
203 }
204
205 /** Return list of protocols.
206
207 @param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
208
209 @param[out] ProtocolListSize Size of the ProtocolList.
210
211 @param[out] ProtocolList Protocol list.
212
213 @retval EFI_SUCCESS List of protocols is returned.
214 @retval EFI_BUFFER_TOO_SMALL ProtocolListSize is too small for the result.
215 It has been updated to the size needed.
216 @retval EFI_DEVICE_ERROR SCP returns a SCMI error.
217 @retval !(EFI_SUCCESS) Other errors.
218 **/
219 STATIC
220 EFI_STATUS
BaseDiscoverListProtocols(IN SCMI_BASE_PROTOCOL * This,IN OUT UINT32 * ProtocolListSize,OUT UINT8 * ProtocolList)221 BaseDiscoverListProtocols (
222 IN SCMI_BASE_PROTOCOL *This,
223 IN OUT UINT32 *ProtocolListSize,
224 OUT UINT8 *ProtocolList
225 )
226 {
227 EFI_STATUS Status;
228 UINT32 TotalProtocols;
229 UINT32 *MessageParams;
230 BASE_DISCOVER_LIST *DiscoverList;
231 UINT32 Skip;
232 UINT32 Index;
233 SCMI_COMMAND Cmd;
234 UINT32 PayloadLength;
235 UINT32 RequiredSize;
236
237 Status = BaseGetTotalProtocols (This, &TotalProtocols);
238 if (EFI_ERROR (Status)) {
239 return Status;
240 }
241
242 Status = ScmiCommandGetPayload (&MessageParams);
243 if (EFI_ERROR (Status)) {
244 return Status;
245 }
246
247 RequiredSize = sizeof (UINT8) * TotalProtocols;
248 if (*ProtocolListSize < RequiredSize) {
249 *ProtocolListSize = RequiredSize;
250 return EFI_BUFFER_TOO_SMALL;
251 }
252
253 Cmd.ProtocolId = SCMI_PROTOCOL_ID_BASE;
254 Cmd.MessageId = SCMI_MESSAGE_ID_BASE_DISCOVER_LIST_PROTOCOLS;
255
256 Skip = 0;
257
258 while (Skip < TotalProtocols) {
259
260 *MessageParams = Skip;
261
262 // Note PayloadLength is a IN/OUT parameter.
263 PayloadLength = sizeof (Skip);
264
265 Status = ScmiCommandExecute (
266 &Cmd,
267 &PayloadLength,
268 (UINT32**)&DiscoverList
269 );
270 if (EFI_ERROR (Status)) {
271 return Status;
272 }
273
274 for (Index = 0; Index < DiscoverList->NumProtocols; Index++) {
275 ProtocolList[Skip++] = DiscoverList->Protocols[Index];
276 }
277 }
278
279 *ProtocolListSize = RequiredSize;
280
281 return EFI_SUCCESS;
282 }
283
284 // Instance of the SCMI Base protocol.
285 STATIC CONST SCMI_BASE_PROTOCOL BaseProtocol = {
286 BaseGetVersion,
287 BaseGetTotalProtocols,
288 BaseDiscoverVendor,
289 BaseDiscoverSubVendor,
290 BaseDiscoverImplVersion,
291 BaseDiscoverListProtocols
292 };
293
294 /** Initialize Base protocol and install protocol on a given handle.
295
296 @param[in] Handle Handle to install Base protocol.
297
298 @retval EFI_SUCCESS Base protocol interface installed
299 successfully.
300 **/
301 EFI_STATUS
ScmiBaseProtocolInit(IN OUT EFI_HANDLE * Handle)302 ScmiBaseProtocolInit (
303 IN OUT EFI_HANDLE* Handle
304 )
305 {
306 return gBS->InstallMultipleProtocolInterfaces (
307 Handle,
308 &gArmScmiBaseProtocolGuid,
309 &BaseProtocol,
310 NULL
311 );
312 }
313