Implement some PoC of reading from disk

This commit is contained in:
Nero 2020-04-15 00:17:58 +02:00
parent 6b49a20865
commit 23ddd6b41a

View File

@ -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