Files
jsix_import/src/kernel/main.cpp
Justin C. Miller e477dea5c7 [fb] Output klog to fb if video exists
If there's no video, do as we did before, otherwise route logs to the fb
driver instead. (Need to clean this up to just have a log consumer
general interface?) Also added a "scrollback" class to fb driver and
updated the system_get_log syscall.
2021-01-18 13:48:11 -08:00

206 lines
4.6 KiB
C++

#include <stddef.h>
#include <stdint.h>
#include "j6/signals.h"
#include "kutil/assert.h"
#include "apic.h"
#include "block_device.h"
#include "console.h"
#include "cpu.h"
#include "device_manager.h"
#include "gdt.h"
#include "interrupts.h"
#include "io.h"
#include "kernel_args.h"
#include "kernel_memory.h"
#include "log.h"
#include "objects/channel.h"
#include "objects/event.h"
#include "objects/thread.h"
#include "scheduler.h"
#include "serial.h"
#include "symbol_table.h"
#include "syscall.h"
#ifndef GIT_VERSION
#define GIT_VERSION
#endif
extern "C" {
void kernel_main(kernel::args::header *header);
void (*__ctors)(void);
void (*__ctors_end)(void);
}
void
run_constructors()
{
void (**p)(void) = &__ctors;
while (p < &__ctors_end) {
void (*ctor)(void) = *p++;
ctor();
}
}
extern void __kernel_assert(const char *, unsigned, const char *);
/// Bootstrap the memory managers.
void memory_initialize_pre_ctors(kernel::args::header *kargs);
void memory_initialize_post_ctors(kernel::args::header *kargs);
using namespace kernel;
/// TODO: not this. this is awful.
args::framebuffer *fb = nullptr;
void
init_console()
{
serial_port *com1 = new (&g_com1) serial_port(COM1);
console *cons = new (&g_console) console(com1);
cons->set_color(0x21, 0x00);
cons->puts("jsix OS ");
cons->set_color(0x08, 0x00);
cons->puts(GIT_VERSION " booting...\n");
}
channel *std_out = nullptr;
void
stdout_task()
{
uint8_t buffer[257];
auto *ent = reinterpret_cast<log::logger::entry *>(buffer);
auto *cons = console::get();
log::info(logs::task, "Starting kernel stdout task");
scheduler &s = scheduler::get();
thread *th = thread::from_tcb(s.current());
while (true) {
j6_signal_t current = std_out->signals();
if (!(current & j6_signal_channel_can_recv)) {
th->wait_on_signals(std_out, j6_signal_channel_can_recv);
s.schedule();
}
size_t n = 256;
j6_status_t status = std_out->dequeue(&n, buffer);
if (status != j6_status_ok) {
log::warn(logs::task, "Kernel stdout error: %x", status);
return;
}
buffer[n] = 0;
const char *s = reinterpret_cast<const char *>(buffer);
while (n) {
size_t r = cons->puts(s);
n -= r + 1;
s += r + 1;
}
}
}
void
kernel_main(args::header *header)
{
kutil::assert_set_callback(__kernel_assert);
init_console();
logger_init();
gdt_init();
interrupts_init();
memory_initialize_pre_ctors(header);
run_constructors();
memory_initialize_post_ctors(header);
cpu_id cpu;
cpu.validate();
for (size_t i = 0; i < header->num_modules; ++i) {
args::module &mod = header->modules[i];
switch (mod.type) {
case args::mod_type::symbol_table:
new symbol_table {mod.location, mod.size};
break;
default:
break;
}
}
bool has_video = false;
if (header->video.size > 0) {
fb = memory::to_virtual<args::framebuffer>(reinterpret_cast<uintptr_t>(&header->video));
has_video = true;
logger_clear_immediate();
}
log::debug(logs::boot, " jsix header is at: %016lx", header);
log::debug(logs::boot, " Memory map is at: %016lx", header->mem_map);
log::debug(logs::boot, "ACPI root table is at: %016lx", header->acpi_table);
log::debug(logs::boot, "Runtime service is at: %016lx", header->runtime_services);
device_manager &devices = device_manager::get();
devices.parse_acpi(header->acpi_table);
interrupts_enable();
devices.init_drivers();
devices.get_lapic()->calibrate_timer();
/*
block_device *disk = devices->get_block_device(0);
if (disk) {
for (int i=0; i<1; ++i) {
uint8_t buf[512];
kutil::memset(buf, 0, 512);
kassert(disk->read(0x200, sizeof(buf), buf),
"Disk read returned 0");
console *cons = console::get();
uint8_t *p = &buf[0];
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 16; ++j) {
cons->printf(" %02x", *p++);
}
cons->putc('\n');
}
}
} else {
log::warn(logs::boot, "No block devices present.");
}
*/
syscall_enable();
scheduler *sched = new scheduler(devices.get_lapic());
std_out = new channel;
// Skip program 0, which is the kernel itself
for (size_t i = 1; i < header->num_programs; ++i) {
args::program &prog = header->programs[i];
thread *th = sched->load_process(prog.phys_addr, prog.virt_addr, prog.size, prog.entrypoint);
if (i == 2) {
//th->set_state(thread::state::constant);
}
}
if (!has_video)
sched->create_kernel_task(logger_task, scheduler::max_priority-1, true);
sched->create_kernel_task(stdout_task, scheduler::max_priority-1, true);
const char stdout_message[] = "Hello on the fake stdout channel\n";
size_t message_size = sizeof(stdout_message);
std_out->enqueue(&message_size, reinterpret_cast<const void*>(stdout_message));
sched->start();
}