diff --git a/chrecd/interfaces/chre_slpi.def b/chrecd/interfaces/chre_slpi.def index d9aaeff..b139c49 100644 --- a/chrecd/interfaces/chre_slpi.def +++ b/chrecd/interfaces/chre_slpi.def @@ -27,4 +27,18 @@ HEXAGONRPC_DEFINE_REMOTE_METHOD(0, chre_slpi_start_thread, 0, 0, 0, 0) HEXAGONRPC_DEFINE_REMOTE_METHOD(1, chre_slpi_wait_on_thread_exit, 0, 0, 0, 0) +HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(0, chre_slpi3_start_thread) + +static inline int chre_slpi3_start_thread(const struct fastrpc_context *ctx) +{ + return hexagonrpc(&chre_slpi3_start_thread_def, ctx); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(1, chre_slpi3_wait_on_thread_exit) + +static inline int chre_slpi3_wait_on_thread_exit(const struct fastrpc_context *ctx) +{ + return hexagonrpc(&chre_slpi3_wait_on_thread_exit_def, ctx); +} + #endif /* INTERFACE_CHRE_SLPI_DEF */ diff --git a/hexagonrpcd/apps_std.c b/hexagonrpcd/apps_std.c index 6728f1e..ba6fc03 100644 --- a/hexagonrpcd/apps_std.c +++ b/hexagonrpcd/apps_std.c @@ -20,13 +20,13 @@ */ #include +#include #include #include #include #include #include -#include "aee_error.h" #include "interfaces/apps_std.def" #include "hexagonfs.h" #include "iobuffer.h" @@ -408,15 +408,15 @@ static const struct fastrpc_function_impl apps_std_procs[] = { { .def = NULL, .impl = NULL, }, { .def = NULL, .impl = NULL, }, { - .def = &apps_std_fflush_def, + .def = &apps_std3_fflush_def, .impl = apps_std_fflush, }, { - .def = &apps_std_fclose_def, + .def = &apps_std3_fclose_def, .impl = apps_std_fclose, }, { - .def = &apps_std_fread_def, + .def = &apps_std3_fread_def, .impl = apps_std_fread, }, { .def = NULL, .impl = NULL, }, @@ -424,7 +424,7 @@ static const struct fastrpc_function_impl apps_std_procs[] = { { .def = NULL, .impl = NULL, }, { .def = NULL, .impl = NULL, }, { - .def = &apps_std_fseek_def, + .def = &apps_std3_fseek_def, .impl = apps_std_fseek, }, { .def = NULL, .impl = NULL, }, @@ -437,7 +437,7 @@ static const struct fastrpc_function_impl apps_std_procs[] = { { .def = NULL, .impl = NULL, }, { .def = NULL, .impl = NULL, }, { - .def = &apps_std_fopen_with_env_def, + .def = &apps_std3_fopen_with_env_def, .impl = apps_std_fopen_with_env, }, { .def = NULL, .impl = NULL, }, @@ -447,21 +447,21 @@ static const struct fastrpc_function_impl apps_std_procs[] = { { .def = NULL, .impl = NULL, }, { .def = NULL, .impl = NULL, }, { - .def = &apps_std_opendir_def, + .def = &apps_std3_opendir_def, .impl = apps_std_opendir, }, { - .def = &apps_std_closedir_def, + .def = &apps_std3_closedir_def, .impl = apps_std_closedir, }, { - .def = &apps_std_readdir_def, + .def = &apps_std3_readdir_def, .impl = apps_std_readdir, }, { .def = NULL, .impl = NULL, }, { .def = NULL, .impl = NULL, }, { - .def = &apps_std_stat_def, + .def = &apps_std3_stat_def, .impl = apps_std_stat, }, }; diff --git a/hexagonrpcd/interfaces/adsp_default_listener.def b/hexagonrpcd/interfaces/adsp_default_listener.def index 0e56ed5..ca31622 100644 --- a/hexagonrpcd/interfaces/adsp_default_listener.def +++ b/hexagonrpcd/interfaces/adsp_default_listener.def @@ -26,4 +26,11 @@ HEXAGONRPC_DEFINE_REMOTE_METHOD(0, adsp_default_listener_register, 0, 0, 0, 0) +HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(0, adsp_default_listener3_register) + +static inline int adsp_default_listener3_register(const struct fastrpc_context *ctx) +{ + return hexagonrpc(&adsp_default_listener3_register_def, ctx); +} + #endif /* INTERFACE_ADSP_DEFAULT_LISTENER_DEF */ diff --git a/hexagonrpcd/interfaces/adsp_listener.def b/hexagonrpcd/interfaces/adsp_listener.def index 4f521c0..6d460b0 100644 --- a/hexagonrpcd/interfaces/adsp_listener.def +++ b/hexagonrpcd/interfaces/adsp_listener.def @@ -29,4 +29,29 @@ HEXAGONRPC_DEFINE_REMOTE_METHOD(3, adsp_listener_init2, 0, 0, 0, 0) HEXAGONRPC_DEFINE_REMOTE_METHOD(4, adsp_listener_next2, 2, 1, 4, 1) +HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(3, adsp_listener3_init2) + +static inline int adsp_listener3_init2(int fd) +{ + return hexagonrpc2(&adsp_listener3_init2_def, fd, ADSP_LISTENER_HANDLE); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(4, adsp_listener3_next2, true, + 0, 0, 1, HEXAGONRPC_DELIMITER, 0, 0, 0, 0, 1) + +static inline int adsp_listener3_next2(int fd, + uint32_t ret_rctx, + uint32_t ret_res, + uint32_t ret_outbufs_len, const void *ret_outbufs, + uint32_t *rctx, + uint32_t *handle, + uint32_t *sc, + uint32_t *inbufs_len, + uint32_t inbufs_size, void *inbufs) +{ + return hexagonrpc2(&adsp_listener3_next2_def, fd, ADSP_LISTENER_HANDLE, + ret_rctx, ret_res, ret_outbufs_len, ret_outbufs, + rctx, handle, sc, inbufs_len, inbufs_size, inbufs); +} + #endif /* INTERFACE_ADSP_LISTENER_DEF */ diff --git a/hexagonrpcd/interfaces/apps_std.def b/hexagonrpcd/interfaces/apps_std.def index 2fbbdb1..f70334f 100644 --- a/hexagonrpcd/interfaces/apps_std.def +++ b/hexagonrpcd/interfaces/apps_std.def @@ -35,4 +35,162 @@ HEXAGONRPC_DEFINE_REMOTE_METHOD(27, apps_std_closedir, 2, 0, 0, 0) HEXAGONRPC_DEFINE_REMOTE_METHOD(28, apps_std_readdir, 2, 0, 66, 0) HEXAGONRPC_DEFINE_REMOTE_METHOD(31, apps_std_stat, 1, 1, 24, 0) +HEXAGONRPC_DEFINE_REMOTE_METHOD3(1, apps_std3_freopen, true, + 0, HEXAGONRPC_DELIMITER, 0, 1) + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(2, apps_std3_fflush, false, + 0, HEXAGONRPC_DELIMITER) + +static inline int apps_std3_fflush(struct fastrpc_context *ctx, uint32_t stream) +{ + return hexagonrpc(&apps_std3_fflush_def, ctx, stream); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(3, apps_std3_fclose, false, + 0, HEXAGONRPC_DELIMITER) + +static inline int apps_std3_fclose(struct fastrpc_context *ctx, uint32_t stream) +{ + return hexagonrpc(&apps_std3_fclose_def, ctx, stream); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(4, apps_std3_fread, true, + 0, HEXAGONRPC_DELIMITER, 0, 0, 1) + +static inline int apps_std3_fread(struct fastrpc_context *ctx, + uint32_t stream, + uint32_t *written, uint32_t *is_eof, + uint32_t size, void *buf) +{ + return hexagonrpc(&apps_std3_fread_def, ctx, + stream, written, is_eof, size, buf); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(9, apps_std3_fseek, false, + 0, 0, 0, HEXAGONRPC_DELIMITER) + +static inline int apps_std3_fseek(struct fastrpc_context *ctx, + uint32_t stream, uint32_t pos, uint32_t whence) +{ + return hexagonrpc(&apps_std3_fseek_def, ctx, stream, pos, whence); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(19, apps_std3_fopen_with_env, true, + 1, 1, 1, 1, HEXAGONRPC_DELIMITER, 0) + +static inline int apps_std3_fopen_with_env(struct fastrpc_context *ctx, + uint32_t envvar_len, const char *envvar, + uint32_t delim_len, const char *delim, + uint32_t name_len, const char *name, + uint32_t mode_len, const char *mode) +{ + return hexagonrpc(&apps_std3_fopen_with_env_def, ctx, + envvar_len, (const void *) envvar, + delim_len, (const void *) delim, + name_len, (const void *) name, + mode_len, (const void *) mode); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(26, apps_std3_opendir, true, + 1, HEXAGONRPC_DELIMITER, 0, 0) + +static inline int apps_std3_opendir(struct fastrpc_context *ctx, + uint32_t path_len, const char *path, + uint32_t *handle_lo, uint32_t *handle_hi) +{ + return hexagonrpc(&apps_std3_opendir_def, ctx, + path_len, (const void *) path, + handle_lo, handle_hi); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(27, apps_std3_closedir, false, + 0, 0, HEXAGONRPC_DELIMITER) + +static inline int apps_std3_closedir(struct fastrpc_context *ctx, + uint32_t handle_lo, uint32_t handle_hi) +{ + return hexagonrpc(&apps_std3_closedir_def, ctx, handle_lo, handle_hi); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(28, apps_std3_readdir, true, + 0, 0, HEXAGONRPC_DELIMITER, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0) + +static inline int apps_std3_readdir(struct fastrpc_context *ctx, + uint32_t handle_lo, uint32_t handle_hi, + uint32_t *inode, char *path, uint32_t *eof) +{ + uint32_t *buf = (uint32_t *) path; + + return hexagonrpc(&apps_std3_readdir_def, ctx, + handle_lo, handle_hi, inode, + &buf[0], &buf[1], &buf[2], &buf[3], + &buf[4], &buf[5], &buf[6], &buf[7], + &buf[8], &buf[9], &buf[10], &buf[11], + &buf[12], &buf[13], &buf[14], &buf[15], + &buf[16], &buf[17], &buf[18], &buf[19], + &buf[20], &buf[21], &buf[22], &buf[23], + &buf[24], &buf[25], &buf[26], &buf[27], + &buf[28], &buf[29], &buf[30], &buf[31], + &buf[32], &buf[33], &buf[34], &buf[35], + &buf[36], &buf[37], &buf[38], &buf[39], + &buf[40], &buf[41], &buf[42], &buf[43], + &buf[44], &buf[45], &buf[46], &buf[47], + &buf[48], &buf[49], &buf[50], &buf[51], + &buf[52], &buf[53], &buf[54], &buf[55], + &buf[56], &buf[57], &buf[58], &buf[57], + &buf[60], &buf[61], &buf[62], &buf[63], eof); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(29, apps_std3_mkdir, false, + 1, 0, HEXAGONRPC_DELIMITER) + +static inline int apps_std3_mkdir(struct fastrpc_context *ctx, + uint32_t path_size, const char *path, + uint32_t mode) +{ + return hexagonrpc(&apps_std3_mkdir_def, ctx, + path_size, (const void *) path, mode); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(31, apps_std3_stat, true, + 1, HEXAGONRPC_DELIMITER, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0) + +static inline int apps_std3_stat(struct fastrpc_context *ctx, + uint32_t path_size, const char *path, + uint32_t *tsz_lo, uint32_t *tsz_hi, + uint32_t *dev_lo, uint32_t *dev_hi, + uint32_t *ino_lo, uint32_t *ino_hi, + uint32_t *mode, uint32_t *nlink, + uint32_t *rdev_lo, uint32_t *rdev_hi, + uint32_t *size_lo, uint32_t *size_hi, + uint32_t *atime_sec_lo, uint32_t *atime_sec_hi, + uint32_t *atime_nsec_lo, uint32_t *atime_nsec_hi, + uint32_t *mtime_sec_lo, uint32_t *mtime_sec_hi, + uint32_t *mtime_nsec_lo, uint32_t *mtime_nsec_hi, + uint32_t *ctime_sec_lo, uint32_t *ctime_sec_hi, + uint32_t *ctime_nsec_lo, uint32_t *ctime_nsec_hi) +{ + return hexagonrpc(&apps_std3_stat_def, ctx, + path_size, (const void *) path, + tsz_lo, tsz_hi, + dev_lo, dev_hi, + ino_lo, ino_hi, + mode, nlink, + rdev_lo, rdev_hi, + size_lo, size_hi, + atime_sec_lo, atime_sec_hi, + atime_nsec_lo, atime_nsec_hi, + mtime_sec_lo, mtime_sec_hi, + mtime_nsec_lo, mtime_nsec_hi, + ctime_sec_lo, ctime_sec_hi, + ctime_nsec_lo, ctime_nsec_hi); +} + #endif /* INTERFACE_APPS_STD_DEF */ diff --git a/hexagonrpcd/listener.c b/hexagonrpcd/listener.c index 9de0a16..aa7dfef 100644 --- a/hexagonrpcd/listener.c +++ b/hexagonrpcd/listener.c @@ -20,117 +20,146 @@ */ #include +#include #include #include #include +#include #include -#include "aee_error.h" #include "interfaces/adsp_listener.def" #include "iobuffer.h" #include "listener.h" -static int adsp_listener_init2(int fd) +static int check_buf_sizes(const struct hrpc_method_def_interp3 *def, + uint8_t n_inbufs, uint8_t n_outbufs, + const struct fastrpc_io_buffer *inbufs) { - return fastrpc2(&adsp_listener_init2_def, fd, ADSP_LISTENER_HANDLE); -} + const uint32_t *prim_in = inbufs[0].p; + uint8_t n_def_outbufs; + size_t i, j = 1; + size_t off; + size_t n_prim_in; + + if (def->msg_id < 31) + off = 0; + else + off = 1; + + for (i = 0; i < def->n_args; i++) { + if (def->args[i] == HEXAGONRPC_DELIMITER) + break; -static int adsp_listener_next2(int fd, - uint32_t ret_rctx, - uint32_t ret_res, - uint32_t ret_outbuf_len, void *ret_outbuf, - uint32_t *rctx, - uint32_t *handle, - uint32_t *sc, - uint32_t *inbufs_len, - uint32_t inbufs_size, void *inbufs) -{ - return fastrpc2(&adsp_listener_next2_def, fd, ADSP_LISTENER_HANDLE, - ret_rctx, - ret_res, - ret_outbuf_len, ret_outbuf, - rctx, - handle, - sc, - inbufs_len, - inbufs_size, inbufs); -} + if (!def->args[i]) + continue; -static struct fastrpc_io_buffer *allocate_outbufs(const struct fastrpc_function_def_interp2 *def, - uint32_t *first_inbuf) -{ - struct fastrpc_io_buffer *out; - size_t out_count; - size_t i, j; - off_t off; - uint32_t *sizes; - - out_count = def->out_bufs + (def->out_nums && 1); - /* - * POSIX allows malloc to return a non-NULL pointer to a zero-size area - * in memory. Since the code below assumes non-zero size if the pointer - * is non-NULL, exit early if we do not need to allocate anything. - */ - if (out_count == 0) - return NULL; + /* + * We can't check the size because the primary input buffer is + * too small, so skip checking and print an error later. + */ + if ((off + i) * sizeof(uint32_t) >= inbufs[0].s) + continue; - out = malloc(sizeof(struct fastrpc_io_buffer) * out_count); - if (out == NULL) - return NULL; + if (j >= n_inbufs) { + fprintf(stderr, "listener: not enough input buffers\n"); + return 1; + } + + if ((size_t) prim_in[off + i] * def->args[i] > inbufs[j].s) { + fprintf(stderr, "listener: input buffer too small\n"); + return 1; + } - out[0].s = def->out_nums * 4; - if (out[0].s) { - out[0].p = malloc(def->out_nums * 4); - if (out[0].p == NULL) - goto err_free_out; + j++; } - off = def->out_nums && 1; - sizes = &first_inbuf[def->in_nums + def->in_bufs]; + n_prim_in = i; + if (def->args[i] == HEXAGONRPC_DELIMITER) + i++; - for (i = 0; i < def->out_bufs; i++) { - out[off + i].s = sizes[i]; - out[off + i].p = malloc(sizes[i]); - if (out[off + i].p == NULL) - goto err_free_prev; + if (def->has_prim_out) + n_def_outbufs = 1; + else + n_def_outbufs = 0; + + for (; i < def->n_args; i++) { + if (def->args[i]) { + n_def_outbufs++; + n_prim_in++; + } } - return out; + if (n_def_outbufs != n_outbufs) { + fprintf(stderr, "listener: wrong amount of output buffers\n"); + return 1; + } -err_free_prev: - for (j = 0; j < i; j++) - free(out[off + j].p); + if ((off + n_prim_in) * sizeof(uint32_t) > inbufs[0].s) { + fprintf(stderr, "listener: primary input buffer too small\n"); + return 1; + } -err_free_out: - free(out); - return NULL; + return 0; } -static int check_inbuf_sizes(const struct fastrpc_function_def_interp2 *def, - const struct fastrpc_io_buffer *inbufs) +static struct fastrpc_io_buffer *allocate_outbufs(const struct hrpc_method_def_interp3 *def, + const uint32_t *prim_in) { - uint8_t i; - const uint32_t *sizes = &((const uint32_t *) inbufs[0].p)[def->in_nums]; - - if (inbufs[0].s != 4 * (def->in_nums - + def->in_bufs - + def->out_bufs)) { - fprintf(stderr, "Invalid number of input numbers: %" PRIu32 " (expected %u)\n", - inbufs[0].s, - 4 * (def->in_nums - + def->in_bufs - + def->out_bufs)); - return -1; + struct fastrpc_io_buffer *out; + // This is only used when there is a delimiter. + const uint32_t *size = NULL; + size_t n_outbufs, n_prim_out = 0; + size_t i; + + out = malloc(sizeof(struct fastrpc_io_buffer) * def->n_args); + if (out == NULL) + return NULL; + + if (def->has_prim_out) + n_outbufs = 1; + else + n_outbufs = 0; + + for (i = 0; i < def->n_args; i++) { + if (def->args[i] == HEXAGONRPC_DELIMITER) { + size = &prim_in[i]; + i++; + break; + } } - for (i = 0; i < def->in_bufs; i++) { - if (inbufs[i + 1].s != sizes[i]) { - fprintf(stderr, "Invalid buffer size\n"); - return -1; + for (; i < def->n_args; i++) { + if (def->args[i]) { + out[n_outbufs].s = (size_t) def->args[i] * *size; + out[n_outbufs].p = malloc(out[n_outbufs].s); + if (out[n_outbufs].p == NULL && out[n_outbufs].s) + goto err_free_outbufs; + + n_outbufs++; + size = &size[1]; + } else { + n_prim_out++; } } - return 0; + if (def->has_prim_out) { + out[0].s = sizeof(uint32_t) * n_prim_out; + out[0].p = malloc(out[0].s); + if (out[0].p == NULL && out[0].s) + goto err_free_outbufs; + } + + return out; + +err_free_outbufs: + if (!def->has_prim_out) + free(out[0].p); + + for (i = 1; i < n_outbufs; i++) + free(out[i].p); + + free(out); + return NULL; } static int return_for_next_invoke(int fd, @@ -160,7 +189,7 @@ static int return_for_next_invoke(int fd, outbufs_encode(REMOTE_SCALARS_OUTBUFS(*sc), returned, outbufs); } - ret = adsp_listener_next2(fd, + ret = adsp_listener3_next2(fd, *rctx, result, outbufs_len, outbufs, rctx, handle, sc, @@ -215,11 +244,16 @@ static int invoke_requested_procedure(size_t n_ifaces, struct fastrpc_io_buffer **returned) { const struct fastrpc_function_impl *impl; - uint8_t in_count; - uint8_t out_count; uint32_t method = REMOTE_SCALARS_METHOD(sc); int ret; + if (method < 31) + method = REMOTE_SCALARS_METHOD(sc); + else if (decoded[0].s >= sizeof(uint32_t)) + method = *(const uint32_t *) decoded[0].p; + else + method = UINT32_MAX; + if (sc & 0xff) { fprintf(stderr, "Handles are not supported, but got %u in, %u out\n", (sc & 0xf0) >> 4, sc & 0xf); @@ -247,26 +281,15 @@ static int invoke_requested_procedure(size_t n_ifaces, return 1; } - in_count = impl->def->in_bufs + ((impl->def->in_nums - || impl->def->in_bufs - || impl->def->out_bufs) && 1); - out_count = impl->def->out_bufs + (impl->def->out_nums && 1); - - if (REMOTE_SCALARS_INBUFS(sc) != in_count - || REMOTE_SCALARS_OUTBUFS(sc) != out_count) { - fprintf(stderr, "Unexpected buffer count: %08x\n", sc); - *result = AEE_EBADPARM; - return 1; - } - - ret = check_inbuf_sizes(impl->def, decoded); + ret = check_buf_sizes(impl->def, REMOTE_SCALARS_INBUFS(sc), + REMOTE_SCALARS_OUTBUFS(sc), decoded); if (ret) { *result = AEE_EBADPARM; return 1; } *returned = allocate_outbufs(impl->def, decoded[0].p); - if (*returned == NULL && out_count > 0) { + if (*returned == NULL && impl->def->n_args > 0) { perror("Could not allocate output buffers"); *result = AEE_ENOMEMORY; return 1; @@ -290,7 +313,7 @@ int run_fastrpc_listener(int fd, uint32_t n_outbufs = 0; int ret; - ret = adsp_listener_init2(fd); + ret = adsp_listener3_init2(fd); if (ret) { fprintf(stderr, "Could not initialize the listener: %u\n", ret); return ret; diff --git a/hexagonrpcd/listener.h b/hexagonrpcd/listener.h index 1332c6e..9581247 100644 --- a/hexagonrpcd/listener.h +++ b/hexagonrpcd/listener.h @@ -29,7 +29,7 @@ #include "iobuffer.h" struct fastrpc_function_impl { - const struct fastrpc_function_def_interp2 *def; + const struct hrpc_method_def_interp3 *def; uint32_t (*impl)(void *data, const struct fastrpc_io_buffer *inbufs, struct fastrpc_io_buffer *outbufs); diff --git a/hexagonrpcd/localctl.c b/hexagonrpcd/localctl.c index 3eaef88..86e910f 100644 --- a/hexagonrpcd/localctl.c +++ b/hexagonrpcd/localctl.c @@ -19,13 +19,13 @@ * along with this program. If not, see . */ +#include #include #include #include #include #include -#include "aee_error.h" #include "iobuffer.h" #include "listener.h" #include "localctl.h" @@ -145,8 +145,14 @@ void fastrpc_localctl_deinit(struct fastrpc_interface *iface) } static const struct fastrpc_function_impl localctl_procs[] = { - { .def = &remotectl_open_def, .impl = localctl_open, }, - { .def = &remotectl_close_def, .impl = localctl_close, }, + { + .def = &remotectl3_open_def, + .impl = localctl_open, + }, + { + .def = &remotectl3_close_def, + .impl = localctl_close, + }, }; const struct fastrpc_interface localctl_interface = { diff --git a/hexagonrpcd/meson.build b/hexagonrpcd/meson.build index b33ddd5..451aa10 100644 --- a/hexagonrpcd/meson.build +++ b/hexagonrpcd/meson.build @@ -1,5 +1,4 @@ executable('hexagonrpcd', - 'aee_error.c', 'apps_std.c', 'interfaces.c', 'hexagonfs.c', diff --git a/hexagonrpcd/rpcd.c b/hexagonrpcd/rpcd.c index 1331803..62948c3 100644 --- a/hexagonrpcd/rpcd.c +++ b/hexagonrpcd/rpcd.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -32,7 +33,6 @@ #include #include -#include "aee_error.h" #include "apps_std.h" #include "hexagonfs.h" #include "interfaces/adsp_default_listener.def" @@ -53,17 +53,14 @@ static int remotectl_open(int fd, char *name, struct fastrpc_context **ctx, void &dlret, 256, err); - if (ret == -1) { - err_cb(strerror(errno)); + if (ret) { + err_cb(hexagonrpc_strerror(errno)); return ret; } - if (dlret == -5) { + if (dlret) { err_cb(err); return dlret; - } else if (dlret) { - err_cb(aee_strerror[dlret]); - return dlret; } *ctx = fastrpc_create_context(fd, handle); @@ -82,13 +79,13 @@ static int remotectl_close(struct fastrpc_context *ctx, void (*err_cb)(const cha &dlret, 256, err); - if (ret == -1) { - err_cb(strerror(errno)); + if (ret) { + err_cb(hexagonrpc_strerror(errno)); return ret; } if (dlret) { - err_cb(aee_strerror[dlret]); + err_cb(err); return dlret; } @@ -97,11 +94,6 @@ static int remotectl_close(struct fastrpc_context *ctx, void (*err_cb)(const cha return ret; } -static int adsp_default_listener_register(struct fastrpc_context *ctx) -{ - return fastrpc(&adsp_default_listener_register_def, ctx); -} - static void remotectl_err(const char *err) { fprintf(stderr, "Could not remotectl: %s\n", err); @@ -116,7 +108,7 @@ static int register_fastrpc_listener(int fd) if (ret) return 1; - ret = adsp_default_listener_register(ctx); + ret = adsp_default_listener3_register(ctx); if (ret) { fprintf(stderr, "Could not register ADSP default listener\n"); goto err; diff --git a/hexagonrpcd/aee_error.h b/include/libhexagonrpc/error.h similarity index 96% rename from hexagonrpcd/aee_error.h rename to include/libhexagonrpc/error.h index 911165e..96f737c 100644 --- a/hexagonrpcd/aee_error.h +++ b/include/libhexagonrpc/error.h @@ -2,6 +2,7 @@ * Imported FastRPC error numbers * * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, The Sensor Shell Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -83,6 +84,6 @@ #define AEE_ECPUEXCEPTION 48 #define AEE_EREADONLY 49 -extern const char *aee_strerror[]; +const char *hexagonrpc_strerror(int ret); #endif diff --git a/include/libhexagonrpc/fastrpc.h b/include/libhexagonrpc/fastrpc.h index 69f0d17..e581a91 100644 --- a/include/libhexagonrpc/fastrpc.h +++ b/include/libhexagonrpc/fastrpc.h @@ -23,6 +23,7 @@ #define FASTRPC_H #include +#include #include #include @@ -41,6 +42,8 @@ #define REMOTE_SCALARS_INBUFS(sc) (((sc) >> 16) & 0xff) #define REMOTE_SCALARS_OUTBUFS(sc) (((sc) >> 8) & 0xff) +#define HEXAGONRPC_DELIMITER 0xFFFFFFFF + struct fastrpc_context { int fd; uint32_t handle; @@ -54,6 +57,13 @@ struct fastrpc_function_def_interp2 { uint8_t out_bufs; }; +struct hrpc_method_def_interp3 { + uint32_t msg_id; + bool has_prim_out; + size_t n_args; + const uint32_t *args; +}; + struct fastrpc_context *fastrpc_create_context(int fd, uint32_t handle); static inline void fastrpc_destroy_context(struct fastrpc_context *ctx) @@ -70,4 +80,14 @@ int fastrpc2(const struct fastrpc_function_def_interp2 *def, int fastrpc(const struct fastrpc_function_def_interp2 *def, const struct fastrpc_context *ctx, ...); +int vhexagonrpc2(const struct hrpc_method_def_interp3 *def, + int fd, uint32_t handle, va_list list); +int vhexagonrpc(const struct hrpc_method_def_interp3 *def, + const struct fastrpc_context *ctx, va_list list); +int hexagonrpc2(const struct hrpc_method_def_interp3 *def, + int fd, uint32_t handle, ...); +int hexagonrpc(const struct hrpc_method_def_interp3 *def, + const struct fastrpc_context *ctx, ...); + + #endif diff --git a/include/libhexagonrpc/interface.h b/include/libhexagonrpc/interface.h index 0b6700f..c7a0af2 100644 --- a/include/libhexagonrpc/interface.h +++ b/include/libhexagonrpc/interface.h @@ -36,6 +36,12 @@ outnums, outbufs) \ extern const struct fastrpc_function_def_interp2 name##_def; +#define HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(mid, name) \ + extern const struct hrpc_method_def_interp3 name##_def; + +#define HEXAGONRPC_DEFINE_REMOTE_METHOD3(mid, name, has_oprim, ...) \ + HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(mid, name) + #else /* HEXAGONRPC_BUILD_METHOD_DEFINITIONS */ #define HEXAGONRPC_DEFINE_REMOTE_METHOD(mid, name, \ @@ -49,6 +55,23 @@ .out_bufs = outbufs, \ }; +#define HEXAGONRPC_DEFINE_REMOTE_METHOD3_EMPTY(mid, name) \ + const struct hrpc_method_def_interp3 name##_def = { \ + .msg_id = mid, \ + .has_prim_out = false, \ + .n_args = 0, \ + .args = NULL, \ + }; + +#define HEXAGONRPC_DEFINE_REMOTE_METHOD3(mid, name, has_oprim, ...) \ + static const uint32_t name##_args[] = { __VA_ARGS__ }; \ + const struct hrpc_method_def_interp3 name##_def = { \ + .msg_id = mid, \ + .has_prim_out = has_oprim, \ + .n_args = sizeof(name##_args) / sizeof(*name##_args), \ + .args = name##_args, \ + }; + #endif /* HEXAGONRPC_BUILD_METHOD_DEFINITIONS */ #endif /* LIBHEXAGONRPC_INTERFACE_H */ diff --git a/include/libhexagonrpc/interfaces/remotectl.def b/include/libhexagonrpc/interfaces/remotectl.def index ba23c57..7f9ac1e 100644 --- a/include/libhexagonrpc/interfaces/remotectl.def +++ b/include/libhexagonrpc/interfaces/remotectl.def @@ -29,4 +29,30 @@ HEXAGONRPC_DEFINE_REMOTE_METHOD(0, remotectl_open, 0, 1, 2, 1) HEXAGONRPC_DEFINE_REMOTE_METHOD(1, remotectl_close, 1, 0, 1, 1) +HEXAGONRPC_DEFINE_REMOTE_METHOD3(0, remotectl3_open, true, + 1, HEXAGONRPC_DELIMITER, 0, 1, 0) + +static inline int remotectl3_open(int fd, + uint32_t n_str, const char *str, + uint32_t *handle, + uint32_t err_len, char *err, + uint32_t *dlerr) +{ + return hexagonrpc2(&remotectl3_open_def, fd, REMOTECTL_HANDLE, + n_str, (const void *) str, + handle, err_len, (void *) err, dlerr); +} + +HEXAGONRPC_DEFINE_REMOTE_METHOD3(0, remotectl3_close, true, + 0, HEXAGONRPC_DELIMITER, 1, 0) + +static inline int remotectl3_close(int fd, + uint32_t handle, + uint32_t err_len, char *err, + uint32_t *dlerr) +{ + return hexagonrpc2(&remotectl3_close_def, fd, REMOTECTL_HANDLE, + handle, err_len, (void *) err, dlerr); +} + #endif /* INTERFACE_REMOTECTL_DEF */ diff --git a/libhexagonrpc/context.c b/libhexagonrpc/context.c index c3fa204..646ab4f 100644 --- a/libhexagonrpc/context.c +++ b/libhexagonrpc/context.c @@ -54,3 +54,21 @@ int fastrpc(const struct fastrpc_function_def_interp2 *def, return ret; } +int vhexagonrpc(const struct hrpc_method_def_interp3 *def, + const struct fastrpc_context *ctx, va_list arg_list) +{ + return vhexagonrpc2(def, ctx->fd, ctx->handle, arg_list); +} + +int hexagonrpc(const struct hrpc_method_def_interp3 *def, + const struct fastrpc_context *ctx, ...) +{ + va_list arg_list; + int ret; + + va_start(arg_list, ctx); + ret = vhexagonrpc(def, ctx, arg_list); + va_end(arg_list); + + return ret; +} diff --git a/hexagonrpcd/aee_error.c b/libhexagonrpc/error.c similarity index 89% rename from hexagonrpcd/aee_error.c rename to libhexagonrpc/error.c index f0f2930..7b2cc20 100644 --- a/hexagonrpcd/aee_error.c +++ b/libhexagonrpc/error.c @@ -2,6 +2,7 @@ * Imported FastRPC error messages * * Copyright (c) 2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, The Sensor Shell Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -29,7 +30,10 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -const char *aee_strerror[] = { +#include +#include + +static const char *err_tab[] = { "No error", "General failure", "Insufficient RAM", @@ -81,3 +85,13 @@ const char *aee_strerror[] = { "A CPU exception occurred", "Cannot change read-only object or parameter", }; + +const char *hexagonrpc_strerror(int ret) +{ + if (ret == -1) + return strerror(errno); + else if (ret >= 0 && (unsigned int) ret < sizeof(err_tab) / sizeof(*err_tab)) + return err_tab[ret]; + + return "Unknown error"; +} diff --git a/libhexagonrpc/fastrpc.c b/libhexagonrpc/fastrpc.c index cee9323..420543a 100644 --- a/libhexagonrpc/fastrpc.c +++ b/libhexagonrpc/fastrpc.c @@ -250,3 +250,221 @@ int fastrpc2(const struct fastrpc_function_def_interp2 *def, return ret; } + +/* + * This populates relevant arguments with information necessary to receive + * output from the remote processor. + * + * First, it allocates a new first output buffer to contain the returned 32-bit + * integers. This output buffer must be freed after use. + * + * With a peek at the output arguments, it populates the fastrpc_invoke_args + * struct to give information about the provided buffers to the kernel, and + * adds an entry to the first input buffer to tell the remote processor the + * size of the function-level output buffer. + */ +static void prepare_outbufs3(const struct hrpc_method_def_interp3 *def, + struct fastrpc_invoke_args *args, + size_t delim, + uint32_t *n_prim_in, uint8_t *n_outbufs, + uint32_t *prim, + va_list peek) +{ + uint32_t n_prim_out = 0; + size_t i; + + if (def->has_prim_out) + *n_outbufs = 1; + else + *n_outbufs = 0; + + for (i = delim; i < def->n_args; i++) { + if (def->args[i]) { + prim[*n_prim_in] = va_arg(peek, uint32_t); + + args[*n_outbufs].length = prim[*n_prim_in] * def->args[i]; + args[*n_outbufs].ptr = (__u64) va_arg(peek, void *); + args[*n_outbufs].fd = -1; + + (*n_prim_in)++; + (*n_outbufs)++; + } else { + va_arg(peek, uint32_t *); + n_prim_out++; + } + } + + if (def->has_prim_out) { + args[0].length = sizeof(uint32_t) * n_prim_out; + args[0].ptr = (__u64) &prim[*n_prim_in]; + args[0].fd = -1; + } +} + +static void return_prim_out(const struct hrpc_method_def_interp3 *def, + size_t delim, + const uint32_t *prim_out, + va_list list) +{ + uint32_t *ptr; + size_t i, j = 0; + + for (i = delim; i < def->n_args; i++) { + if (def->args[i]) { + va_arg(list, uint32_t); + va_arg(list, void *); + } else { + ptr = va_arg(list, uint32_t *); + *ptr = prim_out[j]; + j++; + } + } +} + +/* + * This is the main function to invoke a FastRPC procedure call. The first + * parameter specifies how to populate the ioctl-level buffers. The second and + * third parameters specify where to send the invocation to. The fourth is the + * list of arguments that the procedure call should interact with. + * + * A good example for this would be the adsp_listener_next2 call: + * + * static inline void adsp_listener_next2(int fd, uint32_t handle, + * uint32_t prev_ctx, + * uint32_t prev_result, + * uint32_t nested_outbufs_len, + * void *nested_outbufs, + * uint32_t *ctx, + * uint32_t *nested_handle, + * uint32_t *nested_sc, + * uint32_t *nested_inbufs_len, + * uint32_t nested_inbufs_size, + * void *nested_inbufs) + * { + * uint32_t args[] = { 0, 0, 1, HEXAGONRPC_DELIMITER, 0, 0, 0, 1 }; + * struct hrpc_method_def_interp3 def = { + * .mid = 4, + * .has_out_prim = true, + * .n_args = 8, + * .args = args, + * }; + * return vhexagonrpc2(def, fd, handle, + * prev_ctx, + * prev_result, + * nested_outbufs_len, + * nested_outbufs, + * ctx, + * nested_handle, + * nested_sc, + * nested_inbufs_len, + * nested_inbufs_size, + * nested_inbufs); + * } + */ +int vhexagonrpc2(const struct hrpc_method_def_interp3 *def, + int fd, uint32_t handle, va_list list) +{ + va_list peek; + struct fastrpc_invoke invoke; + struct fastrpc_invoke_args *args; + uint32_t *prim; + uint32_t n_prim_in = 0; + uint32_t msg_id; + uint8_t n_inbufs = 1, n_outbufs; + size_t i; + int ret = -1; + + /* + * If there are only input buffers specified in the method definition, + * we need an extra primary input argument for their sizes. + */ + args = malloc(sizeof(struct fastrpc_invoke_args) * (def->n_args + 1)); + if (args == NULL) + return -1; + + /* + * The input and output buffers need a size in the primary input buffer + * so all arguments except the optional delimiter contribute to the + * primary buffers. + */ + prim = malloc(sizeof(uint32_t) * (def->n_args + 1)); + if (prim == NULL) + goto err_free_args; + + /* + * The apps_std interface demonstrates that there is support + * for more than 32 methods for a single interface. Support + * extended method IDs that go beyond 5 bits and the ID + * reserved for this purpose. + */ + if (def->msg_id >= 31) { + prim[n_prim_in] = def->msg_id; + n_prim_in++; + msg_id = 31; + } else { + msg_id = def->msg_id; + } + + for (i = 0; i < def->n_args; i++) { + if (def->args[i] == HEXAGONRPC_DELIMITER) { + i++; + break; + } + + prim[n_prim_in] = va_arg(list, uint32_t); + + if (def->args[i]) { + args[n_inbufs].length = prim[n_prim_in] * def->args[i]; + args[n_inbufs].ptr = (__u64) va_arg(list, const void *); + args[n_inbufs].fd = -1; + n_inbufs++; + } + + n_prim_in++; + } + + va_copy(peek, list); + prepare_outbufs3(def, &args[n_inbufs], i, &n_prim_in, &n_outbufs, prim, peek); + va_end(peek); + + args[0].length = sizeof(uint32_t) * n_prim_in; + args[0].ptr = (__u64) prim; + args[0].fd = -1; + + // Pass the primary input buffer if not empty, otherwise skip it. + if (n_prim_in != 0) { + invoke.args = (__u64) args; + } else { + invoke.args = (__u64) &args[1]; + n_inbufs--; + } + + invoke.handle = handle; + invoke.sc = REMOTE_SCALARS_MAKE(msg_id, n_inbufs, n_outbufs); + + ret = ioctl(fd, FASTRPC_IOCTL_INVOKE, (__u64) &invoke); + if (ret == -1) + goto err_free_prim; + + return_prim_out(def, i, &prim[n_prim_in], list); + +err_free_prim: + free(prim); +err_free_args: + free(args); + + return ret; +} + +int hexagonrpc2(const struct hrpc_method_def_interp3 *def, + int fd, uint32_t handle, ...) +{ + va_list list; + int ret; + + va_start(list, handle); + ret = vhexagonrpc2(def, fd, handle, list); + va_end(list); + + return ret; +} diff --git a/libhexagonrpc/meson.build b/libhexagonrpc/meson.build index 922088c..0150540 100644 --- a/libhexagonrpc/meson.build +++ b/libhexagonrpc/meson.build @@ -1,5 +1,6 @@ libhexagonrpc = shared_library('hexagonrpc', 'context.c', + 'error.c', 'fastrpc.c', 'interfaces.c', 'session.c',