From 4130562b1555cabe441efe9420cebe12e7ed8d39 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sat, 13 Jan 2024 16:43:49 -0500 Subject: application loading --- kernel/entry.cpp | 140 ++++++++++++++++++++++--------------------------------- 1 file changed, 56 insertions(+), 84 deletions(-) (limited to 'kernel/entry.cpp') diff --git a/kernel/entry.cpp b/kernel/entry.cpp index 445d560..f7ba71d 100644 --- a/kernel/entry.cpp +++ b/kernel/entry.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -103,6 +104,8 @@ uint64_t initfs_len; [[noreturn]] static void with_kernel_p4(); +extern "C" void load_gdt_and_idt(); + extern "C" [[noreturn]] void entry() { //TODO?: maybe we should check if the limine requests were @@ -113,9 +116,9 @@ extern "C" [[noreturn]] void entry() { paging::mark_all_pram_used(); auto memmap = memmap_request.response; for (uint64_t i = 0; i < memmap->entry_count; ++i) { - //we don't start allocating physical pages until after we are done using - //limine structures (specifically at the call to paging::map_kernel_stack), - //so we consider bootloader reclaimable to be free. usable and bootloader + //we don't allocate any physical pages until after we are done using limine + //structures (specifically at the call to paging::map_kernel_stacks), so + //we consider bootloader reclaimable to be free. usable and bootloader //reclaimable are guaranteed by limine spec to be page-aligned. auto entry = memmap->entries[i]; if (entry->type == LIMINE_MEMMAP_USABLE || @@ -175,79 +178,29 @@ extern "C" [[noreturn]] void entry() { //switch to kernel p4 - paging::map_kernel_stack(); + paging::map_kernel_stacks(); + load_gdt_and_idt(); switch_to_kernel_p4(&with_kernel_p4); } +static void print_mem() { + uint64_t used_vram_mib = (paging::get_used_vram_page_count() + 128) / 256; + uint64_t free_pram_mib = (paging::get_free_pram_page_count() + 128) / 256; + terminal::put_int_decimal(used_vram_mib); + terminal::put_string_sz(" MiB kernel memory mapped.\n"); + terminal::put_int_decimal(free_pram_mib); + terminal::put_string_sz(" MiB physical memory free.\n"); +} + [[noreturn]] static void print_and_halt(const char *msg) { terminal::put_string_sz(msg); while (1) asm ("hlt"); } -static void draw_indent(unsigned indent) { - for (unsigned i = 0; i < indent; ++i) - terminal::put_char(' '); -} - -static void dir_tree( - const vfile::vfile &root, const vfile::vfile &f, unsigned indent -) { - - draw_indent(indent); - terminal::put_string(f.dir_entry.name); - terminal::put_char('\n'); - - std::optional followed; - utility::vector children; - - switch (f.dir_entry.type) { - - case storage::file_type::regular_file: - draw_indent(indent + 2); - terminal::put_string_sz("type: regular file\n"); - draw_indent(indent + 2); - terminal::put_string_sz("length: "); - terminal::put_int_decimal(f.dir_entry.length); - terminal::put_string_sz(" bytes\n"); - break; - - case storage::file_type::symlink: - draw_indent(indent + 2); - terminal::put_string_sz("type: symlink\n"); - draw_indent(indent + 2); - terminal::put_string_sz("target: "); - terminal::put_string(f.dir_entry.target); - terminal::put_char('\n'); - if (f.follow_symlinks(root, followed) != storage::fs_result::success) - print_and_halt("failed to follow symlink."); - if (!followed) { - draw_indent(indent + 4); - terminal::put_string_sz("[broken]\n"); - } - dir_tree(root, *followed, indent + 4); - break; - - case storage::file_type::directory: - if (f.get_children(children) != storage::fs_result::success) - print_and_halt("failed to get children."); - draw_indent(indent + 2); - terminal::put_string_sz("type: directory\n"); - draw_indent(indent + 2); - terminal::put_string_sz("children:\n"); - if (children.count == 0) { - draw_indent(indent + 4); - terminal::put_string_sz("[empty]\n"); - } - else - for (unsigned i = 0; i < children.count; ++i) - dir_tree(root, children.buffer[i], indent + 4); - break; - - } - -} +extern "C" [[noreturn]] void start_user_mode( + uint64_t rip, uint64_t rsp, uint64_t p4_paddr); [[noreturn]] static void with_kernel_p4() { @@ -257,27 +210,46 @@ static void dir_tree( storage::fs::tarfs_instance initfs_fs(&initfs_bd); initfs_bd.mounted_as = &initfs_fs; - terminal::put_string_sz("kernel initialization complete.\n"); - - int used_vram_kib = paging::get_used_vram_page_count() * 4; - int free_pram_kib = paging::get_free_pram_page_count() * 4; + vfile::vfile vfs_root; + vfs_root.bd = &initfs_bd; + vfs_root.dir_entry.type = storage::file_type::directory; + vfs_root.path.absolute = true; - terminal::put_int_decimal(used_vram_kib); - terminal::put_string_sz(" kiB kernel memory mapped.\n"); - terminal::put_int_decimal(free_pram_kib); - terminal::put_string_sz(" kiB physical memory free.\n"); + if (initfs_fs.get_root_node(vfs_root.dir_entry.node) != + storage::fs_result::success) + print_and_halt("failed to get root node of initfs."); - vfile::vfile root; - root.bd = &initfs_bd; - root.dir_entry.type = storage::file_type::directory; - root.path.absolute = true; + utility::string init_path_string("/bin/init.elf", 13); + vfile::canon_path init_path; + vfile::canonize_path(init_path_string, init_path); - if (initfs_fs.get_root_node(root.dir_entry.node) != + std::optional init_file; + if (vfile::lookup_path(vfs_root, init_path, init_file) != storage::fs_result::success) - print_and_halt("failed to get root node."); - - terminal::put_string_sz("initfs"); - dir_tree(root, root, 0); - print_and_halt("halting."); + print_and_halt("failed to look up /bin/init.elf."); + if (!init_file) + print_and_halt("/bin/init.elf does not exist."); + + terminal::put_string_sz("/bin/init.elf is "); + terminal::put_int_decimal(init_file->dir_entry.length); + terminal::put_string_sz(" bytes long.\n"); + + application::app_instance *init; + if (application::create_app(*init_file, init) != + application::create_app_result::success) + print_and_halt("failed to parse /bin/init.elf."); + + terminal::put_string_sz("/bin/init.elf loaded:\n instruction pointer 0x"); + terminal::put_int_hex(init->saved_regs.rip, 8); + terminal::put_string_sz("\n stack pointer 0x"); + terminal::put_int_hex(init->saved_regs.rsp, 8); + terminal::put_string_sz("\n "); + terminal::put_int_decimal(init->count_mapped_vram_pages() * 2); + terminal::put_string_sz(" MiB userspace memory used\n"); + + print_mem(); + terminal::put_string_sz("switching to /bin/init.elf.\n"); + application::running_app = init; + start_user_mode(init->saved_regs.rip, init->saved_regs.rsp, init->p4_paddr); } -- cgit v1.2.3