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:
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);