:: commit 859b767b5d89f25b4563580d0ff7d0b3bbd3060d

mintsuki <mintsuki@protonmail.com> — 2019-06-02 22:14

parents: 33ce263987

Misc fixes to disk driver and real mode ints

diff --git a/drivers/disk.c b/drivers/disk.c
index b4f12e9a..8558d5e6 100644
--- a/drivers/disk.c
+++ b/drivers/disk.c
@@ -7,7 +7,7 @@
 
 #define SECTOR_SIZE 512
 
-static uint64_t last_sector = -1;
+static uint64_t cached_sector = -1;
 static uint8_t sector_buf[512];
 
 static struct {
@@ -18,25 +18,38 @@ static struct {
     uint64_t lba;
 } dap = { 16, 1, 0, 0, 0 };
 
-int read_sector(int drive, void *buffer, uint64_t lba, size_t count) {
+static int cache_sector(int drive, uint64_t lba) {
+    if (lba == cached_sector)
+        return 0;
+
     dap.offset = (uint16_t)(size_t)sector_buf;
+    dap.lba = lba;
+
+    struct rm_regs r = {0};
+    r.eax = 0x4200;
+    r.edx = drive;
+    r.esi = (uint32_t)&dap;
+
+    rm_int(0x13, &r, &r);
+
+    if (r.eflags & EFLAGS_CF) {
+        int ah = (r.eax >> 8) & 0xff;
+        print("Disk error %x. Drive %x, LBA %x.\n", ah, drive, lba);
+        return ah;
+    }
+
+    cached_sector = lba;
 
+    return 0;
+}
+
+int read_sector(int drive, void *buffer, uint64_t lba, uint64_t count) {
     while (count--) {
-        dap.lba = lba;
-        struct rm_regs r = {0};
-        r.eax = 0x4200;
-        r.edx = drive;
-        r.esi = (unsigned int)&dap;
-        rm_int(0x13, &r, &r);
-
-        int ah = (r.eax >> 8) & 0xFF;
-        if (ah) {
-            print("Disk error %x\n", ah);
-            return ah;
-        }
+        int ret;
+        if ((ret = cache_sector(drive, lba++)))
+            return ret;
 
         memcpy(buffer, sector_buf, SECTOR_SIZE);
-        last_sector = lba++;
 
         buffer += SECTOR_SIZE;
     }
@@ -44,29 +57,22 @@ int read_sector(int drive, void *buffer, uint64_t lba, size_t count) {
     return 0;
 }
 
-int read(int drive, void *buffer, int offset, size_t count) {
-    int res;
-    
-    if (last_sector == (uint64_t)-1)
-        if ((res = read_sector(drive, sector_buf, 0, 1)))
-            return res;
-    
-    uint64_t cur_sector = last_sector + (offset / SECTOR_SIZE);
-    offset %= SECTOR_SIZE;
-
-    size_t sectors_count = 1 + ((offset + count) / SECTOR_SIZE);
-
-    while (sectors_count--) {
-        if (cur_sector != last_sector)
-            if ((res = read_sector(drive, sector_buf, cur_sector, 1)))
-                return res;
-
-        size_t limited_count = ((offset + count) > SECTOR_SIZE) ? (size_t)(SECTOR_SIZE - offset) : count;
-        memcpy(buffer, &sector_buf[offset], limited_count);
-
-        offset = (offset + limited_count) % SECTOR_SIZE;
-        buffer += limited_count;
-        cur_sector++;
+int read(int drive, void *buffer, uint64_t loc, uint64_t count) {
+    uint64_t progress = 0;
+    while (progress < count) {
+        uint64_t sect = (loc + progress) / SECTOR_SIZE;
+
+        int ret;
+        if ((ret = cache_sector(drive, sect)))
+            return ret;
+
+        uint64_t chunk = count - progress;
+        uint64_t offset = (loc + progress) % SECTOR_SIZE;
+        if (chunk > SECTOR_SIZE - offset)
+            chunk = SECTOR_SIZE - offset;
+
+        memcpy(buffer + progress, &sector_buf[offset], chunk);
+        progress += chunk;
     }
 
     return 0;
diff --git a/drivers/disk.h b/drivers/disk.h
index 67cf9f35..4f9191e2 100644
--- a/drivers/disk.h
+++ b/drivers/disk.h
@@ -1,9 +1,10 @@
 #ifndef __DISK_H__
 #define __DISK_H__
 
+#include <stddef.h>
 #include <stdint.h>
 
-int read_sector(int, void *, uint64_t, size_t);
-int read(int, void *, int, size_t);
+int read_sector(int, void *, uint64_t, uint64_t);
+int read(int, void *, uint64_t, uint64_t);
 
 #endif
diff --git a/lib/real.c b/lib/real.c
index b5796656..ca41cbd2 100644
--- a/lib/real.c
+++ b/lib/real.c
@@ -23,6 +23,7 @@ void rm_int(
         "push esi\n\t"
         "push edi\n\t"
         "push ebp\n\t"
+        "pushf\n\t"
 
         // Jump to real mode
         "jmp 0x08:1f\n\t"
@@ -48,6 +49,7 @@ void rm_int(
         // Load in_regs
         "mov dword ptr ds:[5f], esp\n\t"
         "mov esp, dword ptr ds:[7f]\n\t"
+        "popfd\n\t"
         "pop ebp\n\t"
         "pop edi\n\t"
         "pop esi\n\t"
@@ -64,7 +66,7 @@ void rm_int(
         // Load out_regs
         "mov dword ptr ds:[5f], esp\n\t"
         "mov esp, dword ptr ds:[6f]\n\t"
-        "add esp, 7*4\n\t"
+        "lea esp, [esp + 8*4]\n\t"
         "push eax\n\t"
         "push ebx\n\t"
         "push ecx\n\t"
@@ -72,6 +74,7 @@ void rm_int(
         "push esi\n\t"
         "push edi\n\t"
         "push ebp\n\t"
+        "pushfd\n\t"
         "mov esp, dword ptr ds:[5f]\n\t"
 
         // Jump back to pmode
@@ -88,6 +91,7 @@ void rm_int(
         "mov ss, ax\n\t"
 
         // Restore non-scratch GPRs
+        "popf\n\t"
         "pop ebp\n\t"
         "pop edi\n\t"
         "pop esi\n\t"
diff --git a/lib/real.h b/lib/real.h
index 352bfdfe..6dcd37af 100644
--- a/lib/real.h
+++ b/lib/real.h
@@ -6,7 +6,10 @@
 #define rm_seg(x) (unsigned short)(((int)x & 0xFFFF0) >> 4)
 #define rm_off(x) (unsigned short)(((int)x & 0x0000F) >> 0)
 
+#define EFLAGS_CF (1 << 0)
+
 struct rm_regs {
+    uint32_t eflags;
     uint32_t ebp;
     uint32_t edi;
     uint32_t esi;
tab: 248 wrap: offon