diff --git a/boot/kernel.asm b/boot/kernel.asm index 3a089bf..d68eef7 100644 --- a/boot/kernel.asm +++ b/boot/kernel.asm @@ -1,88 +1,78 @@ cpu 8086 - org 0x7C00 + org 0 + jmp 0x07C0:init -stack: equ 0x7C00 -framsz: equ 0x300 + %include "inc/bpb.asm" - jmp init +banner: db "rdos", 0xA, 0xD, 0 - ; Data on user stack while in kernel (5 words): - ; AX BP IP CS flags + ; syscalls push a register set to stack + ; this is for accessing it +rsdssi: equ 0x08 +rsesdi: equ 0x0C +rsbp: equ 0x10 +rslpad: equ 0x12 +rscsip: equ 0x14 +rsflag: equ 0x18 - ; Kernel stack: - ; [frame] SP SS - ; BP-^ - ; The start of the frame is available via BP. - ; The frame is followed by a long ptr to the user stack. +lpads: times 0x30 call entry - ; Main entry point -int20h: xor ah, ah -int21h: push bp - push ax - ; Test if SS=0, if it is, we assume we are already on kernel stack - mov ax, ss - test ax, ax - jz rentry - - ; Save user stack - mov ax, ss - mov [cs:stack-2], ax - mov [cs:stack-4], sp - - ; Set up kernel stack - xor ax, ax - mov ss, ax - mov sp, (stack-4) - - jmp scall - - ; This is like the above, except that it doesnt switch stacks. - ; The 'user' stack data is after (below on stack) the kernel frame. - ; [frame] SP SS AX BP IP CS flags - ; \-\--^ -rentry: mov ax, sp - push ss +entry: push bp + ; BX+0C: ES:DI + push es + push di + ; BX+08: DS:SI + push ds + push si + ; BX+00: AX,CX,DX,BX + push bx + push dx + push cx push ax -scall: sub sp, framsz - mov bp, sp + mov ax, ss + mov es, ax + mov bx, sp - call getax - call jmptab - - ; Restore user stack - mov sp, [bp+framsz] - mov ax, [bp+framsz+2] + ; This needs to be done when coming from userspace + mov ax, cs mov ss, ax + xor sp, sp + int 3 + + ; Jump back to userspace +ujump: cli + mov ax, es + mov ss, ax + mov sp, bx + + ; Pop whole registerset + ; base registers pop ax + pop cx + pop dx + pop bx + ; string ptrs + pop si + pop ds + pop di + pop es + ; BP is special pop bp + ; skip landing pad number + add sp, 2 + ; pop IP, CS and flags iret - ; Lookup address of subfunction - ; Mesh up the stack so we return to subfunction - ; and subfunction later returns to scall -jmptab: push ax - push bx - xor bx, bx - add bl, ah - add bl, ah - mov bx, [cs:bx+sftab] - mov [bp-4], bx - pop bx + ; Processes register set DS:BX as syscall +scall: ; Clear status flags + and byte [bx+rsflag], 0 ret - ; Get AX from the user stack -getax: push ds - push si - lds si, [bp+framsz] - lodsw - pop ds - pop si - ret - - ; No such subfunction - set carry and exit -sferr: stc + ; No such subfunction +sferr: ; set carry + or byte [bx+rsflag], 1 ret ; Subfunction table @@ -146,34 +136,93 @@ setint: push es pop es ret -; ===== end of resident, begin of transient startup code +bpb: times bpb_len db 0 +drvnum: db 0 + align 4 +drvpos: dd 0 +buffer: times 512 db 0 -init: xor ax, ax + ; Select active drive + ; IN dl drive number A=0, B=1, C=2, ... +select: mov [drvnum], dl + ret + + ; Set sector number +seek: mov [drvpos], ax + mov [drvpos+2], dx + ret + + ; Read sector from disk +read: ; this uses the EBIOS extensions + + ; qword sector number + xor ax, ax + push ax + push ax + mov ax, [drvpos+2] + push ax + mov ax, [drvpos] + push ax + + ; dword target buffer + mov ax, buffer + push cs + push ax + + ; word number of sectors + mov ax, 1 + push ax + + ; size & passing + mov di, 0x10 + push di + + mov si, sp + mov ah, 0x42 + mov dl, [drvnum] + call dnconv + stc + int 0x13 + + add sp, di + + ret + + ; Convert between drive number and BIOS dl + ; Bidirectional mapping + ; 0 <-> 0, 1 <-> 1, 2 <-> 0x80, 3 <-> 0x81 +dnconv: mov cx, 7 + ror dx, 1 + rol dl, 1 +dncl: rcl dl, 1 + rcr dh, 1 + loop dncl + xchg dh, dl + ret + +init: cli + mov ax, cs mov ds, ax mov es, ax - mov ax, 0x1000 mov ss, ax xor sp, sp - mov al, 0x21 - mov dx, int21h - call setint + xor dh, dh + call dnconv + call select - mov ax, 0x2520 - mov dx, int20h - int 0x21 + xor ax, ax + xor dx, dx + call seek - mov ax, 0x3520 - int 0x21 + call read - mov ah, 0x3f - int 3 - int 0x21 + mov ax, [buffer+0x1FE] int 3 main: push cs pop ds - mov si, msg + mov si, banner mov ah, 0x0e xor bx, bx loop: lodsb @@ -184,4 +233,3 @@ loop: lodsb end: hlt jmp end -msg: db "rdos kernel stub", 0x0A, 0x0D, 0