diff --git a/src/boot/allocator.cpp b/src/boot/allocator.cpp index 7bdc7c0..1975de8 100644 --- a/src/boot/allocator.cpp +++ b/src/boot/allocator.cpp @@ -71,10 +71,10 @@ allocator::add_modules() allocate_pages(1, alloc_type::init_args, true)); if (m_modules) - m_modules->next = reinterpret_cast(mods); + m_modules->next = mods; m_modules = mods; - m_next_mod = mods->modules; + m_next_mod = reinterpret_cast(mods+1); return; } @@ -109,9 +109,9 @@ allocator::allocate_pages(size_t count, alloc_type type, bool zero) } module * -allocator::allocate_module() +allocator::allocate_module(size_t extra) { - static constexpr size_t size = sizeof(module); + size_t size = sizeof(module) + extra; size_t remaining = reinterpret_cast(m_modules) + page_size @@ -120,8 +120,8 @@ allocator::allocate_module() if (size > remaining) add_modules(); - ++m_modules->count; module *m = m_next_mod; + m->bytes = size; m_next_mod = util::offset_pointer(m_next_mod, size); return m; } diff --git a/src/boot/allocator.h b/src/boot/allocator.h index fcb53ff..74defb6 100644 --- a/src/boot/allocator.h +++ b/src/boot/allocator.h @@ -32,7 +32,7 @@ public: void * allocate_pages(size_t count, alloc_type type, bool zero = false); - module * allocate_module(); + module * allocate_module(size_t extra = 0); void memset(void *start, size_t size, uint8_t value); void copy(void *to, const void *from, size_t size); diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index 5fd8482..3f1853e 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -167,15 +167,15 @@ load_module( fs::file &disk, const wchar_t *name, const wchar_t *path, - bootproto::module_type type, - uint16_t subtype) + bootproto::module_type type) { status_line status(L"Loading module", name); - bootproto::module *mod = g_alloc.allocate_module(); + bootproto::module *mod = g_alloc.allocate_module(sizeof(util::buffer)); mod->type = type; - mod->subtype = subtype; - mod->data = load_file(disk, path); + + util::buffer *data = mod->data(); + *data = load_file(disk, path); } } // namespace loader diff --git a/src/boot/loader.h b/src/boot/loader.h index 5bf0521..9bf23de 100644 --- a/src/boot/loader.h +++ b/src/boot/loader.h @@ -60,14 +60,12 @@ load_program( /// \arg name The human-readable name of the module /// \arg path The path of the file to load the module from /// \arg type The major type to set on the module -/// \arg subtype The subtype to set on the module void load_module( fs::file &disk, const wchar_t *name, const wchar_t *path, - bootproto::module_type type, - uint16_t subtype); + bootproto::module_type type); } // namespace loader } // namespace boot diff --git a/src/boot/main.cpp b/src/boot/main.cpp index 0461b22..ca88353 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -125,7 +125,7 @@ load_resources( loader::parse_program(L"init server", init, args->init); loader::load_module(disk, L"initrd", bc.initrd(), - bootproto::module_type::initrd, 0); + bootproto::module_type::initrd); return reinterpret_cast(kentry); } @@ -194,6 +194,7 @@ efi_main(uefi::handle image, uefi::system_table *st) change_pointer(args); change_pointer(args->pml4); + change_pointer(args->symbol_table.pointer); change_pointer(args->init.sections.pointer); //status.next(); diff --git a/src/boot/video.cpp b/src/boot/video.cpp index d2d6a2b..6fd391f 100644 --- a/src/boot/video.cpp +++ b/src/boot/video.cpp @@ -109,20 +109,15 @@ make_module(screen *s) { using bootproto::module; using bootproto::module_type; - using bootproto::device_type; - using bootproto::devices::uefi_fb; + namespace devices = bootproto::devices; - uefi_fb *fb = new uefi_fb; + module *mod = g_alloc.allocate_module(sizeof(devices::uefi_fb)); + mod->type = module_type::device; + mod->type_id = devices::type_id_uefi_fb; + + devices::uefi_fb *fb = mod->data(); fb->framebuffer = s->framebuffer; fb->mode = s->mode; - - module *mod = g_alloc.allocate_module(); - mod->type = module_type::device; - mod->subtype = static_cast(device_type::uefi_fb); - mod->data = { - .pointer = fb, - .count = sizeof(uefi_fb), - }; } } // namespace video diff --git a/src/libraries/bootproto/bootproto/devices/framebuffer.h b/src/libraries/bootproto/bootproto/devices/framebuffer.h index 1df3f01..523ea6c 100644 --- a/src/libraries/bootproto/bootproto/devices/framebuffer.h +++ b/src/libraries/bootproto/bootproto/devices/framebuffer.h @@ -3,10 +3,13 @@ /// Data structures describing bootloader-passed framebuffer #include +#include namespace bootproto { namespace devices { +inline constexpr uint64_t type_id_uefi_fb = "uefi.fb"_id; + enum class fb_layout : uint8_t { rgb8, bgr8, unknown = 0xff }; struct video_mode diff --git a/src/libraries/bootproto/bootproto/init.h b/src/libraries/bootproto/bootproto/init.h index 46e429f..89121dd 100644 --- a/src/libraries/bootproto/bootproto/init.h +++ b/src/libraries/bootproto/bootproto/init.h @@ -11,29 +11,21 @@ namespace bootproto { enum class module_type : uint8_t { none, initrd, device, }; -enum class initrd_format : uint8_t { none, zstd, }; -enum class device_type : uint16_t { none, uefi_fb, }; struct module { - module_type type; - // 1 byte padding - uint16_t subtype; - // 4 bytes padding - util::buffer data; + uint16_t bytes; //< Size of this module in bytes, including this header + module_type type; //< Type of module + // 5 bytes padding + uint64_t type_id; //< Optional subtype or id + + template T * data() { return reinterpret_cast(this+1); } + template const T * data() const { return reinterpret_cast(this+1); } }; -struct module_page_header +struct modules_page { - uint8_t count; - uintptr_t next; -}; - -struct modules_page : - public module_page_header -{ - static constexpr unsigned per_page = (0x1000 - sizeof(module_page_header)) / sizeof(module); - module modules[per_page]; + modules_page *next; }; } // namespace bootproto diff --git a/src/user/srv.init/j6romfs.h b/src/user/srv.init/j6romfs.h index a2c68e1..c859e78 100644 --- a/src/user/srv.init/j6romfs.h +++ b/src/user/srv.init/j6romfs.h @@ -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; diff --git a/src/user/srv.init/loader.cpp b/src/user/srv.init/loader.cpp index 9dc4f8b..8fee7e0 100644 --- a/src/user/srv.init/loader.cpp +++ b/src/user/srv.init/loader.cpp @@ -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(data.pointer); @@ -119,9 +120,23 @@ load_program( return false; } + uint64_t arg0 = 0; + uint64_t *stack = reinterpret_cast(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 *arg_dest = reinterpret_cast(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; diff --git a/src/user/srv.init/loader.h b/src/user/srv.init/loader.h index dae253b..dfc9034 100644 --- a/src/user/srv.init/loader.h +++ b/src/user/srv.init/loader.h @@ -3,16 +3,18 @@ /// Routines for loading and starting other programs #include +#include 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); diff --git a/src/user/srv.init/main.cpp b/src/user/srv.init/main.cpp index 6f014f3..db5a762 100644 --- a/src/user/srv.init/main.cpp +++ b/src/user/srv.init/main.cpp @@ -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 mods; + load_modules(_arg_modules_phys, sys, __handle_self, mods); module const *initrd_module; std::vector 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(); + 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; } + diff --git a/src/user/srv.init/modules.cpp b/src/user/srv.init/modules.cpp index 41d375c..e3ed853 100644 --- a/src/user/srv.init/modules.cpp +++ b/src/user/srv.init/modules.cpp @@ -1,78 +1,40 @@ #include #include +#include +#include #include #include +#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 &modules) { - return reinterpret_cast( - reinterpret_cast(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(m_page->next); + modules_page const *p = reinterpret_cast(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(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(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}; } diff --git a/src/user/srv.init/modules.h b/src/user/srv.init/modules.h index a30d529..2b417d1 100644 --- a/src/user/srv.init/modules.h +++ b/src/user/srv.init/modules.h @@ -2,73 +2,15 @@ /// \file modules.h /// Routines for loading initial argument modules +#include + #include #include #include - -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 &modules);