You've already forked hexagonrpc
mirror of
https://github.com/linux-msm/hexagonrpc.git
synced 2026-02-25 13:13:52 -08:00
When loading a new skel file, the DSP may access a testsig.so file. This calls apps_std_fopen_with_env which is relative to a specified directory, but also apps_std_stat. Since the same "testsig.so" path is accessed relative to ADSP_LIBRARY_PATH and to the current working directory, infer that the current working directory should be ADSP_LIBRARY_PATH.
474 lines
11 KiB
C
474 lines
11 KiB
C
/*
|
|
* FastRPC operating system interface implementation
|
|
*
|
|
* Copyright (C) 2023 The Sensor Shell Contributors
|
|
*
|
|
* This file is part of sensh.
|
|
*
|
|
* Sensh is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
#include "aee_error.h"
|
|
#include "interfaces/apps_std.def"
|
|
#include "hexagonfs.h"
|
|
#include "iobuffer.h"
|
|
#include "listener.h"
|
|
|
|
struct apps_std_ctx {
|
|
int rootfd;
|
|
int adsp_avs_cfg_dirfd;
|
|
int adsp_library_dirfd;
|
|
struct hexagonfs_fd *fds[HEXAGONFS_MAX_FD];
|
|
};
|
|
|
|
static const int apps_std_whence_table[] = {
|
|
SEEK_SET,
|
|
SEEK_CUR,
|
|
SEEK_END,
|
|
};
|
|
|
|
/*
|
|
* This is a placeholder function used to complete any I/O operations.
|
|
* File descriptors do not have a flush operation because their reads and
|
|
* writes are blocking.
|
|
*/
|
|
static uint32_t apps_std_fflush(void *data,
|
|
const struct fastrpc_io_buffer *inbufs,
|
|
struct fastrpc_io_buffer *outbufs)
|
|
{
|
|
#ifdef HEXAGONRPC_VERBOSE
|
|
uint32_t *fd = inbufs[0].p;
|
|
|
|
printf("ignore fflush(%u)\n", *fd);
|
|
#endif
|
|
|
|
memset(outbufs[0].p, 0, outbufs[0].s);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t apps_std_fclose(void *data,
|
|
const struct fastrpc_io_buffer *inbufs,
|
|
struct fastrpc_io_buffer *outbufs)
|
|
{
|
|
struct apps_std_ctx *ctx = data;
|
|
const uint32_t *first_in = inbufs[0].p;
|
|
int ret;
|
|
|
|
ret = hexagonfs_close(ctx->fds, *first_in);
|
|
if (ret) {
|
|
fprintf(stderr, "Could not close: %s\n", strerror(-ret));
|
|
return AEE_EFAILED;
|
|
}
|
|
|
|
#ifdef HEXAGONRPC_VERBOSE
|
|
printf("close(%u)\n", *first_in);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t apps_std_fread(void *data,
|
|
const struct fastrpc_io_buffer *inbufs,
|
|
struct fastrpc_io_buffer *outbufs)
|
|
{
|
|
struct apps_std_ctx *ctx = data;
|
|
const struct {
|
|
uint32_t fd;
|
|
uint32_t buf_size;
|
|
} *first_in = inbufs[0].p;
|
|
struct {
|
|
uint32_t written;
|
|
uint32_t is_eof;
|
|
} *first_out = outbufs[0].p;
|
|
ssize_t ret;
|
|
|
|
ret = hexagonfs_read(ctx->fds, first_in->fd,
|
|
first_in->buf_size, outbufs[1].p);
|
|
if (ret < 0) {
|
|
fprintf(stderr, "Could not read file: %s\n", strerror(-ret));
|
|
return AEE_EFAILED;
|
|
}
|
|
|
|
#ifdef HEXAGONRPC_VERBOSE
|
|
printf("read(%u, %u) -> %ld\n", first_in->fd,
|
|
first_in->buf_size,
|
|
ret);
|
|
#endif
|
|
|
|
first_out->written = ret;
|
|
first_out->is_eof = first_out->written < first_in->buf_size;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t apps_std_fseek(void *data,
|
|
const struct fastrpc_io_buffer *inbufs,
|
|
struct fastrpc_io_buffer *outbufs)
|
|
{
|
|
struct apps_std_ctx *ctx = data;
|
|
const struct {
|
|
uint32_t fd;
|
|
uint32_t pos;
|
|
uint32_t whence;
|
|
} *first_in = inbufs[0].p;
|
|
int ret;
|
|
int whence;
|
|
|
|
whence = apps_std_whence_table[first_in->whence];
|
|
|
|
ret = hexagonfs_lseek(ctx->fds, first_in->fd, first_in->pos, whence);
|
|
if (ret) {
|
|
fprintf(stderr, "Could not seek stream: %s\n", strerror(-ret));
|
|
return AEE_EFAILED;
|
|
}
|
|
|
|
#ifdef HEXAGONRPC_VERBOSE
|
|
printf("lseek(%u, %d, %d)\n", first_in->fd,
|
|
first_in->pos,
|
|
first_in->whence);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t apps_std_fopen_with_env(void *data,
|
|
const struct fastrpc_io_buffer *inbufs,
|
|
struct fastrpc_io_buffer *outbufs)
|
|
{
|
|
struct apps_std_ctx *ctx = data;
|
|
uint32_t *out = outbufs[0].p;
|
|
char rw_mode;
|
|
int dirfd, fd;
|
|
|
|
// The name and environment variable must also be NULL-terminated
|
|
if (((const char *) inbufs[1].p)[inbufs[1].s - 1] != 0
|
|
|| ((const char *) inbufs[3].p)[inbufs[3].s - 1] != 0
|
|
|| ((const char *) inbufs[4].p)[inbufs[4].s - 1] != 0)
|
|
return AEE_EBADPARM;
|
|
|
|
rw_mode = ((const char *) inbufs[4].p)[0];
|
|
if (rw_mode == 'w' || rw_mode == 'a') {
|
|
fprintf(stderr, "Tried to open %s for writing\n",
|
|
(const char *) inbufs[3].p);
|
|
return AEE_EUNSUPPORTED;
|
|
}
|
|
|
|
if (!strcmp(inbufs[1].p, "ADSP_LIBRARY_PATH")) {
|
|
dirfd = ctx->adsp_library_dirfd;
|
|
} else if (!strcmp(inbufs[1].p, "ADSP_AVS_CFG_PATH")) {
|
|
dirfd = ctx->adsp_avs_cfg_dirfd;
|
|
} else {
|
|
fprintf(stderr, "Unknown search directory %s\n",
|
|
(const char *) inbufs[1].p);
|
|
return AEE_EBADPARM;
|
|
}
|
|
|
|
if (dirfd < 0) {
|
|
fprintf(stderr, "Could not open virtual %s: %s\n",
|
|
(const char *) inbufs[1].p, strerror(-dirfd));
|
|
return AEE_EFAILED;
|
|
}
|
|
|
|
fd = hexagonfs_openat(ctx->fds, ctx->rootfd, dirfd, inbufs[3].p);
|
|
if (fd < 0) {
|
|
fprintf(stderr, "Could not open %s: %s\n",
|
|
(const char *) inbufs[3].p,
|
|
strerror(errno));
|
|
return AEE_EFAILED;
|
|
}
|
|
|
|
#ifdef HEXAGONRPC_VERBOSE
|
|
printf("openat($%s, %s) -> %d\n", (const char *) inbufs[1].p,
|
|
(const char *) inbufs[3].p,
|
|
fd);
|
|
#endif
|
|
|
|
*out = fd;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t apps_std_opendir(void *data,
|
|
const struct fastrpc_io_buffer *inbufs,
|
|
struct fastrpc_io_buffer *outbufs)
|
|
{
|
|
struct apps_std_ctx *ctx = data;
|
|
uint64_t *dir_out = outbufs[0].p;
|
|
int ret;
|
|
|
|
// The name must be NULL-terminated
|
|
if (((const char *) inbufs[1].p)[inbufs[1].s - 1] != 0)
|
|
return AEE_EBADPARM;
|
|
|
|
ret = hexagonfs_openat(ctx->fds, ctx->rootfd, ctx->rootfd, inbufs[1].p);
|
|
if (ret < 0) {
|
|
fprintf(stderr, "Could not open %s: %s\n",
|
|
(const char *) inbufs[1].p,
|
|
strerror(-ret));
|
|
return AEE_EFAILED;
|
|
}
|
|
|
|
#ifdef HEXAGONRPC_VERBOSE
|
|
printf("opendir(%s) -> %d\n", (const char *) inbufs[1].p, ret);
|
|
#endif
|
|
|
|
*dir_out = ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t apps_std_closedir(void *data,
|
|
const struct fastrpc_io_buffer *inbufs,
|
|
struct fastrpc_io_buffer *outbufs)
|
|
{
|
|
struct apps_std_ctx *ctx = data;
|
|
const uint64_t *dir = inbufs[0].p;
|
|
int ret;
|
|
|
|
ret = hexagonfs_close(ctx->fds, *dir);
|
|
if (ret)
|
|
return AEE_EFAILED;
|
|
|
|
#ifdef HEXAGONRPC_VERBOSE
|
|
printf("closedir(%ld)\n", *dir);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t apps_std_readdir(void *data,
|
|
const struct fastrpc_io_buffer *inbufs,
|
|
struct fastrpc_io_buffer *outbufs)
|
|
{
|
|
struct apps_std_ctx *ctx = data;
|
|
const uint64_t *dir = inbufs[0].p;
|
|
struct {
|
|
uint32_t inode;
|
|
char name[255];
|
|
uint32_t is_eof;
|
|
} *first_out = outbufs[0].p;
|
|
int ret;
|
|
|
|
ret = hexagonfs_readdir(ctx->fds, *dir, 255, first_out->name);
|
|
if (ret < 0) {
|
|
fprintf(stderr, "Could not read from directory: %s\n",
|
|
strerror(-ret));
|
|
return AEE_EFAILED;
|
|
}
|
|
|
|
#ifdef HEXAGONRPC_VERBOSE
|
|
printf("readdir(%ld) -> %s\n", *dir, first_out->name);
|
|
#endif
|
|
|
|
first_out->inode = 0;
|
|
first_out->is_eof = (*first_out->name == '\0');
|
|
|
|
return 0;
|
|
}
|
|
|
|
static uint32_t apps_std_stat(void *data,
|
|
const struct fastrpc_io_buffer *inbufs,
|
|
struct fastrpc_io_buffer *outbufs)
|
|
{
|
|
struct apps_std_ctx *ctx = data;
|
|
struct {
|
|
uint64_t tsz; // Unknown purpose
|
|
uint64_t dev;
|
|
uint64_t ino;
|
|
uint32_t mode;
|
|
uint32_t nlink;
|
|
uint64_t rdev;
|
|
uint64_t size;
|
|
int64_t atime;
|
|
int64_t atimensec;
|
|
int64_t mtime;
|
|
int64_t mtimensec;
|
|
int64_t ctime;
|
|
int64_t ctimensec;
|
|
} *first_out = outbufs[0].p;
|
|
const char *pathname = inbufs[1].p;
|
|
struct stat stats;
|
|
int fd, ret;
|
|
|
|
if (((const char *) inbufs[1].p)[inbufs[1].s - 1] != 0)
|
|
return AEE_EBADPARM;
|
|
|
|
fd = hexagonfs_openat(ctx->fds, ctx->rootfd, ctx->adsp_library_dirfd, pathname);
|
|
if (fd < 0) {
|
|
fprintf(stderr, "Could not open %s: %s\n",
|
|
pathname, strerror(-fd));
|
|
return AEE_EFAILED;
|
|
}
|
|
|
|
ret = hexagonfs_fstat(ctx->fds, fd, &stats);
|
|
if (ret) {
|
|
fprintf(stderr, "Could not stat %s: %s\n",
|
|
pathname, strerror(-fd));
|
|
return AEE_EFAILED;
|
|
}
|
|
|
|
hexagonfs_close(ctx->fds, fd);
|
|
|
|
#ifdef HEXAGONRPC_VERBOSE
|
|
printf("stat(%s)\n", pathname);
|
|
#endif
|
|
|
|
first_out->tsz = 0;
|
|
|
|
first_out->dev = stats.st_dev;
|
|
first_out->ino = stats.st_ino;
|
|
first_out->mode = stats.st_mode;
|
|
first_out->nlink = stats.st_nlink;
|
|
first_out->rdev = stats.st_rdev;
|
|
first_out->size = stats.st_size;
|
|
first_out->atime = (int64_t) stats.st_atim.tv_sec;
|
|
first_out->atimensec = (int64_t) stats.st_atim.tv_nsec;
|
|
first_out->mtime = (int64_t) stats.st_mtim.tv_sec;
|
|
first_out->mtimensec = (int64_t) stats.st_mtim.tv_nsec;
|
|
first_out->ctime = (int64_t) stats.st_ctim.tv_nsec;
|
|
first_out->ctimensec = (int64_t) stats.st_ctim.tv_nsec;
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct fastrpc_interface *fastrpc_apps_std_init(struct hexagonfs_dirent *root)
|
|
{
|
|
struct fastrpc_interface *iface;
|
|
struct apps_std_ctx *ctx;
|
|
|
|
iface = malloc(sizeof(struct fastrpc_interface));
|
|
if (iface == NULL)
|
|
return NULL;
|
|
|
|
ctx = calloc(1, sizeof(struct apps_std_ctx));
|
|
if (ctx == NULL)
|
|
goto err_free_iface;
|
|
|
|
memcpy(iface, &apps_std_interface, sizeof(struct fastrpc_interface));
|
|
|
|
ctx->rootfd = hexagonfs_open_root(ctx->fds, root);
|
|
if (ctx->rootfd < 0)
|
|
goto err_free_ctx;
|
|
|
|
ctx->adsp_avs_cfg_dirfd = hexagonfs_openat(ctx->fds,
|
|
ctx->rootfd,
|
|
ctx->rootfd,
|
|
"/vendor/etc/acdbdata/");
|
|
ctx->adsp_library_dirfd = hexagonfs_openat(ctx->fds,
|
|
ctx->rootfd,
|
|
ctx->rootfd,
|
|
"/usr/lib/qcom/adsp/");
|
|
|
|
iface->data = ctx;
|
|
|
|
return iface;
|
|
|
|
err_free_ctx:
|
|
free(ctx);
|
|
err_free_iface:
|
|
free(iface);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void fastrpc_apps_std_deinit(struct fastrpc_interface *iface)
|
|
{
|
|
struct apps_std_ctx *ctx = iface->data;
|
|
int i;
|
|
|
|
for (i = 0; i < HEXAGONFS_MAX_FD; i++) {
|
|
if (ctx->fds[i] != NULL)
|
|
hexagonfs_close(ctx->fds, i);
|
|
}
|
|
|
|
free(iface->data);
|
|
free(iface);
|
|
}
|
|
|
|
static const struct fastrpc_function_impl apps_std_procs[] = {
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{
|
|
.def = &apps_std_fflush_def,
|
|
.impl = apps_std_fflush,
|
|
},
|
|
{
|
|
.def = &apps_std_fclose_def,
|
|
.impl = apps_std_fclose,
|
|
},
|
|
{
|
|
.def = &apps_std_fread_def,
|
|
.impl = apps_std_fread,
|
|
},
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{
|
|
.def = &apps_std_fseek_def,
|
|
.impl = apps_std_fseek,
|
|
},
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{
|
|
.def = &apps_std_fopen_with_env_def,
|
|
.impl = apps_std_fopen_with_env,
|
|
},
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{
|
|
.def = &apps_std_opendir_def,
|
|
.impl = apps_std_opendir,
|
|
},
|
|
{
|
|
.def = &apps_std_closedir_def,
|
|
.impl = apps_std_closedir,
|
|
},
|
|
{
|
|
.def = &apps_std_readdir_def,
|
|
.impl = apps_std_readdir,
|
|
},
|
|
{ .def = NULL, .impl = NULL, },
|
|
{ .def = NULL, .impl = NULL, },
|
|
{
|
|
.def = &apps_std_stat_def,
|
|
.impl = apps_std_stat,
|
|
},
|
|
};
|
|
|
|
const struct fastrpc_interface apps_std_interface = {
|
|
.name = "apps_std",
|
|
.n_procs = 32,
|
|
.procs = apps_std_procs,
|
|
};
|