12 Commits
Author SHA1 Message Date
Joel Selvaraj b7eff23db1 hexagonrpcd/rpcd_builder: introduce /system/vendor mapping
Needed for some Xiaomi phones such as the Poco F1.
Based on https://gitlab.com/sdm670-mainline/hexagonrpc/-/merge_requests/1.
Thanks to the initial work of @longnoserob in the above MR!
2024-05-14 02:03:35 -05:00
Joel Selvaraj 716e1e27c7 README: add socinfo sysfs mapping to HexagonFS table
Introduced in https://gitlab.com/sdm670-mainline/hexagonrpc/-/merge_requests/2.
2024-05-14 02:03:35 -05:00
Joel Selvaraj 54ba43fbc3 hexagonrpcd/rpcd_builder: add mapping for socinfo sysfs
Needed for some Xiaomi phones such as Poco F1.
Based on https://gitlab.com/sdm670-mainline/hexagonrpc/-/merge_requests/1.
Thanks to the initial findings of @longnoserob in the above MR!
2024-05-14 01:49:46 -05:00
Richard Acayan f6d8a0e686 tests: add initial hexagonfs test
The virtual filesystem is important, but is only tested in the full
program. Add the initial test for it.
2024-04-26 17:50:58 -04:00
Richard Acayan 9db873f24f hexagonrpcd: hexagonfs: constify dirent data
The data in the directory entry structure is meant to be used in opening
a file. It should not change during the program.

For the virtual directory, the pointer to constant data must be wrapped
because the data for the open file is not constant.
2024-04-17 17:03:07 -04:00
Richard Acayan 3f46980dc9 hexagonrpcd: correct -d default in help text
The name of the DSP defaults to none, but the -d option is wrongly
documented as having a default of "adsp". Correct this in the help text.
2024-04-15 18:35:46 -04:00
Richard Acayan 30fa49eb20 build: add hexagonrpcd_verbose option
There is extra debug logging in the code which can be activated by
`meson configure build -Dc_args=-DHEXAGONRPC_VERBOSE`. This may be
difficult to trigger, since it requires -D twice in the same argument.
Add the hexagonrpcd_verbose option to make it easier to configure the
extra logging.

This can be activated with `-Dhexagonrpcd_verbose=true` and deactivated
with `-Dhexagonrpcd_verbose=false`.
2024-04-11 17:59:03 -04:00
Richard Acayan b7ad1021a2 build: apply default C flags to all targets
The warning flags should be applied to the entire C codebase in order to
help ensure correct code. No extra warnings are emitted by doing this.
2024-04-11 17:45:47 -04:00
Richard Acayan f23297f962 tests: set warning flags
Most subdirectories in this project have all, pedantic, and some extra
warnings enabled. Set this for tests as well, as there is no real
justification otherwise.
2024-04-09 19:18:44 -04:00
Richard Acayan c4c469bd8a tests: iobuffer: convert binary data to unsigned char arrays
Signed character arrays can overflow when specifying values greater than
127. The actual data is not affected, but this can cause compiler
warnings. Use unsigned character arrays so the compiler does not
complain about overflows.
2024-04-09 19:16:04 -04:00
Richard Acayan 6840e1dcfa tests: iobuffer: exit with code 0 on success
This file seems to implicitly return 0 when everything is successful,
but this is unclear when reading it. Explicitly return zero when all
tests are successful.
2024-04-09 19:10:30 -04:00
Richard Acayan aaef8a1e28 hexagonrpcd: use the dsp directory as the default for libraries
This variable represents the subdirectory in the dsp/ directory where
libraries should be searched. This is the argument to the optional `-d`
and is used when creating the filesystem. Initialize it to an empty
string so HexagonFS searches in /usr/share/qcom/dsp/ by default.
2024-04-09 17:05:21 -04:00
16 changed files with 289 additions and 43 deletions

No files matched your search

+1
View File
@@ -133,6 +133,7 @@ These files are searched for in:
/usr/share/qcom/sensors/config /vendor/etc/sensors/config
/usr/share/qcom/sensors/registry /mnt/vendor/persist/sensors/registry/registry
/usr/share/qcom/sensors/sns_reg.conf /vendor/etc/sensors/sns_reg_config
/usr/share/qcom/socinfo /sys/devices/soc0
These files and directories should be populated with files from your device's
Android firmware.
+1 -1
View File
@@ -1,7 +1,7 @@
executable('chrecd',
'interfaces.c',
'main.c',
c_args : ['-Wall', '-Wextra', '-Wpedantic'],
c_args : cflags,
include_directories : include,
install : true,
link_with : libhexagonrpc,
+1 -1
View File
@@ -33,7 +33,7 @@ struct hexagonfs_fd;
struct hexagonfs_file_ops {
void (*close)(void *fd_data);
int (*from_dirent)(void *dirent_data, bool dir, void **fd_data);
int (*from_dirent)(const void *dirent_data, bool dir, void **fd_data);
int (*openat)(struct hexagonfs_fd *dir,
const char *segment,
bool expect_dir,
+2 -2
View File
@@ -47,7 +47,7 @@ static void mapped_close(void *fd_data)
free(ctx);
}
static int mapped_from_dirent(void *dirent_data, bool dir, void **fd_data)
static int mapped_from_dirent(const void *dirent_data, bool dir, void **fd_data)
{
struct mapped_ctx *ctx;
const char *name = dirent_data;
@@ -222,7 +222,7 @@ static void mapped_or_empty_close(void *fd_data)
mapped_close(fd_data);
}
static int mapped_or_empty_from_dirent(void *dirent_data, bool dir, void **fd_data)
static int mapped_or_empty_from_dirent(const void *dirent_data, bool dir, void **fd_data)
{
int ret;
+2 -2
View File
@@ -41,7 +41,7 @@ static void plat_subtype_name_close(void *fd_data)
free(ctx->name);
}
static int plat_subtype_name_from_dirent(void *dirent_data,
static int plat_subtype_name_from_dirent(const void *dirent_data,
bool dir,
void **fd_data)
{
@@ -54,7 +54,7 @@ static int plat_subtype_name_from_dirent(void *dirent_data,
if (ctx == NULL)
return -ENOMEM;
ctx->fd = open((const char *) dirent_data, O_RDONLY);
ctx->fd = open(dirent_data, O_RDONLY);
if (ctx->fd == -1)
return -errno;
+16 -7
View File
@@ -31,10 +31,10 @@
* This function searches for the relevant path segment in the path directory.
* It is not optimized because it is dealing with small directories.
*/
static struct hexagonfs_dirent *walk_dir(struct hexagonfs_dirent **dir,
static const struct hexagonfs_dirent *walk_dir(const struct hexagonfs_dirent *const *dir,
const char *segment)
{
struct hexagonfs_dirent **curr = dir;
const struct hexagonfs_dirent *const *curr = dir;
while (*curr != NULL) {
if (!strcmp(segment, (*curr)->name))
@@ -46,9 +46,17 @@ static struct hexagonfs_dirent *walk_dir(struct hexagonfs_dirent **dir,
return *curr;
}
static int virt_dir_from_dirent(void *dirent_data, bool dir, void **fd_data)
static int virt_dir_from_dirent(const void *dirent_data, bool dir, void **fd_data)
{
*fd_data = dirent_data;
const struct hexagonfs_dirent *const **wrapper;
wrapper = malloc(sizeof(*wrapper));
if (wrapper == NULL)
return -ENOMEM;
*wrapper = dirent_data;
*fd_data = wrapper;
return 0;
}
@@ -57,12 +65,12 @@ static int virt_dir_openat(struct hexagonfs_fd *dir,
bool expect_dir,
struct hexagonfs_fd **out)
{
const struct hexagonfs_dirent *const **dirlist = dir->data;
const struct hexagonfs_dirent *ent;
struct hexagonfs_fd *fd;
struct hexagonfs_dirent *ent;
struct hexagonfs_dirent **dirlist = dir->data;
int ret;
ent = walk_dir(dirlist, segment);
ent = walk_dir(*dirlist, segment);
if (ent == NULL)
return -ENOENT;
@@ -89,6 +97,7 @@ err:
static void virt_dir_close(void *fd_data)
{
free(fd_data);
}
static int virt_dir_stat(struct hexagonfs_fd *fd, struct stat *stats)
+1 -1
View File
@@ -11,7 +11,7 @@ executable('hexagonrpcd',
'localctl.c',
'rpcd.c',
'rpcd_builder.c',
c_args : ['-Wall', '-Wextra', '-Wpedantic', '-Wno-unused-parameter'],
c_args : cflags,
include_directories : include,
install : true,
link_with : libhexagonrpc,
+2 -2
View File
@@ -132,7 +132,7 @@ static void print_usage(const char *argv0)
printf("Usage: %s [options] -f DEVICE\n\n", argv0);
printf("Server for FastRPC remote procedure calls from Qualcomm DSPs\n\n"
"Options:\n"
"\t-d DSP\t\tDSP name (default: adsp)\n"
"\t-d DSP\t\tDSP name (default: "")\n"
"\t-f DEVICE\tFastRPC device node to attach to\n"
"\t-p PROGRAM\tRun client program with shared file descriptor\n"
"\t-R DIR\t\tRoot directory of served files (default: /usr/share/qcom/)\n"
@@ -237,7 +237,7 @@ int main(int argc, char* argv[])
{
char *fastrpc_node = NULL;
const char *device_dir = "/usr/share/qcom/";
const char *dsp;
const char *dsp = "";
const char **progs;
pid_t *pids;
size_t n_progs = 0;
+39 -18
View File
@@ -31,6 +31,7 @@
#define SENSORS_CONFIG "/sensors/config/"
#define SENSORS_REGISTRY "/sensors/registry/"
#define SNS_REG_CONFIG "/sensors/sns_reg.conf"
#define SYSFS_SOCINFO "/socinfo/"
static struct hexagonfs_dirent *hfs_mkdir(const char *name, size_t n_ents, ...)
{
@@ -110,9 +111,9 @@ static struct hexagonfs_dirent *hfs_map_or_empty(const char *name, const char *p
*/
struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
{
char *acdbdata, *dsp_libs, *sns_cfg, *sns_reg, *sns_reg_config;
char *acdbdata, *dsp_libs, *sns_cfg, *sns_reg, *sns_reg_config, *socinfo;
size_t n_prefix;
struct hexagonfs_dirent *persist_dir;
struct hexagonfs_dirent *persist_dir, *vendor_dir;
n_prefix = strlen(prefix);
@@ -120,6 +121,7 @@ struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
sns_cfg = malloc(n_prefix + strlen(SENSORS_CONFIG) + 1);
sns_reg = malloc(n_prefix + strlen(SENSORS_REGISTRY) + 1);
sns_reg_config = malloc(n_prefix + strlen(SNS_REG_CONFIG) + 1);
socinfo = malloc(n_prefix + strlen(SYSFS_SOCINFO) + 1);
dsp_libs = malloc(n_prefix + strlen(DSP_LIBS) + strlen(dsp) + 1);
@@ -143,6 +145,11 @@ struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
strcat(sns_reg_config, SNS_REG_CONFIG);
}
if (socinfo != NULL) {
strcpy(socinfo, prefix);
strcat(socinfo, SYSFS_SOCINFO);
}
if (dsp_libs != NULL) {
strcpy(dsp_libs, prefix);
strcat(dsp_libs, DSP_LIBS);
@@ -161,21 +168,11 @@ struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
)
);
return hfs_mkdir("/", 4,
hfs_mkdir("mnt", 1,
hfs_mkdir("vendor", 1,
persist_dir
)
),
persist_dir,
hfs_mkdir("usr", 1,
hfs_mkdir("lib", 1,
hfs_mkdir("qcom", 1,
hfs_map_or_empty("adsp", dsp_libs)
)
)
),
hfs_mkdir("vendor", 1,
/*
* Some platforms need vendor in / and some need it in /system. Form
* a hard link between both locations.
*/
vendor_dir = hfs_mkdir("vendor", 1,
hfs_mkdir("etc", 2,
hfs_mkdir("sensors", 2,
hfs_map_or_empty("config", sns_cfg),
@@ -183,6 +180,30 @@ struct hexagonfs_dirent *construct_root_dir(const char *prefix, const char *dsp)
),
hfs_map("acdbdata", acdbdata)
)
)
);
return hfs_mkdir("/", 6,
hfs_mkdir("mnt", 1,
hfs_mkdir("vendor", 1,
persist_dir
)
),
persist_dir,
hfs_mkdir("sys", 1,
hfs_mkdir("devices", 1,
hfs_map_or_empty("soc0", socinfo)
)
),
hfs_mkdir("system", 1,
vendor_dir
),
hfs_mkdir("usr", 1,
hfs_mkdir("lib", 1,
hfs_mkdir("qcom", 1,
hfs_map_or_empty("adsp", dsp_libs)
)
)
),
vendor_dir
);
}
+1
View File
@@ -3,6 +3,7 @@ libhexagonrpc = shared_library('hexagonrpc',
'fastrpc.c',
'interfaces.c',
'session.c',
c_args : cflags,
include_directories : include,
install : true
)
+6
View File
@@ -3,6 +3,12 @@ project('fastrpc', 'c')
include = include_directories('include')
client_target = get_option('libexecdir') / 'hexagonrpc'
cflags = ['-Wall', '-Wextra', '-Wpedantic', '-Wno-unused-parameter']
if get_option('hexagonrpcd_verbose')
cflags += '-DHEXAGONRPC_VERBOSE'
endif
subdir('libhexagonrpc')
subdir('hexagonrpcd')
subdir('chrecd')
+2
View File
@@ -0,0 +1,2 @@
option('hexagonrpcd_verbose', type : 'boolean', value : true,
description : 'Compile hexagonrpcd with extra logging for each remote method invocation')
+15
View File
@@ -7,7 +7,22 @@ endif
test_iobuffer = executable('test_iobuffer',
'test_iobuffer.c',
'../hexagonrpcd/iobuffer.c',
c_args : cflags,
include_directories : include,
)
sample_file = custom_target('sample_file',
input : 'sample_file.txt',
output : 'sample_file.txt',
command : ['cp', '@INPUT@', '@OUTPUT@']
)
test_hexagonfs = executable('test_hexagonfs',
'test_hexagonfs.c',
'../hexagonrpcd/hexagonfs.c',
'../hexagonrpcd/hexagonfs_mapped.c',
c_args : cflags,
include_directories : include,
)
test('iobuffer', test_iobuffer)
test('hexagonfs', test_hexagonfs, args : [sample_file])
+91
View File
@@ -0,0 +1,91 @@
/*
* FastRPC reverse tunnel - sample file for HexagonFS mapped file test
*
* Copyright (C) 2024 The HexagonRPC Contributors
*
* This file is part of HexagonRPC.
*
* HexagonRPC 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/>.
*/
#![feature(io_error_more)]
use std::collections::HashMap;
use std::io::Error;
use std::io::ErrorKind;
use std::io::Result;
use std::process::ExitCode;
trait HexagonFSFile {
fn seek(&self) -> Result<u64>;
fn read(&self) -> Result<usize>;
fn openat<'a>(&'a self, name: &str) -> Result<Box<dyn HexagonFSFile + 'a>>;
}
trait HexagonFSDirent {
fn open<'a>(&'a self) -> Box<dyn HexagonFSFile + 'a>;
}
struct VirtDir<'a> {
def: &'a VirtDirDirent<'a>,
}
impl<'a> HexagonFSFile for VirtDir<'a> {
fn seek(&self) -> Result<u64>
{
Err(Error::new(ErrorKind::IsADirectory, "Is a directory"))
}
fn read(&self) -> Result<usize>
{
Err(Error::new(ErrorKind::IsADirectory, "Is a directory"))
}
fn openat<'b>(&'b self, name: &str) -> Result<Box<dyn HexagonFSFile + 'b>>
{
let resolution = self.def.files.get(name);
match resolution {
Some(dirent) => Ok(dirent.open()),
None => Err(Error::new(ErrorKind::NotFound, "No such file or directory"))
}
}
}
struct VirtDirDirent<'a> {
files: HashMap<&'a str, Box<dyn HexagonFSDirent>>
}
impl<'b> HexagonFSDirent for VirtDirDirent<'b> {
fn open<'a>(&'a self) -> Box<dyn HexagonFSFile + 'a>
{
Box::new(VirtDir {
def: self
})
}
}
fn main() -> ExitCode
{
let root_dir = &VirtDirDirent { files: HashMap::from([
("sys", Box::new(VirtDirDirent { files: HashMap::from([
])}) as Box<dyn HexagonFSDirent>),
])};
let rootfd = root_dir.open();
let dirfd = rootfd.openat("");
return ExitCode::SUCCESS;
}
+98
View File
@@ -0,0 +1,98 @@
/*
* FastRPC reverse tunnel - tests for virtual filesystem
*
* Copyright (C) 2024 The HexagonRPC Contributors
*
* This file is part of HexagonRPC.
*
* HexagonRPC 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 <fcntl.h>
#include <libhexagonrpc/fastrpc.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include "../hexagonrpcd/hexagonfs.h"
static int test_mapped_seq_read(const char *path)
{
struct hexagonfs_fd file = {
.is_assigned = true,
.up = NULL,
.ops = &hexagonfs_mapped_ops,
};
int ret, fd;
char *buf1, *buf2;
buf1 = malloc(256);
if (buf1 == NULL)
return 1;
buf2 = malloc(256);
if (buf2 == NULL)
return 1;
fd = open(path, O_RDONLY);
if (fd == -1)
return 1;
ret = hexagonfs_mapped_ops.from_dirent(path, false, &file.data);
if (ret)
return 1;
memset(buf1, 0, 6);
memset(buf2, 0, 6);
read(fd, buf1, 1);
read(fd, &buf1[1], 5);
hexagonfs_mapped_ops.read(&file, 1, buf2);
hexagonfs_mapped_ops.read(&file, 5, &buf2[1]);
if (memcmp(buf1, buf2, 6))
return 1;
memset(buf1, 0, 27);
memset(buf2, 0, 27);
lseek(fd, 819 - 6, SEEK_CUR);
read(fd, buf1, 27);
hexagonfs_mapped_ops.seek(&file, 819 - 6, SEEK_CUR);
hexagonfs_mapped_ops.read(&file, 27, buf2);
if (memcmp(buf1, buf2, 27))
return 1;
hexagonfs_mapped_ops.close(file.data);
close(fd);
free(buf2);
free(buf1);
return 0;
}
int main(int argc, const char **argv)
{
int ret;
if (argc < 2)
return 1;
ret = test_mapped_seq_read(argv[1]);
if (ret)
return ret;
return 0;
}
+11 -9
View File
@@ -24,7 +24,7 @@
#include "../hexagonrpcd/iobuffer.h"
static const char misaligned_iobufs[] = {
static const unsigned char misaligned_iobufs[] = {
/* inbuf 0 (4 bytes misaligned) */
0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
@@ -58,16 +58,16 @@ static const char misaligned_iobufs[] = {
':', 'D',
};
static char misaligned_decoded0[] = { 0x12, };
static char misaligned_decoded1[] = {
static unsigned char misaligned_decoded0[] = { 0x12, };
static unsigned char misaligned_decoded1[] = {
0x02, 0x46, 0x8A, 0xCF, 0x13, 0x57, 0x9B, 0xDF, 0x04, 0x8C,
};
static char misaligned_decoded2[] = { 'A', 'B', 'C', };
static char misaligned_decoded3[] = { 'F', 'a', 's', 't', };
static char misaligned_decoded4[] = { 'S', 'l', 'o', 'w', '\0', };
static char misaligned_decoded5[] = { 'f', 'a', 's', 't', 'e', 'r', };
static char misaligned_decoded6[] = { 'F', 'a', 's', 't', 'R', 'P', 'C', };
static char misaligned_decoded7[] = { ':', 'D', };
static unsigned char misaligned_decoded2[] = { 'A', 'B', 'C', };
static unsigned char misaligned_decoded3[] = { 'F', 'a', 's', 't', };
static unsigned char misaligned_decoded4[] = { 'S', 'l', 'o', 'w', '\0', };
static unsigned char misaligned_decoded5[] = { 'f', 'a', 's', 't', 'e', 'r', };
static unsigned char misaligned_decoded6[] = { 'F', 'a', 's', 't', 'R', 'P', 'C', };
static unsigned char misaligned_decoded7[] = { ':', 'D', };
static const struct fastrpc_io_buffer misaligned_decoded[] = {
{ .s = 1, .p = misaligned_decoded0, },
@@ -242,4 +242,6 @@ int main(int argc, const char **argv)
ret = test_out_misaligned();
if (ret)
return ret;
return 0;
}