5 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
9 changed files with 264 additions and 30 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
@@ -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)
+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
);
}
+14
View File
@@ -11,4 +11,18 @@ test_iobuffer = executable('test_iobuffer',
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;
}