mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[boot] Build, load, and pass initrd from boot to init
The initrd image is now created by the build system, loaded by the bootloader, and passed to srv.init, which loads it (but doesn't do anything with it yet, so this is actually a functional regression). This simplifies a lot of the modules code between boot and init as well: Gone are the many subclasses of module and all the data being inline with the module structs, except for any loaded files. Now the only modules loaded and passed will be the initrd, and any devices only the bootloader has knowledge of, like the UEFI framebuffer.
This commit is contained in:
@@ -9,8 +9,9 @@
|
||||
#include <j6/syscalls.h>
|
||||
#include <util/enum_bitfields.h>
|
||||
|
||||
using bootproto::module_flags;
|
||||
using bootproto::module_program;
|
||||
#include "loader.h"
|
||||
|
||||
using bootproto::module;
|
||||
|
||||
extern j6_handle_t __handle_self;
|
||||
|
||||
@@ -18,54 +19,62 @@ constexpr uintptr_t load_addr = 0xf8000000;
|
||||
constexpr size_t stack_size = 0x10000;
|
||||
constexpr uintptr_t stack_top = 0x80000000000;
|
||||
|
||||
j6_handle_t
|
||||
map_phys(j6_handle_t sys, uintptr_t phys, size_t len, uintptr_t addr)
|
||||
{
|
||||
j6_handle_t vma = j6_handle_invalid;
|
||||
j6_status_t res = j6_system_map_phys(sys, &vma, phys, len, 0);
|
||||
if (res != j6_status_ok)
|
||||
return j6_handle_invalid;
|
||||
|
||||
if (!addr)
|
||||
addr = phys;
|
||||
|
||||
res = j6_vma_map(vma, __handle_self, addr);
|
||||
if (res != j6_status_ok)
|
||||
return j6_handle_invalid;
|
||||
|
||||
return vma;
|
||||
}
|
||||
|
||||
bool
|
||||
load_program(
|
||||
const module_program &prog,
|
||||
const char *name,
|
||||
uintptr_t base_address,
|
||||
size_t size,
|
||||
j6_handle_t sys, j6_handle_t slp,
|
||||
char *err_msg)
|
||||
{
|
||||
if (prog.mod_flags && module_flags::no_load) {
|
||||
sprintf(err_msg, " skipping pre-loaded program module '%s' at %lx", prog.filename, prog.base_address);
|
||||
return true;
|
||||
}
|
||||
|
||||
j6_handle_t elf_vma = j6_handle_invalid;
|
||||
j6_status_t res = j6_system_map_phys(sys, &elf_vma, prog.base_address, prog.size, 0);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': creating physical vma: %lx", prog.filename, res);
|
||||
j6_handle_t elf_vma = map_phys(sys, base_address, size);
|
||||
if (elf_vma == j6_handle_invalid) {
|
||||
sprintf(err_msg, " ** error loading program '%s': creating physical vma", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = j6_vma_map(elf_vma, __handle_self, prog.base_address);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': mapping vma: %lx", prog.filename, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
const void *addr = reinterpret_cast<const void *>(prog.base_address);
|
||||
elf::file progelf {addr, prog.size};
|
||||
const void *addr = reinterpret_cast<const void *>(base_address);
|
||||
elf::file progelf {addr, size};
|
||||
|
||||
if (!progelf.valid()) {
|
||||
sprintf(err_msg, " ** error loading program '%s': ELF is invalid", prog.filename);
|
||||
sprintf(err_msg, " ** error loading program '%s': ELF is invalid", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
j6_handle_t proc = j6_handle_invalid;
|
||||
res = j6_process_create(&proc);
|
||||
j6_status_t res = j6_process_create(&proc);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': creating process: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': creating process: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = j6_process_give_handle(proc, sys);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': giving system handle: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': giving system handle: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = j6_process_give_handle(proc, slp);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': giving SLP handle: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': giving SLP handle: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -79,14 +88,14 @@ load_program(
|
||||
if (seg.flags && elf::segment_flags::exec)
|
||||
flags |= j6_vm_flag_exec;
|
||||
|
||||
uintptr_t start = prog.base_address + seg.offset;
|
||||
uintptr_t start = base_address + seg.offset;
|
||||
size_t prologue = start & 0xfff;
|
||||
size_t epilogue = seg.mem_size - (prologue+seg.file_size);
|
||||
|
||||
j6_handle_t sub_vma = j6_handle_invalid;
|
||||
res = j6_vma_create_map(&sub_vma, seg.mem_size+prologue, load_addr, flags);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': creating sub vma: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': creating sub vma: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -98,13 +107,13 @@ load_program(
|
||||
|
||||
res = j6_vma_map(sub_vma, proc, seg.vaddr & ~0xfffull);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': mapping sub vma to child: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': mapping sub vma to child: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = j6_vma_unmap(sub_vma, __handle_self);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': unmapping sub vma: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': unmapping sub vma: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -112,7 +121,7 @@ load_program(
|
||||
j6_handle_t stack_vma = j6_handle_invalid;
|
||||
res = j6_vma_create_map(&stack_vma, stack_size, load_addr, j6_vm_flag_write);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': creating stack vma: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': creating stack vma: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -121,26 +130,26 @@ load_program(
|
||||
|
||||
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", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': mapping stack vma: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = j6_vma_unmap(stack_vma, __handle_self);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': unmapping stack vma: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': unmapping stack vma: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
j6_handle_t thread = j6_handle_invalid;
|
||||
res = j6_thread_create(&thread, proc, stack_top - 6*sizeof(uint64_t), progelf.entrypoint());
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': creating thread: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': creating thread: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
res = j6_vma_unmap(elf_vma, __handle_self);
|
||||
if (res != j6_status_ok) {
|
||||
sprintf(err_msg, " ** error loading program '%s': unmapping elf vma: %lx", prog.filename, res);
|
||||
sprintf(err_msg, " ** error loading program '%s': unmapping elf vma: %lx", name, res);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,3 +12,9 @@ bool load_program(
|
||||
const bootproto::module_program &prog,
|
||||
j6_handle_t sys, j6_handle_t slp,
|
||||
char *err_msg);
|
||||
|
||||
j6_handle_t map_phys(j6_handle_t sys, uintptr_t phys, size_t len, uintptr_t addr = 0);
|
||||
|
||||
inline j6_handle_t map_phys(j6_handle_t sys, void *phys, size_t len, uintptr_t addr = 0) {
|
||||
return map_phys(sys, reinterpret_cast<uintptr_t>(phys), len, addr);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
|
||||
#include <j6/cap_flags.h>
|
||||
#include <j6/errors.h>
|
||||
@@ -10,11 +11,11 @@
|
||||
|
||||
#include "loader.h"
|
||||
#include "modules.h"
|
||||
#include "ramdisk.h"
|
||||
#include "service_locator.h"
|
||||
|
||||
using bootproto::module;
|
||||
using bootproto::module_type;
|
||||
using bootproto::module_program;
|
||||
|
||||
extern "C" {
|
||||
int main(int, const char **);
|
||||
@@ -61,19 +62,38 @@ main(int argc, const char **argv)
|
||||
|
||||
modules mods = modules::load_modules(_arg_modules_phys, sys, __handle_self);
|
||||
|
||||
for (auto &mod : mods.of_type(module_type::program)) {
|
||||
auto &prog = static_cast<const module_program&>(mod);
|
||||
module const *initrd_module;
|
||||
std::vector<module const*> devices;
|
||||
|
||||
char message[100];
|
||||
sprintf(message, " loading program module '%s' at %lx", prog.filename, prog.base_address);
|
||||
j6_log(message);
|
||||
for (auto &mod : mods) {
|
||||
switch (mod.type) {
|
||||
case module_type::initrd:
|
||||
initrd_module = &mod;
|
||||
break;
|
||||
|
||||
if (!load_program(prog, sys_child, slp_mb_child, message)) {
|
||||
j6_log(message);
|
||||
return 2;
|
||||
case module_type::device:
|
||||
devices.push_back(&mod);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unknown module??
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!initrd_module)
|
||||
return 1;
|
||||
|
||||
j6_handle_t initrd_vma =
|
||||
map_phys(sys, initrd_module->data.pointer, initrd_module->data.count);
|
||||
if (initrd_vma == j6_handle_invalid) {
|
||||
j6_log(" ** error loading ramdisk: mapping physical vma");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ramdisk initrd {initrd_module->data};
|
||||
util::buffer manifest = initrd.load_file("init.manifest");
|
||||
|
||||
service_locator_start(slp_mb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,28 +20,24 @@ const module *
|
||||
module_iterator::operator++()
|
||||
{
|
||||
do {
|
||||
m_mod = util::offset_pointer(m_mod, m_mod->mod_length);
|
||||
|
||||
if (m_mod->mod_type == type::none) {
|
||||
if (++m_idx >= modules_page::per_page) {
|
||||
// We've reached the end of a page, see if there's another
|
||||
const modules_page *page = get_page(m_mod);
|
||||
if (!page->next) {
|
||||
m_mod = nullptr;
|
||||
if (!m_page->next) {
|
||||
m_page = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
m_mod = page->modules;
|
||||
m_idx = 0;
|
||||
m_page = reinterpret_cast<modules_page*>(m_page->next);
|
||||
}
|
||||
}
|
||||
while (m_type != type::none && m_type != m_mod->mod_type);
|
||||
|
||||
return m_mod;
|
||||
while (m_type != type::none && m_type != deref()->type);
|
||||
return deref();
|
||||
}
|
||||
|
||||
const module *
|
||||
module_iterator::operator++(int)
|
||||
{
|
||||
const module *tmp = m_mod;
|
||||
const module *tmp = deref();
|
||||
operator++();
|
||||
return tmp;
|
||||
}
|
||||
@@ -64,7 +60,7 @@ load_page(uintptr_t address, j6_handle_t system, j6_handle_t self)
|
||||
modules
|
||||
modules::load_modules(uintptr_t address, j6_handle_t system, j6_handle_t self)
|
||||
{
|
||||
const module *first = nullptr;
|
||||
const modules_page *first = nullptr;
|
||||
while (address) {
|
||||
const modules_page *page = load_page(address, system, self);
|
||||
|
||||
@@ -73,7 +69,7 @@ modules::load_modules(uintptr_t address, j6_handle_t system, j6_handle_t self)
|
||||
j6_log(message);
|
||||
|
||||
if (!first)
|
||||
first = page->modules;
|
||||
first = page;
|
||||
address = page->next;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,27 +13,32 @@ public:
|
||||
using type = bootproto::module_type;
|
||||
using module = bootproto::module;
|
||||
|
||||
module_iterator(const module *m, type t = type::none) :
|
||||
m_mod {m}, m_type {t} {}
|
||||
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 == m_mod; }
|
||||
bool operator!=(const module* m) const { return m != m_mod; }
|
||||
bool operator==(const module_iterator &i) const { return i.m_mod == m_mod; }
|
||||
bool operator!=(const module_iterator &i) const { return i.m_mod != m_mod; }
|
||||
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 *m_mod; }
|
||||
operator const module & () const { return *m_mod; }
|
||||
const module * operator->() const { return m_mod; }
|
||||
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; }
|
||||
module_iterator end() const { return {nullptr, 0}; }
|
||||
|
||||
private:
|
||||
module const * m_mod;
|
||||
inline const module * deref() const { return m_page ? &m_page->modules[m_idx] : nullptr; }
|
||||
|
||||
unsigned m_idx;
|
||||
bootproto::modules_page const *m_page;
|
||||
type m_type;
|
||||
};
|
||||
|
||||
@@ -48,15 +53,15 @@ public:
|
||||
j6_handle_t system,
|
||||
j6_handle_t self);
|
||||
|
||||
iterator of_type(type t) const { return iterator {m_root, t}; }
|
||||
iterator of_type(type t) const { return iterator {m_root, 0, t}; }
|
||||
|
||||
iterator begin() const { return iterator {m_root}; }
|
||||
iterator end() const { return nullptr; }
|
||||
iterator begin() const { return iterator {m_root, 0}; }
|
||||
iterator end() const { return {nullptr, 0}; }
|
||||
|
||||
private:
|
||||
using module = bootproto::module;
|
||||
|
||||
modules(const module* root) : m_root {root} {}
|
||||
modules(const bootproto::modules_page* root) : m_root {root} {}
|
||||
|
||||
const module *m_root;
|
||||
const bootproto::modules_page *m_root;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user