diff --git a/apps/app.c b/apps/app.c index c5f55f95..10c5c975 100644 --- a/apps/app.c +++ b/apps/app.c @@ -10,7 +10,7 @@ void bye() int main() { atexit(bye); - printf("Welcome to %s!\n", "Luna"); + printf("Welcome to %s from userspace!\n", "Luna"); char* address = (char*)malloc(1); printf("address: %p\n", address); diff --git a/kernel/debug.cmake b/kernel/debug.cmake index c775e522..85d5d129 100644 --- a/kernel/debug.cmake +++ b/kernel/debug.cmake @@ -1,2 +1,3 @@ target_compile_definitions(moon PRIVATE LOCKED_VALUE_DEBUG) +target_compile_definitions(moon PRIVATE DEBUG_MODE) target_compile_options(moon PRIVATE -fsanitize=undefined) diff --git a/kernel/src/boot/Init.cpp b/kernel/src/boot/Init.cpp index 9a8f90ef..f997f2a7 100644 --- a/kernel/src/boot/Init.cpp +++ b/kernel/src/boot/Init.cpp @@ -25,7 +25,12 @@ void Init::early_init() Framebuffer::init(); - setup_log(log_debug_enabled(), log_serial_enabled(), true); +#ifdef DEBUG_MODE + constexpr bool should_log_console = true; +#else + constexpr bool should_log_console = false; +#endif + setup_log(log_debug_enabled(), log_serial_enabled(), should_log_console); CPU::platform_init(); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 09964795..3a454809 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -12,18 +12,12 @@ #include "memory/KernelVM.h" #include "memory/MemoryManager.h" #include "thread/Scheduler.h" +#include "video/Framebuffer.h" +#include "video/TextConsole.h" #include #include #include -void heap_thread() -{ - CPU::disable_interrupts(); - dump_heap_usage(); - kdbgln("Kernel uses %lu vm pages", KernelVM::used() / ARCH_PAGE_SIZE); - kernel_exit(); -} - void reap_thread() { while (true) @@ -38,24 +32,23 @@ void reap_thread() } } -Result init() +static void identify_processor() { - kinfoln("Starting Moon %s, built on %s at %s", MOON_VERSION, __DATE__, __TIME__); - kinfoln("Current platform: %s", CPU::platform_string()); kinfoln("Current processor: %s", CPU::identify().value_or("(unknown)")); +} - Timer::init(); - +static void identify_memory() +{ kinfoln("Total memory: %s", to_dynamic_unit(MemoryManager::total()).release_value().chars()); kinfoln("Free memory: %s", to_dynamic_unit(MemoryManager::free()).release_value().chars()); kinfoln("Used memory: %s", to_dynamic_unit(MemoryManager::used()).release_value().chars()); kinfoln("Reserved memory: %s", to_dynamic_unit(MemoryManager::reserved()).release_value().chars()); +} - Thread::init(); - Scheduler::init(); - +static Result try_init_vfs() +{ VFS::root_fs = TRY(TmpFS::FileSystem::create()); VFS::Inode& root_inode = VFS::root_inode(); @@ -68,6 +61,16 @@ Result init() kinfoln("root inode's 'usr' entry inode number: %zu", TRY(root_inode.find("usr"))->inode_number()); + return {}; +} + +static void init_vfs() +{ + try_init_vfs().release_value(); +} + +static Result try_init_userspace() +{ TarStream::Entry entry; while (TRY(g_initrd.read_next_entry(entry))) { @@ -80,22 +83,96 @@ Result init() } } - TRY(Scheduler::new_kernel_thread(heap_thread)); - TRY(Scheduler::new_kernel_thread(reap_thread)); + return {}; +} +static void init_userspace() +{ + try_init_userspace().release_value(); +} + +static void create_reaper() +{ + Scheduler::new_kernel_thread(reap_thread).release_value(); +} + +static void scan_pci() +{ PCI::scan( [](const PCI::Device& device) { kinfoln("Found PCI mass storage device %.4x:%.4x, at address %u:%u:%u", device.id.vendor, device.id.device, device.address.bus, device.address.slot, device.address.function); }, { .klass = 1 }); +} - CPU::platform_finish_init(); - +static void transfer_control() +{ // Disable console logging before transferring control to userspace. setup_log(log_debug_enabled(), log_serial_enabled(), false); CPU::enable_interrupts(); +} + +struct SplashAction +{ + const char* message; + void (*action)(void); +}; + +constexpr SplashAction actions[] = { + { "Identify Processor", identify_processor }, { "Initialize Timer", Timer::init }, + { "Identify System Memory", identify_memory }, { "Initialize Threads", Thread::init }, + { "Initialize Scheduler", Scheduler::init }, { "Initialize File System", init_vfs }, + { "Initialize Userspace", init_userspace }, { "Create Reaper Thread", create_reaper }, + { "Find Available Devices", scan_pci }, { "Final CPU Initialization", CPU::platform_finish_init }, + { "Start Userspace", transfer_control }, +}; + +static constexpr u32 WHITE = 0xffffffff; +static constexpr u32 RED = 0xffff0000; +static constexpr u32 BLACK = 0xff000000; + +static void update_splash(const char* message, u32 current, u32 total) +{ + const u32 line_height = Framebuffer::height() / 2; + const u32 line_begin = 100; + const u32 line_length = Framebuffer::width() - 200; + + if (current != total) + { + const u32 line_completed = (line_length / total) * current; + + Framebuffer::rect(line_begin, line_height, line_completed, 2, WHITE); + Framebuffer::rect(line_begin + line_completed, line_height, line_length - line_completed, 2, RED); + } + else { Framebuffer::rect(line_begin, line_height, line_length, 2, WHITE); } + + Framebuffer::rect(line_begin, line_height + 20, line_length, 16, BLACK); + + TextConsole::move_to(Framebuffer::width() / 2 - 100, line_height + 20); + TextConsole::print(message).release_value(); + + TextConsole::move_to(0, 0); + + for (int i = 0; i < 3000000; i++) CPU::pause(); +} + +Result init() +{ + kinfoln("Starting Moon %s, built on %s at %s", MOON_VERSION, __DATE__, __TIME__); + + constexpr usize total_actions = sizeof(actions) / sizeof(actions[0]); + + for (usize i = 0; i < total_actions; i++) + { +#ifndef DEBUG_MODE + update_splash(actions[i].message, (u32)i, (u32)(total_actions - 1)); +#else + (void)update_splash; +#endif + actions[i].action(); + } return {}; }