2 Api's to communicate with OP-TEE OS (Trusted OS based on ARM TrustZone) via
5 Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/ArmMmuLib.h>
18 #include <Library/ArmSmcLib.h>
19 #include <Library/BaseMemoryLib.h>
20 #include <Library/BaseLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/OpteeLib.h>
24 #include <IndustryStandard/ArmStdSmc.h>
28 STATIC OPTEE_SHARED_MEMORY_INFORMATION OpteeSharedMemoryInformation
= { 0 };
31 Check for OP-TEE presence.
39 ARM_SMC_ARGS ArmSmcArgs
;
41 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
42 // Send a Trusted OS Calls UID command
43 ArmSmcArgs
.Arg0
= ARM_SMC_ID_TOS_UID
;
44 ArmCallSmc (&ArmSmcArgs
);
46 if ((ArmSmcArgs
.Arg0
== OPTEE_OS_UID0
) &&
47 (ArmSmcArgs
.Arg1
== OPTEE_OS_UID1
) &&
48 (ArmSmcArgs
.Arg2
== OPTEE_OS_UID2
) &&
49 (ArmSmcArgs
.Arg3
== OPTEE_OS_UID3
)) {
58 OpteeSharedMemoryRemap (
62 ARM_SMC_ARGS ArmSmcArgs
;
63 EFI_PHYSICAL_ADDRESS PhysicalAddress
;
64 EFI_PHYSICAL_ADDRESS Start
;
65 EFI_PHYSICAL_ADDRESS End
;
69 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
70 ArmSmcArgs
.Arg0
= OPTEE_SMC_GET_SHARED_MEMORY_CONFIG
;
72 ArmCallSmc (&ArmSmcArgs
);
73 if (ArmSmcArgs
.Arg0
!= OPTEE_SMC_RETURN_OK
) {
74 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory not supported\n"));
75 return EFI_UNSUPPORTED
;
78 if (ArmSmcArgs
.Arg3
!= OPTEE_SMC_SHARED_MEMORY_CACHED
) {
79 DEBUG ((DEBUG_WARN
, "OP-TEE: Only normal cached shared memory supported\n"));
80 return EFI_UNSUPPORTED
;
83 Start
= (ArmSmcArgs
.Arg1
+ SIZE_4KB
- 1) & ~(SIZE_4KB
- 1);
84 End
= (ArmSmcArgs
.Arg1
+ ArmSmcArgs
.Arg2
) & ~(SIZE_4KB
- 1);
85 PhysicalAddress
= Start
;
88 if (Size
< SIZE_4KB
) {
89 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory too small\n"));
90 return EFI_BUFFER_TOO_SMALL
;
93 Status
= ArmSetMemoryAttributes (PhysicalAddress
, Size
, EFI_MEMORY_WB
);
94 if (EFI_ERROR (Status
)) {
98 OpteeSharedMemoryInformation
.Base
= (UINTN
)PhysicalAddress
;
99 OpteeSharedMemoryInformation
.Size
= Size
;
112 if (!IsOpteePresent ()) {
113 DEBUG ((DEBUG_WARN
, "OP-TEE not present\n"));
114 return EFI_UNSUPPORTED
;
117 Status
= OpteeSharedMemoryRemap ();
118 if (EFI_ERROR (Status
)) {
119 DEBUG ((DEBUG_WARN
, "OP-TEE shared memory remap failed\n"));
128 IsOpteeSmcReturnRpc (
132 return (Return
!= OPTEE_SMC_RETURN_UNKNOWN_FUNCTION
) &&
133 ((Return
& OPTEE_SMC_RETURN_RPC_PREFIX_MASK
) ==
134 OPTEE_SMC_RETURN_RPC_PREFIX
);
138 Does Standard SMC to OP-TEE in secure world.
140 @param[in] PhysicalArg Physical address of message to pass to secure world
142 @return 0 on success, secure world return code otherwise
148 IN UINT64 PhysicalArg
151 ARM_SMC_ARGS ArmSmcArgs
;
153 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
154 ArmSmcArgs
.Arg0
= OPTEE_SMC_CALL_WITH_ARG
;
155 ArmSmcArgs
.Arg1
= (UINT32
)(PhysicalArg
>> 32);
156 ArmSmcArgs
.Arg2
= (UINT32
)PhysicalArg
;
159 ArmCallSmc (&ArmSmcArgs
);
161 if (IsOpteeSmcReturnRpc (ArmSmcArgs
.Arg0
)) {
162 switch (ArmSmcArgs
.Arg0
) {
163 case OPTEE_SMC_RETURN_RPC_FOREIGN_INTERRUPT
:
165 // A foreign interrupt was raised while secure world was
166 // executing, since they are handled in UEFI a dummy RPC is
167 // performed to let UEFI take the interrupt through the normal
173 // Do nothing in case RPC is not implemented.
177 ArmSmcArgs
.Arg0
= OPTEE_SMC_RETURN_FROM_RPC
;
183 return ArmSmcArgs
.Arg0
;
188 EfiGuidToRfc4122Uuid (
189 OUT RFC4122_UUID
*Rfc4122Uuid
,
193 Rfc4122Uuid
->Data1
= SwapBytes32 (Guid
->Data1
);
194 Rfc4122Uuid
->Data2
= SwapBytes16 (Guid
->Data2
);
195 Rfc4122Uuid
->Data3
= SwapBytes16 (Guid
->Data3
);
196 CopyMem (Rfc4122Uuid
->Data4
, Guid
->Data4
, sizeof (Rfc4122Uuid
->Data4
));
202 IN OUT OPTEE_OPEN_SESSION_ARG
*OpenSessionArg
205 OPTEE_MESSAGE_ARG
*MessageArg
;
209 if (OpteeSharedMemoryInformation
.Base
== 0) {
210 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
211 return EFI_NOT_STARTED
;
214 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
215 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
217 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_OPEN_SESSION
;
220 // Initialize and add the meta parameters needed when opening a
223 MessageArg
->Params
[0].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
224 OPTEE_MESSAGE_ATTRIBUTE_META
;
225 MessageArg
->Params
[1].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
226 OPTEE_MESSAGE_ATTRIBUTE_META
;
227 EfiGuidToRfc4122Uuid (
228 (RFC4122_UUID
*)&MessageArg
->Params
[0].Union
.Value
,
229 &OpenSessionArg
->Uuid
231 ZeroMem (&MessageArg
->Params
[1].Union
.Value
, sizeof (EFI_GUID
));
232 MessageArg
->Params
[1].Union
.Value
.C
= OPTEE_LOGIN_PUBLIC
;
234 MessageArg
->NumParams
= 2;
236 if (OpteeCallWithArg ((UINTN
)MessageArg
)) {
237 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
238 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
241 OpenSessionArg
->Session
= MessageArg
->Session
;
242 OpenSessionArg
->Return
= MessageArg
->Return
;
243 OpenSessionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;
254 OPTEE_MESSAGE_ARG
*MessageArg
;
258 if (OpteeSharedMemoryInformation
.Base
== 0) {
259 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
260 return EFI_NOT_STARTED
;
263 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
264 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
266 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_CLOSE_SESSION
;
267 MessageArg
->Session
= Session
;
269 OpteeCallWithArg ((UINTN
)MessageArg
);
276 OpteeToMessageParam (
277 OUT OPTEE_MESSAGE_PARAM
*MessageParams
,
279 IN OPTEE_MESSAGE_PARAM
*InParams
283 UINTN ParamSharedMemoryAddress
;
284 UINTN SharedMemorySize
;
287 Size
= (sizeof (OPTEE_MESSAGE_ARG
) + sizeof (UINT64
) - 1) &
288 ~(sizeof (UINT64
) - 1);
289 ParamSharedMemoryAddress
= OpteeSharedMemoryInformation
.Base
+ Size
;
290 SharedMemorySize
= OpteeSharedMemoryInformation
.Size
- Size
;
292 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
293 CONST OPTEE_MESSAGE_PARAM
*InParam
;
294 OPTEE_MESSAGE_PARAM
*MessageParam
;
297 InParam
= InParams
+ Idx
;
298 MessageParam
= MessageParams
+ Idx
;
299 Attribute
= InParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
302 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
303 MessageParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
304 ZeroMem (&MessageParam
->Union
, sizeof (MessageParam
->Union
));
307 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
308 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
309 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
310 MessageParam
->Attribute
= Attribute
;
311 MessageParam
->Union
.Value
.A
= InParam
->Union
.Value
.A
;
312 MessageParam
->Union
.Value
.B
= InParam
->Union
.Value
.B
;
313 MessageParam
->Union
.Value
.C
= InParam
->Union
.Value
.C
;
316 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
317 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
318 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
319 MessageParam
->Attribute
= Attribute
;
321 if (InParam
->Union
.Memory
.Size
> SharedMemorySize
) {
322 return EFI_OUT_OF_RESOURCES
;
326 (VOID
*)ParamSharedMemoryAddress
,
327 (VOID
*)(UINTN
)InParam
->Union
.Memory
.BufferAddress
,
328 InParam
->Union
.Memory
.Size
330 MessageParam
->Union
.Memory
.BufferAddress
= (UINT64
)ParamSharedMemoryAddress
;
331 MessageParam
->Union
.Memory
.Size
= InParam
->Union
.Memory
.Size
;
333 Size
= (InParam
->Union
.Memory
.Size
+ sizeof (UINT64
) - 1) &
334 ~(sizeof (UINT64
) - 1);
335 ParamSharedMemoryAddress
+= Size
;
336 SharedMemorySize
-= Size
;
340 return EFI_INVALID_PARAMETER
;
349 OpteeFromMessageParam (
350 OUT OPTEE_MESSAGE_PARAM
*OutParams
,
352 IN OPTEE_MESSAGE_PARAM
*MessageParams
357 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
358 OPTEE_MESSAGE_PARAM
*OutParam
;
359 CONST OPTEE_MESSAGE_PARAM
*MessageParam
;
362 OutParam
= OutParams
+ Idx
;
363 MessageParam
= MessageParams
+ Idx
;
364 Attribute
= MessageParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
367 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
368 OutParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
369 ZeroMem (&OutParam
->Union
, sizeof (OutParam
->Union
));
372 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
373 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
374 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
375 OutParam
->Attribute
= Attribute
;
376 OutParam
->Union
.Value
.A
= MessageParam
->Union
.Value
.A
;
377 OutParam
->Union
.Value
.B
= MessageParam
->Union
.Value
.B
;
378 OutParam
->Union
.Value
.C
= MessageParam
->Union
.Value
.C
;
381 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
382 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
383 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
384 OutParam
->Attribute
= Attribute
;
386 if (MessageParam
->Union
.Memory
.Size
> OutParam
->Union
.Memory
.Size
) {
387 return EFI_BAD_BUFFER_SIZE
;
391 (VOID
*)(UINTN
)OutParam
->Union
.Memory
.BufferAddress
,
392 (VOID
*)(UINTN
)MessageParam
->Union
.Memory
.BufferAddress
,
393 MessageParam
->Union
.Memory
.Size
395 OutParam
->Union
.Memory
.Size
= MessageParam
->Union
.Memory
.Size
;
399 return EFI_INVALID_PARAMETER
;
408 OpteeInvokeFunction (
409 IN OUT OPTEE_INVOKE_FUNCTION_ARG
*InvokeFunctionArg
413 OPTEE_MESSAGE_ARG
*MessageArg
;
417 if (OpteeSharedMemoryInformation
.Base
== 0) {
418 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
419 return EFI_NOT_STARTED
;
422 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
423 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
425 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_INVOKE_FUNCTION
;
426 MessageArg
->Function
= InvokeFunctionArg
->Function
;
427 MessageArg
->Session
= InvokeFunctionArg
->Session
;
429 Status
= OpteeToMessageParam (
431 OPTEE_MAX_CALL_PARAMS
,
432 InvokeFunctionArg
->Params
438 MessageArg
->NumParams
= OPTEE_MAX_CALL_PARAMS
;
440 if (OpteeCallWithArg ((UINTN
)MessageArg
)) {
441 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
442 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
445 if (OpteeFromMessageParam (
446 InvokeFunctionArg
->Params
,
447 OPTEE_MAX_CALL_PARAMS
,
450 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
451 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
454 InvokeFunctionArg
->Return
= MessageArg
->Return
;
455 InvokeFunctionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;