TianoCore EDK2 master
Loading...
Searching...
No Matches
Optee.c
Go to the documentation of this file.
1
12#include <Library/ArmMmuLib.h>
13#include <Library/ArmSmcLib.h>
15#include <Library/BaseLib.h>
16#include <Library/DebugLib.h>
17#include <Library/OpteeLib.h>
18
20#include <OpteeSmc.h>
21#include <Uefi.h>
22
23STATIC OPTEE_SHARED_MEMORY_INFORMATION OpteeSharedMemoryInformation = { 0 };
24
28BOOLEAN
29EFIAPI
31 VOID
32 )
33{
34 ARM_SMC_ARGS ArmSmcArgs;
35
36 ZeroMem (&ArmSmcArgs, sizeof (ARM_SMC_ARGS));
37 // Send a Trusted OS Calls UID command
38 ArmSmcArgs.Arg0 = ARM_SMC_ID_TOS_UID;
39 ArmCallSmc (&ArmSmcArgs);
40
41 if ((ArmSmcArgs.Arg0 == OPTEE_OS_UID0) &&
42 (ArmSmcArgs.Arg1 == OPTEE_OS_UID1) &&
43 (ArmSmcArgs.Arg2 == OPTEE_OS_UID2) &&
44 (ArmSmcArgs.Arg3 == OPTEE_OS_UID3))
45 {
46 return TRUE;
47 } else {
48 return FALSE;
49 }
50}
51
54OpteeSharedMemoryRemap (
55 VOID
56 )
57{
58 ARM_SMC_ARGS ArmSmcArgs;
59 EFI_PHYSICAL_ADDRESS PhysicalAddress;
62 EFI_STATUS Status;
63 UINTN Size;
64
65 ZeroMem (&ArmSmcArgs, sizeof (ARM_SMC_ARGS));
66 ArmSmcArgs.Arg0 = OPTEE_SMC_GET_SHARED_MEMORY_CONFIG;
67
68 ArmCallSmc (&ArmSmcArgs);
69 if (ArmSmcArgs.Arg0 != OPTEE_SMC_RETURN_OK) {
70 DEBUG ((DEBUG_WARN, "OP-TEE shared memory not supported\n"));
71 return EFI_UNSUPPORTED;
72 }
73
74 if (ArmSmcArgs.Arg3 != OPTEE_SMC_SHARED_MEMORY_CACHED) {
75 DEBUG ((DEBUG_WARN, "OP-TEE: Only normal cached shared memory supported\n"));
76 return EFI_UNSUPPORTED;
77 }
78
79 Start = (ArmSmcArgs.Arg1 + SIZE_4KB - 1) & ~(SIZE_4KB - 1);
80 End = (ArmSmcArgs.Arg1 + ArmSmcArgs.Arg2) & ~(SIZE_4KB - 1);
81 PhysicalAddress = Start;
82 Size = End - Start;
83
84 if (Size < SIZE_4KB) {
85 DEBUG ((DEBUG_WARN, "OP-TEE shared memory too small\n"));
86 return EFI_BUFFER_TOO_SMALL;
87 }
88
89 Status = ArmSetMemoryAttributes (
90 PhysicalAddress,
91 Size,
92 EFI_MEMORY_WB | EFI_MEMORY_XP,
93 0
94 );
95 if (EFI_ERROR (Status)) {
96 return Status;
97 }
98
99 OpteeSharedMemoryInformation.Base = (UINTN)PhysicalAddress;
100 OpteeSharedMemoryInformation.Size = Size;
101
102 return EFI_SUCCESS;
103}
104
106EFIAPI
107OpteeInit (
108 VOID
109 )
110{
111 EFI_STATUS Status;
112
113 if (!IsOpteePresent ()) {
114 DEBUG ((DEBUG_WARN, "OP-TEE not present\n"));
115 return EFI_UNSUPPORTED;
116 }
117
118 Status = OpteeSharedMemoryRemap ();
119 if (EFI_ERROR (Status)) {
120 DEBUG ((DEBUG_WARN, "OP-TEE shared memory remap failed\n"));
121 return Status;
122 }
123
124 return EFI_SUCCESS;
125}
126
127STATIC
128BOOLEAN
129IsOpteeSmcReturnRpc (
130 UINT32 Return
131 )
132{
133 return (Return != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION) &&
134 ((Return & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) ==
135 OPTEE_SMC_RETURN_RPC_PREFIX);
136}
137
146STATIC
147UINT32
149 IN UINT64 PhysicalArg
150 )
151{
152 ARM_SMC_ARGS ArmSmcArgs;
153
154 ZeroMem (&ArmSmcArgs, sizeof (ARM_SMC_ARGS));
155 ArmSmcArgs.Arg0 = OPTEE_SMC_CALL_WITH_ARG;
156 ArmSmcArgs.Arg1 = (UINT32)(PhysicalArg >> 32);
157 ArmSmcArgs.Arg2 = (UINT32)PhysicalArg;
158
159 while (TRUE) {
160 ArmCallSmc (&ArmSmcArgs);
161
162 if (IsOpteeSmcReturnRpc (ArmSmcArgs.Arg0)) {
163 switch (ArmSmcArgs.Arg0) {
164 case OPTEE_SMC_RETURN_RPC_FOREIGN_INTERRUPT:
165 //
166 // A foreign interrupt was raised while secure world was
167 // executing, since they are handled in UEFI a dummy RPC is
168 // performed to let UEFI take the interrupt through the normal
169 // vector.
170 //
171 break;
172
173 default:
174 // Do nothing in case RPC is not implemented.
175 break;
176 }
177
178 ArmSmcArgs.Arg0 = OPTEE_SMC_RETURN_FROM_RPC;
179 } else {
180 break;
181 }
182 }
183
184 return ArmSmcArgs.Arg0;
185}
186
187STATIC
188VOID
189EfiGuidToRfc4122Uuid (
190 OUT RFC4122_UUID *Rfc4122Uuid,
191 IN EFI_GUID *Guid
192 )
193{
194 Rfc4122Uuid->Data1 = SwapBytes32 (Guid->Data1);
195 Rfc4122Uuid->Data2 = SwapBytes16 (Guid->Data2);
196 Rfc4122Uuid->Data3 = SwapBytes16 (Guid->Data3);
197 CopyMem (Rfc4122Uuid->Data4, Guid->Data4, sizeof (Rfc4122Uuid->Data4));
198}
199
201EFIAPI
202OpteeOpenSession (
203 IN OUT OPTEE_OPEN_SESSION_ARG *OpenSessionArg
204 )
205{
206 OPTEE_MESSAGE_ARG *MessageArg;
207
208 MessageArg = NULL;
209
210 if (OpteeSharedMemoryInformation.Base == 0) {
211 DEBUG ((DEBUG_WARN, "OP-TEE not initialized\n"));
212 return EFI_NOT_STARTED;
213 }
214
215 MessageArg = (OPTEE_MESSAGE_ARG *)OpteeSharedMemoryInformation.Base;
216 ZeroMem (MessageArg, sizeof (OPTEE_MESSAGE_ARG));
217
218 MessageArg->Command = OPTEE_MESSAGE_COMMAND_OPEN_SESSION;
219
220 //
221 // Initialize and add the meta parameters needed when opening a
222 // session.
223 //
224 MessageArg->Params[0].Attribute = OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT |
225 OPTEE_MESSAGE_ATTRIBUTE_META;
226 MessageArg->Params[1].Attribute = OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT |
227 OPTEE_MESSAGE_ATTRIBUTE_META;
228 EfiGuidToRfc4122Uuid (
229 (RFC4122_UUID *)&MessageArg->Params[0].Union.Value,
230 &OpenSessionArg->Uuid
231 );
232 ZeroMem (&MessageArg->Params[1].Union.Value, sizeof (EFI_GUID));
233 MessageArg->Params[1].Union.Value.C = OPTEE_LOGIN_PUBLIC;
234
235 MessageArg->NumParams = 2;
236
237 if (OpteeCallWithArg ((UINTN)MessageArg) != 0) {
238 MessageArg->Return = OPTEE_ERROR_COMMUNICATION;
239 MessageArg->ReturnOrigin = OPTEE_ORIGIN_COMMUNICATION;
240 }
241
242 OpenSessionArg->Session = MessageArg->Session;
243 OpenSessionArg->Return = MessageArg->Return;
244 OpenSessionArg->ReturnOrigin = MessageArg->ReturnOrigin;
245
246 return EFI_SUCCESS;
247}
248
250EFIAPI
251OpteeCloseSession (
252 IN UINT32 Session
253 )
254{
255 OPTEE_MESSAGE_ARG *MessageArg;
256
257 MessageArg = NULL;
258
259 if (OpteeSharedMemoryInformation.Base == 0) {
260 DEBUG ((DEBUG_WARN, "OP-TEE not initialized\n"));
261 return EFI_NOT_STARTED;
262 }
263
264 MessageArg = (OPTEE_MESSAGE_ARG *)OpteeSharedMemoryInformation.Base;
265 ZeroMem (MessageArg, sizeof (OPTEE_MESSAGE_ARG));
266
267 MessageArg->Command = OPTEE_MESSAGE_COMMAND_CLOSE_SESSION;
268 MessageArg->Session = Session;
269
270 OpteeCallWithArg ((UINTN)MessageArg);
271
272 return EFI_SUCCESS;
273}
274
275STATIC
277OpteeToMessageParam (
278 OUT OPTEE_MESSAGE_PARAM *MessageParams,
279 IN UINT32 NumParams,
280 IN OPTEE_MESSAGE_PARAM *InParams
281 )
282{
283 UINT32 Idx;
284 UINTN ParamSharedMemoryAddress;
285 UINTN SharedMemorySize;
286 UINTN Size;
287
288 Size = (sizeof (OPTEE_MESSAGE_ARG) + sizeof (UINT64) - 1) &
289 ~(sizeof (UINT64) - 1);
290 ParamSharedMemoryAddress = OpteeSharedMemoryInformation.Base + Size;
291 SharedMemorySize = OpteeSharedMemoryInformation.Size - Size;
292
293 for (Idx = 0; Idx < NumParams; Idx++) {
294 CONST OPTEE_MESSAGE_PARAM *InParam;
295 OPTEE_MESSAGE_PARAM *MessageParam;
296 UINT32 Attribute;
297
298 InParam = InParams + Idx;
299 MessageParam = MessageParams + Idx;
300 Attribute = InParam->Attribute & OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK;
301
302 switch (Attribute) {
303 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE:
304 MessageParam->Attribute = OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE;
305 ZeroMem (&MessageParam->Union, sizeof (MessageParam->Union));
306 break;
307
308 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT:
309 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT:
310 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT:
311 MessageParam->Attribute = Attribute;
312 MessageParam->Union.Value.A = InParam->Union.Value.A;
313 MessageParam->Union.Value.B = InParam->Union.Value.B;
314 MessageParam->Union.Value.C = InParam->Union.Value.C;
315 break;
316
317 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT:
318 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT:
319 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT:
320 MessageParam->Attribute = Attribute;
321
322 if (InParam->Union.Memory.Size > SharedMemorySize) {
323 return EFI_OUT_OF_RESOURCES;
324 }
325
326 CopyMem (
327 (VOID *)ParamSharedMemoryAddress,
328 (VOID *)(UINTN)InParam->Union.Memory.BufferAddress,
329 InParam->Union.Memory.Size
330 );
331 MessageParam->Union.Memory.BufferAddress = (UINT64)ParamSharedMemoryAddress;
332 MessageParam->Union.Memory.Size = InParam->Union.Memory.Size;
333
334 Size = (InParam->Union.Memory.Size + sizeof (UINT64) - 1) &
335 ~(sizeof (UINT64) - 1);
336 ParamSharedMemoryAddress += Size;
337 SharedMemorySize -= Size;
338 break;
339
340 default:
341 return EFI_INVALID_PARAMETER;
342 }
343 }
344
345 return EFI_SUCCESS;
346}
347
348STATIC
350OpteeFromMessageParam (
351 OUT OPTEE_MESSAGE_PARAM *OutParams,
352 IN UINT32 NumParams,
353 IN OPTEE_MESSAGE_PARAM *MessageParams
354 )
355{
356 UINT32 Idx;
357
358 for (Idx = 0; Idx < NumParams; Idx++) {
359 OPTEE_MESSAGE_PARAM *OutParam;
360 CONST OPTEE_MESSAGE_PARAM *MessageParam;
361 UINT32 Attribute;
362
363 OutParam = OutParams + Idx;
364 MessageParam = MessageParams + Idx;
365 Attribute = MessageParam->Attribute & OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK;
366
367 switch (Attribute) {
368 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE:
369 OutParam->Attribute = OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE;
370 ZeroMem (&OutParam->Union, sizeof (OutParam->Union));
371 break;
372
373 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT:
374 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT:
375 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT:
376 OutParam->Attribute = Attribute;
377 OutParam->Union.Value.A = MessageParam->Union.Value.A;
378 OutParam->Union.Value.B = MessageParam->Union.Value.B;
379 OutParam->Union.Value.C = MessageParam->Union.Value.C;
380 break;
381
382 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT:
383 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT:
384 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT:
385 OutParam->Attribute = Attribute;
386
387 if (MessageParam->Union.Memory.Size > OutParam->Union.Memory.Size) {
388 return EFI_BAD_BUFFER_SIZE;
389 }
390
391 CopyMem (
392 (VOID *)(UINTN)OutParam->Union.Memory.BufferAddress,
393 (VOID *)(UINTN)MessageParam->Union.Memory.BufferAddress,
394 MessageParam->Union.Memory.Size
395 );
396 OutParam->Union.Memory.Size = MessageParam->Union.Memory.Size;
397 break;
398
399 default:
400 return EFI_INVALID_PARAMETER;
401 }
402 }
403
404 return EFI_SUCCESS;
405}
406
408EFIAPI
409OpteeInvokeFunction (
410 IN OUT OPTEE_INVOKE_FUNCTION_ARG *InvokeFunctionArg
411 )
412{
413 EFI_STATUS Status;
414 OPTEE_MESSAGE_ARG *MessageArg;
415
416 MessageArg = NULL;
417
418 if (OpteeSharedMemoryInformation.Base == 0) {
419 DEBUG ((DEBUG_WARN, "OP-TEE not initialized\n"));
420 return EFI_NOT_STARTED;
421 }
422
423 MessageArg = (OPTEE_MESSAGE_ARG *)OpteeSharedMemoryInformation.Base;
424 ZeroMem (MessageArg, sizeof (OPTEE_MESSAGE_ARG));
425
426 MessageArg->Command = OPTEE_MESSAGE_COMMAND_INVOKE_FUNCTION;
427 MessageArg->Function = InvokeFunctionArg->Function;
428 MessageArg->Session = InvokeFunctionArg->Session;
429
430 Status = OpteeToMessageParam (
431 MessageArg->Params,
432 OPTEE_MAX_CALL_PARAMS,
433 InvokeFunctionArg->Params
434 );
435 if (Status) {
436 return Status;
437 }
438
439 MessageArg->NumParams = OPTEE_MAX_CALL_PARAMS;
440
441 if (OpteeCallWithArg ((UINTN)MessageArg) != 0) {
442 MessageArg->Return = OPTEE_ERROR_COMMUNICATION;
443 MessageArg->ReturnOrigin = OPTEE_ORIGIN_COMMUNICATION;
444 }
445
446 if (OpteeFromMessageParam (
447 InvokeFunctionArg->Params,
448 OPTEE_MAX_CALL_PARAMS,
449 MessageArg->Params
450 ) != 0)
451 {
452 MessageArg->Return = OPTEE_ERROR_COMMUNICATION;
453 MessageArg->ReturnOrigin = OPTEE_ORIGIN_COMMUNICATION;
454 }
455
456 InvokeFunctionArg->Return = MessageArg->Return;
457 InvokeFunctionArg->ReturnOrigin = MessageArg->ReturnOrigin;
458
459 return EFI_SUCCESS;
460}
UINT64 UINTN
EFI_STATUS ArmSetMemoryAttributes(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN UINT64 Attributes, IN UINT64 AttributeMask)
VOID ArmCallSmc(IN OUT ARM_SMC_ARGS *Args)
Definition: ArmSmcLibNull.c:14
UINT16 EFIAPI SwapBytes16(IN UINT16 Value)
Definition: SwapBytes16.c:25
UINT32 EFIAPI SwapBytes32(IN UINT32 Value)
Definition: SwapBytes32.c:25
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
BOOLEAN EFIAPI IsOpteePresent(VOID)
Definition: Optee.c:30
STATIC UINT32 OpteeCallWithArg(IN UINT64 PhysicalArg)
Definition: Optee.c:148
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
Definition: Base.h:213