Misc fixes to disk driver and real mode ints

This commit is contained in:
mintsuki 2019-06-03 00:14:32 +02:00
parent 33ce263987
commit 859b767b5d
4 changed files with 52 additions and 38 deletions

View File

@ -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;
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;
size_t sectors_count = 1 + ((offset + count) / SECTOR_SIZE);
int ret;
if ((ret = cache_sector(drive, sect)))
return ret;
while (sectors_count--) {
if (cur_sector != last_sector)
if ((res = read_sector(drive, sector_buf, cur_sector, 1)))
return res;
uint64_t chunk = count - progress;
uint64_t offset = (loc + progress) % SECTOR_SIZE;
if (chunk > SECTOR_SIZE - offset)
chunk = SECTOR_SIZE - offset;
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++;
memcpy(buffer + progress, &sector_buf[offset], chunk);
progress += chunk;
}
return 0;

View File

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

View File

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

View File

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