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:
		
							
								
								
									
										127
									
								
								fault.nasm
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								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:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								kernel.c
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								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();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								task.nasm
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								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
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user