1 /*
2  * Copyright (c) 2019, The Linux Foundation. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *    * Redistributions of source code must retain the above copyright
8  *      notice, this list of conditions and the following disclaimer.
9  *    * Redistributions in binary form must reproduce the above
10  *      copyright notice, this list of conditions and the following
11  *      disclaimer in the documentation and/or other materials provided
12  *      with the distribution.
13  *    * Neither the name of The Linux Foundation nor the names of its
14  *      contributors may be used to endorse or promote products derived
15  *      from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 //#include "qurt_mutex.h"
31 #include <stdio.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <assert.h>
36 #include <pthread.h>
37 #include <dlfcn.h>
38 #include <stdlib.h>
39 #include <sys/eventfd.h>
40 
41 #include "platform_libs.h"
42 #include "HAP_farf.h"
43 #include "verify.h"
44 #include "mod_table.h"
45 #include "remote_priv.h"
46 #include "rpcmem.h"
47 #include "adsp_listener.h"
48 #include "listener_buf.h"
49 #include "shared.h"
50 #include "AEEstd.h"
51 #include "fastrpc_apps_user.h"
52 #include "AEEStdErr.h"
53 
54 #define LOGL(format, ...) VERIFY_PRINT_INFO(format, ##__VA_ARGS__)
55 #ifndef MALLOC
56 #define MALLOC malloc
57 #endif
58 
59 #ifndef CALLOC
60 #define CALLOC calloc
61 #endif
62 
63 #ifndef FREE
64 #define FREE free
65 #endif
66 
67 #ifndef REALLOC
68 #define REALLOC realloc
69 #endif
70 
71 #ifndef FREEIF
72 #define FREEIF(pv) \
73    do {\
74       if(pv) { \
75          void* tmp = (void*)pv;\
76          pv = 0;\
77          FREE(tmp);\
78       } \
79    } while(0)
80 #endif
81 
82 #include <unistd.h>
83 #include <stdio.h>
84 #include <string.h>
85 #include <errno.h>
86 #include <unistd.h>
87 #include <sys/eventfd.h>
88 
89 struct listener {
90    pthread_t thread;
91    int eventfd;
92 };
93 
94 static struct listener linfo[NUM_DOMAINS_EXTEND] =
95 { [0 ... NUM_DOMAINS_EXTEND - 1] = { .thread = 0, .eventfd = -1 } };
96 
97 //TODO: fix this to work over any number of buffers
98 //      needs qaic to support extra buffers
99 #define MAX_BUFS 250
100 struct invoke_bufs {
101    adsp_listener_buffer outbufs[MAX_BUFS];
102    adsp_listener_buffer inbufs[MAX_BUFS];
103    int inbufLenReqs[MAX_BUFS];
104    int outbufLenReqs[MAX_BUFS];
105    remote_arg args[2*MAX_BUFS];
106 };
107 
108 extern void set_thread_context(int domain);
109 
__QAIC_IMPL(apps_remotectl_open)110 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_remotectl_open)(const char* name, uint32* handle, char* dlStr, int dlerrorLen, int* dlErr) __QAIC_IMPL_ATTRIBUTE
111 {
112    return mod_table_open(name, handle, dlStr, dlerrorLen, dlErr);
113 }
114 
__QAIC_IMPL(apps_remotectl_close)115 __QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_remotectl_close)(uint32 handle, char* errStr, int errStrLen, int* dlErr) __QAIC_IMPL_ATTRIBUTE
116 {
117    return mod_table_close(handle, errStr, errStrLen, dlErr);
118 }
119 
120 #define RPC_FREEIF(heapid, buf) \
121 do {\
122    if(heapid == -1)  {\
123       FREEIF(buf);\
124    } else {\
125       if(buf) {\
126          rpcmem_free_internal(buf);\
127          buf = 0;\
128       }\
129    }\
130 } while (0)
131 
rpcmem_realloc(int heapid,uint32 flags,void * buf,int oldsize,int size)132 static __inline void* rpcmem_realloc(int heapid, uint32 flags, void* buf, int oldsize, int size) {
133    if(heapid == -1) {
134       return REALLOC(buf, size);
135    } else {
136       void* bufnew = rpcmem_alloc_internal(heapid, flags, size);
137       if(buf && bufnew) {
138          memmove(bufnew, buf, oldsize);
139          rpcmem_free_internal(buf);
140          buf = NULL;
141       }
142       return bufnew;
143    }
144 }
145 
listener(void * arg)146 static void* listener(void* arg) {
147    struct listener* me = (struct listener*)arg;
148    int numOutBufs = 0;
149    int nErr = AEE_SUCCESS;
150    adsp_listener_invoke_ctx ctx = 0;
151    struct invoke_bufs* bufs = 0;
152    boolean bNeedMore;
153    int result = -1;
154    adsp_listener_remote_handle handle;
155    uint32 sc;
156    int ii, inBufsAllocated = 0;
157    const char* eheap = getenv("ADSP_LISTENER_HEAP_ID");
158    int heapid = eheap == 0 ? 0 : (uint32)atoi(eheap);
159    const char* eflags = getenv("ADSP_LISTENER_HEAP_FLAGS");
160    uint32 flags = eflags == 0 ? RPCMEM_HEAP_DEFAULT : (uint32)atoi(eflags);
161 
162    if(eheap || eflags) {
163       FARF(HIGH, "listener using ion heap: %d flags: %x\n", (int)heapid, (int)flags);
164    }
165 
166    VERIFYC(NULL != (bufs = rpcmem_realloc(heapid, flags, 0, 0, sizeof(*bufs))), AEE_ENORPCMEMORY);
167    memset(bufs, 0, sizeof(*bufs));
168    set_thread_context((int)(me - &linfo[0]));
169 
170    do {
171  invoke:
172       bNeedMore = FALSE;
173       sc = 0xffffffff;
174       if(result != AEE_SUCCESS) {
175          numOutBufs = 0;
176       }
177       nErr = __QAIC_HEADER(adsp_listener_next_invoke)(
178                         ctx, result, bufs->outbufs, numOutBufs, &ctx,
179                         &handle, &sc, bufs->inbufs, inBufsAllocated,
180                         bufs->inbufLenReqs, MAX_BUFS, bufs->outbufLenReqs, MAX_BUFS);
181       if(nErr) {
182          VERIFY_EPRINTF("listener protocol failure %x\n", nErr);
183          VERIFY(AEE_SUCCESS == (nErr = __QAIC_HEADER(adsp_listener_next_invoke)(
184                         ctx, nErr, 0, 0, &ctx,
185                         &handle, &sc, bufs->inbufs, inBufsAllocated,
186                         bufs->inbufLenReqs, MAX_BUFS, bufs->outbufLenReqs, MAX_BUFS)));
187       }
188 
189       if(MAX_BUFS < REMOTE_SCALARS_INBUFS(sc) || MAX_BUFS < REMOTE_SCALARS_OUTBUFS(sc)) {
190          result = AEE_EMAXBUFS;
191          goto invoke;
192       }
193       for(ii = 0; ii < (int)REMOTE_SCALARS_INBUFS(sc); ++ii) {
194          if(bufs->inbufs[ii].dataLen < bufs->inbufLenReqs[ii]) {
195             if(0 != bufs->inbufLenReqs[ii]) {
196                bufs->inbufs[ii].data = rpcmem_realloc(heapid, flags, bufs->inbufs[ii].data,  bufs->inbufs[ii].dataLen, bufs->inbufLenReqs[ii]);
197                if(0 == bufs->inbufs[ii].data) {
198                   bufs->inbufs[ii].dataLen = 0;
199                   result = AEE_ENORPCMEMORY;
200                   goto invoke;
201                }
202             }
203             bufs->inbufs[ii].dataLen = bufs->inbufLenReqs[ii];
204             inBufsAllocated = STD_MAX(inBufsAllocated, ii + 1);
205             bNeedMore = TRUE;
206          }
207          bufs->args[ii].buf.pv = bufs->inbufs[ii].data;
208          bufs->args[ii].buf.nLen = bufs->inbufLenReqs[ii];
209       }
210       for(ii = 0; ii < (int)REMOTE_SCALARS_OUTBUFS(sc); ++ii) {
211          if(bufs->outbufs[ii].dataLen < bufs->outbufLenReqs[ii]) {
212             if(0 !=  bufs->outbufLenReqs[ii]) {
213                bufs->outbufs[ii].data = rpcmem_realloc(heapid, flags, bufs->outbufs[ii].data, bufs->outbufs[ii].dataLen, bufs->outbufLenReqs[ii]);
214                if(0 == bufs->outbufs[ii].data) {
215                   result = AEE_ENORPCMEMORY;
216                   goto invoke;
217                }
218             }
219             bufs->outbufs[ii].dataLen = bufs->outbufLenReqs[ii];
220          }
221          bufs->args[ii + REMOTE_SCALARS_INBUFS(sc)].buf.pv = bufs->outbufs[ii].data;
222          bufs->args[ii + REMOTE_SCALARS_INBUFS(sc)].buf.nLen = bufs->outbufLenReqs[ii];
223       }
224       numOutBufs = REMOTE_SCALARS_OUTBUFS(sc);
225       if(bNeedMore) {
226          assert(inBufsAllocated >= REMOTE_SCALARS_INBUFS(sc));
227          if(0 != (result = __QAIC_HEADER(adsp_listener_invoke_get_in_bufs)(ctx, bufs->inbufs,
228                                                                   REMOTE_SCALARS_INBUFS(sc)))) {
229             FARF(HIGH, "adsp_listener_invoke_get_in_bufs failed  %x\n", result);
230             goto invoke;
231          }
232       }
233 
234       result = mod_table_invoke(handle, sc, bufs->args);
235    } while(1);
236 bail:
237    for(ii = 0; ii < MAX_BUFS && bufs; ++ii) {
238       RPC_FREEIF(heapid, bufs->outbufs[ii].data);
239       RPC_FREEIF(heapid, bufs->inbufs[ii].data);
240    }
241    RPC_FREEIF(heapid, bufs);
242    if(nErr != AEE_SUCCESS) {
243       VERIFY_EPRINTF("Error %x: listener thread exiting\n", nErr);
244    }
245    return (void*)(uintptr_t)nErr;
246 }
247 
listener_start_thread(struct listener * me)248 static int listener_start_thread(struct listener* me) {
249    return pthread_create(&me->thread, 0, listener, (void*)me);
250 }
251 #define MIN_BUF_SIZE 0x1000
252 #define ALIGNB(sz) ((sz) == 0 ? MIN_BUF_SIZE : _SBUF_ALIGN((sz), MIN_BUF_SIZE))
253 
listener2(void * arg)254 static void* listener2(void* arg) {
255    struct listener* me = (struct listener*)arg;
256    int nErr = AEE_SUCCESS;
257    adsp_listener_invoke_ctx ctx = 0;
258    uint8* outBufs = 0;
259    int outBufsLen = 0, outBufsCapacity = 0;
260    uint8* inBufs = 0;
261    int inBufsLen = 0, inBufsLenReq = 0;
262    int result = -1;
263    adsp_listener_remote_handle handle = -1;
264    uint32 sc = 0;
265    const char* eheap = getenv("ADSP_LISTENER_HEAP_ID");
266    int heapid = eheap == 0 ? -1 : atoi(eheap);
267    const char* eflags = getenv("ADSP_LISTENER_HEAP_FLAGS");
268    uint32 flags = eflags == 0 ? 0 : (uint32)atoi(eflags);
269    const char* emin = getenv("ADSP_LISTENER_MEM_CACHE_SIZE");
270    int cache_size = emin == 0 ? 0 : atoi(emin);
271    remote_arg args[512];
272    struct sbuf buf;
273    eventfd_t event = 0xff;
274 
275    memset(args, 0, sizeof(args));
276    set_thread_context((int)(me - &linfo[0]));
277    if(eheap || eflags || emin) {
278       FARF(HIGH, "listener using ion heap: %d flags: %x cache: %lld\n", (int)heapid, (int)flags, cache_size);
279    }
280 
281    do {
282  invoke:
283       sc = 0xffffffff;
284       if(result != 0) {
285          outBufsLen = 0;
286       }
287       FARF(HIGH, "responding message for %x %x %x %x", ctx, handle, sc, result);
288       nErr = __QAIC_HEADER(adsp_listener_next2)(
289                         ctx, result, outBufs, outBufsLen,
290                         &ctx, &handle, &sc, inBufs, inBufsLen, &inBufsLenReq);
291       FARF(HIGH, "got message for %x %x %x %x", ctx, handle, sc, nErr);
292       if(nErr) {
293          VERIFY_EPRINTF("listener protocol failure %x\n", nErr);
294          if (nErr == AEE_EINTERRUPTED) {
295             goto invoke;
296          }
297          VERIFY(0 == (nErr = __QAIC_HEADER(adsp_listener_next2)(
298                         ctx, nErr, 0, 0,
299                         &ctx, &handle, &sc, inBufs, inBufsLen,
300                         &inBufsLenReq)));
301       }
302       if(ALIGNB(inBufsLenReq * 2) < inBufsLen && inBufsLen > cache_size) {
303          void* buf;
304          int size = ALIGNB(inBufsLenReq * 2);
305          if(NULL == (buf = rpcmem_realloc(heapid, flags, inBufs, inBufsLen, size))) {
306             result = AEE_ENORPCMEMORY;
307             FARF(HIGH, "rpcmem_realloc shrink failed");
308             goto invoke;
309          }
310          inBufs = buf;
311          inBufsLen = size;
312       }
313       if(inBufsLenReq > inBufsLen) {
314          void* buf;
315          int req;
316          int oldLen = inBufsLen;
317          int size = _SBUF_ALIGN(inBufsLenReq, MIN_BUF_SIZE);
318          if(AEE_SUCCESS == (buf = rpcmem_realloc(heapid, flags, inBufs, inBufsLen, size))) {
319             result = AEE_ENORPCMEMORY;
320             FARF(ERROR, "rpcmem_realloc failed");
321             goto invoke;
322          }
323          inBufs = buf;
324          inBufsLen = size;
325          if(0 != (result = __QAIC_HEADER(adsp_listener_get_in_bufs2)(ctx, oldLen,
326                                                                      inBufs + oldLen,
327                                                                      inBufsLen - oldLen, &req))) {
328             FARF(HIGH, "adsp_listener_invoke_get_in_bufs2 failed  %x", result);
329             goto invoke;
330          }
331          if(req > inBufsLen) {
332             result = AEE_EBADSIZE;
333             FARF(HIGH, "adsp_listener_invoke_get_in_bufs2 failed  %x", result);
334             goto invoke;
335          }
336       }
337       if(REMOTE_SCALARS_INHANDLES(sc) + REMOTE_SCALARS_OUTHANDLES(sc) > 0) {
338          result = AEE_EINVARGS;
339          goto invoke;
340       }
341 
342       sbuf_init(&buf, 0, inBufs, inBufsLen);
343       unpack_in_bufs(&buf, args,  REMOTE_SCALARS_INBUFS(sc));
344       unpack_out_lens(&buf, args + REMOTE_SCALARS_INBUFS(sc), REMOTE_SCALARS_OUTBUFS(sc));
345 
346       sbuf_init(&buf, 0, 0, 0);
347       pack_out_bufs(&buf, args + REMOTE_SCALARS_INBUFS(sc), REMOTE_SCALARS_OUTBUFS(sc));
348       outBufsLen = sbuf_needed(&buf);
349 
350       if(ALIGNB(outBufsLen*2) < outBufsCapacity && outBufsCapacity > cache_size) {
351          void* buf;
352          int size = ALIGNB(outBufsLen*2);
353          if(NULL == (buf = rpcmem_realloc(heapid, flags, outBufs, outBufsCapacity, size))) {
354             result = AEE_ENORPCMEMORY;
355             FARF(HIGH, "listener rpcmem_realloc shrink failed");
356             goto invoke;
357          }
358          outBufs = buf;
359          outBufsCapacity = size;
360       }
361       if(outBufsLen > outBufsCapacity) {
362          void* buf;
363          int size = ALIGNB(outBufsLen);
364          if(NULL == (buf = rpcmem_realloc(heapid, flags, outBufs, outBufsCapacity, size))) {
365             result = AEE_ENORPCMEMORY;
366             FARF(ERROR, "listener rpcmem_realloc failed");
367             goto invoke;
368          }
369          outBufs = buf;
370          outBufsLen = size;
371          outBufsCapacity = size;
372       }
373       sbuf_init(&buf, 0, outBufs, outBufsLen);
374       pack_out_bufs(&buf, args + REMOTE_SCALARS_INBUFS(sc), REMOTE_SCALARS_OUTBUFS(sc));
375 
376       result = mod_table_invoke(handle, sc, args);
377    } while(1);
378 bail:
379    RPC_FREEIF(heapid, outBufs);
380    RPC_FREEIF(heapid, inBufs);
381    if(nErr != AEE_SUCCESS) {
382       VERIFY_EPRINTF("Error %x: listener thread exited", nErr);
383    }
384    eventfd_write(me->eventfd, event);
385    dlerror();
386    return (void*)(uintptr_t)nErr;
387 }
listener_start_thread2(struct listener * me)388 static int listener_start_thread2(struct listener* me) {
389    return pthread_create(&me->thread, 0, listener2, (void*)me);
390 }
391 
392 extern int apps_remotectl_skel_invoke(uint32 _sc, remote_arg* _pra);
393 extern int apps_std_skel_invoke(uint32 _sc, remote_arg* _pra);
394 extern int apps_mem_skel_invoke(uint32 _sc, remote_arg* _pra);
395 extern int adspmsgd_apps_skel_invoke(uint32_t _sc, remote_arg* _pra);
396 
397 #include "adsp_listener_stub.c"
398 PL_DEP(mod_table)
399 PL_DEP(apps_std);
400 
listener_android_deinit(void)401 void listener_android_deinit(void) {
402    PL_DEINIT(mod_table);
403    PL_DEINIT(apps_std);
404 }
405 
listener_android_init(void)406 int listener_android_init(void) {
407    int nErr = 0;
408 
409    VERIFY(AEE_SUCCESS == (nErr = PL_INIT(mod_table)));
410    VERIFY(AEE_SUCCESS == (nErr = PL_INIT(apps_std)));
411    VERIFY(AEE_SUCCESS == (nErr = mod_table_register_const_handle(0, "apps_remotectl", apps_remotectl_skel_invoke)));
412    VERIFY(AEE_SUCCESS == (nErr = mod_table_register_static("apps_std", apps_std_skel_invoke)));
413    VERIFY(AEE_SUCCESS == (nErr = mod_table_register_static("apps_mem", apps_mem_skel_invoke)));
414    VERIFY(AEE_SUCCESS == (nErr = mod_table_register_static("adspmsgd_apps", adspmsgd_apps_skel_invoke)));
415 bail:
416    if(nErr != AEE_SUCCESS) {
417       listener_android_deinit();
418       VERIFY_EPRINTF("Error %x: fastrpc listener initialization error", nErr);
419    }
420    return nErr;
421 }
422 
listener_android_domain_deinit(int domain)423 void listener_android_domain_deinit(int domain) {
424    struct listener* me = &linfo[domain];
425 
426    FARF(HIGH, "fastrpc listener joining to exit");
427    if(me->thread) {
428       pthread_join(me->thread, 0);
429       me->thread = 0;
430    }
431    FARF(HIGH, "fastrpc listener joined");
432    if(me->eventfd != -1) {
433       close(me->eventfd);
434       me->eventfd = -1;
435    }
436 }
437 
listener_android_domain_init(int domain)438 int listener_android_domain_init(int domain) {
439    struct listener* me = &linfo[domain];
440    int nErr = 0;
441 
442    VERIFYC(-1 != (me->eventfd = eventfd(0, 0)), AEE_EINVALIDFD);
443    nErr = __QAIC_HEADER(adsp_listener_init2)();
444    if(AEE_EUNSUPPORTEDAPI == nErr) {
445       FARF(HIGH, "listener2 initialization error falling back to listener1 %x", nErr);
446       VERIFY(AEE_SUCCESS == (nErr = __QAIC_HEADER(adsp_listener_init)()));
447       VERIFY(AEE_SUCCESS == (nErr = listener_start_thread(me)));
448    } else if(AEE_SUCCESS == nErr) {
449       FARF(HIGH, "listener2 initialized for domain %d", domain);
450       VERIFY(AEE_SUCCESS == (nErr = listener_start_thread2(me)));
451    }
452 
453 bail:
454    if(nErr != AEE_SUCCESS) {
455       VERIFY_EPRINTF("Error %x: listener android domain init failed. domain %d\n", nErr, domain);
456       listener_android_domain_deinit(domain);
457    }
458    return nErr;
459 }
460 
listener_android_geteventfd(int domain,int * fd)461 int listener_android_geteventfd(int domain, int *fd) {
462    struct listener* me = &linfo[domain];
463    int nErr = 0;
464 
465    VERIFYC(-1 != me->eventfd, AEE_EINVALIDFD);
466    *fd = me->eventfd;
467 bail:
468    if (nErr != AEE_SUCCESS) {
469 	VERIFY_EPRINTF("Error %x: listener android getevent file descriptor failed for domain %d\n", nErr, domain);
470    }
471    return nErr;
472 }
473 
474 PL_DEFINE(listener_android, listener_android_init, listener_android_deinit)
475