From 09add3eecce39ef4ba094c1eea4581c034eca669 Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Wed, 16 Oct 2024 19:43:41 -0400 Subject: [PATCH 1/7] fastrpc: libhexagonrpc: add interpretation three of method call format The method call format as interpreted last time had some limitations. First, input words could not appear after the input buffers, making it impossible to represent the apps_std_mkdir method accurately. Second, it was assumed that the lengths in the primary input buffer represent the number of bytes. In reality, the lengths represent the number of elements, which just happened to be octets in the majority of remote methods found, and the adsp_perf_get_usecs remote method could not be represented. Update the format for the third time to remove these limitations. This format allows the mixing of words and lengths of other buffers in the primary buffer by using 0 to denote words in an array of arguments. It also allows a greater size of elements, denoted by any non-zero value. --- include/libhexagonrpc/fastrpc.h | 20 +++ include/libhexagonrpc/interface.h | 23 ++++ libhexagonrpc/context.c | 18 +++ libhexagonrpc/fastrpc.c | 218 ++++++++++++++++++++++++++++++ 4 files changed, 279 insertions(+) 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/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/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; +} From 916db473b47a78b72c63b3c94add9d73ab28f56d Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Wed, 16 Oct 2024 19:44:52 -0400 Subject: [PATCH 2/7] fastrpc: libhexagonrpc: interfaces: remotectl: add interp3 definitions Add the remote method definitions according to the 3rd format version. --- .../libhexagonrpc/interfaces/remotectl.def | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) 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 */ From 13c14c1611400f8cfe488ee42b26b4a07d966612 Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Wed, 16 Oct 2024 19:47:00 -0400 Subject: [PATCH 3/7] fastrpc: libhexagonrpc: add error API When the kernel side of FastRPC fails, the return value is -1 and errno is set. When the remote side of FastRPC fails, the return value is an AEE error code. It is not specialized for the reverse tunnel. Add an error API that can convert the return value to a string-based error. --- hexagonrpcd/apps_std.c | 2 +- hexagonrpcd/listener.c | 2 +- hexagonrpcd/localctl.c | 2 +- hexagonrpcd/meson.build | 1 - hexagonrpcd/rpcd.c | 17 +++++++---------- .../libhexagonrpc/error.h | 3 ++- .../aee_error.c => libhexagonrpc/error.c | 16 +++++++++++++++- libhexagonrpc/meson.build | 1 + 8 files changed, 28 insertions(+), 16 deletions(-) rename hexagonrpcd/aee_error.h => include/libhexagonrpc/error.h (96%) rename hexagonrpcd/aee_error.c => libhexagonrpc/error.c (89%) diff --git a/hexagonrpcd/apps_std.c b/hexagonrpcd/apps_std.c index 6728f1e..8ecd1aa 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" diff --git a/hexagonrpcd/listener.c b/hexagonrpcd/listener.c index 9de0a16..1860554 100644 --- a/hexagonrpcd/listener.c +++ b/hexagonrpcd/listener.c @@ -20,12 +20,12 @@ */ #include +#include #include #include #include #include -#include "aee_error.h" #include "interfaces/adsp_listener.def" #include "iobuffer.h" #include "listener.h" diff --git a/hexagonrpcd/localctl.c b/hexagonrpcd/localctl.c index 3eaef88..df01e31 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" 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..2cd7e2b 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; } 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/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/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', From eee667b6ccd5eb37551e441031e3cf1265dafe4e Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Wed, 16 Oct 2024 19:47:21 -0400 Subject: [PATCH 4/7] fastrpc: hexagonrpcd: interfaces: convert to interp3 Add the remote method definitions for interfaces used by HexagonRPCD according to the 3rd format version. --- .../interfaces/adsp_default_listener.def | 7 + hexagonrpcd/interfaces/adsp_listener.def | 25 +++ hexagonrpcd/interfaces/apps_std.def | 158 ++++++++++++++++++ 3 files changed, 190 insertions(+) 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 */ From b15e7216602c4233c6d00e8afd864c8147937e6d Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Wed, 16 Oct 2024 19:48:12 -0400 Subject: [PATCH 5/7] fastrpc: chrecd: interfaces: convert to interp3 Add the remote method definitions for the CHRE interface according to the 3rd format version. --- chrecd/interfaces/chre_slpi.def | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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 */ From 64bff607fef5a9ad60a3f697a1707e03395f20ae Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Wed, 16 Oct 2024 19:50:31 -0400 Subject: [PATCH 6/7] fastrpc: hexagonrpcd: use interface-defined inline functions The inline functions are convenient, but shouldn't be defined in every source file that uses them. Use the new functions defined in the interface definitions. --- hexagonrpcd/listener.c | 30 ++---------------------------- hexagonrpcd/rpcd.c | 7 +------ 2 files changed, 3 insertions(+), 34 deletions(-) diff --git a/hexagonrpcd/listener.c b/hexagonrpcd/listener.c index 1860554..eb6cdf7 100644 --- a/hexagonrpcd/listener.c +++ b/hexagonrpcd/listener.c @@ -30,32 +30,6 @@ #include "iobuffer.h" #include "listener.h" -static int adsp_listener_init2(int fd) -{ - return fastrpc2(&adsp_listener_init2_def, fd, ADSP_LISTENER_HANDLE); -} - -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); -} - static struct fastrpc_io_buffer *allocate_outbufs(const struct fastrpc_function_def_interp2 *def, uint32_t *first_inbuf) { @@ -160,7 +134,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, @@ -290,7 +264,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/rpcd.c b/hexagonrpcd/rpcd.c index 2cd7e2b..62948c3 100644 --- a/hexagonrpcd/rpcd.c +++ b/hexagonrpcd/rpcd.c @@ -94,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); @@ -113,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; From 92237debf15f9d6fec20ea210fe6a2d279da8437 Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Wed, 16 Oct 2024 19:52:40 -0400 Subject: [PATCH 7/7] fastrpc: hexagonrpcd: listener: switch to interp3 For a proper transition to version 3 of the method definitions, switch the reverse tunnel to version 3. --- hexagonrpcd/apps_std.c | 18 ++-- hexagonrpcd/listener.c | 195 ++++++++++++++++++++++++++--------------- hexagonrpcd/listener.h | 2 +- hexagonrpcd/localctl.c | 10 ++- 4 files changed, 140 insertions(+), 85 deletions(-) diff --git a/hexagonrpcd/apps_std.c b/hexagonrpcd/apps_std.c index 8ecd1aa..ba6fc03 100644 --- a/hexagonrpcd/apps_std.c +++ b/hexagonrpcd/apps_std.c @@ -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/listener.c b/hexagonrpcd/listener.c index eb6cdf7..aa7dfef 100644 --- a/hexagonrpcd/listener.c +++ b/hexagonrpcd/listener.c @@ -24,87 +24,142 @@ #include #include #include +#include #include #include "interfaces/adsp_listener.def" #include "iobuffer.h" #include "listener.h" -static struct fastrpc_io_buffer *allocate_outbufs(const struct fastrpc_function_def_interp2 *def, - uint32_t *first_inbuf) +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) { - 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; + 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; - out = malloc(sizeof(struct fastrpc_io_buffer) * out_count); - if (out == NULL) - return NULL; + if (!def->args[i]) + continue; + + /* + * 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[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; + 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; + } + + 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++; + + if (def->has_prim_out) + n_def_outbufs = 1; + else + n_def_outbufs = 0; - 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; + 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, @@ -189,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); @@ -221,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; 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 df01e31..86e910f 100644 --- a/hexagonrpcd/localctl.c +++ b/hexagonrpcd/localctl.c @@ -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 = {