diff --git a/assets/manifests/default.yaml b/assets/manifests/default.yaml index a33e664..eec9e89 100644 --- a/assets/manifests/default.yaml +++ b/assets/manifests/default.yaml @@ -1,8 +1,12 @@ --- +location: jsix init: srv.init -programs: - - name: panic.serial - target: kernel - flags: panic - - name: srv.logger - - name: drv.uart +initrd: + name: initrd.dat + format: zstd +panic: + - panic.serial +services: + - srv.logger +drivers: + - drv.uart diff --git a/assets/manifests/test.yaml b/assets/manifests/test.yaml index a09b3c0..9df0828 100644 --- a/assets/manifests/test.yaml +++ b/assets/manifests/test.yaml @@ -1,9 +1,13 @@ --- +location: jsix init: srv.init +initrd: + name: initrd.dat + format: zstd flags: ["test"] -programs: - - name: panic.serial - target: kernel - flags: panic - - name: drv.uart - - name: test_runner +panic: + - panic.serial +services: + - test_runner +drivers: + - drv.uart diff --git a/scripts/bonnibel/manifest.py b/scripts/bonnibel/manifest.py index 6ca161f..5cb4704 100644 --- a/scripts/bonnibel/manifest.py +++ b/scripts/bonnibel/manifest.py @@ -2,12 +2,16 @@ from . import BonnibelError class Manifest: from collections import namedtuple - Entry = namedtuple("Entry", ("module", "target", "output", "location", "description", "flags")) + Entry = namedtuple("Entry", ("module", "target", "output", "flags")) + + formats = { + "none": 0x00, + "zstd": 0x01, + } flags = { "graphical": 0x01, - "panic": 0x02, - "symbols": 0x04, + "symbols": 0x80, } boot_flags = { @@ -20,6 +24,8 @@ class Manifest: config = load_config(path) + self.location = config.get("location", "jsix") + self.kernel = self.__build_entry(modules, config.get("kernel", dict()), name="kernel", target="kernel") @@ -27,11 +33,24 @@ class Manifest: self.init = self.__build_entry(modules, config.get("init", None)) - self.programs = [self.__build_entry(modules, i) - for i in config.get("programs", tuple())] + self.panics = [self.__build_entry(modules, i, target="kernel") + for i in config.get("panic", tuple())] + + self.services = [self.__build_entry(modules, i) + for i in config.get("services", tuple())] + + self.drivers = [self.__build_entry(modules, i) + for i in config.get("drivers", tuple())] self.flags = config.get("flags", tuple()) + initrd = config.get("initrd", dict()) + self.initrd = initrd.get("name", "initrd.dat") + self.initrd_format = initrd.get("format", "none") + + if not self.initrd_format in Manifest.formats: + raise BonnibelError(f"Manifest specifies unknown initrd format '{self.initrd_format}'") + self.data = [] for d in config.get("data", tuple()): self.add_data(**d) @@ -56,10 +75,10 @@ class Manifest: if not f in Manifest.flags: raise BonnibelError(f"Manifest specifies unknown flag '{f}'") - return Manifest.Entry(name, target, mod.output, mod.location, mod.description, flags) + return Manifest.Entry(name, target, mod.output, flags) - def add_data(self, output, location, desc, flags=tuple()): - e = Manifest.Entry(None, None, output, location, desc, flags) + def add_data(self, output, desc, flags=tuple()): + e = Manifest.Entry(None, None, output, flags) self.data.append(e) return e @@ -69,35 +88,83 @@ class Manifest: with open(path, 'wb') as outfile: magic = "jsixboot".encode("utf-8") # magic string - version = 0 + version = 1 reserved = 0 + initrd_format = Manifest.formats.get(self.initrd_format, 0) bootflags = sum([Manifest.boot_flags.get(s, 0) for s in self.flags]) - outfile.write(struct.pack("<8sBBHHH", - magic, version, reserved, - len(self.programs), len(self.data), - bootflags)) + outfile.write(struct.pack("<8s BBH HH", + magic, + version, reserved, len(self.panics), + initrd_format, bootflags)) def write_str(s): - outfile.write(struct.pack("next = reinterpret_cast(mods); - mods->modules = reinterpret_cast(mods + 1); m_modules = mods; m_next_mod = mods->modules; return; @@ -110,11 +109,13 @@ allocator::allocate_pages(size_t count, alloc_type type, bool zero) } module * -allocator::allocate_module_untyped(size_t size) +allocator::allocate_module() { + static constexpr size_t size = sizeof(module); + size_t remaining = reinterpret_cast(m_modules) + page_size - - reinterpret_cast(m_next_mod); + - reinterpret_cast(m_next_mod) - sizeof(module); if (size > remaining) add_modules(); @@ -122,8 +123,6 @@ allocator::allocate_module_untyped(size_t size) ++m_modules->count; module *m = m_next_mod; m_next_mod = util::offset_pointer(m_next_mod, size); - - m->mod_length = size; return m; } diff --git a/src/boot/allocator.h b/src/boot/allocator.h index 822f0e7..d0b0f7e 100644 --- a/src/boot/allocator.h +++ b/src/boot/allocator.h @@ -32,10 +32,7 @@ public: void * allocate_pages(size_t count, alloc_type type, bool zero = false); - template - M * allocate_module(size_t extra = 0) { - return static_cast(allocate_module_untyped(sizeof(M) + extra)); - } + module * allocate_module(); void memset(void *start, size_t size, uint8_t value); void copy(void *to, void *from, size_t size); @@ -54,7 +51,6 @@ public: private: void add_register(); void add_modules(); - module * allocate_module_untyped(size_t size); uefi::boot_services &m_bs; diff --git a/src/boot/bootconfig.cpp b/src/boot/bootconfig.cpp index 9335521..36d412d 100644 --- a/src/boot/bootconfig.cpp +++ b/src/boot/bootconfig.cpp @@ -24,7 +24,6 @@ read_descriptor(descriptor &e, util::buffer &data) { e.flags = static_cast(*util::read(data)); e.path = read_string(data); - e.desc = read_string(data); } bootconfig::bootconfig(util::buffer data, uefi::boot_services *bs) @@ -35,29 +34,23 @@ bootconfig::bootconfig(util::buffer data, uefi::boot_services *bs) error::raise(uefi::status::load_error, L"Bad header in jsix_boot.dat"); const uint8_t version = *util::read(data); - if (version != 0) + if (version != 1) error::raise(uefi::status::incompatible_version, L"Bad version in jsix_boot.dat"); data += 1; // reserved byte - uint16_t num_programs = *util::read(data); - uint16_t num_data = *util::read(data); - + uint16_t num_panics = *util::read(data); + m_initrd_format = *util::read(data); m_flags = *util::read(data); read_descriptor(m_kernel, data); read_descriptor(m_init, data); + m_initrd = read_string(data); - m_programs.count = num_programs; - m_programs.pointer = new descriptor [num_programs]; + m_panics.count = num_panics; + m_panics.pointer = new descriptor [num_panics]; - for (unsigned i = 0; i < num_programs; ++i) - read_descriptor(m_programs[i], data); - - m_data.count = num_programs; - m_data.pointer = new descriptor [num_data]; - - for (unsigned i = 0; i < num_data; ++i) - read_descriptor(m_data[i], data); + for (unsigned i = 0; i < num_panics; ++i) + read_descriptor(m_panics[i], data); } } // namespace boot diff --git a/src/boot/bootconfig.h b/src/boot/bootconfig.h index a5a8cf5..66e6921 100644 --- a/src/boot/bootconfig.h +++ b/src/boot/bootconfig.h @@ -16,7 +16,6 @@ using desc_flags = bootproto::desc_flags; struct descriptor { desc_flags flags; wchar_t const *path; - wchar_t const *desc; }; /// A bootconfig is a manifest of potential files. @@ -31,15 +30,17 @@ public: inline uint16_t flags() const { return m_flags; } inline const descriptor & kernel() const { return m_kernel; } inline const descriptor & init() const { return m_init; } - descriptors programs() { return m_programs; } - descriptors data() { return m_data; } + inline const wchar_t * initrd() const { return m_initrd; } + inline uint16_t initrd_format() const { return m_initrd_format; } + inline const descriptors & panics() { return m_panics; } private: uint16_t m_flags; + uint16_t m_initrd_format; descriptor m_kernel; descriptor m_init; - descriptors m_programs; - descriptors m_data; + descriptors m_panics; + wchar_t const *m_initrd; }; } // namespace boot diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index b7abf62..63b4075 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -24,52 +24,26 @@ using memory::alloc_type; util::buffer load_file( fs::file &disk, - const descriptor &desc) + const wchar_t *path) { - status_line status(L"Loading file", desc.path); + status_line status(L"Loading file", path); - fs::file file = disk.open(desc.path); + fs::file file = disk.open(path); util::buffer b = file.load(); //console::print(L" Loaded at: 0x%lx, %d bytes\r\n", b.data, b.size); return b; } - -static void -create_module(util::buffer data, const descriptor &desc, bool loaded) -{ - size_t path_len = wstrlen(desc.path); - bootproto::module_program *mod = g_alloc.allocate_module(path_len); - mod->mod_type = bootproto::module_type::program; - mod->base_address = reinterpret_cast(data.pointer); - mod->size = data.count; - if (loaded) - mod->mod_flags = static_cast( - static_cast(mod->mod_flags) | - static_cast(bootproto::module_flags::no_load)); - - // TODO: support non-ascii path characters and do real utf-16 to utf-8 - // conversion - for (int i = 0; i < path_len; ++i) { - char c = desc.path[i]; - mod->filename[i] = c == '\\' ? '/' : c; - } - mod->filename[path_len] = 0; -} - bootproto::program * load_program( fs::file &disk, - const descriptor &desc, - bool add_module) + const wchar_t *name, + const descriptor &desc) { - status_line status(L"Loading program", desc.desc); + status_line status(L"Loading program", name); - util::buffer data = load_file(disk, desc); - - if (add_module) - create_module(data, desc, true); + util::buffer data = load_file(disk, desc.path); elf::file program(data.pointer, data.count); if (!program.valid()) { @@ -129,12 +103,17 @@ load_program( void load_module( fs::file &disk, - const descriptor &desc) + const wchar_t *name, + const wchar_t *path, + bootproto::module_type type, + uint16_t subtype) { - status_line status(L"Loading module", desc.desc); + status_line status(L"Loading module", name); - util::buffer data = load_file(disk, desc); - create_module(data, desc, false); + bootproto::module *mod = g_alloc.allocate_module(); + mod->type = type; + mod->subtype = subtype; + mod->data = load_file(disk, path); } void diff --git a/src/boot/loader.h b/src/boot/loader.h index b72f94c..3f6d9c1 100644 --- a/src/boot/loader.h +++ b/src/boot/loader.h @@ -2,11 +2,11 @@ /// Definitions for loading the kernel into memory #pragma once +#include #include namespace bootproto { struct program; - struct module; } namespace boot { @@ -21,29 +21,35 @@ namespace loader { /// Load a file from disk into memory. /// \arg disk The opened UEFI filesystem to load from -/// \arg desc The program descriptor identifying the file +/// \arg path The path of the file to load util::buffer load_file( fs::file &disk, - const descriptor &desc); + const wchar_t *path); /// Parse and load an ELF file in memory into a loaded image. /// \arg disk The opened UEFI filesystem to load from /// \arg desc The descriptor identifying the program -/// \arg add_module Also create a module for this loaded program +/// \arg name The human-readable name of the program to load bootproto::program * load_program( fs::file &disk, - const descriptor &desc, - bool add_module = false); + const wchar_t *name, + const descriptor &desc); /// Load a file from disk into memory, creating an init args module -/// \arg disk The opened UEFI filesystem to load from -/// \arg desc The program descriptor identifying the file +/// \arg disk The opened UEFI filesystem to load from +/// \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 descriptor &desc); + const wchar_t *name, + const wchar_t *path, + bootproto::module_type type, + uint16_t subtype); /// Verify that a loaded ELF has the j6 kernel header /// \arg program The program to check for a header diff --git a/src/boot/main.cpp b/src/boot/main.cpp index 30c30af..fb418c2 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -75,48 +75,36 @@ load_resources(bootproto::args *args, video::screen *screen, uefi::handle image, fs::file bc_data = disk.open(L"jsix_boot.dat"); bootconfig bc {bc_data.load(), bs}; - args->kernel = loader::load_program(disk, bc.kernel(), true); - args->init = loader::load_program(disk, bc.init()); + args->kernel = loader::load_program(disk, L"kernel", bc.kernel()); + args->init = loader::load_program(disk, L"init server", bc.init()); args->flags = static_cast(bc.flags()); + loader::load_module(disk, L"initrd", bc.initrd(), + bootproto::module_type::initrd, bc.initrd_format()); + namespace bits = util::bits; using bootproto::desc_flags; if (screen) { video::make_module(screen); - // Go through the screen-specific descriptors first to - // give them priority - for (const descriptor &d : bc.programs()) { - if (!bits::has(d.flags, desc_flags::graphical)) - continue; - - if (bits::has(d.flags, desc_flags::panic)) - args->panic = loader::load_program(disk, d); - else - loader::load_module(disk, d); + // Find the screen-specific panic handler first to + // give it priority + for (const descriptor &d : bc.panics()) { + if (bits::has(d.flags, desc_flags::graphical)) { + args->panic = loader::load_program(disk, L"panic handler", d); + break; + } } } - // Load the non-graphical descriptors - for (const descriptor &d : bc.programs()) { - if (bits::has(d.flags, desc_flags::graphical)) - continue; - - if (bits::has(d.flags, desc_flags::panic) && !args->panic) - args->panic = loader::load_program(disk, d); - else - loader::load_module(disk, d); - } - - // For now the only data we load is the symbol table - for (const descriptor &d : bc.data()) { - if (!bits::has(d.flags, desc_flags::symbols)) - continue; - - util::buffer symbol_table = loader::load_file(disk, d); - args->symbol_table = symbol_table.pointer; - break; + if (!args->panic) { + for (const descriptor &d : bc.panics()) { + if (!bits::has(d.flags, desc_flags::graphical)) { + args->panic = loader::load_program(disk, L"panic handler", d); + break; + } + } } loader::verify_kernel_header(*args->kernel); diff --git a/src/boot/status.h b/src/boot/status.h index eacb4b8..cfcc506 100644 --- a/src/boot/status.h +++ b/src/boot/status.h @@ -4,6 +4,7 @@ #include #include +#include "video.h" namespace uefi { struct boot_services; @@ -11,10 +12,6 @@ namespace uefi { namespace boot { -namespace video { - struct screen; -} - // Abstract base class for status reporters. class status { diff --git a/src/boot/video.cpp b/src/boot/video.cpp index 9b0e73f..d2d6a2b 100644 --- a/src/boot/video.cpp +++ b/src/boot/video.cpp @@ -2,6 +2,8 @@ #include #include +#include + #include "allocator.h" #include "console.h" #include "error.h" @@ -10,10 +12,7 @@ namespace boot { namespace video { -using bootproto::fb_layout; -using bootproto::fb_type; -using bootproto::module_flags; -using bootproto::module_framebuffer; +using bootproto::devices::fb_layout; using bootproto::module_type; static uefi::protos::graphics_output * @@ -70,7 +69,7 @@ pick_mode(uefi::boot_services *bs) .vertical = gop->mode->info->vertical_resolution, .horizontal = gop->mode->info->horizontal_resolution, .scanline = gop->mode->info->pixels_per_scanline, - .layout = layout::unknown, + .layout = fb_layout::unknown, }; s->framebuffer = { @@ -82,12 +81,12 @@ pick_mode(uefi::boot_services *bs) switch (info->pixel_format) { case uefi::pixel_format::rgb8: type = L"rgb8"; - s->mode.layout = layout::rgb8; + s->mode.layout = fb_layout::rgb8; break; case uefi::pixel_format::bgr8: type = L"bgr8"; - s->mode.layout = layout::bgr8; + s->mode.layout = fb_layout::bgr8; break; default: @@ -108,13 +107,22 @@ pick_mode(uefi::boot_services *bs) void make_module(screen *s) { - using bootproto::module_framebuffer; - module_framebuffer *modfb = g_alloc.allocate_module(); - modfb->mod_type = module_type::framebuffer; - modfb->type = fb_type::uefi; + using bootproto::module; + using bootproto::module_type; + using bootproto::device_type; + using bootproto::devices::uefi_fb; - modfb->framebuffer = s->framebuffer; - modfb->mode = s->mode; + uefi_fb *fb = new uefi_fb; + 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/boot/video.h b/src/boot/video.h index d3bc6bf..3873c47 100644 --- a/src/boot/video.h +++ b/src/boot/video.h @@ -5,7 +5,7 @@ #include #include -#include +#include #include namespace uefi { @@ -15,13 +15,8 @@ namespace uefi { namespace boot { namespace video { -using bootproto::video_mode; -using layout = bootproto::fb_layout; - -struct screen { - util::buffer framebuffer; - video_mode mode; -}; +using layout = bootproto::devices::fb_layout; +using screen = bootproto::devices::uefi_fb; /// Pick the best video mode and set up the screen screen * pick_mode(uefi::boot_services *bs); diff --git a/src/libraries/bootproto/bootproto.module b/src/libraries/bootproto/bootproto.module index 6914858..1869fb5 100644 --- a/src/libraries/bootproto/bootproto.module +++ b/src/libraries/bootproto/bootproto.module @@ -4,6 +4,7 @@ bp = module("bootproto", kind = "lib", public_headers = [ "bootproto/bootconfig.h", + "bootproto/devices/framebuffer.h", "bootproto/init.h", "bootproto/kernel.h", "bootproto/memory.h.cog", diff --git a/src/libraries/bootproto/bootproto/bootconfig.h b/src/libraries/bootproto/bootproto/bootconfig.h index 89254fc..32721c7 100644 --- a/src/libraries/bootproto/bootproto/bootconfig.h +++ b/src/libraries/bootproto/bootproto/bootconfig.h @@ -8,9 +8,9 @@ namespace bootproto { enum class desc_flags : uint16_t { - graphical = 0x01, - panic = 0x02, - symbols = 0x04, + graphical = 0x0001, + panic = 0x0002, + symbols = 0x0004, }; is_bitfield(desc_flags); diff --git a/src/libraries/bootproto/bootproto/devices/framebuffer.h b/src/libraries/bootproto/bootproto/devices/framebuffer.h new file mode 100644 index 0000000..1df3f01 --- /dev/null +++ b/src/libraries/bootproto/bootproto/devices/framebuffer.h @@ -0,0 +1,28 @@ +#pragma once +/// \file bootproto/devices/uefi_fb.h +/// Data structures describing bootloader-passed framebuffer + +#include + +namespace bootproto { +namespace devices { + +enum class fb_layout : uint8_t { rgb8, bgr8, unknown = 0xff }; + +struct video_mode +{ + uint32_t vertical; + uint32_t horizontal; + uint32_t scanline; + fb_layout layout; +}; + +struct uefi_fb +{ + util::buffer framebuffer; + video_mode mode; +}; + + +} // namespace devices +} // namespace bootproto diff --git a/src/libraries/bootproto/bootproto/init.h b/src/libraries/bootproto/bootproto/init.h index 72061f9..46e429f 100644 --- a/src/libraries/bootproto/bootproto/init.h +++ b/src/libraries/bootproto/bootproto/init.h @@ -10,61 +10,30 @@ namespace bootproto { -enum class module_type : uint8_t { - none, - program, - framebuffer, -}; - -enum class module_flags : uint8_t { - none = 0x00, - - /// This module was already handled by the bootloader, - /// no action is needed. The module is included for - /// informational purposes only. - no_load = 0x01, -}; -is_bitfield(module_flags); +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 mod_type; - module_flags mod_flags; - uint32_t mod_length; + module_type type; + // 1 byte padding + uint16_t subtype; + // 4 bytes padding + util::buffer data; }; -struct module_program : - public module -{ - uintptr_t base_address; - size_t size; - char filename[]; -}; - -enum class fb_layout : uint8_t { rgb8, bgr8, unknown = 0xff }; -enum class fb_type : uint8_t { uefi }; - -struct video_mode -{ - uint32_t vertical; - uint32_t horizontal; - uint32_t scanline; - fb_layout layout; -}; - -struct module_framebuffer : - public module -{ - util::buffer framebuffer; - video_mode mode; - fb_type type; -}; - -struct modules_page +struct module_page_header { uint8_t count; - module *modules; 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]; +}; + } // namespace bootproto diff --git a/src/user/drv.uart/uart.module b/src/user/drv.uart/uart.module index f9fbcb9..9f2562f 100644 --- a/src/user/drv.uart/uart.module +++ b/src/user/drv.uart/uart.module @@ -4,6 +4,7 @@ module("drv.uart", targets = [ "user" ], deps = [ "libc", "util" ], description = "UART driver", + drivers = [ "pc.uart" ], sources = [ "io.cpp", "main.cpp", diff --git a/src/user/drv.uefi_fb/uefi_fb.module b/src/user/drv.uefi_fb/uefi_fb.module index 3b3e25b..d747aab 100644 --- a/src/user/drv.uefi_fb/uefi_fb.module +++ b/src/user/drv.uefi_fb/uefi_fb.module @@ -4,6 +4,7 @@ module("drv.uefi_fb", targets = [ "user" ], deps = [ "libc" ], description = "UEFI framebuffer driver", + drivers = [ "uefi.fb" ], sources = [ "font.cpp", "main.cpp", diff --git a/src/user/srv.init/loader.cpp b/src/user/srv.init/loader.cpp index 8bc773a..4c1663d 100644 --- a/src/user/srv.init/loader.cpp +++ b/src/user/srv.init/loader.cpp @@ -9,8 +9,9 @@ #include #include -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(prog.base_address); - elf::file progelf {addr, prog.size}; + const void *addr = reinterpret_cast(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; } diff --git a/src/user/srv.init/loader.h b/src/user/srv.init/loader.h index 3f6b0f4..f9a5cdf 100644 --- a/src/user/srv.init/loader.h +++ b/src/user/srv.init/loader.h @@ -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(phys), len, addr); +} diff --git a/src/user/srv.init/main.cpp b/src/user/srv.init/main.cpp index 7020ab6..e0d1147 100644 --- a/src/user/srv.init/main.cpp +++ b/src/user/srv.init/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -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(mod); + module const *initrd_module; + std::vector 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; } diff --git a/src/user/srv.init/modules.cpp b/src/user/srv.init/modules.cpp index 137c41f..41d375c 100644 --- a/src/user/srv.init/modules.cpp +++ b/src/user/srv.init/modules.cpp @@ -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(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; } diff --git a/src/user/srv.init/modules.h b/src/user/srv.init/modules.h index 3e160fe..945660d 100644 --- a/src/user/srv.init/modules.h +++ b/src/user/srv.init/modules.h @@ -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; };