From 02f03d22240542ed325b03767c5b597c817cf333 Mon Sep 17 00:00:00 2001 From: Lucia Ceionia Date: Thu, 2 Feb 2023 00:50:16 -0600 Subject: [PATCH] Usermode can now call system functions (currently get key, gfx mode) with INT 21H, Test switch to graphics mode is done from Usermode --- fault.nasm | 127 +++++++++++++++++++++++++++++++++++++++----------- kernel.c | 9 ++-- task.nasm | 28 +++++++++++ usermode.nasm | 4 ++ 4 files changed, 136 insertions(+), 32 deletions(-) diff --git a/fault.nasm b/fault.nasm index 508552f..54fb458 100644 --- a/fault.nasm +++ b/fault.nasm @@ -14,6 +14,106 @@ call error_environment 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 unhandled_handler: mov ax, 0x10 @@ -37,33 +137,6 @@ mov dword [error_screen+0x08], 0x0f000f00 | 'T' | ':' << 16 mov dword [error_screen+0x0C], ebx 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 divisionErrorHandler: diff --git a/kernel.c b/kernel.c index fa1aea6..7ce9374 100644 --- a/kernel.c +++ b/kernel.c @@ -112,7 +112,8 @@ void ensure_v86env() { while (d < &_ev86code) *d++ = *s++; 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() { @@ -155,9 +156,7 @@ void TestV86() { FARPTR v86_entry = i386LinearToFp(v86Test); enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); } -void TestGfx() { - FARPTR v86_entry = i386LinearToFp(v86GfxMode); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); +void TestUser() { char *vga = jmp_usermode_test(); for (int i = 0; i < 320; i++) { vga[i] = i; @@ -304,7 +303,7 @@ void start() { *vga_text = (*vga_text & 0xFF00) | key; vga_text++; } - TestGfx(); + TestUser(); kbd_wait(); TestDiskRead(); kbd_wait(); diff --git a/task.nasm b/task.nasm index 084e9ce..c0e9525 100644 --- a/task.nasm +++ b/task.nasm @@ -4,6 +4,7 @@ mov ax, 0x28 ltr ax ret +global task_ptr task_ptr: equ (0x310000-4) ; return address in EAX @@ -49,6 +50,16 @@ mov fs, ax mov eax, [edx+8+16] ; es mov es, ax ; 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 eax, [edx+32+16] ; ss mov ss, ax @@ -62,13 +73,30 @@ mov eax, [edx+12+16] ; ds mov ds, ax mov eax, ecx ; restore return value 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); global enter_v86 +global _enter_v86_internal_no_task enter_v86: pop eax ; return address mov ecx, esp ; return stack call save_current_task +_enter_v86_internal_no_task: mov ebp, esp ; save stack pointer push dword [ebp+0] ; ss push dword [ebp+4] ; esp diff --git a/usermode.nasm b/usermode.nasm index 2ad8cfa..c0c7e24 100644 --- a/usermode.nasm +++ b/usermode.nasm @@ -6,6 +6,10 @@ mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16 mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16 mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16 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 xor eax, eax .loop: