Can create usermode children, Can load programs from disk

This commit is contained in:
Lucia Ceionia 2023-02-06 05:49:03 -06:00
parent 6e66cb9bbe
commit 0e3ae9c4e3
10 changed files with 201 additions and 27 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
*.o
*.bin
*.lock
*.com
bx_enh_dbg.ini

View File

@ -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

View File

@ -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
View File

@ -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();
}

View File

@ -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);

View File

@ -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
View 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
View File

@ -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();

View File

@ -4,5 +4,6 @@
#include "interrupt.h"
#include "v86defs.h"
#include "kbd.h"
#include "helper.h"
void RunTests();

View File

@ -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