242 lines
5.4 KiB
NASM
242 lines
5.4 KiB
NASM
extern error_screen ; 80x50 words
|
|
|
|
; Switches to text mode and shit
|
|
extern error_environment
|
|
_fault_coda:
|
|
xchg bx,bx
|
|
mov ax, 0x10
|
|
mov es, ax
|
|
; move to 'safe' location
|
|
mov ebp, 0x318000
|
|
mov esp, ebp
|
|
call error_environment
|
|
.hlt:
|
|
hlt
|
|
jmp .hlt
|
|
|
|
extern gpf_handler_v86
|
|
global gpfHandler
|
|
gpfHandler:
|
|
cli ; make sure we're in a 'friendly' env
|
|
push eax
|
|
push ebx
|
|
push ecx
|
|
; save old ds
|
|
mov bx, ds
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov word [_gpf_old_ds], bx
|
|
; relocate stack so other interrupts don't fuck us over
|
|
; not sure if this is necessary, it doesn't seem to fix our race conditions...
|
|
mov ebx, esp
|
|
sub esp, 0x1000
|
|
xor ecx, ecx
|
|
.l:
|
|
mov eax, [ebx]
|
|
mov [esp+ecx], eax
|
|
add ebx, 4
|
|
add ecx, 4
|
|
cmp ebx, 0x320000 ; tss esp0
|
|
jl .l
|
|
pop ecx
|
|
pop ebx
|
|
sti ; we shouldn't crash now?
|
|
mov eax, dword [esp+16] ; EFLAGS
|
|
and eax, 1 << 17 ; VM flag
|
|
test eax, eax
|
|
pop eax
|
|
jnz gpf_handler_v86
|
|
jmp gpf_handler_32
|
|
gpf_unhandled:
|
|
mov dword [error_screen+0x00], 0x0f000f00 | 'G' | 'P' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'F' | '!' << 16
|
|
jmp _fault_coda
|
|
|
|
_gpf_old_ds: dw 0
|
|
extern get_key
|
|
extern task_ptr
|
|
extern _enter_v86_internal_no_task
|
|
extern return_prev_task
|
|
extern v86VideoInt
|
|
gpf_handler_32:
|
|
push eax
|
|
mov eax, dword [esp+8] ; EIP
|
|
movzx eax, word [eax]
|
|
cmp eax, 0x30CD ; int 0x30
|
|
je .int30
|
|
cmp eax, 0x21CD ; int 0x21
|
|
je .int21
|
|
jmp gpf_unhandled
|
|
.int21:
|
|
pop eax ; command
|
|
cmp al, 0x00 ; get key
|
|
jne .s1
|
|
call get_key
|
|
jmp .return_to_offender
|
|
.s1: cmp al, 0x10 ; video interrupt
|
|
jne .return_to_offender
|
|
add esp, 4
|
|
add dword [esp+0], 2
|
|
; add a new task
|
|
call _gpf_create_return_task
|
|
; now enter v86 mode
|
|
; get regs from return stack
|
|
mov eax, [esp+12] ; return esp
|
|
mov eax, [eax] ; regs
|
|
push eax ; regs
|
|
mov eax, v86VideoInt
|
|
and eax, 0xffff
|
|
push eax ; ip
|
|
mov eax, v86VideoInt
|
|
shr eax, 4
|
|
and eax, 0xf000
|
|
push eax ; cs
|
|
push 0xFF00 ; sp
|
|
push 0x8000 ; ss
|
|
jmp _enter_v86_internal_no_task ; NOT a function call
|
|
.int30:
|
|
pop eax ; return value
|
|
jmp return_prev_task
|
|
.return_to_offender:
|
|
add dword [esp+4], 2
|
|
push eax
|
|
mov ax, word [_gpf_old_ds]
|
|
mov ds, ax
|
|
pop eax
|
|
add esp, 4 ; error code
|
|
iret
|
|
|
|
_gpf_create_return_task:
|
|
; handler stack stored in edx
|
|
mov edx, esp
|
|
mov esp, dword [task_ptr]
|
|
mov eax, [edx+20] ; ss
|
|
push eax
|
|
mov eax, [edx+16] ; esp
|
|
push eax
|
|
mov eax, [edx+12] ; eflags
|
|
push eax
|
|
mov eax, [edx+8] ; cs
|
|
push eax
|
|
mov eax, [edx+4] ; eip
|
|
push eax
|
|
mov ax, word [_gpf_old_ds] ; restore old ds
|
|
mov ds, ax
|
|
push ds
|
|
push es
|
|
push fs
|
|
push gs
|
|
push ebp
|
|
push ebx
|
|
push esi
|
|
push edi
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [task_ptr], esp ; save new task pointer
|
|
mov esp, edx ; restore handler stack
|
|
ret
|
|
|
|
global unhandled_handler
|
|
unhandled_handler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | 'E' | 'R' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'R' | 'O' << 16
|
|
mov dword [error_screen+0x08], 0x0f000f00 | 'R' | '!' << 16
|
|
jmp _fault_coda
|
|
|
|
global pageFaultHandler
|
|
pageFaultHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
pop eax ; error code
|
|
mov ebx, 0x0f000f00 | '0' | '!' << 16
|
|
and eax, 0x7 ; U/S,R/W,P
|
|
add ebx, eax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | 'P' | 'G' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'F' | 'L' << 16
|
|
mov dword [error_screen+0x08], 0x0f000f00 | 'T' | ':' << 16
|
|
mov dword [error_screen+0x0C], ebx
|
|
jmp _fault_coda
|
|
|
|
|
|
global divisionErrorHandler
|
|
divisionErrorHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'D' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'E' | '!' << 16
|
|
jmp _fault_coda
|
|
global boundRangeHandler
|
|
boundRangeHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'B' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'R' | '!' << 16
|
|
jmp _fault_coda
|
|
global invalidOpcodeHandler
|
|
invalidOpcodeHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'U' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'D' | '!' << 16
|
|
jmp _fault_coda
|
|
global deviceNotAvailableHandler
|
|
deviceNotAvailableHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'N' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'D' | '!' << 16
|
|
jmp _fault_coda
|
|
global doubleFaultHandler
|
|
doubleFaultHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [0xb8000+0x00], 0x0f000f00 | '#' | 'D' << 16
|
|
mov dword [0xb8000+0x04], 0x0f000f00 | 'F' | '!' << 16
|
|
; double faults simply abort right then
|
|
.hlt: hlt
|
|
jmp .hlt
|
|
global invalidTSSHandler
|
|
invalidTSSHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'T' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'S' | '!' << 16
|
|
jmp _fault_coda
|
|
global segmentNotPresentHandler
|
|
segmentNotPresentHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'N' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'P' | '!' << 16
|
|
jmp _fault_coda
|
|
global stackSegmentHandler
|
|
stackSegmentHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'S' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'S' | '!' << 16
|
|
jmp _fault_coda
|
|
global x87FloatingHandler
|
|
x87FloatingHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'M' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'F' | '!' << 16
|
|
jmp _fault_coda
|
|
global alignmentCheckHandler
|
|
alignmentCheckHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'A' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'C' | '!' << 16
|
|
jmp _fault_coda
|
|
global controlProtectionHandler
|
|
controlProtectionHandler:
|
|
mov ax, 0x10
|
|
mov ds, ax
|
|
mov dword [error_screen+0x00], 0x0f000f00 | '#' | 'C' << 16
|
|
mov dword [error_screen+0x04], 0x0f000f00 | 'P' | '!' << 16
|
|
jmp _fault_coda
|