Usermode can now call system functions (currently get key, gfx mode) with INT 21H, Test switch to graphics mode is done from Usermode

This commit is contained in:
Lucia Ceionia 2023-02-02 00:50:16 -06:00
parent 679eb8cf57
commit 02f03d2224
4 changed files with 136 additions and 32 deletions

View File

@ -14,6 +14,106 @@ call error_environment
hlt hlt
jmp .hlt jmp .hlt
extern gpf_handler_v86
global gpfHandler
gpfHandler:
push eax
push ebx
mov bx, ds
mov ax, 0x10
mov ds, ax
mov word [_gpf_old_ds], bx
pop ebx
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 v86GfxMode
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 ; set video mode
jne .return_to_offender
add dword [esp+4], 2
; add a new task
call _gpf_create_return_task
; now enter v86 mode
; push args
mov eax, v86GfxMode
and eax, 0xffff
push eax ; ip
mov eax, v86GfxMode
shr eax, 16
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 global unhandled_handler
unhandled_handler: unhandled_handler:
mov ax, 0x10 mov ax, 0x10
@ -37,33 +137,6 @@ mov dword [error_screen+0x08], 0x0f000f00 | 'T' | ':' << 16
mov dword [error_screen+0x0C], ebx mov dword [error_screen+0x0C], ebx
jmp _fault_coda jmp _fault_coda
extern gpf_handler_v86
global gpfHandler
gpfHandler:
push eax
mov ax, 0x10
mov ds, ax
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_handler_32:
push eax
mov eax, dword [esp+8] ; EIP
movzx eax, word [eax]
cmp eax, 0x30CD ; int 0x30
jne gpf_unhandled
pop eax ; return value
jmp return_prev_task
extern return_prev_task
global divisionErrorHandler global divisionErrorHandler
divisionErrorHandler: divisionErrorHandler:

View File

@ -112,7 +112,8 @@ void ensure_v86env() {
while (d < &_ev86code) while (d < &_ev86code)
*d++ = *s++; *d++ = *s++;
for (int i = 0; i < 80*50; i++) for (int i = 0; i < 80*50; i++)
if (!error_screen[i]) error_screen[i] = 0x0f00; if (!(error_screen[i] & 0xFF00))
error_screen[i] = 0x0f00 | (error_screen[i] & 0x00FF);
} }
void error_environment() { void error_environment() {
@ -155,9 +156,7 @@ void TestV86() {
FARPTR v86_entry = i386LinearToFp(v86Test); FARPTR v86_entry = i386LinearToFp(v86Test);
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry));
} }
void TestGfx() { void TestUser() {
FARPTR v86_entry = i386LinearToFp(v86GfxMode);
enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry));
char *vga = jmp_usermode_test(); char *vga = jmp_usermode_test();
for (int i = 0; i < 320; i++) { for (int i = 0; i < 320; i++) {
vga[i] = i; vga[i] = i;
@ -304,7 +303,7 @@ void start() {
*vga_text = (*vga_text & 0xFF00) | key; *vga_text = (*vga_text & 0xFF00) | key;
vga_text++; vga_text++;
} }
TestGfx(); TestUser();
kbd_wait(); kbd_wait();
TestDiskRead(); TestDiskRead();
kbd_wait(); kbd_wait();

View File

@ -4,6 +4,7 @@ mov ax, 0x28
ltr ax ltr ax
ret ret
global task_ptr
task_ptr: equ (0x310000-4) task_ptr: equ (0x310000-4)
; return address in EAX ; return address in EAX
@ -49,6 +50,16 @@ mov fs, ax
mov eax, [edx+8+16] ; es mov eax, [edx+8+16] ; es
mov es, ax mov es, ax
; SS:ESP <- return stack ; SS:ESP <- return stack
push ecx
mov eax, [edx+32+16] ; ss
mov ecx, [edx+20+16] ; cs
and eax, 3
and ecx, 3
or eax, ecx
pop ecx
cmp eax, 3
je .ret_stack
.ret_no_stack:
mov esp, [edx+28+16] ; esp mov esp, [edx+28+16] ; esp
mov eax, [edx+32+16] ; ss mov eax, [edx+32+16] ; ss
mov ss, ax mov ss, ax
@ -62,13 +73,30 @@ mov eax, [edx+12+16] ; ds
mov ds, ax mov ds, ax
mov eax, ecx ; restore return value mov eax, ecx ; restore return value
iret iret
.ret_stack:
mov eax, [edx+32+16] ; ss
push eax
mov eax, [edx+28+16] ; esp
push eax
mov eax, [edx+24+16] ; eflags
push eax
mov eax, [edx+20+16] ; cs
push eax
mov eax, [edx+16+16] ; eip
push eax
mov eax, [edx+12+16] ; ds
mov ds, ax
mov eax, ecx ; restore return value
iret
; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip); ; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip);
global enter_v86 global enter_v86
global _enter_v86_internal_no_task
enter_v86: enter_v86:
pop eax ; return address pop eax ; return address
mov ecx, esp ; return stack mov ecx, esp ; return stack
call save_current_task call save_current_task
_enter_v86_internal_no_task:
mov ebp, esp ; save stack pointer mov ebp, esp ; save stack pointer
push dword [ebp+0] ; ss push dword [ebp+0] ; ss
push dword [ebp+4] ; esp push dword [ebp+4] ; esp

View File

@ -6,6 +6,10 @@ mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16
mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16 mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16
mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16 mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16
mov word [0xb8010], 0x0f00 | '!' mov word [0xb8010], 0x0f00 | '!'
mov eax, 0 ; command = 00, get key
int 0x21 ; OS call
mov eax, 0x00030010 ; command = 10, set video mode 3
int 0x21 ; OS call
mov edi, 0xA0000 mov edi, 0xA0000
xor eax, eax xor eax, eax
.loop: .loop: