#define DEBUG
#include <sys/atpic.h>
#include <sys/console.h>
#include <sys/io.h>
#include <sys/kernel.h>
#include <sys/memory.h>
#include <sys/paging.h>
#include <sys/proc.h>
#include <sys/types.h>
#include <dev/blockdev.h>
#include <dev/ide.h>
#include <fs/ext2.h>
#include <kern/scheduler.h>
#include <stdlib.h>
#include <debug.h>
console_t global_console;
static inline void idle(void) {
asm volatile ("hlt" : : );
}
struct gdt_entry {
uint16_t limit_low;
uint16_t base_low;
uint8_t base_middle;
uint8_t access;
uint8_t flags;
uint8_t base_high;
} __attribute__((__packed__));
struct gdt_desc {
uint16_t limit;
uint32_t addr;
} __attribute__((__packed__));
struct gdt_entry gdt[6];
static void setup_gdt(void);
static void setup_tss(void);
static struct proc *launch(const char *binary, uint32_t mem);
void kernel_main() {
kprint("kernel main entered\n");
console_init(&global_console);
setup_gdt();
kmem_init();
paging_init();
console_clear(&global_console);
console_print(&global_console, "xos kernel loaded\n");
setup_idt();
struct proc *proc1 = launch("/init", 0x70000000);
struct proc *proc2 = launch("/init2", 0x70000000);
sched_add(proc1);
sched_add(proc2);
sched_run_next_proc();
while(1){idle();};
}
static struct proc *launch(const char *binary, uint32_t mem) {
struct blockdev *hda0 = ide_create_partition(IDE_CHANNEL_PRIMARY, IDE_DRIVE_MASTER, 0);
ext2_mount *root = fs_mount_ext2(hda0);
void *init_code = kmalloc_align(PAGE_SIZE, 4096);
void *init_data2 = kmalloc_align(PAGE_SIZE, 4096);
struct proc *p = proc_create();
uint32_t in = fs_find(root, binary);
ext2_inode init_file;
fs_read_inode(root, in, &init_file);
/*fs_inode_read_block(root, &init_file, 0, init_code);*/
void *code_mapped = (void *)mem;
void *code_mapped2 = (void *)(mem + PAGE_SIZE);
pd_map_page(p->pd, code_mapped, init_code, PT_FLAG_USER | PT_FLAG_WRITABLE);
pd_map_page(p->pd, code_mapped2, init_data2, PT_FLAG_USER | PT_FLAG_WRITABLE);
fs_inode_read_block(root, &init_file, 0, init_code);
*(p->pcb) = (struct pcb){
.esp = mem + 2*PAGE_SIZE,
.eip = (uint32_t)code_mapped,
.eax = 42,
.ebp = 0,
};
return p;
}
void panic(const char *msg) {
kprint("\n\nPANIC\n=====\n\n");
kprint(msg);
console_print(&global_console, "\n\nPANIC\n=====\n\n");
console_print(&global_console, msg);
while(1) {};
}
static void setup_gdt(void) {
gdt[0] = (struct gdt_entry){0};
// kernel code
gdt[1] = (struct gdt_entry){limit_low: 0xffff, base_low: 0, base_middle: 0, access: 0x9a, flags: 0xcf, base_high: 0};
// kernel data
gdt[2] = (struct gdt_entry){limit_low: 0xffff, base_low: 0, base_middle: 0, access: 0x92, flags: 0xcf, base_high: 0};
// userspace code
gdt[3] = (struct gdt_entry){limit_low: 0xffff, base_low: 0, base_middle: 0, access: 0xfa, flags: 0xcf, base_high: 0};
// userspace data
gdt[4] = (struct gdt_entry){limit_low: 0xffff, base_low: 0, base_middle: 0, access: 0xf2, flags: 0xcf, base_high: 0};
// userspace tss
gdt[5] = (struct gdt_entry){limit_low: 0xffff, base_low: 0, base_middle: 0, access: 0x92, flags: 0xcf, base_high: 0};
struct gdt_desc gdt_load = {limit: 6 * 8, addr: (uint32_t)gdt};
asm volatile (
"lgdt %0\n"
:
: "m"(gdt_load)
: "memory"
);
setup_tss();
}
struct tss_entry {
uint32_t link;
uint32_t esp0;
uint32_t ss0;
uint32_t pad[23];
} __attribute__((__packed__));
struct tss_entry userspace_tss;
static void setup_tss(void) {
uint32_t base = (uint32_t)&userspace_tss;
uint32_t limit = sizeof(userspace_tss);// + (uint32_t)&userspace_tss;
gdt[5] = (struct gdt_entry){
base_low: (base & 0xffff),
base_middle: (base >> 16) & 0xff,
base_high: (base >> 24) & 0xff,
limit_low: (limit & 0xffff),
access: 0xe9,
flags: 0x00,
};
userspace_tss.esp0 = 0x200000 - 0x20000; // FIXME: this leaves 128k of regular kernel stack space
userspace_tss.ss0 = 0x10;
asm volatile (
"mov $0x2b, %%ax\n"
"ltr %%ax"
:
:
: "eax"
);
}
void syscall_entry(uint32_t syscall) {
khexprint("syscall", syscall);
khexprint("current esp", current->pcb->esp);
khexprint("current eip", current->pcb->eip);
if (syscall == 4) {
uint32_t fd = *(uint32_t *)(current->pcb->esp + 4);
void *buf = *(void **)(current->pcb->esp + 8);
uint32_t len = *(uint32_t *)(current->pcb->esp + 12);
khexprint("fd", fd);
khexprint("buf", (uint32_t)buf);
khexprint("len", len);
char msg[128];
memcpy(msg, buf, len);
msg[len] = '\0';
console_print(&global_console, msg);
}
sched_run_next_proc();
}