From 88e57cf7f2581900eb31cb835a18ad414e37786c Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sat, 19 Nov 2022 04:40:01 +0200 Subject: [PATCH] foo --- .gitignore | 3 +- kern/Makefile | 6 +-- kern/kern.ld | 15 +++---- kern/src/asmutil.h | 61 ++++++++++++++++++++++++++ kern/src/boot.asm | 30 ++++++++----- kern/src/con.h | 11 +++++ kern/src/disp.c | 104 +++++++++++++++++++++++++++++++++++++++++++ kern/src/disp.h | 31 +++++++++++++ kern/src/intr.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++ kern/src/intr.h | 48 ++++++++++++++++++++ kern/src/intrent.asm | 63 +++++++++++++++++++++++++++ kern/src/libc/inttypes.h | 11 +++++ kern/src/main.c | 9 ++++ 13 files changed, 477 insertions(+), 24 deletions(-) create mode 100644 kern/src/asmutil.h create mode 100644 kern/src/con.h create mode 100644 kern/src/disp.c create mode 100644 kern/src/disp.h create mode 100644 kern/src/intr.c create mode 100644 kern/src/intr.h create mode 100644 kern/src/intrent.asm create mode 100644 kern/src/libc/inttypes.h diff --git a/.gitignore b/.gitignore index 8a10a5b..8821a9c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ *.swp *.img *.map -dis1 -dis2 +dis *.log 86kern diff --git a/kern/Makefile b/kern/Makefile index 70e479b..f4ff034 100644 --- a/kern/Makefile +++ b/kern/Makefile @@ -13,13 +13,14 @@ CC = ia16-elf-gcc LD = ia16-elf-ld CFLAGS = -march=i8088 -mtune=i8088 -MMD +LDFLAGS = -T kern.ld -Map kern.map $(img): $(bin) dd if=/dev/zero of=$@ bs=512 count=$(disk_numsec) dd if=$< of=$@ bs=512 conv=notrunc $(bin): $(obj) - $(LD) -T kern.ld -Map kern.map -o $@ $(obj) + $(LD) -o $@ $(obj) $(LDFLAGS) -include $(dep) @@ -45,5 +46,4 @@ debug: $(img) .PHONY: disasm disasm: $(bin) - ndisasm -o 0x7c00 $< >dis1 - ndisasm -o 0x98000 -e 512 $< >dis2 + ndisasm -o 0x600 $< >dis diff --git a/kern/kern.ld b/kern/kern.ld index 3922811..c851a6d 100644 --- a/kern/kern.ld +++ b/kern/kern.ld @@ -2,19 +2,18 @@ OUTPUT_FORMAT(binary) ENTRY(_start) SECTIONS { - . = 0x7c00; + /* we'll relocate the boot sector to this address immediately, and + * continue loading the kernel from the end of it + */ + . = 0x600; + _bootsect_start = .; .bootsect : { * (.bootsect); } - _bootsect_end = .; - /* load high out of the way, to leave the rest of RAM for userland - * reserving the top 32kb for the kernel for now - */ - . = 0x98000; _kern_start = .; _kern_start_seg = _kern_start >> 4; - .text : AT(_bootsect_end) { + .text : { * (.startup); * (.text*); } @@ -22,7 +21,7 @@ SECTIONS { * (.rodata*); * (.data*); } - .bss ALIGN(4) (NOLOAD): { + .bss ALIGN(4): { _bss_start = .; _bss_start_off = _bss_start - _kern_start; * (.bss*); diff --git a/kern/src/asmutil.h b/kern/src/asmutil.h new file mode 100644 index 0000000..751def6 --- /dev/null +++ b/kern/src/asmutil.h @@ -0,0 +1,61 @@ +#ifndef ASMUTIL_H_ +#define ASMUTIL_H_ + +#include + +struct wordregs { + uint16_t ax, bx, cx, dx; + uint16_t si, di, cflag; +} __attribute__((packed)); + +struct byteregs { + uint8_t al, ah; + uint8_t bl, bh; + uint8_t cl, ch; + uint8_t dl, dh; +} __attribute__((packed)); + +union regs { + struct wordregs w; + struct byteregs h; +}; + +void int86(int n, union regs *inregs, union regs *outregs); + +#define FP_SEG(x) ((uint16_t)((uint32_t)(x) >> 16)) +#define FP_OFFS(x) ((uint16_t)(x)) +#define MK_FP(s, o) (((uint32_t)(s) << 16) | (uint32_t)(o)) + +#define enable() asm("sti") +#define disable() asm("cli") + +#define outp(p, v) \ + asm volatile( \ + "outb %1, %0" \ + :: "d"(p), "a"((unsigned char)v)) + +#define outpw(p, v) \ + asm volatile( \ + "outw %1, %0" \ + :: "d"(p), "a"((unsigned short)v)) + +static inline unsigned char inp(int p) +{ + unsigned char res; + asm volatile( + "inb %1, %0" \ + : "=a"(res) : "d"(p)); + return res; +} + +static inline unsigned short inpw(int p) +{ + unsigned short res; + asm volatile( + "inw %1, %0" \ + : "=a"(res) : "d"(p)); + return res; +} + + +#endif /* ASMUTIL_H_ */ diff --git a/kern/src/boot.asm b/kern/src/boot.asm index 5be618b..25486e6 100644 --- a/kern/src/boot.asm +++ b/kern/src/boot.asm @@ -3,18 +3,19 @@ bits 16 section .bootsect +extern _bootsect_start extern _kern_start_seg extern _kern_size -boot_driveno equ 7b00h -num_read_tries equ 7b06h ; 2 bytes -sect_pending equ 7b08h ; 2 bytes -sect_per_track equ 7b0ah ; 2 bytes -cur_head equ 7b0ch ; 2 bytes - current head -start_sect equ 7b0eh ; 2 bytes - start sector in track -destptr equ 7b10h ; 2 bytes - destination pointer -num_heads equ 7b12h ; 2 bytes - number of heads -cur_cyl equ 7b14h ; 2 bytes - current cylinder +boot_driveno equ 0500h +num_read_tries equ 0506h ; 2 bytes +sect_pending equ 0508h ; 2 bytes +sect_per_track equ 050ah ; 2 bytes +cur_head equ 050ch ; 2 bytes - current head +start_sect equ 050eh ; 2 bytes - start sector in track +destptr equ 0510h ; 2 bytes - destination pointer +num_heads equ 0512h ; 2 bytes - number of heads +cur_cyl equ 0514h ; 2 bytes - current cylinder %macro floppy_motor_off 0 pushf @@ -66,10 +67,17 @@ start: mov ds, ax mov es, ax mov ss, ax + mov [boot_driveno], dl ; save boot drive number + + ; relocate boot sector to 600h + mov si, 0x7c00 + mov di, _bootsect_start + mov cx, 256 + rep movsw + jmp 00:.setcs .setcs: - mov sp, 0x7b00 ; temp stack below our vars - mov [boot_driveno], dl + mov sp, _bootsect_start ; temp stack below our relocated address ; query sectors per track mov ah, 8 ; get drive parameters call, dl already has the drive diff --git a/kern/src/con.h b/kern/src/con.h new file mode 100644 index 0000000..9a356fc --- /dev/null +++ b/kern/src/con.h @@ -0,0 +1,11 @@ +#ifndef CON_H_ +#define CON_H_ + +struct console { + void (*clear)(void*); + void (*putc)(void*, char c); + + void *data; +}; + +#endif /* CON_H_ */ diff --git a/kern/src/disp.c b/kern/src/disp.c new file mode 100644 index 0000000..f6e9014 --- /dev/null +++ b/kern/src/disp.c @@ -0,0 +1,104 @@ +#include "disp.h" + +static void detect_video(void); + +struct console con_disp = { clear_disp, disp_putc, 0 }; + +static uint16_t __far *vmem; +static uint16_t cur_attr; +static int cur_x, cur_y; +static int cur_scroll; +static int mono; + +void init_disp(void) +{ + detect_video(); +} + +static void detect_video(void) +{ + mono = 0; + disp_type = DISP_UNK; + + if(detect_vgainfo() == 0) { + goto done; + } + if(detect_egainfo() == 0) { + goto done; + } + if(detect_eqlist() == 0) { + goto done; + } + +done: + vmem = mono ? MK_FP(0xb000, 0) : MK_FP(0xb800, 0); +} + +static int detect_vgainfo(void) +{ + union regs regs; + + regs.w.ax = 0x1a00; + int86(0x10, ®s, ®s); + if(regs.h.al != 0x1a) { + return -1; + } + + switch(regs.h.bl) { + case 1: + disp_type = DISP_MDA; + mono = 1; + break; + case 2: + disp_type = DISP_CGA; + break; + case 4: + disp_type = DISP_EGA; + break; + case 5: + disp_type = DISP_EGA; + mono = 1; + break; + case 6: + disp_type = DISP_PGA; + break; + case 7: + disp_type = DISP_VGA; + mono = 1; + break; + case 8: + disp_type = DISP_VGA; + break; + case 0xa: + case 0xc: + disp_type = DISP_MCGA; + break; + case 0xb: + disp_type = DISP_MCGA; + mono = 1; + break; + default: + return -1; + } + return 0; +} + +static int detect_egainfo(void) +{ + union regs regs; + + regs.w.ax = 0x1200; + regs.w.bx = 0xff10; + int86(0x10, ®s, ®s); + if(regs.h.bh == 0xff) { + return -1; + } + + disp_type = DISP_EGA; + mono = regs.h.bh; + return 0; +} + +static int detect_eqlist(void) +{ +} diff --git a/kern/src/disp.h b/kern/src/disp.h new file mode 100644 index 0000000..48a4d0a --- /dev/null +++ b/kern/src/disp.h @@ -0,0 +1,31 @@ +#ifndef DISP_H_ +#define DISP_H_ + +#include +#include "con.h" + +enum { + BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LTGREY, + GREY, LTBLUE, LTGREEN, LTCYAN, LTRED, LTMAGENTA, YELLOW, WHITE +}; + +enum { DISP_UNK, DISP_MDA, DISP_CGA, DISP_EGA, DISP_PGA, DISP_MCGA, DISP_VGA }; + +#define DISP_ATTR(fg, bg) (((uint8_t)(bg) << 4) | ((uint8_t)(fg))) + +extern struct console con_disp; +int disp_type; + +void init_disp(void); + +void clear_disp(void); +void scroll_disp(int line); + +void set_cursor(int x, int y); +void set_fgcolor(int color); +void set_bgcolor(int color); + +void draw_glyph(int x, int y, int c, int attr); +void draw_text(int x, int y, const char *s, int attr); + +#endif /* DISP_H_ */ diff --git a/kern/src/intr.c b/kern/src/intr.c new file mode 100644 index 0000000..e682b30 --- /dev/null +++ b/kern/src/intr.c @@ -0,0 +1,109 @@ +#include "intr.h" + +/* PIC command and data ports */ +#define PIC1_CMD 0x20 +#define PIC1_DATA 0x21 +#define PIC2_CMD 0xa0 +#define PIC2_DATA 0xa1 + +/* PIC initialization command word 1 bits */ +#define ICW1_ICW4_NEEDED (1 << 0) +#define ICW1_SINGLE (1 << 1) +#define ICW1_INTERVAL4 (1 << 2) +#define ICW1_LEVEL (1 << 3) +#define ICW1_INIT (1 << 4) +/* PIC initialization command word 4 bits */ +#define ICW4_8086 (1 << 0) +#define ICW4_AUTO_EOI (1 << 1) +#define ICW4_BUF_SLAVE (1 << 3) /* 1000 */ +#define ICW4_BUF_MASTER (3 << 2) /* 1100 */ +#define ICW4_SPECIAL (1 << 4) +/* PIC operation command word 2 bits */ +#define OCW2_EOI (1 << 5) + + +#define MAX_INTR 32 +static intr_func_t intrfunc[MAX_INTR]; + +static void (*intr_unhandled)(struct intr_frame *frm); + +void intr_entry_div(); +void intr_entry_trap(); +void intr_entry_nmi(); +void intr_entry_break(); +void intr_entry_ovf(); +void intr_entry_bound(); +void intr_entry_ill(); +void intr_entry_irq0(); +void intr_entry_irq1(); +void intr_entry_irq2(); +void intr_entry_irq3(); +void intr_entry_irq4(); +void intr_entry_irq5(); +void intr_entry_irq6(); +void intr_entry_irq7(); + +extern int _kern_start_seg; +#define KERN_CS ((uint16_t)(&_kern_start_seg)) + + +void init_intr(void) +{ + int i; + + for(i=0; i +#include "asmutil.h" + +#define IRQ_TO_INUM(x) ((x) + 8) +#define INUM_TO_IRQ(x) ((x) - 8) + +/* general purpose registers, pushed by interrupt entry routine */ +struct registers { + uint16_t di, si, bp, sp; + uint16_t bx, dx, cx, ax; +} __attribute__((packed)); + +struct intr_frame { + /* registers pushed by intr_entry_* */ + struct registers regs; + /* interrupt number */ + uint16_t inum; + /* pushed by CPU during interrupt entry */ + uint16_t ip, cs, flags; +} __attribute__((packed)); + +typedef void (*intr_func_t)(struct intr_frame *frm); + +void init_intr(void); +void dispatch_intr(struct intr_frame frm); + +/* set low level interrupt vector */ +void set_intr_vect(int n, uint16_t seg, uint16_t offs); +/* set interrupt callback */ +void set_intr(int n, intr_func_t func); + +void mask_irq(int n); +void unmask_irq(int n); + +#define end_of_irq(n) \ + asm volatile( \ + "\n\ttest $8, %0" \ + "\n\tjz 0f" \ + "\n\tmov $0x20, %%ax" \ + "\n\tout %%ax, $0xa0" \ + "\n0:\tmov $0x20, %%ax" \ + "\n\tout %%ax, $0x20" \ + :: "a"(n)) + +#endif /* INTR_H_ */ diff --git a/kern/src/intrent.asm b/kern/src/intrent.asm new file mode 100644 index 0000000..0fd515d --- /dev/null +++ b/kern/src/intrent.asm @@ -0,0 +1,63 @@ +; interrupt entry routines + cpu 8086 + bits 16 + section .text + +extern dispatch_intr + +%macro INTR_ENTRY 2 +global intr_entry_%2 +intr_entry_%2: + push bp + push ax + push bp + mov bp, sp + mov ax, %1 + mov [bp + 4], ax + pop bp + pop ax + jmp intr_entry_common +%endmacro + +intr_entry_common: + push ax + mov ax, sp + add ax, 2 + push cx + push dx + push bx + push ax ; saved sp + push bp + push si + push di + call dispatch_intr + pop di + pop si + pop bp + pop bx ; throw away saved sp + pop bx + pop dx + pop cx + pop ax + add sp, 2 ; remove interrupt number from the stack + iret + +; CPU exceptions +INTR_ENTRY 0, div +INTR_ENTRY 1, trap +INTR_ENTRY 2, nmi +INTR_ENTRY 3, break +INTR_ENTRY 4, ovf +INTR_ENTRY 5, bound +INTR_ENTRY 6, ill +; IRQs +INTR_ENTRY 8, irq0 +INTR_ENTRY 9, irq1 +INTR_ENTRY 10, irq2 +INTR_ENTRY 11, irq3 +INTR_ENTRY 12, irq4 +INTR_ENTRY 13, irq5 +INTR_ENTRY 14, irq6 +INTR_ENTRY 15, irq7 + +; vi:ts=8 sts=8 sw=8 ft=nasm: diff --git a/kern/src/libc/inttypes.h b/kern/src/libc/inttypes.h new file mode 100644 index 0000000..27fc5ab --- /dev/null +++ b/kern/src/libc/inttypes.h @@ -0,0 +1,11 @@ +#ifndef KLIBC_INTTYPES_H_ +#define KLIBC_INTTYPES_H_ + +typedef signed char int8_t; +typedef short int16_t; +typedef long int32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; + +#endif /* KLIBC_INTTYPES_H_ */ diff --git a/kern/src/main.c b/kern/src/main.c index 1ca879b..71a613f 100644 --- a/kern/src/main.c +++ b/kern/src/main.c @@ -1,13 +1,22 @@ +#include "intr.h" + void kmain(void) { + /* int i, j; unsigned short __far *vmem = (void __far*)0xb8000000ul; unsigned short c; + */ + + init_disp(); + init_intr(); + /* for(i=0; i<25; i++) { c = ((i & 0xf) << 8) | '@'; for(j=0; j<80; j++) { *vmem++ = c; } } + */ } -- 1.7.10.4