From 750b1edc16d3f88674d14533da7cfcdc5b37405a Mon Sep 17 00:00:00 2001 From: Lucia Ceionia Date: Thu, 2 Feb 2023 14:52:26 -0600 Subject: [PATCH] Register arguments can be passed to v86 code --- dosfs/dosfs.c | 17 +++-------------- fault.nasm | 16 ++++++++++------ interrupt.c | 2 +- kernel.c | 43 +++++++++++++++++++------------------------ link.ld | 2 +- task.nasm | 13 ++++++++++++- usermode.nasm | 9 ++++++++- v86.nasm | 6 ++++++ v86defs.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 111 insertions(+), 48 deletions(-) create mode 100644 v86defs.h diff --git a/dosfs/dosfs.c b/dosfs/dosfs.c index bcc934d..8433d22 100755 --- a/dosfs/dosfs.c +++ b/dosfs/dosfs.c @@ -11,19 +11,7 @@ #include "dosfs.h" #include "tmpstring.c" #include "../interrupt.h" - -struct __attribute((__packed__)) Int13DiskPacket_t { - uint8_t size; // 0x10 - uint8_t reserved; // 0x00 - uint16_t blocks; - uint32_t transfer_buffer; // 0x2300:0000 - uint64_t start_block; -}; - -extern struct Int13DiskPacket_t v86disk_addr_packet; - -extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip); -extern void v86DiskRead(); +#include "../v86defs.h" // all reading at 0x23000 - be careful! uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) { @@ -32,8 +20,9 @@ uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t v86disk_addr_packet.transfer_buffer = (uintptr_t)buffer & 0x000F | (((uintptr_t)buffer & 0xFFFF0) << 12); + union V86Regs_t regs; FARPTR v86_entry = i386LinearToFp(v86DiskRead); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); return 0; } uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) { diff --git a/fault.nasm b/fault.nasm index dffecbe..4f580ce 100644 --- a/fault.nasm +++ b/fault.nasm @@ -40,7 +40,7 @@ extern get_key extern task_ptr extern _enter_v86_internal_no_task extern return_prev_task -extern v86GfxMode +extern v86VideoInt gpf_handler_32: push eax mov eax, dword [esp+8] ; EIP @@ -56,19 +56,23 @@ cmp al, 0x00 ; get key jne .s1 call get_key jmp .return_to_offender -.s1: cmp al, 0x10 ; set video mode +.s1: cmp al, 0x10 ; video interrupt jne .return_to_offender add esp, 4 add dword [esp+0], 2 ; add a new task call _gpf_create_return_task ; now enter v86 mode -; push args -mov eax, v86GfxMode +; get regs from return stack +mov eax, [esp+12] ; return esp +mov eax, [eax] ; regs +push eax ; regs +mov eax, v86VideoInt and eax, 0xffff push eax ; ip -mov eax, v86GfxMode -shr eax, 16 +mov eax, v86VideoInt +shr eax, 4 +and eax, 0xf000 push eax ; cs push 0xFF00 ; sp push 0x8000 ; ss diff --git a/interrupt.c b/interrupt.c index f1bec2e..d06380d 100644 --- a/interrupt.c +++ b/interrupt.c @@ -51,7 +51,7 @@ FARPTR i386LinearToFp(void *ptr) { unsigned seg, off; off = (uintptr_t) ptr & 0xffff; - seg = ((uintptr_t) ptr >> 16); + seg = ((uintptr_t) ptr >> 4) & 0xf000; return MK_FP(seg, off); } diff --git a/kernel.c b/kernel.c index 97473ab..b884222 100644 --- a/kernel.c +++ b/kernel.c @@ -5,6 +5,7 @@ #include "interrupt.h" #include "tss.h" #include "paging.h" +#include "v86defs.h" typedef unsigned short word; @@ -53,22 +54,6 @@ uint32_t get_cr4() { return reg; } -struct __attribute((__packed__)) Int13DiskPacket_t { - uint8_t size; // 0x10 - uint8_t reserved; // 0x00 - uint16_t blocks; - uint32_t transfer_buffer; // 0x2300:0000 - uint64_t start_block; -}; - -extern struct Int13DiskPacket_t v86disk_addr_packet; - -extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip); -extern void v86Test(); -extern void v86TransFlag(); -extern void v86GfxMode(); -extern void v86TextMode(); -extern void v86DiskRead(); extern char *jmp_usermode_test(); extern char _edata, _v86code, _ev86code, _bstart, _bend, _loadusercode, _usercode, _eusercode; @@ -119,8 +104,9 @@ void ensure_v86env() { void error_environment() { ensure_v86env(); + union V86Regs_t regs; FARPTR v86_entry = i386LinearToFp(v86TextMode); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); printStr("Oh noes!!! System error! ;c Press E for a fun recovery :3", &error_screen[80]); uint16_t *vga_text = ((uint16_t*)0xB8000); for (int i = 0; i < 80*50; i++) @@ -128,7 +114,7 @@ void error_environment() { uint8_t key; for (key = get_key(); key != 'e' && key != 'E'; key = get_key()); v86_entry = i386LinearToFp(v86TransFlag); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); } /* @@ -136,8 +122,8 @@ Real Mode Accessible (First MB) 00000 - 00400 IVT (1kB) 00400 - 01000 Unused (3kB) 01000 - 04000 Free (12kB) - 04000 - 07C00 Free (15kB) - 07C00 - 08000 Boot (512B) + 04000 - 07C00 V86 Code (15kB) + 07C00 - 08000 Boot & V86 Code (512B) 08000 - 20000 V86 Code (96kB) 20000 - 30000 Disk Buffer (64kB) 30000 - 80000 Free (320kB) @@ -158,8 +144,15 @@ Protected Only (1MB+) */ void TestV86() { + union V86Regs_t regs; + regs.d.edi = 0x11111111; + regs.d.esi = 0x22222222; + regs.d.ebx = 0x33333333; + regs.d.edx = 0x44444444; + regs.d.ecx = 0x55555555; + regs.d.eax = 0x66666666; FARPTR v86_entry = i386LinearToFp(v86Test); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); } void TestUser() { char *vga = jmp_usermode_test(); @@ -168,13 +161,15 @@ void TestUser() { } } void TestDiskRead() { + union V86Regs_t regs; word *vga_text = (word *)0xb8000 + (80*5); vga_text += printStr("Setting Text Mode... ", vga_text); - FARPTR v86_entry = i386LinearToFp(v86TextMode); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); + regs.w.ax = 3; // text mode + FARPTR v86_entry = i386LinearToFp(v86VideoInt); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); vga_text += printStr("Done. Starting Disk Read... ", vga_text); v86_entry = i386LinearToFp(v86DiskRead); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry)); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); vga_text = (word *)0xb8000; char *diskReadBuf = (char *)0x23000; for (int i = 0; i < (80*25)/2; i++) { diff --git a/link.ld b/link.ld index 480846f..c175a20 100644 --- a/link.ld +++ b/link.ld @@ -15,7 +15,7 @@ SECTIONS { _edata = .; } - .realmode 0x8000 : + .realmode 0x4000 : AT ( ADDR(.data) + SIZEOF(.data) ) { _v86code = .; *(.v86); _ev86code = .; } diff --git a/task.nasm b/task.nasm index c0e9525..61696d9 100644 --- a/task.nasm +++ b/task.nasm @@ -89,7 +89,7 @@ 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); +; extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip, union V86Regs_t *regs); global enter_v86 global _enter_v86_internal_no_task enter_v86: @@ -98,6 +98,17 @@ mov ecx, esp ; return stack call save_current_task _enter_v86_internal_no_task: mov ebp, esp ; save stack pointer +mov eax, dword [ebp+16] ; regs +test eax, eax +jz .no_regs +; load regs: edi, esi, ebx, edx, ecx, eax +mov edi, dword [eax+0] +mov esi, dword [eax+4] +mov ebx, dword [eax+8] +mov edx, dword [eax+12] +mov ecx, dword [eax+16] +mov eax, dword [eax+20] +.no_regs: push dword [ebp+0] ; ss push dword [ebp+4] ; esp pushfd ; eflags diff --git a/usermode.nasm b/usermode.nasm index c0c7e24..00a6b64 100644 --- a/usermode.nasm +++ b/usermode.nasm @@ -8,7 +8,14 @@ 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 +push 0x00000013 ; eax AH=0,AL=3 set video mode 3 +push 0x00000000 ; ecx +push 0x00000000 ; edx +push 0x00000000 ; ebx +push 0x00000000 ; esi +push 0x00000000 ; edi +push esp ; regs +mov eax, 0x10 ; command = 10 int 0x21 ; OS call mov edi, 0xA0000 xor eax, eax diff --git a/v86.nasm b/v86.nasm index 4f872c2..b6ca0ca 100644 --- a/v86.nasm +++ b/v86.nasm @@ -84,6 +84,12 @@ int 0x10 int 0x30 jmp $ +global v86VideoInt +v86VideoInt: +int 0x10 +int 0x30 +jmp $ + global v86DiskRead v86DiskRead: xor ax, ax ; TODO fix assuming we're in first 64k diff --git a/v86defs.h b/v86defs.h new file mode 100644 index 0000000..cebd680 --- /dev/null +++ b/v86defs.h @@ -0,0 +1,51 @@ +#include + +extern void v86Test(); +extern void v86TransFlag(); +extern void v86GfxMode(); +extern void v86TextMode(); +extern void v86DiskRead(); +extern void v86VideoInt(); + +union __attribute((__packed__)) V86Regs_t { + struct dword_regs { + uint32_t edi; + uint32_t esi; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + } d; + struct word_regs { + uint16_t di, _upper_di; + uint16_t si, _upper_si; + uint16_t bx, _upper_bx; + uint16_t dx, _upper_dx; + uint16_t cx, _upper_cx; + uint16_t ax, _upper_ax; + } w; + struct byte_regs { + uint16_t di, _upper_di; + uint16_t si, _upper_si; + uint8_t bl, bh; + uint16_t _upper_bx; + uint8_t dl, dh; + uint16_t _upper_dx; + uint8_t cl, ch; + uint16_t _upper_cx; + uint8_t al, ah; + uint16_t _upper_ax; + } h; +}; + +extern void enter_v86(uint32_t ss, uint32_t esp, uint32_t cs, uint32_t eip, union V86Regs_t *regs); + +struct __attribute((__packed__)) Int13DiskPacket_t { + uint8_t size; // 0x10 + uint8_t reserved; // 0x00 + uint16_t blocks; + uint32_t transfer_buffer; // 0x2300:0000 + uint64_t start_block; +}; + +extern struct Int13DiskPacket_t v86disk_addr_packet;