1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "libnos_datagram"
18 #include <log/log.h>
19 #include <nos/device.h>
20
21 #include <ctype.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <getopt.h>
25 #include <linux/types.h>
26 #include <poll.h>
27 #include <pthread.h>
28 #include <stdarg.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/ioctl.h>
34 #include <sys/stat.h>
35 #include <sys/types.h>
36 #include <unistd.h>
37
38 #include <android-base/properties.h>
39 #include <application.h>
40
41 /*****************************************************************************/
42 /* Ideally, this should be in <linux/citadel.h> */
43 #define CITADEL_IOC_MAGIC 'c'
44 struct citadel_ioc_tpm_datagram {
45 __u64 buf;
46 __u32 len;
47 __u32 command;
48 };
49
50 /* GSA nos call request struct */
51 struct gsa_ioc_nos_call_req {
52 __u8 app_id;
53 __u8 reserved;
54 __u16 params;
55 __u32 arg_len;
56 __u64 buf;
57 __u32 reply_len;
58 __u32 call_status;
59 };
60
61 #define CITADEL_IOC_TPM_DATAGRAM _IOW(CITADEL_IOC_MAGIC, 1, \
62 struct citadel_ioc_tpm_datagram)
63 #define CITADEL_IOC_RESET _IO(CITADEL_IOC_MAGIC, 2)
64 #define GSC_IOC_GSA_NOS_CALL _IOW(CITADEL_IOC_MAGIC, 3, \
65 struct gsa_ioc_nos_call_req)
66 /*****************************************************************************/
67
68 #define DEV_CITADEL "/dev/citadel0"
69 #define DEV_DAUNTLESS "/dev/gsc0"
70
71 /* Allocate 4KB buffer for GSA mbox data transmission */
72 #define MAX_GSA_NOS_CALL_TRANSFER 4096
73 static uint8_t gsa_nos_call_buf[MAX_GSA_NOS_CALL_TRANSFER];
74 static pthread_mutex_t nos_call_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
75
76 static pthread_mutex_t in_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
77 static uint8_t in_buf[MAX_DEVICE_TRANSFER];
read_datagram(void * ctx,uint32_t command,uint8_t * buf,uint32_t len)78 static int read_datagram(void *ctx, uint32_t command, uint8_t *buf, uint32_t len) {
79 struct citadel_ioc_tpm_datagram dg = {
80 .buf = (unsigned long)in_buf,
81 .len = len,
82 .command = command,
83 };
84 int ret;
85 int fd;
86
87 if (!ctx) {
88
89 ALOGE("%s: invalid (NULL) device\n", __func__);
90 return -ENODEV;
91 }
92 fd = *(int *)ctx;
93 if (fd < 0) {
94 ALOGE("%s: invalid device\n", __func__);
95 return -ENODEV;
96 }
97
98 if (len > MAX_DEVICE_TRANSFER) {
99 ALOGE("%s: invalid len (%d > %d)\n", __func__,
100 len, MAX_DEVICE_TRANSFER);
101 return -E2BIG;
102 }
103
104 /* Lock the in buffer while it is used for this transaction */
105 if (pthread_mutex_lock(&in_buf_mutex) != 0) {
106 ALOGE("%s: failed to lock in_buf_mutex: %s", __func__, strerror(errno));
107 return -errno;
108 }
109
110 ret = ioctl(fd, CITADEL_IOC_TPM_DATAGRAM, &dg);
111 if (ret < 0) {
112 ALOGE("can't send spi message: %s", strerror(errno));
113 ret = -errno;
114 goto out;
115 }
116
117 memcpy(buf, in_buf, len);
118
119 out:
120 if (pthread_mutex_unlock(&in_buf_mutex) != 0) {
121 ALOGE("%s: failed to unlock in_buf_mutex: %s", __func__, strerror(errno));
122 ret = -errno;
123 }
124 return ret;
125 }
126
127 static pthread_mutex_t out_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
128 static uint8_t out_buf[MAX_DEVICE_TRANSFER];
write_datagram(void * ctx,uint32_t command,const uint8_t * buf,uint32_t len)129 static int write_datagram(void *ctx, uint32_t command, const uint8_t *buf, uint32_t len) {
130 struct citadel_ioc_tpm_datagram dg = {
131 .buf = (unsigned long)out_buf,
132 .len = len,
133 .command = command,
134 };
135 int ret;
136 int fd;
137
138 if (!ctx) {
139 ALOGE("%s: invalid (NULL) device\n", __func__);
140 return -ENODEV;
141 }
142 fd = *(int *)ctx;
143 if (fd < 0) {
144 ALOGE("%s: invalid device\n", __func__);
145 return -ENODEV;
146 }
147
148 if (len > MAX_DEVICE_TRANSFER) {
149 ALOGE("%s: invalid len (%d > %d)\n", __func__, len,
150 MAX_DEVICE_TRANSFER);
151 return -E2BIG;
152 }
153
154 /* Lock the out buffer while it is used for this transaction */
155 if (pthread_mutex_lock(&out_buf_mutex) != 0) {
156 ALOGE("%s: failed to lock out_buf_mutex: %s", __func__, strerror(errno));
157 return -errno;
158 }
159
160 memcpy(out_buf, buf, len);
161
162 ret = ioctl(fd, CITADEL_IOC_TPM_DATAGRAM, &dg);
163 if (ret < 0) {
164 ALOGE("can't send spi message: %s", strerror(errno));
165 ret = -errno;
166 goto out;
167 }
168
169 out:
170 if (pthread_mutex_unlock(&out_buf_mutex) != 0) {
171 ALOGE("%s: failed to unlock out_buf_mutex: %s", __func__, strerror(errno));
172 ret = -errno;
173 }
174 return ret;
175 }
176
wait_for_interrupt(void * ctx,int msecs)177 static int wait_for_interrupt(void *ctx, int msecs) {
178 int fd = *(int *)ctx;
179 struct pollfd fds = {fd, POLLIN, 0};
180 int rv;
181
182 rv = poll(&fds, 1 /*nfds*/, msecs);
183 if (rv < 0) {
184 ALOGE("poll: %s", strerror(errno));
185 }
186
187 return rv;
188 }
189
reset(void * ctx)190 static int reset(void *ctx) {
191 int ret;
192 int fd;
193
194 if (!ctx) {
195
196 ALOGE("%s: invalid (NULL) device\n", __func__);
197 return -ENODEV;
198 }
199 fd = *(int *)ctx;
200 if (fd < 0) {
201 ALOGE("%s: invalid device\n", __func__);
202 return -ENODEV;
203 }
204
205 ret = ioctl(fd, CITADEL_IOC_RESET);
206 if (ret < 0) {
207 ALOGE("can't reset Citadel: %s", strerror(errno));
208 return -errno;
209 }
210 return 0;
211 }
212
close_device(void * ctx)213 static void close_device(void *ctx) {
214 int fd;
215
216 if (!ctx) {
217 ALOGE("%s: invalid (NULL) device (ignored)\n", __func__);
218 return;
219 }
220 fd = *(int *)ctx;
221 if (fd < 0) {
222 ALOGE("%s: invalid device (ignored)\n", __func__);
223 return;
224 }
225
226 if (close(fd) < 0)
227 ALOGE("Problem closing device (ignored): %s", strerror(errno));
228 free(ctx);
229 }
230
231 /* Detect if GSA kernel support nos_call interface
232 * Returns true on success or false on failure.
233 */
detect_gsa_nos_call_interface(int fd)234 static bool detect_gsa_nos_call_interface(int fd) {
235 int ret;
236 errno = 0;
237
238 if (fd < 0) {
239 ALOGE("invalid device handle (%d)", fd);
240 return false;
241 }
242
243 /* Send app_id = 0 and params = 0 to detect GSA IOCTL interface */
244 struct gsa_ioc_nos_call_req gsa_nos_call_req = {
245 .app_id = 0,
246 .reserved = 0,
247 .params = 0,
248 .arg_len = 0,
249 .buf = (unsigned long)gsa_nos_call_buf,
250 .reply_len = 0,
251 .call_status = 0,
252 };
253
254 ret = ioctl(fd, GSC_IOC_GSA_NOS_CALL, &gsa_nos_call_req);
255 if (ret < 0) {
256 ALOGE("can't send GSA mbox command: %s", strerror(errno));
257 }
258
259 /* GSA kernel is not support GSA_NOS_CALL if return EINVAL or ENOTTY */
260 if (!errno) {
261 return true;
262 } else {
263 return false;
264 }
265 }
266
one_pass_call(void * ctx,uint8_t app_id,uint16_t params,const uint8_t * args,uint32_t arg_len,uint8_t * reply,uint32_t * reply_len,uint32_t * status_code)267 static int one_pass_call(void *ctx, uint8_t app_id, uint16_t params,
268 const uint8_t *args, uint32_t arg_len,
269 uint8_t *reply, uint32_t *reply_len,
270 uint32_t *status_code) {
271 *status_code = APP_SUCCESS;
272 int ret;
273 int fd;
274
275 struct gsa_ioc_nos_call_req gsa_nos_call_req = {
276 .app_id = app_id,
277 .reserved = 0,
278 .params = params,
279 .arg_len = arg_len,
280 .buf = (unsigned long)gsa_nos_call_buf,
281 .reply_len = *reply_len,
282 .call_status = *status_code,
283 };
284
285 ALOGD("Calling App 0x%02x with params 0x%04x", app_id, params);
286
287 if (!ctx || (arg_len && !args) ||
288 (reply_len && *reply_len && !reply) ||
289 (arg_len > MAX_GSA_NOS_CALL_TRANSFER) ||
290 (reply_len && *reply_len > MAX_GSA_NOS_CALL_TRANSFER) ||
291 !status_code) {
292 ALOGE("Invalid args to %s()", __func__);
293 return -EINVAL;
294 }
295
296 fd = *(int *)ctx;
297 if (fd < 0) {
298 ALOGE("%s: invalid device\n", __func__);
299 return -ENODEV;
300 }
301
302 /* Lock the out buffer while it is used for this transaction */
303 if (pthread_mutex_lock(&nos_call_buf_mutex) != 0) {
304 ALOGE("%s: failed to lock nos_call_buf_mutex: %s", __func__, strerror(errno));
305 return -errno;
306 }
307
308 if (arg_len) {
309 memcpy(gsa_nos_call_buf, args, arg_len);
310 }
311
312 ret = ioctl(fd, GSC_IOC_GSA_NOS_CALL, &gsa_nos_call_req);
313 if (ret < 0) {
314 ALOGE("can't send GSA mbox command: %s", strerror(errno));
315 goto exit;
316 }
317
318 *status_code = gsa_nos_call_req.call_status;
319 if (reply_len != NULL) {
320 *reply_len = gsa_nos_call_req.reply_len;
321 if (*reply_len) {
322 memcpy(reply, gsa_nos_call_buf, *reply_len);
323 }
324 }
325
326 exit:
327 if (pthread_mutex_unlock(&nos_call_buf_mutex) != 0) {
328 ALOGE("%s: failed to unlock nos_call_buf_mutex: %s", __func__,
329 strerror(errno));
330 return -errno;
331 }
332
333 ALOGD("App 0x%02x returning 0x%x", app_id, *status_code);
334 return ret;
335 }
336
default_device(void)337 static const char *default_device(void) {
338 struct stat statbuf;
339 int rv;
340
341 rv = stat(DEV_CITADEL, &statbuf);
342 if (!rv) {
343 return DEV_CITADEL;
344 }
345
346 rv = stat(DEV_DAUNTLESS, &statbuf);
347 if (!rv) {
348 return DEV_DAUNTLESS;
349 }
350
351 return 0;
352 }
353
nos_device_open(const char * device_name,struct nos_device * dev)354 int nos_device_open(const char *device_name, struct nos_device *dev) {
355 int fd, *new_ctx;
356
357 if (!device_name) {
358 device_name = default_device();
359 }
360
361 if (!device_name) {
362 ALOGE("can't find device node\n");
363 return -ENODEV;
364 }
365
366 fd = open(device_name, O_RDWR);
367 if (fd < 0) {
368 ALOGE("can't open device \"%s\": %s", device_name, strerror(errno));
369 return -errno;
370 }
371
372 /* Our context is just a pointer to an int holding the fd */
373 new_ctx = (int *)malloc(sizeof(int));
374 if (!new_ctx) {
375 ALOGE("can't malloc new ctx: %s", strerror(errno));
376 close(fd);
377 return -ENOMEM;
378 }
379 *new_ctx = fd;
380
381 dev->ctx = new_ctx;
382 dev->ops.read = read_datagram;
383 dev->ops.write = write_datagram;
384 dev->ops.wait_for_interrupt = wait_for_interrupt;
385 dev->ops.reset = reset;
386 dev->ops.close = close_device;
387 dev->ops.one_pass_call = one_pass_call;
388 dev->use_one_pass_call = detect_gsa_nos_call_interface(fd);
389 return 0;
390 }
391