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"));
127 Does Standard SMC to OP-TEE in secure world.
129 @param[in] PhysicalArg Physical address of message to pass to secure world
131 @return 0 on success, secure world return code otherwise
137 IN UINT64 PhysicalArg
140 ARM_SMC_ARGS ArmSmcArgs
;
142 ZeroMem (&ArmSmcArgs
, sizeof (ARM_SMC_ARGS
));
143 ArmSmcArgs
.Arg0
= OPTEE_SMC_CALL_WITH_ARG
;
144 ArmSmcArgs
.Arg1
= (UINT32
)(PhysicalArg
>> 32);
145 ArmSmcArgs
.Arg2
= (UINT32
)PhysicalArg
;
148 ArmCallSmc (&ArmSmcArgs
);
150 if (ArmSmcArgs
.Arg0
== OPTEE_SMC_RETURN_RPC_FOREIGN_INTERRUPT
) {
152 // A foreign interrupt was raised while secure world was
153 // executing, since they are handled in UEFI a dummy RPC is
154 // performed to let UEFI take the interrupt through the normal
157 ArmSmcArgs
.Arg0
= OPTEE_SMC_RETURN_FROM_RPC
;
163 return ArmSmcArgs
.Arg0
;
168 EfiGuidToRfc4122Uuid (
169 OUT RFC4122_UUID
*Rfc4122Uuid
,
173 Rfc4122Uuid
->Data1
= SwapBytes32 (Guid
->Data1
);
174 Rfc4122Uuid
->Data2
= SwapBytes16 (Guid
->Data2
);
175 Rfc4122Uuid
->Data3
= SwapBytes16 (Guid
->Data3
);
176 CopyMem (Rfc4122Uuid
->Data4
, Guid
->Data4
, sizeof (Rfc4122Uuid
->Data4
));
182 IN OUT OPTEE_OPEN_SESSION_ARG
*OpenSessionArg
185 OPTEE_MESSAGE_ARG
*MessageArg
;
189 if (OpteeSharedMemoryInformation
.Base
== 0) {
190 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
191 return EFI_NOT_STARTED
;
194 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
195 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
197 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_OPEN_SESSION
;
200 // Initialize and add the meta parameters needed when opening a
203 MessageArg
->Params
[0].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
204 OPTEE_MESSAGE_ATTRIBUTE_META
;
205 MessageArg
->Params
[1].Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
|
206 OPTEE_MESSAGE_ATTRIBUTE_META
;
207 EfiGuidToRfc4122Uuid (
208 (RFC4122_UUID
*)&MessageArg
->Params
[0].Union
.Value
,
209 &OpenSessionArg
->Uuid
211 ZeroMem (&MessageArg
->Params
[1].Union
.Value
, sizeof (EFI_GUID
));
212 MessageArg
->Params
[1].Union
.Value
.C
= OPTEE_LOGIN_PUBLIC
;
214 MessageArg
->NumParams
= 2;
216 if (OpteeCallWithArg ((UINTN
)MessageArg
)) {
217 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
218 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
221 OpenSessionArg
->Session
= MessageArg
->Session
;
222 OpenSessionArg
->Return
= MessageArg
->Return
;
223 OpenSessionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;
234 OPTEE_MESSAGE_ARG
*MessageArg
;
238 if (OpteeSharedMemoryInformation
.Base
== 0) {
239 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
240 return EFI_NOT_STARTED
;
243 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
244 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
246 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_CLOSE_SESSION
;
247 MessageArg
->Session
= Session
;
249 OpteeCallWithArg ((UINTN
)MessageArg
);
256 OpteeToMessageParam (
257 OUT OPTEE_MESSAGE_PARAM
*MessageParams
,
259 IN OPTEE_MESSAGE_PARAM
*InParams
263 UINTN ParamSharedMemoryAddress
;
264 UINTN SharedMemorySize
;
267 Size
= (sizeof (OPTEE_MESSAGE_ARG
) + sizeof (UINT64
) - 1) &
268 ~(sizeof (UINT64
) - 1);
269 ParamSharedMemoryAddress
= OpteeSharedMemoryInformation
.Base
+ Size
;
270 SharedMemorySize
= OpteeSharedMemoryInformation
.Size
- Size
;
272 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
273 CONST OPTEE_MESSAGE_PARAM
*InParam
;
274 OPTEE_MESSAGE_PARAM
*MessageParam
;
277 InParam
= InParams
+ Idx
;
278 MessageParam
= MessageParams
+ Idx
;
279 Attribute
= InParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
282 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
283 MessageParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
284 ZeroMem (&MessageParam
->Union
, sizeof (MessageParam
->Union
));
287 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
288 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
289 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
290 MessageParam
->Attribute
= Attribute
;
291 MessageParam
->Union
.Value
.A
= InParam
->Union
.Value
.A
;
292 MessageParam
->Union
.Value
.B
= InParam
->Union
.Value
.B
;
293 MessageParam
->Union
.Value
.C
= InParam
->Union
.Value
.C
;
296 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
297 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
298 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
299 MessageParam
->Attribute
= Attribute
;
301 if (InParam
->Union
.Memory
.Size
> SharedMemorySize
) {
302 return EFI_OUT_OF_RESOURCES
;
306 (VOID
*)ParamSharedMemoryAddress
,
307 (VOID
*)(UINTN
)InParam
->Union
.Memory
.BufferAddress
,
308 InParam
->Union
.Memory
.Size
310 MessageParam
->Union
.Memory
.BufferAddress
= (UINT64
)ParamSharedMemoryAddress
;
311 MessageParam
->Union
.Memory
.Size
= InParam
->Union
.Memory
.Size
;
313 Size
= (InParam
->Union
.Memory
.Size
+ sizeof (UINT64
) - 1) &
314 ~(sizeof (UINT64
) - 1);
315 ParamSharedMemoryAddress
+= Size
;
316 SharedMemorySize
-= Size
;
320 return EFI_INVALID_PARAMETER
;
329 OpteeFromMessageParam (
330 OUT OPTEE_MESSAGE_PARAM
*OutParams
,
332 IN OPTEE_MESSAGE_PARAM
*MessageParams
337 for (Idx
= 0; Idx
< NumParams
; Idx
++) {
338 OPTEE_MESSAGE_PARAM
*OutParam
;
339 CONST OPTEE_MESSAGE_PARAM
*MessageParam
;
342 OutParam
= OutParams
+ Idx
;
343 MessageParam
= MessageParams
+ Idx
;
344 Attribute
= MessageParam
->Attribute
& OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK
;
347 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
:
348 OutParam
->Attribute
= OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE
;
349 ZeroMem (&OutParam
->Union
, sizeof (OutParam
->Union
));
352 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT
:
353 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT
:
354 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT
:
355 OutParam
->Attribute
= Attribute
;
356 OutParam
->Union
.Value
.A
= MessageParam
->Union
.Value
.A
;
357 OutParam
->Union
.Value
.B
= MessageParam
->Union
.Value
.B
;
358 OutParam
->Union
.Value
.C
= MessageParam
->Union
.Value
.C
;
361 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT
:
362 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT
:
363 case OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT
:
364 OutParam
->Attribute
= Attribute
;
366 if (MessageParam
->Union
.Memory
.Size
> OutParam
->Union
.Memory
.Size
) {
367 return EFI_BAD_BUFFER_SIZE
;
371 (VOID
*)(UINTN
)OutParam
->Union
.Memory
.BufferAddress
,
372 (VOID
*)(UINTN
)MessageParam
->Union
.Memory
.BufferAddress
,
373 MessageParam
->Union
.Memory
.Size
375 OutParam
->Union
.Memory
.Size
= MessageParam
->Union
.Memory
.Size
;
379 return EFI_INVALID_PARAMETER
;
388 OpteeInvokeFunction (
389 IN OUT OPTEE_INVOKE_FUNCTION_ARG
*InvokeFunctionArg
393 OPTEE_MESSAGE_ARG
*MessageArg
;
397 if (OpteeSharedMemoryInformation
.Base
== 0) {
398 DEBUG ((DEBUG_WARN
, "OP-TEE not initialized\n"));
399 return EFI_NOT_STARTED
;
402 MessageArg
= (OPTEE_MESSAGE_ARG
*)OpteeSharedMemoryInformation
.Base
;
403 ZeroMem (MessageArg
, sizeof (OPTEE_MESSAGE_ARG
));
405 MessageArg
->Command
= OPTEE_MESSAGE_COMMAND_INVOKE_FUNCTION
;
406 MessageArg
->Function
= InvokeFunctionArg
->Function
;
407 MessageArg
->Session
= InvokeFunctionArg
->Session
;
409 Status
= OpteeToMessageParam (
411 OPTEE_MAX_CALL_PARAMS
,
412 InvokeFunctionArg
->Params
418 MessageArg
->NumParams
= OPTEE_MAX_CALL_PARAMS
;
420 if (OpteeCallWithArg ((UINTN
)MessageArg
)) {
421 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
422 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
425 if (OpteeFromMessageParam (
426 InvokeFunctionArg
->Params
,
427 OPTEE_MAX_CALL_PARAMS
,
430 MessageArg
->Return
= OPTEE_ERROR_COMMUNICATION
;
431 MessageArg
->ReturnOrigin
= OPTEE_ORIGIN_COMMUNICATION
;
434 InvokeFunctionArg
->Return
= MessageArg
->Return
;
435 InvokeFunctionArg
->ReturnOrigin
= MessageArg
->ReturnOrigin
;