1 /*
2  *
3  * Copyright (C) 2017 GlobalLogic
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <cstring>
19 
20 #define LOG_TAG "OpteeIPC"
21 #include <utils/Log.h>
22 
23 #include <gatekeeper_ipc.h>
24 #include "optee_ipc.h"
25 
26 #undef LOG_TAG
27 #define LOG_TAG "OpteeGatekeeper"
28 
29 namespace android {
30 namespace hardware {
31 namespace gatekeeper {
32 namespace V1_0 {
33 namespace optee {
34 
OpteeIPC()35 OpteeIPC::OpteeIPC()
36     : inUse(false)
37 {
38 }
39 
~OpteeIPC()40 OpteeIPC::~OpteeIPC()
41 {
42     disconnect();
43     finalize();
44 }
45 
initialize()46 bool OpteeIPC::initialize()
47 {
48     TEEC_Result res;
49 
50     res = TEEC_InitializeContext(NULL, &ctx);
51     if (res != TEEC_SUCCESS) {
52         ALOGE("TEEC_InitializeContext failed with code 0x%x", res);
53         return false;
54     }
55 
56     return true;
57 }
58 
connect(const TEEC_UUID & uuid)59 bool OpteeIPC::connect(const TEEC_UUID& uuid)
60 {
61     if (inUse) {
62         ALOGE("Is already connected");
63 
64         return false;
65     }
66 
67     TEEC_Result res;
68 
69     uint32_t err_origin;
70     res = TEEC_OpenSession(&ctx, &sess, &uuid, TEEC_LOGIN_PUBLIC,
71             NULL, NULL, &err_origin);
72     if (res != TEEC_SUCCESS) {
73         ALOGE("TEEC_Opensession failed with code 0x%x origin 0x%x",
74             res, err_origin);
75 
76         return false;
77     }
78 
79     inUse = true;
80 
81     return true;
82 }
83 
finalize()84 void OpteeIPC::finalize()
85 {
86     TEEC_FinalizeContext(&ctx);
87 }
88 
disconnect()89 void OpteeIPC::disconnect()
90 {
91     if (inUse) {
92         TEEC_CloseSession(&sess);
93     }
94 
95     inUse = false;
96 }
97 
call(uint32_t cmd,const uint8_t * in,uint32_t in_size,uint8_t * out,uint32_t & out_size)98 bool OpteeIPC::call(uint32_t cmd,
99         const uint8_t *in,  uint32_t  in_size,
100               uint8_t *out, uint32_t& out_size)
101 {
102     TEEC_Operation op;
103     memset(&op, 0, sizeof(op));
104 
105     op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
106                                      TEEC_MEMREF_TEMP_OUTPUT,
107                                      TEEC_NONE, TEEC_NONE);
108 
109     op.params[0].tmpref.buffer = (void*)in;
110     op.params[0].tmpref.size = in_size;
111 
112     op.params[1].tmpref.buffer = out;
113     op.params[1].tmpref.size = out_size;
114 
115     uint32_t err_origin;
116     TEEC_Result res = TEEC_InvokeCommand(&sess, cmd, &op, &err_origin);
117     if (res != TEEC_SUCCESS) {
118 	ALOGE("TEEC_InvokeCommand failed with code 0x%08x origin 0x%08x",
119 		res, err_origin);
120 	if (res == TEEC_ERROR_TARGET_DEAD) {
121 		disconnect();
122 		connect(TA_GATEKEEPER_UUID);
123 	}
124         return false;
125     }
126 
127     return true;
128 }
129 
130 }  // namespace optee
131 }  // namespace V1_0
132 }  // namespace gatekeeper
133 }  // namespace hardware
134 }  // namespace android
135