Files
my-kern/kernel/kernel.c
2021-02-02 22:35:28 +01:00

167 lines
4.3 KiB
C

#include <drivers/ports.h>
#include <drivers/vgascreen.h>
#include <libc/libc.h>
#include <libc/stdbool.h>
#include <cpu/isr.h>
#include <cpu/timer.h>
#include <drivers/keyboard.h>
#include <mem/mem.h>
#include <multiboot.h>
#include <drivers/serial.h>
#include <kprint.h>
#include <libc/readline.h>
#include <libc/string.h>
#include <libk.h>
#define BOOTLOADER_NAME_MAX_LENGTH 64
#define CMDLINE_MAX_LENGTH 256
const char *msg_booted = "Booted Successfully!\n";
const char *newline = "\n";
const char *msg_unknown_command = "Unknown command: ";
char bootloader_name[BOOTLOADER_NAME_MAX_LENGTH];
char cmdline[CMDLINE_MAX_LENGTH];
typedef void (*cmd_handler_func)(const char *);
typedef struct {
char *cmd;
cmd_handler_func handler;
} cmd_handler;
void print(const char *arg);
void echo(const char *arg);
void help(const char *arg);
cmd_handler cmd_handlers[] = {
{"help", help},
{"echo", echo},
{"print", print},
{NULL, NULL},
};
void print_bootinfo() {
kprint("Bootloader name: ");
kprint(bootloader_name[0] == 0 ? "NULL" : bootloader_name);
kprint(newline);
kprint("cmdline: ");
kprint(cmdline[0] == 0 ? "NULL" : cmdline);
kprint(newline);
}
void help(const char* arg) {
kprint("Available commands:\n");
int index = 0;
while (true) {
if (cmd_handlers[index].cmd == NULL) {
break;
}
kprint(cmd_handlers[index].cmd);
kprint(newline);
index += 1;
}
}
void echo(const char *arg) {
kprint(arg);
kprint(newline);
}
void print(const char *arg) {
if (strcmp(arg, "mmap") == 0) {
print_mmap_info();
} else if (strcmp(arg, "malloc") == 0) {
print_malloc_info();
} else if (strcmp(arg, "tick") == 0) {
print_current_tick();
} else if (strcmp(arg, "bootinfo") == 0) {
print_bootinfo();
} else {
kprint("Unknown print ");
kprint(arg);
kprint(newline);
}
}
void main_loop();
void store_bootloader_info(multiboot_info_t *multiboot_info) {
// get bootloader and cmdline
if (multiboot_info->flags & MULTIBOOT_INFO_CMDLINE) {
int cmdline_length = strlen((const char *) multiboot_info->cmdline);
if (cmdline_length > CMDLINE_MAX_LENGTH) {
kprint("cmdline to long!");
k_panic();
}
memcpy(cmdline, (char *) multiboot_info->cmdline, cmdline_length);
}
if (multiboot_info->flags & MULTIBOOT_INFO_BOOT_LOADER_NAME) {
int bootloader_length = strlen((const char *) multiboot_info->boot_loader_name);
if (bootloader_length > BOOTLOADER_NAME_MAX_LENGTH) {
kprint("bootloader name to long!");
k_panic();
}
memcpy(bootloader_name, (char *) multiboot_info->boot_loader_name, bootloader_length);
}
}
void init_mmap(multiboot_info_t *multiboot_info) {
if (multiboot_info->flags & (1 << 6)) {
init_mmap_multiboot((struct multiboot_mmap_entry *) multiboot_info->mmap_addr,
multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry));
// todo fallback on other mechanisms?
} else {
kprint("mmap invalid!\n");
k_panic();
}
}
void kmain(multiboot_info_t *multiboot_info) {
isr_install();
vga_clear_screen();
vga_clear_screen(' ', VGA_WHITE | (VGA_GRAY << VGA_SHIFT_BG));
kprint_register(vga_kprint);
serial_init();
kprint_register(serial_kprint);
store_bootloader_info(multiboot_info);
init_mmap(multiboot_info);
kprint(msg_booted);
kprint(newline);
// init done, enable interrupts
__asm__ __volatile__("sti");
// init timer for future task switching
init_timer(50);
// setup PS/2 keyboard
init_keyboard();
// enter main loop
while (true) {
main_loop();
}
}
void main_loop() {
char *msg = readline(NULL);
char *args = strchr(msg, ' ') + 1;
args[-1] = 0;
int test_index = 0;
while (true) {
if (cmd_handlers[test_index].cmd == 0) {
kprint(msg_unknown_command);
kprint(msg);
kprint(newline);
break;
}
if (strcmp(cmd_handlers[test_index].cmd, msg) == 0) {
cmd_handlers[test_index].handler(args);
break;
}
test_index++;
}
free(msg);
}