[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 <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <util/hash.h>
|
#include <util/hash.h>
|
||||||
|
|
||||||
#include <zstd.h>
|
#include <zstd.h>
|
||||||
|
#include <zstd_errors.h>
|
||||||
|
|
||||||
#include "j6romfs.h"
|
#include "j6romfs.h"
|
||||||
|
|
||||||
@@ -37,31 +39,13 @@ fs::fs(util::const_buffer data) :
|
|||||||
util::const_buffer
|
util::const_buffer
|
||||||
fs::load_simple(char const *path) const
|
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};
|
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];
|
uint8_t *data = new uint8_t [in->size];
|
||||||
size_t total = load_inode_data(in, util::buffer::from(data, in->size));
|
size_t total = load_inode_data(in, util::buffer::from(data, in->size));
|
||||||
return util::buffer::from(data, total);
|
return util::buffer::from(data, total);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {0, 0};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
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,
|
size_t decom = ZSTD_decompress(dest.pointer, dest.count,
|
||||||
src.pointer, in->compressed);
|
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;
|
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 *
|
const inode *
|
||||||
fs::lookup_inode_in_dir(const inode *dir, const char *name) const
|
fs::lookup_inode_in_dir(const inode *dir, const char *name) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,9 +50,36 @@ public:
|
|||||||
fs(util::const_buffer data);
|
fs(util::const_buffer data);
|
||||||
|
|
||||||
util::const_buffer load_simple(char const *path) const;
|
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:
|
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;
|
const inode * lookup_inode_in_dir(const inode *in, const char *name) const;
|
||||||
|
|
||||||
util::const_buffer m_data;
|
util::const_buffer m_data;
|
||||||
|
|||||||
@@ -141,7 +141,6 @@ load_program(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] reinterpret_cast<const uint8_t*>(data.pointer);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,24 +25,6 @@ uintptr_t _arg_modules_phys; // This gets filled in in _start
|
|||||||
|
|
||||||
extern j6_handle_t __handle_self;
|
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
|
int
|
||||||
main(int argc, const char **argv)
|
main(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
@@ -113,24 +95,46 @@ main(int argc, const char **argv)
|
|||||||
// have driver_source objects..
|
// have driver_source objects..
|
||||||
j6romfs::fs initrd {initrd_module->data};
|
j6romfs::fs initrd {initrd_module->data};
|
||||||
|
|
||||||
char err_msg [128];
|
char message[256];
|
||||||
|
|
||||||
util::const_buffer uart_elf = load_driver_for("uart", initrd);
|
initrd.for_each("/jsix/drivers",
|
||||||
if (uart_elf.pointer) {
|
[=, &message](const j6romfs::inode *in, const char *name) {
|
||||||
if (!load_program("UART driver", uart_elf, sys_child, slp_mb_child, err_msg)) {
|
if (in->type != j6romfs::inode_type::file)
|
||||||
j6_log(err_msg);
|
return;
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
util::const_buffer logger_elf = load_service("logger", initrd);
|
delete [] data;
|
||||||
if (uart_elf.pointer) {
|
});
|
||||||
if (!load_program("logger service", logger_elf, sys_child, slp_mb_child, err_msg)) {
|
|
||||||
j6_log(err_msg);
|
initrd.for_each("/jsix/services",
|
||||||
return 1;
|
[=, &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);
|
service_locator_start(slp_mb);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user