Can create usermode children, Can load programs from disk
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,4 +1,5 @@
 | 
			
		||||
*.o
 | 
			
		||||
*.bin
 | 
			
		||||
*.lock
 | 
			
		||||
*.com
 | 
			
		||||
bx_enh_dbg.ini
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,7 @@ jmp _fault_coda
 | 
			
		||||
 | 
			
		||||
_gpf_old_ds: dw 0
 | 
			
		||||
extern get_key
 | 
			
		||||
extern get_scancode
 | 
			
		||||
extern task_ptr
 | 
			
		||||
extern _enter_v86_internal_no_task
 | 
			
		||||
extern return_prev_task
 | 
			
		||||
@@ -76,7 +77,11 @@ cmp al, 0x00 ; get key
 | 
			
		||||
jne .s1
 | 
			
		||||
call get_key
 | 
			
		||||
jmp .return_to_offender
 | 
			
		||||
.s1: cmp al, 0x86 ; v86 interrupt call
 | 
			
		||||
.s1: cmp al, 0x01 ; get scancode
 | 
			
		||||
jne .s86
 | 
			
		||||
call get_scancode
 | 
			
		||||
jmp .return_to_offender
 | 
			
		||||
.s86: cmp al, 0x86 ; v86 interrupt call
 | 
			
		||||
jne .return_to_offender
 | 
			
		||||
add esp, 4
 | 
			
		||||
add dword [esp+0], 2
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								kernel.c
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								kernel.c
									
									
									
									
									
								
							@@ -219,7 +219,7 @@ void FileSelect() {
 | 
			
		||||
    int32_t fileHovered = 0, lastFileHovered = 0;
 | 
			
		||||
    for (char reload = 1;;) {
 | 
			
		||||
        // Info line (4)
 | 
			
		||||
        printStr("T to run tests - X to view in hex - V to view as text", &vga_text[80*4+2]);
 | 
			
		||||
        printStr("T to run tests - X to view in hex - V to view as text - P to load as program", &vga_text[80*4+2]);
 | 
			
		||||
        VOLINFO vi; DIRINFO di;
 | 
			
		||||
        if (reload) {
 | 
			
		||||
            OpenVol(&vi);
 | 
			
		||||
@@ -250,6 +250,14 @@ void FileSelect() {
 | 
			
		||||
                DrawScreen();
 | 
			
		||||
                reload = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_P:
 | 
			
		||||
                File83ToPath((char*)entries[fileHovered].name, (char*)path);
 | 
			
		||||
                create_child(0x380000, (uintptr_t)ProgramLoadTest, 2, path, &vi);
 | 
			
		||||
                SetVideo25Lines();
 | 
			
		||||
                SetCursorDisabled();
 | 
			
		||||
                DrawScreen();
 | 
			
		||||
                reload = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case KEY_X:
 | 
			
		||||
                File83ToPath((char*)entries[fileHovered].name, (char*)path);
 | 
			
		||||
                //HexViewTest(path, &vi);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										61
									
								
								progs.c
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								progs.c
									
									
									
									
									
								
							@@ -1,4 +1,6 @@
 | 
			
		||||
#include "progs.h"
 | 
			
		||||
#include "helper.h"
 | 
			
		||||
#include "kbd.h"
 | 
			
		||||
 | 
			
		||||
void HexViewTest(uint8_t *path, VOLINFO *vi) {
 | 
			
		||||
    uint32_t err;
 | 
			
		||||
@@ -309,3 +311,62 @@ void TextViewTest(uint8_t *path, VOLINFO *vi) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
// 400000 - 700000 Usermode Code (3mB)
 | 
			
		||||
// 700000 - 800000 Usermode Stack (1mB)
 | 
			
		||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
 | 
			
		||||
void ProgramLoadTest(uint8_t *path, VOLINFO *vi) {
 | 
			
		||||
    uint16_t *vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
    for (int i = 0; i < 80*25; i++)
 | 
			
		||||
        vga_text[i] = 0x0f00;
 | 
			
		||||
    uint32_t successcount;
 | 
			
		||||
    uint8_t *diskReadBuf = (uint8_t *)0x400000;
 | 
			
		||||
    {
 | 
			
		||||
        uint32_t err;
 | 
			
		||||
        uint8_t *scratch = (uint8_t *)0x20000;
 | 
			
		||||
        FILEINFO fi;
 | 
			
		||||
        err = DFS_OpenFile(vi, path, DFS_READ, scratch, &fi);
 | 
			
		||||
        if (err) {
 | 
			
		||||
            vga_text += printStr("Open Error: ", vga_text);
 | 
			
		||||
            printDword(err, vga_text);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (fi.filelen > 0x300000) {
 | 
			
		||||
            vga_text += printStr("File too large.", vga_text);
 | 
			
		||||
            kbd_wait();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        DFS_Seek(&fi, 0, scratch);
 | 
			
		||||
        if (fi.pointer != 0) {
 | 
			
		||||
            vga_text += printStr("Seek Error", vga_text);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        err = DFS_ReadFile(&fi, scratch, diskReadBuf, &successcount, fi.filelen);
 | 
			
		||||
        if (err && err != DFS_EOF) {
 | 
			
		||||
            vga_text += printStr("Read Error: ", vga_text);
 | 
			
		||||
            printDword(err, vga_text);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (successcount < fi.filelen) {
 | 
			
		||||
            vga_text += printStr("Could not read all file bytes.", vga_text);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    vga_text += printStr("Successfully loaded program \"", vga_text);
 | 
			
		||||
    vga_text += printStr((char*)path, vga_text);
 | 
			
		||||
    vga_text += printStr("\", ", vga_text);
 | 
			
		||||
    vga_text += printDec(successcount, vga_text);
 | 
			
		||||
    vga_text += printStr(" Bytes.", vga_text);
 | 
			
		||||
    vga_text = nextLine(vga_text);
 | 
			
		||||
    vga_text += printStr("Press any key to run.", vga_text);
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
    uint32_t res = create_user_child(0x800000, 0x400000, 0);
 | 
			
		||||
    vga_text = (uint16_t *)0xb8000;
 | 
			
		||||
    for (int i = 0; i < 80*25; i++)
 | 
			
		||||
        vga_text[i] = 0x0f00;
 | 
			
		||||
    vga_text += printStr("Program returned code: ", vga_text);
 | 
			
		||||
    vga_text += printDec(res, vga_text);
 | 
			
		||||
    vga_text += printStr(" (0x", vga_text);
 | 
			
		||||
    vga_text += printDword(res, vga_text);
 | 
			
		||||
    vga_text += printStr("). Press any key to exit.", vga_text);
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								progs.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								progs.h
									
									
									
									
									
								
							@@ -9,3 +9,4 @@
 | 
			
		||||
 | 
			
		||||
void HexViewTest(uint8_t *path, VOLINFO *vi);
 | 
			
		||||
void TextViewTest(uint8_t *path, VOLINFO *vi);
 | 
			
		||||
void ProgramLoadTest(uint8_t *path, VOLINFO *vi);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										70
									
								
								task.nasm
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								task.nasm
									
									
									
									
									
								
							@@ -11,7 +11,6 @@ task_ptr: equ (0x310000-4)
 | 
			
		||||
; extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
 | 
			
		||||
global create_child
 | 
			
		||||
create_child:
 | 
			
		||||
xchg bx,bx
 | 
			
		||||
mov eax, [esp] ; return address
 | 
			
		||||
lea ecx, [esp+4] ; return stack, minus address
 | 
			
		||||
call save_current_task
 | 
			
		||||
@@ -30,6 +29,37 @@ push return_prev_task ; if child returns, return to prev task
 | 
			
		||||
push eax
 | 
			
		||||
ret
 | 
			
		||||
 | 
			
		||||
; extern void create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
 | 
			
		||||
global create_user_child
 | 
			
		||||
create_user_child:
 | 
			
		||||
mov eax, [esp] ; return address
 | 
			
		||||
lea ecx, [esp+4] ; return stack, minus address
 | 
			
		||||
call save_current_task
 | 
			
		||||
mov eax, [esp+8] ; new eip
 | 
			
		||||
mov ecx, [esp+12] ; argc
 | 
			
		||||
mov esi, esp ; old esp
 | 
			
		||||
mov esp, [esp+4] ; new esp
 | 
			
		||||
lea esi, [esi+16] ; args
 | 
			
		||||
mov edx, ecx
 | 
			
		||||
neg edx
 | 
			
		||||
lea esp, [esp+edx*4] ; adjust for args
 | 
			
		||||
mov edi, esp
 | 
			
		||||
; copy varargs to new stack
 | 
			
		||||
rep movsd
 | 
			
		||||
push 0x00000000 ; if child returns, return to null, crashing
 | 
			
		||||
mov ecx, 0x20 | 3
 | 
			
		||||
mov ds, cx
 | 
			
		||||
mov es, cx
 | 
			
		||||
mov fs, cx
 | 
			
		||||
mov gs, cx
 | 
			
		||||
mov ecx, esp
 | 
			
		||||
push 0x20 | 3
 | 
			
		||||
push ecx
 | 
			
		||||
pushfd
 | 
			
		||||
push 0x18 | 3
 | 
			
		||||
push eax
 | 
			
		||||
iret
 | 
			
		||||
 | 
			
		||||
; return address in EAX
 | 
			
		||||
; return stack in ECX
 | 
			
		||||
; we can modify EAX, ECX, EDX
 | 
			
		||||
@@ -145,22 +175,22 @@ iret
 | 
			
		||||
; return address in eax, return stack in ebp
 | 
			
		||||
;extern save_current_task
 | 
			
		||||
 | 
			
		||||
extern user_test
 | 
			
		||||
global jmp_usermode_test
 | 
			
		||||
jmp_usermode_test:
 | 
			
		||||
pop eax ; return address
 | 
			
		||||
mov ecx, esp ; return stack
 | 
			
		||||
call save_current_task
 | 
			
		||||
mov esp, 0x800000 ; usermode stack
 | 
			
		||||
mov eax, 0x20 | 3
 | 
			
		||||
mov ds, ax
 | 
			
		||||
mov es, ax
 | 
			
		||||
mov fs, ax
 | 
			
		||||
mov gs, ax
 | 
			
		||||
mov eax, esp
 | 
			
		||||
push 0x20 | 3
 | 
			
		||||
push eax
 | 
			
		||||
pushfd
 | 
			
		||||
push 0x18 | 3
 | 
			
		||||
push user_test
 | 
			
		||||
iret
 | 
			
		||||
;extern user_test
 | 
			
		||||
;global jmp_usermode_test
 | 
			
		||||
;jmp_usermode_test:
 | 
			
		||||
;pop eax ; return address
 | 
			
		||||
;mov ecx, esp ; return stack
 | 
			
		||||
;call save_current_task
 | 
			
		||||
;mov esp, 0x800000 ; usermode stack
 | 
			
		||||
;mov eax, 0x20 | 3
 | 
			
		||||
;mov ds, ax
 | 
			
		||||
;mov es, ax
 | 
			
		||||
;mov fs, ax
 | 
			
		||||
;mov gs, ax
 | 
			
		||||
;mov eax, esp
 | 
			
		||||
;push 0x20 | 3
 | 
			
		||||
;push eax
 | 
			
		||||
;pushfd
 | 
			
		||||
;push 0x18 | 3
 | 
			
		||||
;push user_test
 | 
			
		||||
;iret
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								testpgrm.nasm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								testpgrm.nasm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
[BITS 32]
 | 
			
		||||
[ORG 0x400000]
 | 
			
		||||
xchg bx,bx
 | 
			
		||||
mov edi, 0xB8000
 | 
			
		||||
mov ecx, 80*25
 | 
			
		||||
mov eax, 0x2f00
 | 
			
		||||
rep stosw
 | 
			
		||||
mov edi, 0xB8000
 | 
			
		||||
mov esi, str0
 | 
			
		||||
mov ecx, str0_end - str0
 | 
			
		||||
mov eax, 0x2f00
 | 
			
		||||
.loop:
 | 
			
		||||
lodsb
 | 
			
		||||
stosw
 | 
			
		||||
loop .loop
 | 
			
		||||
mov edi, 0xB8000 + 160 - 2
 | 
			
		||||
.key_loop:
 | 
			
		||||
mov eax, 1 ; command = 01h, get scancode
 | 
			
		||||
int 0x21 ; OS call
 | 
			
		||||
cmp al, 0x3B ; F1
 | 
			
		||||
je .exit
 | 
			
		||||
cmp al, 0x3C ; F2
 | 
			
		||||
je .crash
 | 
			
		||||
cmp ah, 0x00
 | 
			
		||||
je .key_loop
 | 
			
		||||
mov byte [edi], ah ; ASCII value
 | 
			
		||||
add edi, 2
 | 
			
		||||
jmp .key_loop
 | 
			
		||||
.exit:
 | 
			
		||||
mov eax, 0x1337 ; Exit code/Return value
 | 
			
		||||
int 0x30 ; Exit
 | 
			
		||||
.crash:
 | 
			
		||||
jmp 0x00000000
 | 
			
		||||
 | 
			
		||||
str0: db "Running usermode program from disk! Press F1 to exit. Press F2 to crash."
 | 
			
		||||
str0_end:
 | 
			
		||||
							
								
								
									
										23
									
								
								tests.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								tests.c
									
									
									
									
									
								
							@@ -1,6 +1,7 @@
 | 
			
		||||
#include "tests.h"
 | 
			
		||||
 | 
			
		||||
extern char *jmp_usermode_test();
 | 
			
		||||
extern char *user_test();
 | 
			
		||||
extern uint32_t create_user_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
 | 
			
		||||
 | 
			
		||||
void TestV86() {
 | 
			
		||||
    union V86Regs_t regs;
 | 
			
		||||
@@ -21,12 +22,16 @@ void ReloadUser() {
 | 
			
		||||
    while (d < &_eusercode)
 | 
			
		||||
        *d++ = *s++;
 | 
			
		||||
}
 | 
			
		||||
void TestUser() {
 | 
			
		||||
char TestUser() {
 | 
			
		||||
    ReloadUser();
 | 
			
		||||
    char *vga = jmp_usermode_test();
 | 
			
		||||
    char *vga = (char *)(uintptr_t)create_user_child(0x800000, (uintptr_t)user_test, 0);
 | 
			
		||||
    if ((uintptr_t)vga != 0xA0000) {
 | 
			
		||||
        return 1;
 | 
			
		||||
    }
 | 
			
		||||
    for (int i = 0; i < 320; i++) {
 | 
			
		||||
        vga[i] = i;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
void TestDiskRead() {
 | 
			
		||||
    union V86Regs_t regs;
 | 
			
		||||
@@ -119,17 +124,25 @@ void TestFAT() {
 | 
			
		||||
 | 
			
		||||
void RunTests() {
 | 
			
		||||
    uint16_t *vga_text = (uint16_t*)0xb8000;
 | 
			
		||||
    for (int i = 0; i < 80*25; i++)
 | 
			
		||||
        vga_text[i] = 0x1f00;
 | 
			
		||||
    uint8_t key;
 | 
			
		||||
    vga_text += printStr("V86 Test... ", vga_text);
 | 
			
		||||
    //asm ("xchgw %bx, %bx");
 | 
			
		||||
    TestV86(); // has int 3 wait in v86
 | 
			
		||||
    vga_text = (uint16_t *)0xb8000 + (80*3);
 | 
			
		||||
    vga_text += printStr("Done. Press 'N' for next test.", vga_text);
 | 
			
		||||
    while ((key = get_key()) != 'N') {
 | 
			
		||||
    for(;;) {
 | 
			
		||||
        key = get_key();
 | 
			
		||||
        if (key == 'N' || key == 'n') break;
 | 
			
		||||
        *vga_text = (*vga_text & 0xFF00) | key;
 | 
			
		||||
        vga_text++;
 | 
			
		||||
    }
 | 
			
		||||
    TestUser();
 | 
			
		||||
    if (TestUser()) {
 | 
			
		||||
        // Usermode returned wrong value
 | 
			
		||||
        vga_text = nextLine(vga_text);
 | 
			
		||||
        vga_text += printStr("Usermode test failed! Press any key to continue.", vga_text);
 | 
			
		||||
    }
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
    TestDiskRead();
 | 
			
		||||
    kbd_wait();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								tests.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								tests.h
									
									
									
									
									
								
							@@ -4,5 +4,6 @@
 | 
			
		||||
#include "interrupt.h"
 | 
			
		||||
#include "v86defs.h"
 | 
			
		||||
#include "kbd.h"
 | 
			
		||||
#include "helper.h"
 | 
			
		||||
 | 
			
		||||
void RunTests();
 | 
			
		||||
 
 | 
			
		||||
@@ -6,8 +6,24 @@ 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 dword [0xb8000+160], 0x0f000f00 | 'F' | 'a' << 16
 | 
			
		||||
mov dword [0xb8004+160], 0x0f000f00 | 'u' | 'l' << 16
 | 
			
		||||
mov dword [0xb8008+160], 0x0f000f00 | 't' | 's' << 16
 | 
			
		||||
mov dword [0xb800C+160], 0x0f000f00 | ':' | ' ' << 16
 | 
			
		||||
mov dword [0xb8000+320], 0x0f000f00 | 'd' | ':' << 16
 | 
			
		||||
mov dword [0xb8004+320], 0x0f000f00 | ' ' | '#' << 16
 | 
			
		||||
mov dword [0xb8008+320], 0x0f000f00 | 'D' | 'I' << 16
 | 
			
		||||
mov dword [0xb800C+320], 0x0f000f00 | 'V' | ' ' << 16
 | 
			
		||||
mov dword [0xb8000+480], 0x0f000f00 | 'p' | ':' << 16
 | 
			
		||||
mov dword [0xb8004+480], 0x0f000f00 | ' ' | 'P' << 16
 | 
			
		||||
mov dword [0xb8008+480], 0x0f000f00 | 'G' | 'F' << 16
 | 
			
		||||
mov dword [0xb800C+480], 0x0f000f00 | 'L' | 'T' << 16
 | 
			
		||||
mov eax, 0 ; command = 00h, get key
 | 
			
		||||
int 0x21 ; OS call
 | 
			
		||||
cmp al, 'd'
 | 
			
		||||
je .div_err
 | 
			
		||||
cmp al, 'p'
 | 
			
		||||
je .page_err
 | 
			
		||||
push 0x00000013 ; eax  AH=0,AL=3 set video mode 3
 | 
			
		||||
push 0x00000000 ; ecx
 | 
			
		||||
push 0x00000000 ; edx
 | 
			
		||||
@@ -31,7 +47,9 @@ mov eax, 0xA0000
 | 
			
		||||
;.dbg:
 | 
			
		||||
;loop .dbg
 | 
			
		||||
int 0x30 ; Exit
 | 
			
		||||
.page_err:
 | 
			
		||||
mov edx, 0x105000 ; somewhere in kernel mem
 | 
			
		||||
mov edx, [edx] ; should page fault
 | 
			
		||||
.div_err:
 | 
			
		||||
xor ebx, ebx
 | 
			
		||||
div bl ; Unhandled DIV0 exception
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user