summaryrefslogtreecommitdiff
path: root/kernel/source/entry.cpp
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2024-05-18 21:53:38 -0400
committerBenji Dial <benji@benjidial.net>2024-05-18 21:53:38 -0400
commitb1a912a8a6ff472a49b2e0a09cfd433adfc2cb24 (patch)
tree5009d4415ba13e4baa37f3d0271852528130fd3b /kernel/source/entry.cpp
parenta8a80d326de9550b2a25b1255a2093ab43219ede (diff)
downloadhilbert-os-b1a912a8a6ff472a49b2e0a09cfd433adfc2cb24.tar.gz
reorganization, cross compiler
Diffstat (limited to 'kernel/source/entry.cpp')
-rw-r--r--kernel/source/entry.cpp222
1 files changed, 222 insertions, 0 deletions
diff --git a/kernel/source/entry.cpp b/kernel/source/entry.cpp
new file mode 100644
index 0000000..820b107
--- /dev/null
+++ b/kernel/source/entry.cpp
@@ -0,0 +1,222 @@
+#include <hilbert/kernel/storage/bd/memory.hpp>
+#include <hilbert/kernel/storage/fs/tarfs.hpp>
+#include <hilbert/kernel/application.hpp>
+#include <hilbert/kernel/framebuffer.hpp>
+#include <hilbert/kernel/paging.hpp>
+#include <hilbert/kernel/input.hpp>
+#include <hilbert/kernel/panic.hpp>
+#include <hilbert/kernel/vfile.hpp>
+#include <limine.h>
+
+using namespace hilbert::kernel;
+
+LIMINE_BASE_REVISION(1)
+
+static volatile limine_memmap_request memmap_request {
+ .id = LIMINE_MEMMAP_REQUEST,
+ .revision = 0,
+ .response = 0
+};
+
+static volatile limine_kernel_address_request kernel_address_request {
+ .id = LIMINE_KERNEL_ADDRESS_REQUEST,
+ .revision = 0,
+ .response = 0
+};
+
+static volatile limine_framebuffer_request framebuffer_request {
+ .id = LIMINE_FRAMEBUFFER_REQUEST,
+ .revision = 0,
+ .response = 0
+};
+
+static volatile limine_hhdm_request hhdm_request {
+ .id = LIMINE_HHDM_REQUEST,
+ .revision = 0,
+ .response = 0
+};
+
+static volatile limine_module_request module_request = {
+ .id = LIMINE_MODULE_REQUEST,
+ .revision = 2,
+ .response = 0,
+ .internal_module_count = 0,
+ .internal_modules = 0
+};
+
+bool try_map_module_by_cmdline(
+ const char *cmdline, void *&vaddr_out, uint64_t &len_out
+) {
+ auto response = module_request.response;
+ if (!response)
+ return false;
+ for (uint64_t i = 0; i < response->module_count; ++i) {
+ limine_file *file = response->modules[i];
+ for (uint64_t j = 0; cmdline[j] == file->cmdline[j]; ++j)
+ if (!cmdline[j]) {
+
+ //module start is guaranteed to be page-aligned, end is not.
+ uint64_t start_paddr =
+ (uint64_t)file->address - hhdm_request.response->offset;
+ uint64_t end_paddr =
+ ((start_paddr + file->size - 1) / 4096 + 1) * 4096;
+
+ uint64_t start_vaddr =
+ paging::find_unmapped_vram_region((end_paddr - start_paddr) / 4096);
+ for (uint64_t i = 0; i < end_paddr - start_paddr; i += 4096)
+ paging::map_kernel_page(
+ start_paddr + i, start_vaddr + i, true, false);
+
+ vaddr_out = (void *)start_vaddr;
+ len_out = file->size;
+
+ return true;
+ }
+ }
+ return false;
+}
+
+//defined in linker script, page-aligned:
+extern uint8_t __kernel_start;
+extern uint8_t __kernel_end;
+extern uint8_t __kernel_rx_start;
+extern uint8_t __kernel_rx_end;
+extern uint8_t __kernel_ro_start;
+extern uint8_t __kernel_ro_end;
+extern uint8_t __kernel_rw_start;
+extern uint8_t __kernel_rw_end;
+
+uint8_t *initfs;
+uint64_t initfs_len;
+
+[[noreturn]] static void with_kernel_p4();
+
+extern "C" void load_gdt_and_idt();
+
+static bool have_initfs;
+
+extern "C" [[noreturn]] void entry() {
+
+ //TODO?: maybe we should check if the limine requests were
+ // fulfilled and display some error message if not
+
+ //set up the physical memory usage bitmap:
+
+ paging::mark_all_pram_used();
+ auto memmap = memmap_request.response;
+ for (uint64_t i = 0; i < memmap->entry_count; ++i) {
+ //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 ||
+ entry->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE)
+ paging::mark_pram_region_free(entry->base, entry->base + entry->length);
+ }
+
+ //set up page mappings:
+
+ auto kernel_address = kernel_address_request.response;
+ uint64_t kernel_offset = kernel_address->virtual_base
+ - kernel_address->physical_base;
+
+ uint64_t hhdm = hhdm_request.response->offset;
+
+ //framebuffer might not be page-aligned
+ auto framebuffer = framebuffer_request.response->framebuffers[0];
+ uint64_t fb_start = ((uint64_t)framebuffer->address / 4096) * 4096 - hhdm;
+ uint64_t fb_end = (uint64_t)framebuffer->address
+ + framebuffer->pitch * framebuffer->height - hhdm;
+ fb_end = ((fb_end - 1) / 4096 + 1) * 4096;
+
+ paging::init_kernel_page_tables(kernel_offset);
+
+ //kernel image rx
+ for (uint64_t vaddr = (uint64_t)&__kernel_rx_start;
+ vaddr < (uint64_t)&__kernel_rx_end; vaddr += 4096)
+ paging::map_kernel_page(vaddr - kernel_offset, vaddr, false, true);
+
+ //kernel image ro
+ for (uint64_t vaddr = (uint64_t)&__kernel_ro_start;
+ vaddr < (uint64_t)&__kernel_ro_end; vaddr += 4096)
+ paging::map_kernel_page(vaddr - kernel_offset, vaddr, false, false);
+
+ //kernel image rw
+ for (uint64_t vaddr = (uint64_t)&__kernel_rw_start;
+ vaddr < (uint64_t)&__kernel_rw_end; vaddr += 4096)
+ paging::map_kernel_page(vaddr - kernel_offset, vaddr, true, false);
+
+ //framebuffer
+ uint64_t fb_vaddr =
+ paging::find_unmapped_vram_region((fb_end - fb_start) / 4096);
+ for (uint64_t i = 0; i < fb_end - fb_start; i += 4096)
+ paging::map_kernel_page(fb_start + i, fb_vaddr + i, true, false);
+
+ have_initfs =
+ try_map_module_by_cmdline("initfs", (void *&)initfs, initfs_len);
+
+ //set up framebuffer and terminal:
+ //TODO: assumes framebuffer is 32-bpp rgb
+
+ framebuffer::init_framebuffer(fb_start, fb_vaddr,
+ framebuffer->width, framebuffer->height, framebuffer->pitch);
+
+ //switch to kernel p4
+
+ paging::map_kernel_stacks();
+ load_gdt_and_idt();
+ switch_to_kernel_p4(&with_kernel_p4);
+
+}
+
+[[noreturn]] static void with_kernel_p4() {
+
+ if (!have_initfs)
+ panic(0x5f8860);
+
+ input::init_input();
+ application::init_applications();
+
+ auto *initfs_bd = new storage::bd::memory(initfs, initfs_len);
+ auto *initfs_fs = new storage::fs::tarfs_instance(initfs_bd);
+ initfs_bd->mounted_as = initfs_fs;
+
+ vfile::vfile initfs_root;
+ initfs_root.bd = initfs_bd;
+ initfs_root.dir_entry.type = storage::file_type::directory;
+ initfs_root.path.absolute = true;
+
+ if (initfs_fs->get_root_node(initfs_root.dir_entry.node) !=
+ storage::fs_result::success)
+ panic(0x48a6ed);
+
+ vfile::set_root(initfs_root);
+
+ utility::string init_path_string("/bin/init", 9);
+ vfile::canon_path init_path;
+ vfile::canonize_path(init_path_string, init_path);
+
+ vfile::vfile init_file;
+ if (vfile::lookup_path(init_path, init_file, true) !=
+ storage::fs_result::success)
+ panic(0x7e874d);
+
+ application::process *init_process;
+ application::thread *init_thread;
+ if (application::create_application(init_file, init_process, init_thread) !=
+ application::stream_result::success)
+ panic(0xc39db3);
+
+ init_process->environment.add_end({
+ .a = utility::string("ARGC", 4),
+ .b = utility::string("1", 1)});
+ init_process->environment.add_end({
+ .a = utility::string("ARGV0", 5),
+ .b = utility::string("/bin/init", 9)});
+
+ init_thread->state = application::thread_state::paused;
+ application::paused_threads->insert(init_thread);
+ application::resume_next();
+
+}