diff --git a/Makefile b/Makefile index eef5ab7..b05fd49 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,8 @@ vga11.com: cp437.bin %.bs: boot/%.asm $(NASM) $(NASM_ARGS) -o $@ $< +kernel.bs: kernel/*.asm + # Special case: variations of FAT vbr fat1.bs: boot/fat.asm $(NASM) $(NASM_ARGS) -DFAT12 -DCHS -o $@ $< diff --git a/boot/kernel.asm b/boot/kernel.asm index 954aa03..4fff9eb 100644 --- a/boot/kernel.asm +++ b/boot/kernel.asm @@ -10,8 +10,8 @@ %endmacro ; Far jump via interrupt vector - %macro intjump 1 - jump far [cs:%1*4] + %macro intjmp 1 + jmp far [cs:%1*4] %endmacro ; stack size @@ -22,7 +22,7 @@ banner: db "rdos", 0xA, 0xD, '$' ; Alias for Int 21h,AH=0h int20h: xor ah, ah ; allow extenders to get away with only hooking 21h - jmp [cs:(0x21 * 4)] + intjmp 0x21 int21h: ; inside of kernel, direction always goes up ; the iret will restore it to the user value later @@ -48,6 +48,7 @@ iretfl: push ax pop ax ; iret frame: IP CS FLAGS iret: iret +retf: retf ; Subfunction ptr ; this is used as extra register in int21h @@ -171,185 +172,6 @@ getint: xor bx, bx sferr: stc 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 - - ; 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, [cs:drvpos+2] - push ax - mov ax, [cs: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, [cs:drvnum] - call dnconv - stc - int 0x13 - - add sp, di - ret - - ; Select active drive - ; IN dl drive number A=0, B=1, C=2, ... -select: mov [cs:drvnum], dl - ret - push es - xor ax, ax - push cs - pop es - mov si, drvoff - stosw - stosw - stosw - stosw - pop es - call read - ; load bpb from buffer to bpb -ldbpb: push ds - push es - mov ax, cs - mov ds, ax - mov es, ax - mov si, buffer+0x0B - mov di, bpb - mov cx, bpb_len - rep movsb - pop es - pop ds - ret - - - ; defines for CHS table -chs_spt: equ 0 ; word sectors per track -chs_nos: equ 2 ; word number of sides -chs_po: equ 4 ; dword partition offset -chs_siz: equ 8 - - -fndchs: ; find CHS table entry - ; IN dl DOS drive number (A=0, B=1, ...) - ; OUT cs:si ptr to chs table entry - push ax - mov ax, chs_siz - mul dl - add ax, chstab - mov si, ax - pop ax - ret - - ; compare sector number in disk access packet with zero - ; sets zero flag accordingly -iszero: push ax - mov ax, [bx] - or ax, [bx+2] - pop ax - ret - - ; calculate CHS from dap and CHS table entry - ; IN ds:bx disk access packet - ; cs:si chstab table entry - ; OUT cx,dh chs data for int 13h -calchs: push ax - ; load linear sector number - mov dx, [bx+2] - mov ax, [bx] - ; if any word of it is non-zero, we need to do calculation - call iszero - jz .zero - ; ax is track number (lba / spt) - ; dx is sector (lba % spt) + 1 - div word [cs:si+chs_spt] - inc dx - ; sector number - mov cl, dl - ; ax is cylinder (track / heads) - ; dx is head (track % heads) - xor dx, dx - div word [cs:si+chs_nos] - ; set up cylinder and head number - mov ch, al - mov dh, dl - pop ax - ret - ; set up CHS data for int 13h for reading sector zero -.zero: mov cx, 1 ; C=0, S=1 - mov dh, 0 ; H=0 - pop ax - ret - - ; ABSOLUTE DISK READ / DISK WRITE -int25h: mov ah, 2 - jmp adisk -int26h: mov ah, 3 -adisk: push bp - push ds - push es - mov bp, sp - cmp cx, 0xFFFF - je .islrg - - ; build a disk access packet on the stack - push ds ; dword transfer buffer - push bx - push cx ; word number of sectors - push cs ; dword starting sector number (CS always 0) - push dx - - ; set our freshly created dap as DS:BX - mov bx, sp - push ss - pop ds - -.islrg: mov dl, al - call fndchs - call calchs - mov dl, al - mov al, [bx+4] - mov es, [bx+8] - mov bx, [bx+6] - int 0x13 - jc .ret - -.ret: mov sp, bp - pop es - pop ds - pop bp -retf: retf - ; DOS IDLE INTERRUPT ; Usually hooked by TSRs idle: sti @@ -370,6 +192,8 @@ fputc: push ax pop ax iret + %include "kernel/diskio.asm" + vects: dw int20h, int21h, retf, retf dw retf, int25h, int26h, int20h dw idle, fputc @@ -428,11 +252,4 @@ section .bss stack: resw stacks ; default int 25h/26h handler use a cache to keep geometry for ; the first 4 drives -chstab: resw (4*chs_siz) - -bpb: resb bpb_len -drvnum: resb 1 - align 4 -drvoff: resd 1; partition offset -drvpos: resd 1; absolute physical sector number buffer: resb 512 diff --git a/kernel/diskio.asm b/kernel/diskio.asm new file mode 100644 index 0000000..45d7631 --- /dev/null +++ b/kernel/diskio.asm @@ -0,0 +1,112 @@ + section .bss + +chsspt: equ 0 ; word sectors per track +chsnos: equ 2 ; word number of sides +chspo: equ 4 ; dword partition offset +chssiz: equ 8 + +chstab: resw (4*chssiz) + + section .text + + ; 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 + +fndchs: ; find CHS table entry + ; IN dl DOS drive number (A=0, B=1, ...) + ; OUT cs:si ptr to chs table entry + push ax + mov ax, chssiz + mul dl + add ax, chstab + mov si, ax + pop ax + ret + + ; compare sector number in disk access packet with zero + ; sets zero flag accordingly +iszero: push ax + mov ax, [bx] + or ax, [bx+2] + pop ax + ret + + ; calculate CHS from dap and CHS table entry + ; IN ds:bx disk access packet + ; cs:si chstab table entry + ; OUT cx,dh chs data for int 13h +calchs: push ax + ; load linear sector number + mov dx, [bx+2] + mov ax, [bx] + ; if any word of it is non-zero, we need to do calculation + call iszero + jz .zero + ; ax is track number (lba / spt) + ; dx is sector (lba % spt) + 1 + div word [cs:si+chsspt] + inc dx + ; sector number + mov cl, dl + ; ax is cylinder (track / heads) + ; dx is head (track % heads) + xor dx, dx + div word [cs:si+chsnos] + ; set up cylinder and head number + mov ch, al + mov dh, dl + pop ax + ret + ; set up CHS data for int 13h for reading sector zero +.zero: mov cx, 1 ; C=0, S=1 + mov dh, 0 ; H=0 + pop ax + ret + + ; ABSOLUTE DISK READ / DISK WRITE +int25h: mov ah, 2 + jmp adisk +int26h: mov ah, 3 +adisk: push bp + push ds + push es + mov bp, sp + cmp cx, 0xFFFF + je .islrg + + ; build a disk access packet on the stack + push ds ; dword transfer buffer + push bx + push cx ; word number of sectors + push cs ; dword starting sector number (CS always 0) + push dx + + ; set our freshly created dap as DS:BX + mov bx, sp + push ss + pop ds + +.islrg: mov dl, al + call fndchs + call calchs + mov dl, al + mov al, [bx+4] + mov es, [bx+8] + mov bx, [bx+6] + int 0x13 + jc .ret + +.ret: mov sp, bp + pop es + pop ds + pop bp + retf