Can create usermode children, Can load programs from disk
This commit is contained in:
parent
6e66cb9bbe
commit
0e3ae9c4e3
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
|
||||
|
Loading…
Reference in New Issue
Block a user