mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[srv.init] Iterate and load drivers and services from initrd
Previously we were hard-coding loading specific files (the UART driver and logging server) from the initrd. Now j6romfs has a for_each() method to allow iterating all files in a directory, and init loads all programs from /jsix/drivers and /jsix/services. Eventually this will need more dynamic loading decisions for drivers but for now it's fine.
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <util/hash.h>
|
||||
|
||||
#include <zstd.h>
|
||||
#include <zstd_errors.h>
|
||||
|
||||
#include "j6romfs.h"
|
||||
|
||||
@@ -37,31 +39,13 @@ fs::fs(util::const_buffer data) :
|
||||
util::const_buffer
|
||||
fs::load_simple(char const *path) const
|
||||
{
|
||||
if (!path)
|
||||
const inode *in = lookup_inode(path);
|
||||
if (!in || in->type != inode_type::file)
|
||||
return {0, 0};
|
||||
|
||||
char element [buf_size];
|
||||
inode const *in = m_root;
|
||||
|
||||
while (*path) {
|
||||
path = copy_path_element(path, element);
|
||||
in = lookup_inode_in_dir(in, element);
|
||||
|
||||
if (!in) {
|
||||
// entry was not found
|
||||
break;
|
||||
} else if (*path && in->type == inode_type::file) {
|
||||
// a directory was expected
|
||||
break;
|
||||
} else if (in->type == inode_type::file) {
|
||||
// load the file
|
||||
uint8_t *data = new uint8_t [in->size];
|
||||
size_t total = load_inode_data(in, util::buffer::from(data, in->size));
|
||||
return util::buffer::from(data, total);
|
||||
}
|
||||
}
|
||||
|
||||
return {0, 0};
|
||||
uint8_t *data = new uint8_t [in->size];
|
||||
size_t total = load_inode_data(in, util::buffer::from(data, in->size));
|
||||
return util::buffer::from(data, total);
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -80,10 +64,43 @@ fs::load_inode_data(const inode *in, util::buffer dest) const
|
||||
|
||||
size_t decom = ZSTD_decompress(dest.pointer, dest.count,
|
||||
src.pointer, in->compressed);
|
||||
assert(!ZSTD_isError(decom) && "Error decompressing");
|
||||
if (ZSTD_isError(decom)) {
|
||||
ZSTD_ErrorCode err = ZSTD_getErrorCode(decom);
|
||||
const char *name = ZSTD_getErrorString(err);
|
||||
assert(!name);
|
||||
}
|
||||
|
||||
return decom;
|
||||
}
|
||||
|
||||
const inode *
|
||||
fs::lookup_inode(const char *path) const
|
||||
{
|
||||
if (!path)
|
||||
return nullptr;
|
||||
|
||||
char element [buf_size];
|
||||
inode const *in = m_root;
|
||||
|
||||
while (*path) {
|
||||
path = copy_path_element(path, element);
|
||||
in = lookup_inode_in_dir(in, element);
|
||||
|
||||
if (!in) {
|
||||
// entry was not found
|
||||
break;
|
||||
} else if (!*path) {
|
||||
// found it
|
||||
return in;
|
||||
} else if (*path && in->type == inode_type::file) {
|
||||
// a directory was expected
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const inode *
|
||||
fs::lookup_inode_in_dir(const inode *dir, const char *name) const
|
||||
{
|
||||
|
||||
@@ -50,9 +50,36 @@ public:
|
||||
fs(util::const_buffer data);
|
||||
|
||||
util::const_buffer load_simple(char const *path) const;
|
||||
size_t load_inode_data(const inode *in, util::buffer dest) const;
|
||||
|
||||
template <typename callback>
|
||||
size_t for_each(const char *root, callback &&cb) const
|
||||
{
|
||||
const inode *in = lookup_inode(root);
|
||||
if (!in || in->type != inode_type::directory)
|
||||
return 0;
|
||||
|
||||
uint8_t *dir_data = new uint8_t [in->size];
|
||||
load_inode_data(in, util::buffer::from(dir_data, in->size));
|
||||
const dirent *entries = reinterpret_cast<const dirent*>(dir_data);
|
||||
|
||||
size_t i = 0, max = in->size / sizeof(dirent);
|
||||
for (; i < max; ++i) {
|
||||
const dirent &e = entries[i];
|
||||
const char *name = reinterpret_cast<const char*>(dir_data + e.name_offset);
|
||||
|
||||
cb(&m_inodes[e.inode], name);
|
||||
|
||||
size_t new_max = e.name_offset / sizeof(dirent);
|
||||
if (new_max < max) max = new_max;
|
||||
}
|
||||
|
||||
delete [] dir_data;
|
||||
return i;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t load_inode_data(const inode *in, util::buffer dest) const;
|
||||
const inode * lookup_inode(const char *path) const;
|
||||
const inode * lookup_inode_in_dir(const inode *in, const char *name) const;
|
||||
|
||||
util::const_buffer m_data;
|
||||
|
||||
@@ -141,7 +141,6 @@ load_program(
|
||||
return false;
|
||||
}
|
||||
|
||||
delete [] reinterpret_cast<const uint8_t*>(data.pointer);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,24 +25,6 @@ uintptr_t _arg_modules_phys; // This gets filled in in _start
|
||||
|
||||
extern j6_handle_t __handle_self;
|
||||
|
||||
util::const_buffer
|
||||
load_driver_for(const char *name, const j6romfs::fs &initrd)
|
||||
{
|
||||
char driver[256];
|
||||
snprintf(driver, sizeof(driver), "/jsix/drivers/drv.%s.elf", name);
|
||||
|
||||
return initrd.load_simple(driver);
|
||||
}
|
||||
|
||||
util::const_buffer
|
||||
load_service(const char *name, const j6romfs::fs &initrd)
|
||||
{
|
||||
char service[256];
|
||||
snprintf(service, sizeof(service), "/jsix/services/srv.%s.elf", name);
|
||||
|
||||
return initrd.load_simple(service);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
@@ -113,23 +95,45 @@ main(int argc, const char **argv)
|
||||
// have driver_source objects..
|
||||
j6romfs::fs initrd {initrd_module->data};
|
||||
|
||||
char err_msg [128];
|
||||
char message[256];
|
||||
|
||||
util::const_buffer uart_elf = load_driver_for("uart", initrd);
|
||||
if (uart_elf.pointer) {
|
||||
if (!load_program("UART driver", uart_elf, sys_child, slp_mb_child, err_msg)) {
|
||||
j6_log(err_msg);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
initrd.for_each("/jsix/drivers",
|
||||
[=, &message](const j6romfs::inode *in, const char *name) {
|
||||
if (in->type != j6romfs::inode_type::file)
|
||||
return;
|
||||
|
||||
util::const_buffer logger_elf = load_service("logger", initrd);
|
||||
if (uart_elf.pointer) {
|
||||
if (!load_program("logger service", logger_elf, sys_child, slp_mb_child, err_msg)) {
|
||||
j6_log(err_msg);
|
||||
return 1;
|
||||
sprintf(message, "Loading driver: %s", name);
|
||||
j6_log(message);
|
||||
|
||||
uint8_t *data = new uint8_t [in->size];
|
||||
util::buffer program {data, in->size};
|
||||
|
||||
initrd.load_inode_data(in, program);
|
||||
if (!load_program(name, program, sys_child, slp_mb_child, message)) {
|
||||
j6_log(message);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
});
|
||||
|
||||
initrd.for_each("/jsix/services",
|
||||
[=, &message](const j6romfs::inode *in, const char *name) {
|
||||
if (in->type != j6romfs::inode_type::file)
|
||||
return;
|
||||
|
||||
sprintf(message, "Loading service: %s", name);
|
||||
j6_log(message);
|
||||
|
||||
uint8_t *data = new uint8_t [in->size];
|
||||
util::buffer program {data, in->size};
|
||||
|
||||
initrd.load_inode_data(in, program);
|
||||
if (!load_program(name, program, sys_child, slp_mb_child, message)) {
|
||||
j6_log(message);
|
||||
}
|
||||
|
||||
delete [] data;
|
||||
});
|
||||
|
||||
service_locator_start(slp_mb);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user