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
|
*.o
|
||||||
*.bin
|
*.bin
|
||||||
*.lock
|
*.lock
|
||||||
|
*.com
|
||||||
bx_enh_dbg.ini
|
bx_enh_dbg.ini
|
||||||
|
@ -57,6 +57,7 @@ jmp _fault_coda
|
|||||||
|
|
||||||
_gpf_old_ds: dw 0
|
_gpf_old_ds: dw 0
|
||||||
extern get_key
|
extern get_key
|
||||||
|
extern get_scancode
|
||||||
extern task_ptr
|
extern task_ptr
|
||||||
extern _enter_v86_internal_no_task
|
extern _enter_v86_internal_no_task
|
||||||
extern return_prev_task
|
extern return_prev_task
|
||||||
@ -76,7 +77,11 @@ cmp al, 0x00 ; get key
|
|||||||
jne .s1
|
jne .s1
|
||||||
call get_key
|
call get_key
|
||||||
jmp .return_to_offender
|
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
|
jne .return_to_offender
|
||||||
add esp, 4
|
add esp, 4
|
||||||
add dword [esp+0], 2
|
add dword [esp+0], 2
|
||||||
|
10
kernel.c
10
kernel.c
@ -219,7 +219,7 @@ void FileSelect() {
|
|||||||
int32_t fileHovered = 0, lastFileHovered = 0;
|
int32_t fileHovered = 0, lastFileHovered = 0;
|
||||||
for (char reload = 1;;) {
|
for (char reload = 1;;) {
|
||||||
// Info line (4)
|
// 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;
|
VOLINFO vi; DIRINFO di;
|
||||||
if (reload) {
|
if (reload) {
|
||||||
OpenVol(&vi);
|
OpenVol(&vi);
|
||||||
@ -250,6 +250,14 @@ void FileSelect() {
|
|||||||
DrawScreen();
|
DrawScreen();
|
||||||
reload = 1;
|
reload = 1;
|
||||||
break;
|
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:
|
case KEY_X:
|
||||||
File83ToPath((char*)entries[fileHovered].name, (char*)path);
|
File83ToPath((char*)entries[fileHovered].name, (char*)path);
|
||||||
//HexViewTest(path, &vi);
|
//HexViewTest(path, &vi);
|
||||||
|
61
progs.c
61
progs.c
@ -1,4 +1,6 @@
|
|||||||
#include "progs.h"
|
#include "progs.h"
|
||||||
|
#include "helper.h"
|
||||||
|
#include "kbd.h"
|
||||||
|
|
||||||
void HexViewTest(uint8_t *path, VOLINFO *vi) {
|
void HexViewTest(uint8_t *path, VOLINFO *vi) {
|
||||||
uint32_t err;
|
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 HexViewTest(uint8_t *path, VOLINFO *vi);
|
||||||
void TextViewTest(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, ...);
|
; extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...);
|
||||||
global create_child
|
global create_child
|
||||||
create_child:
|
create_child:
|
||||||
xchg bx,bx
|
|
||||||
mov eax, [esp] ; return address
|
mov eax, [esp] ; return address
|
||||||
lea ecx, [esp+4] ; return stack, minus address
|
lea ecx, [esp+4] ; return stack, minus address
|
||||||
call save_current_task
|
call save_current_task
|
||||||
@ -30,6 +29,37 @@ push return_prev_task ; if child returns, return to prev task
|
|||||||
push eax
|
push eax
|
||||||
ret
|
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 address in EAX
|
||||||
; return stack in ECX
|
; return stack in ECX
|
||||||
; we can modify EAX, ECX, EDX
|
; we can modify EAX, ECX, EDX
|
||||||
@ -145,22 +175,22 @@ iret
|
|||||||
; return address in eax, return stack in ebp
|
; return address in eax, return stack in ebp
|
||||||
;extern save_current_task
|
;extern save_current_task
|
||||||
|
|
||||||
extern user_test
|
;extern user_test
|
||||||
global jmp_usermode_test
|
;global jmp_usermode_test
|
||||||
jmp_usermode_test:
|
;jmp_usermode_test:
|
||||||
pop eax ; return address
|
;pop eax ; return address
|
||||||
mov ecx, esp ; return stack
|
;mov ecx, esp ; return stack
|
||||||
call save_current_task
|
;call save_current_task
|
||||||
mov esp, 0x800000 ; usermode stack
|
;mov esp, 0x800000 ; usermode stack
|
||||||
mov eax, 0x20 | 3
|
;mov eax, 0x20 | 3
|
||||||
mov ds, ax
|
;mov ds, ax
|
||||||
mov es, ax
|
;mov es, ax
|
||||||
mov fs, ax
|
;mov fs, ax
|
||||||
mov gs, ax
|
;mov gs, ax
|
||||||
mov eax, esp
|
;mov eax, esp
|
||||||
push 0x20 | 3
|
;push 0x20 | 3
|
||||||
push eax
|
;push eax
|
||||||
pushfd
|
;pushfd
|
||||||
push 0x18 | 3
|
;push 0x18 | 3
|
||||||
push user_test
|
;push user_test
|
||||||
iret
|
;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"
|
#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() {
|
void TestV86() {
|
||||||
union V86Regs_t regs;
|
union V86Regs_t regs;
|
||||||
@ -21,12 +22,16 @@ void ReloadUser() {
|
|||||||
while (d < &_eusercode)
|
while (d < &_eusercode)
|
||||||
*d++ = *s++;
|
*d++ = *s++;
|
||||||
}
|
}
|
||||||
void TestUser() {
|
char TestUser() {
|
||||||
ReloadUser();
|
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++) {
|
for (int i = 0; i < 320; i++) {
|
||||||
vga[i] = i;
|
vga[i] = i;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
void TestDiskRead() {
|
void TestDiskRead() {
|
||||||
union V86Regs_t regs;
|
union V86Regs_t regs;
|
||||||
@ -119,17 +124,25 @@ void TestFAT() {
|
|||||||
|
|
||||||
void RunTests() {
|
void RunTests() {
|
||||||
uint16_t *vga_text = (uint16_t*)0xb8000;
|
uint16_t *vga_text = (uint16_t*)0xb8000;
|
||||||
|
for (int i = 0; i < 80*25; i++)
|
||||||
|
vga_text[i] = 0x1f00;
|
||||||
uint8_t key;
|
uint8_t key;
|
||||||
vga_text += printStr("V86 Test... ", vga_text);
|
vga_text += printStr("V86 Test... ", vga_text);
|
||||||
//asm ("xchgw %bx, %bx");
|
//asm ("xchgw %bx, %bx");
|
||||||
TestV86(); // has int 3 wait in v86
|
TestV86(); // has int 3 wait in v86
|
||||||
vga_text = (uint16_t *)0xb8000 + (80*3);
|
vga_text = (uint16_t *)0xb8000 + (80*3);
|
||||||
vga_text += printStr("Done. Press 'N' for next test.", vga_text);
|
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 = (*vga_text & 0xFF00) | key;
|
||||||
vga_text++;
|
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();
|
kbd_wait();
|
||||||
TestDiskRead();
|
TestDiskRead();
|
||||||
kbd_wait();
|
kbd_wait();
|
||||||
|
1
tests.h
1
tests.h
@ -4,5 +4,6 @@
|
|||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "v86defs.h"
|
#include "v86defs.h"
|
||||||
#include "kbd.h"
|
#include "kbd.h"
|
||||||
|
#include "helper.h"
|
||||||
|
|
||||||
void RunTests();
|
void RunTests();
|
||||||
|
@ -6,8 +6,24 @@ mov dword [0xb8004], 0x0f000f00 | 'e' | 'r' << 16
|
|||||||
mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16
|
mov dword [0xb8008], 0x0f000f00 | 'm' | 'o' << 16
|
||||||
mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16
|
mov dword [0xb800C], 0x0f000f00 | 'd' | 'e' << 16
|
||||||
mov word [0xb8010], 0x0f00 | '!'
|
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
|
mov eax, 0 ; command = 00h, get key
|
||||||
int 0x21 ; OS call
|
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 0x00000013 ; eax AH=0,AL=3 set video mode 3
|
||||||
push 0x00000000 ; ecx
|
push 0x00000000 ; ecx
|
||||||
push 0x00000000 ; edx
|
push 0x00000000 ; edx
|
||||||
@ -31,7 +47,9 @@ mov eax, 0xA0000
|
|||||||
;.dbg:
|
;.dbg:
|
||||||
;loop .dbg
|
;loop .dbg
|
||||||
int 0x30 ; Exit
|
int 0x30 ; Exit
|
||||||
|
.page_err:
|
||||||
mov edx, 0x105000 ; somewhere in kernel mem
|
mov edx, 0x105000 ; somewhere in kernel mem
|
||||||
mov edx, [edx] ; should page fault
|
mov edx, [edx] ; should page fault
|
||||||
|
.div_err:
|
||||||
xor ebx, ebx
|
xor ebx, ebx
|
||||||
div bl ; Unhandled DIV0 exception
|
div bl ; Unhandled DIV0 exception
|
||||||
|
Loading…
Reference in New Issue
Block a user