os

Toy OS
git clone git://git.margiolis.net/os.git
Log | Files | Refs | README | LICENSE

commit 99e45b41b99f1cab5196fef4d5163c448b84eb82
parent a29e0f76250ff463373a8a83c2d47001abcda2ce
Author: Christos Margiolis <christos@margiolis.net>
Date:   Wed,  8 Dec 2021 22:44:37 +0200

still cannot load kernel after 1mb

Diffstat:
MMakefile | 2+-
Mkern/Makefile | 1+
Mkern/boot.s | 30++++++++++++------------------
Mkern/idt.c | 32+++++---------------------------
Mkern/idt.h | 5-----
Mkern/intr.s | 14++++++++------
Mkern/io.h | 6++++++
Mkern/libk.c | 4++--
Mkern/link.ld | 1+
Akern/pic.c | 84+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Akern/pic.h | 34++++++++++++++++++++++++++++++++++
Mkern/vga.c | 2+-
Mkern/vga.h | 2+-
13 files changed, 156 insertions(+), 61 deletions(-)

diff --git a/Makefile b/Makefile @@ -4,7 +4,7 @@ all: cd kern && make install clean && cd - run: - qemu-system-i386 -hda ${TGTDIR}/os.bin -serial stdio + qemu-system-i386 -hda ${TGTDIR}/os.bin -d cpu -monitor stdio clean: rm -rf ${TGTDIR} diff --git a/kern/Makefile b/kern/Makefile @@ -21,6 +21,7 @@ SRC= *.c *.s OBJ= kern_main.o \ libk.o \ idt.o \ + pic.o \ intr.o \ vga.o \ kbd.o \ diff --git a/kern/boot.s b/kern/boot.s @@ -3,8 +3,9 @@ [bits 16] MAGICOFF equ (0x7c00 + 510) +KERNLOAD equ 0x1000 KERNOFF equ 0x1000 -STACKSIZE equ 0x1000 +STACKSIZE equ 8*1024*1024 section .text global _start @@ -12,15 +13,13 @@ section .text ; Entry point. _start: cli ; Disable interrupts. - jmp 0x0000:zeroseg -zeroseg: xor ax, ax ; Clear segment registers. mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax ; Stack starts at 0. - mov bp, _start ; Set the base and stack pointers. + mov bp, _start mov sp, bp cld ; Read strings from low to high. sti ; Enable interrupts back. @@ -196,12 +195,12 @@ diskerr: jmp $ ; There's nothing we can do at this point. disk_packet: - .size db 0x10 - .zero db 0x00 - .count dw 0x0030 ; FIXME: i don't know why this works... - .off16 dw KERNOFF - .seg16 dw 0x0000 - .lba dq 1 + size: db 0x10 + zero: db 0x00 + count: dw 0x0030 ; FIXME: i don't know why this works... + off16: dw KERNLOAD + seg16: dw 0x0000 + lba: dq 1 ; Set up the GDT (Global Descriptor Table). gdt: @@ -266,14 +265,9 @@ pm_init: mov gs, ax mov ss, ax - mov ebp, kern_stack_top - mov esp, ebp + mov esp, kern_stack_top - call kernel_exec - jmp $ - -; Hand control over to the C kernel. Godspeed! You Black Emperor. -kernel_exec: + ; Hand control over to the C kernel. Godspeed! You Black Emperor. call KERNOFF jmp $ @@ -307,6 +301,6 @@ dw 0xaa55 section .bss align 4096 -kern_stack_bottom: equ $ +kern_stack_bottom: resb STACKSIZE kern_stack_top: diff --git a/kern/idt.c b/kern/idt.c @@ -1,10 +1,10 @@ #include <libc.h> #include "libk.h" #include "idt.h" +#include "pic.h" #include "io.h" static void idt_set_gate(struct gate_desc *, void *, u_int, u_int, u_int); -static void pic_remap(void); static struct gate_desc idt[NINT]; static intrhand_t isr[NINT] = { NULL }; @@ -19,22 +19,6 @@ idt_set_gate(struct gate_desc *gd, void *func, u_int sel, u_int dpl, u_int type) gd->gd_lo = (sel << 16) | (addr & 0xffff); } -/* TODO: explain. */ -static void -pic_remap(void) -{ - outb(PIC_MASTER_CMD, 0x11); - outb(PIC_SLAVE_CMD, 0x11); - outb(PIC_MASTER_DATA, 0x20); - outb(PIC_SLAVE_DATA, 0x28); - outb(PIC_MASTER_DATA, 0x04); - outb(PIC_SLAVE_DATA, 0x02); - outb(PIC_MASTER_DATA, 0x01); - outb(PIC_SLAVE_DATA, 0x01); - outb(PIC_MASTER_DATA, 0x00); - outb(PIC_MASTER_DATA, 0x00); -} - extern void INTVEC(div), INTVEC(dbg), INTVEC(nmsk), INTVEC(bpt), INTVEC(ofl), INTVEC(bnd), INTVEC(ill), INTVEC(dna), INTVEC(dbl), INTVEC(fpusegm), INTVEC(tss), INTVEC(missing), INTVEC(stk), INTVEC(prot), INTVEC(page), @@ -141,20 +125,13 @@ intr_handler(struct reg *r) { intrhand_t handler; - /* TODO: dprintf? */ - /* XXX: why did i write this in the first place???? */ - if (r->r_intrno < ARRLEN(exceptmsg)) - printf("sys: trap: %s\n", exceptmsg[r->r_intrno]); if ((handler = isr[r->r_intrno]) != NULL) handler(r); else if (r->r_intrno < ARRLEN(exceptmsg)) { dump_regs(r); panic("%s: system halted\n", exceptmsg[r->r_intrno]); } - /* EOI */ - if (r->r_intrno >= 40) - outb(PIC_SLAVE_CMD, 0x20); - outb(PIC_MASTER_CMD, 0x20); + pic_eoi(r->r_intrno); } void @@ -163,6 +140,7 @@ intr_register_handler(int intrno, intrhand_t handler) if (intrno < 0 || intrno >= NINT) panic("invalid interrupt number: %d\n", intrno); isr[intrno] = handler; + pic_mask(intrno, PIC_CLEAR_MASK); } void @@ -170,8 +148,8 @@ dump_regs(struct reg *r) { printf("eax=%#08x\tebx=%#08x\tecx=%#08x\tedx=%#08x\n", r->r_eax, r->r_ebx, r->r_ecx, r->r_edx); - printf("esp=%#08x\tebp=%#08x\tesi=%#08x\tedi=%#08x\n", - r->r_esp, r->r_ebp, r->r_esi, r->r_edi); + printf("esi=%#08x\tedi=%#08x\tebp=%#08x\tesp=%#08x\n", + r->r_esi, r->r_edi, r->r_ebp, r->r_esp); printf("ds=%#08x \tes=%#08x \tfs=%#08x \tgs=%#08x\n", r->r_ds, r->r_es, r->r_fs, r->r_gs); printf("eip=%#08x\tcs=%#08x \tss=%#08x \teflags=%#08x\n", diff --git a/kern/idt.h b/kern/idt.h @@ -38,11 +38,6 @@ #define UDSEL SELECTOR(UDSEG, SELGDT, UPL) /* TODO: 9front mem.h */ -#define PIC_MASTER_CMD 0x20 -#define PIC_MASTER_DATA (PIC_MASTER_CMD + 1) -#define PIC_SLAVE_CMD 0xa0 -#define PIC_SLAVE_DATA (PIC_SLAVE_CMD + 1) - struct gate_desc { u_int32_t gd_lo; u_int32_t gd_hi; diff --git a/kern/intr.s b/kern/intr.s @@ -64,22 +64,24 @@ intr_common_stub: push es push fs push gs + mov ax, 0x10 ; Kernel data segment descriptor. mov ds, ax mov es, ax mov fs, ax mov gs, ax - mov eax, esp ; Push the stack. - push eax - mov eax, intr_handler - call eax - pop eax + cld + + push esp + call intr_handler + add esp, 4 + pop gs pop fs pop es pop ds popa - add esp, 8 ; Clean up ISR info. + add esp, 8 iret ; I spent many hours debugging this... ; TODO: irq_common_stub bx? diff --git a/kern/io.h b/kern/io.h @@ -66,4 +66,10 @@ sti(void) __asm__ __volatile("sti"); } +static inline void +io_wait(void) +{ + outb(0x80, 0); +} + #endif /* _IO_H_ */ diff --git a/kern/libk.c b/kern/libk.c @@ -358,7 +358,7 @@ printf(const char *fmt, ...) va_start(ap, fmt); n = vsprintf(buf, fmt, ap); va_end(ap); - vga_write(buf); + vga_puts(buf); return (n); } @@ -376,7 +376,7 @@ panic(const char *fmt, ...) va_start(ap, fmt); n = vsprintf(buf, fmt, ap); va_end(ap); - vga_write(buf); + vga_puts(buf); vga_set_color(VGA_BLACK, VGA_WHITE); hlt(); } diff --git a/kern/link.ld b/kern/link.ld @@ -2,6 +2,7 @@ ENTRY(_start) SECTIONS { .text 0x1000 : { + *(text.prologue) *(.text) . = ALIGN(4096); } diff --git a/kern/pic.c b/kern/pic.c @@ -0,0 +1,84 @@ +#include "pic.h" +#include "idt.h" +#include "io.h" + +/* + * BIOS reserves IRQ 0 to 15 for the PIC. We need to remap it to non-reserved + * vectors so that there are no conflicts when setting our IRQs. + */ +void +pic_remap(void) +{ + u_char m1, m2; + + /* Save masks */ + m1 = inb(PIC_MASTER_DATA); + m2 = inb(PIC_SLAVE_DATA); + + /* Reinit both PICs */ + outb(PIC_MASTER_CMD, ICW1_INIT | ICW1_ICW4); + /* Older machines need some time... */ + io_wait(); + outb(PIC_SLAVE_CMD, ICW1_INIT | ICW1_ICW4); + io_wait(); + /* Change offsets */ + outb(PIC_MASTER_DATA, PIC_MASTER_OFFT); + io_wait(); + outb(PIC_SLAVE_DATA, PIC_SLAVE_OFFT); + io_wait(); + /* Slave PIC at IRQ2 */ + outb(PIC_MASTER_DATA, 0x04); + io_wait(); + /* Tell Slave PIC its cascade identity */ + outb(PIC_SLAVE_DATA, ICW1_SINGLE); + io_wait(); + /* 8086 mode */ + outb(PIC_MASTER_DATA, ICW4_8086); + io_wait(); + outb(PIC_SLAVE_DATA, ICW4_8086); + io_wait(); + /* Restore masks */ + outb(PIC_MASTER_DATA, m1); + outb(PIC_SLAVE_DATA, m2); +} + +void +pic_eoi(u_int32_t intrno) +{ + outb(PIC_MASTER_CMD, PIC_EOI); + if (intrno >= IRQ8) + outb(PIC_SLAVE_CMD, PIC_EOI); +} + +void +pic_mask(u_char irq, int flag) +{ + u_int16_t port; + u_int8_t v; + + if (irq < 8) + port = PIC_MASTER_DATA; + else { + port = PIC_SLAVE_DATA; + irq -= 8; + } + if (flag == PIC_SET_MASK) + v = inb(port) | (1 << irq); + else if (flag == PIC_CLEAR_MASK) + v = inb(port) & ~(1 << irq); + else + return; + outb(port, v); +} + +void +pic_on(void) +{ +} + +void +pic_off(void) +{ + outb(PIC_MASTER_DATA, 0xff); + outb(PIC_SLAVE_DATA, 0xff); +} diff --git a/kern/pic.h b/kern/pic.h @@ -0,0 +1,34 @@ +#ifndef _PIC_H_ +#define _PIC_H_ + +#include <u.h> + +#define PIC_MASTER_CMD 0x20 +#define PIC_MASTER_DATA (PIC_MASTER_CMD + 1) +#define PIC_MASTER_OFFT 0x20 +#define PIC_SLAVE_CMD 0xa0 +#define PIC_SLAVE_DATA (PIC_SLAVE_CMD + 1) +#define PIC_SLAVE_OFFT (PIC_MASTER_OFFT + 8) + +#define PIC_SET_MASK 0 +#define PIC_CLEAR_MASK 1 +#define PIC_EOI 0x20 /* End of interrupt */ + +#define ICW1_ICW4 0x01 /* ICW4 not needed */ +#define ICW1_SINGLE 0x02 /* Single cascade mode */ +#define ICW1_INTVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered mode */ +#define ICW1_INIT 0x10 /* Initialization */ +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered slave */ +#define ICW4_BUF_MASTER 0x0c /* Buffered master */ +#define ICW4_SFNM 0x10 /* Special fully nested */ + +void pic_remap(void); +void pic_eoi(u_int32_t); +void pic_mask(u_char, int); +void pic_on(void); +void pic_off(void); + +#endif /* _PIC_H_ */ diff --git a/kern/vga.c b/kern/vga.c @@ -77,7 +77,7 @@ vga_putc(char c) } void -vga_write(const char *str) +vga_puts(const char *str) { while (*str != '\0') vga_putc(*str++); diff --git a/kern/vga.h b/kern/vga.h @@ -25,7 +25,7 @@ enum vga_color { void vga_clear(u_int8_t, u_int8_t); void vga_set_color(u_int8_t, u_int8_t); void vga_putc(char); -void vga_write(const char *); +void vga_puts(const char *); void vga_curs_enable(u_int8_t, u_int8_t); void vga_curs_disable(void); void vga_curs_setpos(int, int);