[init] Go back to boot modules having inline data

In order to pass along arguments like the framebuffer, it's far simpler
to have that data stored along with the modules than mapping new pages
for every structure. Also now optionally pass a module's data to a
driver as init starts it.
This commit is contained in:
Justin C. Miller
2023-02-10 01:01:01 -08:00
parent 0eddb002f0
commit ea587076ed
14 changed files with 132 additions and 200 deletions

View File

@@ -78,10 +78,10 @@ public:
return i;
}
private:
const inode * lookup_inode(const char *path) const;
const inode * lookup_inode_in_dir(const inode *in, const char *name) const;
private:
util::const_buffer m_data;
inode const *m_inodes;
inode const *m_root;

View File

@@ -42,7 +42,8 @@ load_program(
const char *name,
util::const_buffer data,
j6_handle_t sys, j6_handle_t slp,
char *err_msg)
char *err_msg,
module *arg)
{
uintptr_t base_address = reinterpret_cast<uintptr_t>(data.pointer);
@@ -119,9 +120,23 @@ load_program(
return false;
}
uint64_t arg0 = 0;
uint64_t *stack = reinterpret_cast<uint64_t*>(load_addr + stack_size);
memset(stack - 512, 0, 512 * sizeof(uint64_t)); // Zero top page
stack -= 2; // add null frame
size_t stack_consumed = 2 * sizeof(uint64_t);
if (arg) {
size_t arg_size = arg->bytes - sizeof(module);
uint8_t *arg_data = arg->data<uint8_t>();
uint8_t *arg_dest = reinterpret_cast<uint8_t*>(stack) - arg_size;
memcpy(arg_dest, arg_data, arg_size);
stack_consumed += arg_size;
arg0 = stack_top - stack_consumed;
}
res = j6_vma_map(stack_vma, proc, stack_top-stack_size);
if (res != j6_status_ok) {
sprintf(err_msg, " ** error loading program '%s': mapping stack vma: %lx", name, res);
@@ -135,7 +150,7 @@ load_program(
}
j6_handle_t thread = j6_handle_invalid;
res = j6_thread_create(&thread, proc, stack_top - 6*sizeof(uint64_t), progelf.entrypoint(), 0, 0);
res = j6_thread_create(&thread, proc, stack_top - stack_consumed, progelf.entrypoint(), arg0, 0);
if (res != j6_status_ok) {
sprintf(err_msg, " ** error loading program '%s': creating thread: %lx", name, res);
return false;

View File

@@ -3,16 +3,18 @@
/// Routines for loading and starting other programs
#include <j6/types.h>
#include <util/counted.h>
namespace bootproto {
struct module_program;
struct module;
}
bool load_program(
const char *name,
util::const_buffer data,
j6_handle_t sys, j6_handle_t slp,
char *err_msg);
char *err_msg,
bootproto::module *arg = nullptr);
j6_handle_t map_phys(j6_handle_t sys, uintptr_t phys, size_t len, uintptr_t addr = 0);

View File

@@ -25,6 +25,35 @@ uintptr_t _arg_modules_phys; // This gets filled in in _start
extern j6_handle_t __handle_self;
void
load_driver(
j6romfs::fs &initrd,
const j6romfs::inode *dir,
const char *name,
j6_handle_t sys,
j6_handle_t slp,
module *arg = nullptr)
{
const j6romfs::inode *in = initrd.lookup_inode_in_dir(dir, name);
if (in->type != j6romfs::inode_type::file)
return;
char message [128];
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, slp, message, arg)) {
j6_log(message);
}
delete [] data;
}
int
main(int argc, const char **argv)
{
@@ -60,19 +89,20 @@ main(int argc, const char **argv)
if (s != j6_status_ok)
return s;
modules mods = modules::load_modules(_arg_modules_phys, sys, __handle_self);
std::vector<const module*> mods;
load_modules(_arg_modules_phys, sys, __handle_self, mods);
module const *initrd_module;
std::vector<module const*> devices;
for (auto &mod : mods) {
switch (mod.type) {
for (auto mod : mods) {
switch (mod->type) {
case module_type::initrd:
initrd_module = &mod;
initrd_module = mod;
break;
case module_type::device:
devices.push_back(&mod);
devices.push_back(mod);
break;
default:
@@ -84,8 +114,10 @@ main(int argc, const char **argv)
if (!initrd_module)
return 1;
util::const_buffer initrd_buf = *initrd_module->data<util::const_buffer>();
j6_handle_t initrd_vma =
map_phys(sys, initrd_module->data.pointer, initrd_module->data.count);
map_phys(sys, initrd_buf.pointer, initrd_buf.count);
if (initrd_vma == j6_handle_invalid) {
j6_log(" ** error loading ramdisk: mapping physical vma");
return 1;
@@ -93,28 +125,17 @@ main(int argc, const char **argv)
// TODO: encapsulate this all in a driver_manager, or maybe
// have driver_source objects..
j6romfs::fs initrd {initrd_module->data};
j6romfs::fs initrd {initrd_buf};
char message[256];
initrd.for_each("/jsix/drivers",
[=, &message](const j6romfs::inode *in, const char *name) {
if (in->type != j6romfs::inode_type::file)
return;
const j6romfs::inode *driver_dir = initrd.lookup_inode("/jsix/drivers");
if (!driver_dir) {
j6_log("Could not load drivers directory");
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;
});
load_driver(initrd, driver_dir, "drv.uart.elf", sys_child, slp_mb_child);
initrd.for_each("/jsix/services",
[=, &message](const j6romfs::inode *in, const char *name) {
@@ -138,3 +159,4 @@ main(int argc, const char **argv)
service_locator_start(slp_mb);
return 0;
}

View File

@@ -1,78 +1,40 @@
#include <stdlib.h>
#include <stdio.h>
#include <utility>
#include <arch/memory.h>
#include <j6/errors.h>
#include <j6/syscalls.h>
#include "loader.h"
#include "modules.h"
using module = bootproto::module;
using modules_page = bootproto::modules_page;
static const modules_page *
get_page(const module *mod)
void
load_modules(
uintptr_t address,
j6_handle_t system,
j6_handle_t self,
std::vector<const bootproto::module *> &modules)
{
return reinterpret_cast<const modules_page*>(
reinterpret_cast<uintptr_t>(mod) & ~0xfffull);
}
using bootproto::module;
using bootproto::modules_page;
const module *
module_iterator::operator++()
{
do {
if (++m_idx >= modules_page::per_page) {
// We've reached the end of a page, see if there's another
if (!m_page->next) {
m_page = nullptr;
break;
}
m_idx = 0;
m_page = reinterpret_cast<modules_page*>(m_page->next);
modules_page const *p = reinterpret_cast<const modules_page*>(address);
while (p) {
j6_handle_t mod_vma = map_phys(system, p, arch::frame_size);
if (mod_vma == j6_handle_invalid) {
j6_log(" ** error loading modules: mapping physical vma");
return;
}
module const *m = reinterpret_cast<module const*>(p+1);
while (m->bytes) {
modules.push_back(m);
m = util::offset_pointer(m, m->bytes);
}
p = p->next;
}
while (m_type != type::none && m_type != deref()->type);
return deref();
}
const module *
module_iterator::operator++(int)
{
const module *tmp = deref();
operator++();
return tmp;
}
const modules_page *
load_page(uintptr_t address, j6_handle_t system, j6_handle_t self)
{
j6_handle_t mods_vma = j6_handle_invalid;
j6_status_t s = j6_system_map_phys(system, &mods_vma, address, 0x1000, 0);
if (s != j6_status_ok)
exit(s);
s = j6_vma_map(mods_vma, self, address);
if (s != j6_status_ok)
exit(s);
return reinterpret_cast<const modules_page*>(address);
}
modules
modules::load_modules(uintptr_t address, j6_handle_t system, j6_handle_t self)
{
const modules_page *first = nullptr;
while (address) {
const modules_page *page = load_page(address, system, self);
char message[100];
sprintf(message, "srv.init found %d modules from page at 0x%lx", page->count, address);
j6_log(message);
if (!first)
first = page;
address = page->next;
}
return modules {first};
}

View File

@@ -2,73 +2,15 @@
/// \file modules.h
/// Routines for loading initial argument modules
#include <vector>
#include <bootproto/init.h>
#include <j6/types.h>
#include <util/pointers.h>
class module_iterator
{
public:
using type = bootproto::module_type;
using module = bootproto::module;
module_iterator(const bootproto::modules_page *p, unsigned i, type t = type::none) :
m_page {p}, m_idx {i}, m_type {t} {
if ( t != type::none && p && deref()->type != t ) operator++();
}
const module * operator++();
const module * operator++(int);
bool operator==(const module* m) const { return m == deref(); }
bool operator!=(const module* m) const { return m != deref(); }
bool operator==(const module_iterator &i) const { return i.deref() == deref(); }
bool operator!=(const module_iterator &i) const { return i.deref() != deref(); }
const module & operator*() const { return *deref(); }
operator const module & () const { return *deref(); }
const module * operator->() const { return deref(); }
// Allow iterators to be used in for(:) statments
module_iterator & begin() { return *this; }
module_iterator end() const { return {nullptr, 0}; }
private:
inline const module * deref() const {
if (m_page) {
const module &m = m_page->modules[m_idx];
if (m.type != type::none)
return &m;
}
return nullptr;
}
unsigned m_idx;
bootproto::modules_page const *m_page;
type m_type;
};
class modules
{
public:
using type = bootproto::module_type;
using iterator = module_iterator;
static modules load_modules(
void
load_modules(
uintptr_t address,
j6_handle_t system,
j6_handle_t self);
iterator of_type(type t) const { return iterator {m_root, 0, t}; }
iterator begin() const { return iterator {m_root, 0}; }
iterator end() const { return {nullptr, 0}; }
private:
using module = bootproto::module;
modules(const bootproto::modules_page* root) : m_root {root} {}
const bootproto::modules_page *m_root;
};
j6_handle_t self,
std::vector<const bootproto::module *> &modules);