From 094e278212754ff4b26dd0e85174fe13b3725b0f Mon Sep 17 00:00:00 2001 From: Lucia Ceionia Date: Thu, 9 Feb 2023 13:19:50 -0600 Subject: [PATCH] Moved INT 13H disk operations outside DOSFS driver --- Makefile | 2 +- disk.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++ dosfs/dosfs.c | 84 +---------------------------------- kernel.c | 29 +++++++++--- tests.c | 3 +- v86.nasm | 9 ++-- v86defs.h | 2 +- 7 files changed, 153 insertions(+), 97 deletions(-) create mode 100644 disk.c diff --git a/Makefile b/Makefile index 63efd2a..87ed6e0 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o usermode.o paging.o fault.o tests.o kbd.o helper.o progs.o +objects = entry.o kernel.o task.o handler.o interrupt.o v86.o print.o tss.o dosfs/dosfs.o gdt.o usermode.o paging.o fault.o tests.o kbd.o helper.o progs.o disk.o CFLAGS = -target "i686-elf" -m32 -mgeneral-regs-only -ffreestanding -march=i686 -fno-stack-protector -Wno-int-conversion -nostdlib -c %.o: %.nasm diff --git a/disk.c b/disk.c new file mode 100644 index 0000000..3051343 --- /dev/null +++ b/disk.c @@ -0,0 +1,121 @@ +#include "v86defs.h" +#include "print.h" +#include "dosfs/dosfs.h" +#include "stdint.h" + +extern void *memcpy(void *restrict dest, const void *restrict src, uintptr_t n); + +extern uint32_t _gpf_eax_save; +extern uint32_t _gpf_eflags_save; +extern uint16_t error_screen[80*50]; // defined in kernel.c +__attribute((__no_caller_saved_registers__)) +extern void error_environment(); // defined in kernel.c +uint32_t numHead; +uint32_t secPerTrack; +uint32_t maxCylinder; +char useCHS = -1; +void Disk_SetupCHS() { + union V86Regs_t regs; + // Check for INT 13 Extensions support + regs.h.ah = 0x41; + regs.w.bx = 0x55AA; + regs.h.dl = 0x80; + V8086Int(0x13, ®s); + // LBA supported if CF clear + if (!(_gpf_eflags_save & 0x1)) { + useCHS = 0; + } else { + FARPTR v86_entry = i386LinearToFp(v86DiskGetGeometry); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); + // check CF for error + if (_gpf_eflags_save & 0x1) { + uint16_t *vga = error_screen; + vga += printStr("Could not get Disk Geometry.", vga); + error_environment(); + for(;;); + } + numHead = ((_gpf_eax_save & 0xff00) >> 8) + 1; + secPerTrack = _gpf_eax_save & 0x3f; + maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2); + useCHS = 1; + } +} +uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) { + // NOTE If the buffer provided is outside the 0x20000-0x2FE00 range, + // the function will use that buffer for the Virtual 8086 process + // and copy to the other buffer after + uint8_t *v86buf = buffer; + if ((uintptr_t)v86buf < 0x20000 || (uintptr_t)v86buf > 0x2FE00) + v86buf = (uint8_t *)0x20000; + + // TODO This check should probably happen at the kernel level + if (useCHS == -1) { + Disk_SetupCHS(); + } + + // TODO Do error handling + if (!useCHS) { + // LBA Read + v86disk_addr_packet.start_block = sector; + v86disk_addr_packet.blocks = count; + v86disk_addr_packet.transfer_buffer = + (uintptr_t)v86buf & 0x000F | + (((uintptr_t)v86buf & 0xFFFF0) << 12); + union V86Regs_t regs; + regs.h.ah = 0x42; + FARPTR v86_entry = i386LinearToFp(v86DiskOp); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); + } else { + uint32_t tmp = sector / secPerTrack; + uint32_t sec = (sector % (secPerTrack)) + 1; + uint32_t head = tmp % numHead; + uint32_t cyl = tmp / numHead; + union V86Regs_t regs; + regs.w.ax = 0x0201; + regs.h.ch = cyl & 0xff; + regs.h.cl = sec | ((cyl >> 2) & 0xc0); + regs.h.dh = head; + regs.h.dl = 0x80; + regs.w.bx = (uintptr_t)v86buf & 0xFFFF; + FARPTR v86_entry = i386LinearToFp(v86DiskReadCHS); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); + } + if (v86buf != buffer) + memcpy(buffer, v86buf, count * SECTOR_SIZE); + return 0; +} +uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) { + // NOTE If the buffer provided is outside the 0x20000-0x2FE00 range, + // the function will use copy that buffer into the Virtual 8086 disk range + uint8_t *v86buf = buffer; + if ((uintptr_t)v86buf < 0x20000 || (uintptr_t)v86buf > 0x2FE00) { + v86buf = (uint8_t *)0x20000; + memcpy(v86buf, buffer, count * SECTOR_SIZE); + } + + // TODO This check should probably happen at the kernel level + if (useCHS == -1) { + Disk_SetupCHS(); + } + + // TODO Do error handling + if (!useCHS) { + // LBA Read + v86disk_addr_packet.start_block = sector; + v86disk_addr_packet.blocks = count; + v86disk_addr_packet.transfer_buffer = + (uintptr_t)v86buf & 0x000F | + (((uintptr_t)v86buf & 0xFFFF0) << 12); + union V86Regs_t regs; + regs.w.ax = 0x4300; + FARPTR v86_entry = i386LinearToFp(v86DiskOp); + enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); + } else { + uint16_t *vga = error_screen; + vga += printStr("CHS Write Unimplemented", vga); + error_environment(); + for(;;); + } + return 0; +} + diff --git a/dosfs/dosfs.c b/dosfs/dosfs.c index f9bccea..6ce007b 100755 --- a/dosfs/dosfs.c +++ b/dosfs/dosfs.c @@ -1,3 +1,5 @@ +#include "tmpstring.c" + /* DOSFS Embedded FAT-Compatible Filesystem (C) 2005 Lewin A.R.W. Edwards (sysadm@zws.com) @@ -9,88 +11,6 @@ */ #include "dosfs.h" -#include "tmpstring.c" -#include "../v86defs.h" -#include "../print.h" - -extern uint32_t _gpf_eax_save; -extern uint32_t _gpf_eflags_save; -extern uint16_t error_screen[80*50]; // defined in kernel.c -__attribute((__no_caller_saved_registers__)) -extern void error_environment(); // defined in kernel.c -uint32_t numHead; -uint32_t secPerTrack; -uint32_t maxCylinder; -char useCHS = -1; -uint32_t DFS_ReadSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) { - // NOTE If the buffer provided is outside the 0x20000-0x2FE00 range, - // the function will use that buffer for the Virtual 8086 process - // and copy to the other buffer after - uint8_t *v86buf = buffer; - if ((uintptr_t)v86buf < 0x20000 || (uintptr_t)v86buf > 0x2FE00) - v86buf = (uint8_t *)0x20000; - - // TODO This check should probably happen at the kernel level - if (useCHS == -1) { - union V86Regs_t regs; - // Check for INT 13 Extensions support - regs.h.ah = 0x41; - regs.w.bx = 0x55AA; - regs.h.dl = 0x80; - V8086Int(0x13, ®s); - // LBA supported if CF clear - if (!(_gpf_eflags_save & 0x1)) { - useCHS = 0; - } else { - FARPTR v86_entry = i386LinearToFp(v86DiskGetGeometry); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); - // check CF for error - if (_gpf_eflags_save & 0x1) { - uint16_t *vga = error_screen; - vga += printStr("Could not get Disk Geometry.", vga); - error_environment(); - for(;;); - } - numHead = ((_gpf_eax_save & 0xff00) >> 8) + 1; - secPerTrack = _gpf_eax_save & 0x3f; - maxCylinder = ((_gpf_eax_save & 0xff0000) >> 16) | ((_gpf_eax_save & 0xc0) << 2); - useCHS = 1; - } - } - - // TODO Do error handling - if (!useCHS) { - // LBA Read - v86disk_addr_packet.start_block = sector; - v86disk_addr_packet.blocks = count; - v86disk_addr_packet.transfer_buffer = - (uintptr_t)v86buf & 0x000F | - (((uintptr_t)v86buf & 0xFFFF0) << 12); - union V86Regs_t regs; - FARPTR v86_entry = i386LinearToFp(v86DiskRead); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); - } else { - uint32_t tmp = sector / secPerTrack; - uint32_t sec = (sector % (secPerTrack)) + 1; - uint32_t head = tmp % numHead; - uint32_t cyl = tmp / numHead; - union V86Regs_t regs; - regs.w.ax = 0x0201; - regs.h.ch = cyl & 0xff; - regs.h.cl = sec | ((cyl >> 2) & 0xc0); - regs.h.dh = head; - regs.h.dl = 0x80; - regs.w.bx = (uintptr_t)v86buf & 0xFFFF; - FARPTR v86_entry = i386LinearToFp(v86DiskReadCHS); - enter_v86(0x8000, 0xFF00, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); - } - if (v86buf != buffer) - memcpy(buffer, v86buf, count * SECTOR_SIZE); - return 0; -} -uint32_t DFS_WriteSector(uint8_t unit, uint8_t *buffer, uint32_t sector, uint32_t count) { - for(;;); -} /* Get starting sector# of specified partition on drive #unit diff --git a/kernel.c b/kernel.c index cdfce4b..b1d8f49 100644 --- a/kernel.c +++ b/kernel.c @@ -239,6 +239,16 @@ void PrintFileList() { char IsDir(DIRENT *de) { return de->attr & ATTR_DIRECTORY; } +void ScancodeTest() { + uint16_t *vga = (uint16_t*)0xb8000; + uint16_t scancode; + while(((scancode = get_scancode()) & 0xff) != KEY_F1) { + vga += printWord(scancode, vga); + vga++; + if ((uintptr_t)vga >= 0xb8000+80*25*2) + vga = (uint16_t*)0xb8000; + } +} extern void create_child(uint32_t esp, uint32_t eip, uint32_t argc, ...); void FileSelect() { uint8_t current_path[80]; @@ -255,15 +265,15 @@ void FileSelect() { // Info line (4) { uint16_t *vga = &vga_text[80*4 + 79 - 24]; - printStr("T to run tests", vga); - vga += 80; printStr("X to view in hex", vga); vga += 80; - printStr("V to view as text", vga); + printStr("T to view as text", vga); vga += 80; printStr("P to load as program", vga); vga += 80; printStr("O to open directory", vga); + vga += 80; + printStr("F4 to run tests", vga); } printStr((char*)current_path, &vga_text[80*4 + 2]); for (int i = 2; i < 15; i++) @@ -285,15 +295,15 @@ void FileSelect() { uint16_t key = get_scancode(); uint8_t path[13]; switch (key & 0xff) { // scancode component - case 0x50: // down + case KEY_DOWN: // down fileHovered++; if (fileHovered >= fileCount) fileHovered = 0; break; - case 0x48: // up + case KEY_UP: // up fileHovered--; if (fileHovered < 0) fileHovered = fileCount - 1; break; - case 0x14: // t + case KEY_F4: create_child(0x380000, (uintptr_t)RunTests, 0); SetCursorDisabled(); reload = 1; @@ -313,7 +323,7 @@ void FileSelect() { SetCursorDisabled(); reload = 1; break; - case KEY_V: + case KEY_T: File83ToPath((char*)entries[fileHovered].name, (char*)¤t_path[current_path_end]); //TextViewTest(path, &vi); create_child(0x380000, (uintptr_t)TextViewTest, 2, current_path, &vi); @@ -322,6 +332,7 @@ void FileSelect() { reload = 1; break; case KEY_O: + case 0x9C: // enter release if (IsDir(&entries[fileHovered])) { uint8_t tmp_path[80]; File83ToPath((char*)entries[fileHovered].name, (char*)tmp_path); @@ -346,6 +357,10 @@ void FileSelect() { fileHovered = 0; } break; + case KEY_F6: + ScancodeTest(); + reload = 1; + break; default: break; } diff --git a/tests.c b/tests.c index a1b37cd..da510f0 100644 --- a/tests.c +++ b/tests.c @@ -40,7 +40,8 @@ void TestDiskRead() { v86disk_addr_packet.transfer_buffer = (uintptr_t)diskReadBuf & 0x000F | (((uintptr_t)diskReadBuf & 0xFFFF0) << 12); - FARPTR v86_entry = i386LinearToFp(v86DiskRead); + regs.h.ah = 0x42; + FARPTR v86_entry = i386LinearToFp(v86DiskOp); enter_v86(0x0000, 0x8000, FP_SEG(v86_entry), FP_OFF(v86_entry), ®s); uint16_t *vga_text = (uint16_t *)0xb8000; for (int i = 0; i < (80*25)/2; i++) { diff --git a/v86.nasm b/v86.nasm index 818e893..54ddd5f 100644 --- a/v86.nasm +++ b/v86.nasm @@ -89,11 +89,10 @@ int 0x10 int 0x30 jmp $ -global v86DiskRead -v86DiskRead: -xor ax, ax ; TODO fix assuming we're in first 64k -mov ds, ax -mov ah, 0x42 +global v86DiskOp +v86DiskOp: +xor bx, bx ; TODO fix assuming we're in first 64k +mov ds, bx mov dl, 0x80 ; TODO get this from BIOS or something mov si, v86disk_addr_packet ; ds:si int 0x13 diff --git a/v86defs.h b/v86defs.h index e3cf4a2..f8937d1 100644 --- a/v86defs.h +++ b/v86defs.h @@ -8,7 +8,7 @@ extern void v86Test(); extern void v86TransFlag(); extern void v86Interrupt(); extern void v86TextMode(); -extern void v86DiskRead(); +extern void v86DiskOp(); extern void v86DiskGetGeometry(); extern void v86DiskReadCHS();