148 lines
2.4 KiB
NASM
148 lines
2.4 KiB
NASM
; This is the syscall gateway:
|
|
; - backs up the data from user space (kernel funcs trash many regs)
|
|
; - sets up the kernel stack
|
|
; - calls kernel funcs
|
|
; - exports a specified set of registers back to userspace
|
|
;
|
|
; The syscall table acts as a "export"-list for kernel near funcs.
|
|
; Code invoked via it can reply on SS being zero.
|
|
|
|
section .bss
|
|
|
|
curpsp: resw 1
|
|
|
|
section .data
|
|
|
|
stab: ; syscall table
|
|
; cells: ptr to handler, ptr to sysret
|
|
; 0-7
|
|
dw restart, sret
|
|
dw getc, sretb
|
|
dw putc, sret
|
|
dw err, sret ; reader input
|
|
dw err, sret ; punch outout
|
|
dw err, sret ; list output
|
|
dw conio, sret ; direct console i/o
|
|
dw err, sret
|
|
; 8-f
|
|
dw err, sret
|
|
dw err, sret ; print string
|
|
dw err, sret ; read into buffer
|
|
dw err, sret ; console status
|
|
dw err, sret ; return version num
|
|
dw err, sret ; reset disks
|
|
dw setdd, sret ; select disk
|
|
dw open, sretb ; open file
|
|
.end:
|
|
|
|
section .text
|
|
|
|
absolute 0
|
|
|
|
resb 2 ; ret 0 exit
|
|
resb 2 ; allocation length
|
|
resb 1
|
|
resb 5 ; CP/M entry point
|
|
|
|
; saved userdata
|
|
PSPAX: resw 1
|
|
PSPCX: resw 1
|
|
PSPBP: resw 1
|
|
; SS:SP
|
|
PSPSP: resw 1
|
|
PSPSS: resw 1
|
|
; DS:DX
|
|
PSPDX: resw 1
|
|
PSPDS: resw 1
|
|
; ES:BX
|
|
PSPBX: resw 1
|
|
PSPES: resw 1
|
|
|
|
; default drive
|
|
PSPDD: resb 1
|
|
|
|
section .text
|
|
|
|
; Load current PSP segment into DS
|
|
; OUT ds PSP segment
|
|
; ax 0
|
|
pspds: xor ax, ax
|
|
mov ds, ax
|
|
mov ds, [curpsp]
|
|
ret
|
|
|
|
; Get reloc offset into CX
|
|
reloff: call .l01
|
|
.l01: pop cx
|
|
sub cx, .l01
|
|
ret
|
|
|
|
int21: push ds
|
|
; load program PSP and save userdata
|
|
push ax
|
|
call pspds
|
|
pop word [PSPAX]
|
|
pop word [PSPDS]
|
|
mov [PSPCX], cx
|
|
mov [PSPBP], bp
|
|
mov [PSPSS], ss
|
|
mov [PSPSP], sp
|
|
mov [PSPDX], dx
|
|
mov [PSPES], es
|
|
mov [PSPBX], bx
|
|
|
|
mov ss, ax
|
|
mov sp, stack
|
|
; get offset for PIC
|
|
call reloff
|
|
; get ptr into syscall table
|
|
mov al, [PSPAX+1] ; ah is still 0
|
|
shl ax, 1
|
|
shl ax, 1
|
|
add ax, stab
|
|
add ax, cx
|
|
mov bx, ax
|
|
; load sysret ptr
|
|
mov ax, [cs:bx+2]
|
|
add ax, cx
|
|
push ax
|
|
; load handler ptr
|
|
mov ax, [cs:bx]
|
|
add ax, cx
|
|
push ax
|
|
; restore user data
|
|
mov ax, [PSPAX]
|
|
mov cx, [PSPCX]
|
|
mov bx, [PSPBX]
|
|
mov ds, [PSPDS]
|
|
; launch ROP chain
|
|
ret
|
|
|
|
err: mov ah, 0xFF
|
|
ret
|
|
|
|
; sysret handlers
|
|
; return ES:BX to user
|
|
sretd: mov ds, [ss:curpsp]
|
|
jmp sret.l02
|
|
|
|
; return BX to user
|
|
sretw: mov ds, [ss:curpsp]
|
|
mov es, [PSPES]
|
|
jmp sret.l02
|
|
|
|
; return AL to user
|
|
sretb: mov ds, [ss:curpsp]
|
|
mov ah, [PSPAX+1]
|
|
les bx, [PSPBX]
|
|
jmp sret.l03
|
|
|
|
; return without result
|
|
sret: mov ds, [ss:curpsp]
|
|
.l01: les bx, [PSPBX]
|
|
.l02: mov ax, [PSPAX]
|
|
.l03: mov ss, [PSPSS]
|
|
mov sp, [PSPSP]
|
|
lds dx, [PSPDX]
|
|
iret
|