Luna/kernel/src/main.cpp
apio f83a6ace51 Kernel, libc: Add support for providing a status code to exit()
The exit() libc function already accepted an integer, but didn't pass it on to the kernel since we had no mechanism for it to do that.
Now, the kernel stores a task's exit status to display it later (and in the future, return it to userspace via wait()/waitpid())
2022-10-08 17:56:40 +02:00

167 lines
4.1 KiB
C++

#define MODULE "main"
#include "acpi/RSDT.h"
#include "assert.h"
#include "config.h"
#include "cpu/CPU.h"
#include "gdt/GDT.h"
#include "init/Init.h"
#include "init/InitRD.h"
#include "interrupts/IDT.h"
#include "interrupts/Install.h"
#include "interrupts/Interrupts.h"
#include "io/PCI.h"
#include "io/PIC.h"
#include "io/Serial.h"
#include "log/Log.h"
#include "memory/Memory.h"
#include "memory/MemoryManager.h"
#include "memory/MemoryMap.h"
#include "memory/PMM.h"
#include "memory/VMM.h"
#include "misc/PCITypes.h"
#include "misc/reboot.h"
#include "panic/Panic.h"
#include "rand/Mersenne.h"
#include "render/Framebuffer.h"
#include "render/TextRenderer.h"
#include "std/stdio.h"
#include "std/stdlib.h"
#include "std/string.h"
#include "sys/elf/ELFLoader.h"
#include "thread/PIT.h"
#include "thread/Scheduler.h"
extern "C" void _userspace();
extern "C" void _start()
{
Init::check_magic();
Init::disable_smp(); // Put all other cores except the bootstrap one in an infinite loop
Init::early_init();
kinfoln("Starting Moon %s", moon_version());
CPU::log_cpu_information();
Memory::walk_memory_map();
GDT::load();
kinfoln("Loaded GDT");
Interrupts::install();
IDT::load();
kinfoln("Loaded IDT");
PIC::remap();
PIC::enable_master(0b11111100); // enable keyboard and PIT
PIC::enable_slave(0b11111111);
kinfoln("Prepared PIC");
PIT::initialize(1000); // 1000 times per second
kinfoln("Prepared PIT");
Scheduler::init();
kinfoln("Prepared scheduler");
/*Scheduler::add_kernel_task([]() {
int64_t x = 0;
int64_t y = 0;
int64_t xvel = 10;
int64_t yvel = 10;
while (1)
{
sleep(2);
uint32_t color = (uint32_t)Mersenne::get();
x += xvel;
y += yvel;
if ((x + 10) >= framebuffer0.width())
{
xvel = -xvel;
x = (framebuffer0.width() - 10);
}
if ((y + 10) >= framebuffer0.height())
{
yvel = -yvel;
y = (framebuffer0.height() - 10);
}
if (xvel < 0 && (x - 10) < 0)
{
xvel = -xvel;
x = 0;
}
if (yvel < 0 && (y - 10) < 0)
{
yvel = -yvel;
y = 0;
}
framebuffer0.paint_rect(x, y, 10, 10, Color::from_integer(color));
}
});*/
/*Scheduler::add_kernel_task([]() {
while (1)
{
sleep(100);
uint32_t color = (uint32_t)Mersenne::get();
framebuffer0.paint_rect(Mersenne::get() % (framebuffer0.width() - 256),
Mersenne::get() % (framebuffer0.height() - 256), Mersenne::get() % 255,
Mersenne::get() % 255, Color::from_integer(color));
}
});*/
Scheduler::add_kernel_task([]() {
while (1)
{
sleep(400);
Scheduler::reap_tasks();
}
});
uint64_t demo = Mersenne::get() % 5;
switch (demo)
{
case 0:
kinfoln("Loading demo: example init program");
Scheduler::load_user_task("bin/init");
break;
case 1:
kinfoln("Loading demo: first 50 fibonacci numbers");
Scheduler::load_user_task("bin/fib");
break;
case 2:
kinfoln("Loading demo: leap year calculator");
Scheduler::load_user_task("bin/leap");
break;
case 3:
kinfoln("Loading demo: painting program");
Scheduler::load_user_task("bin/art");
break;
case 4:
kinfoln("Loading demo: memory eating program");
Scheduler::load_user_task("bin/memeater");
break;
default: break;
}
kinfoln("Prepared scheduler tasks");
Init::finish_kernel_boot();
Interrupts::enable();
kinfoln("Interrupts enabled");
PCI::scan([](PCI::Device& dev) {
kinfoln("Found PCI device %x:%x, %s", dev.id().vendor, dev.id().device, pci_type_name(dev.type()));
});
Scheduler::exit(0);
}