diff --git a/drivers/disk.c b/drivers/disk.c index 98c91a71..b4f12e9a 100644 --- a/drivers/disk.c +++ b/drivers/disk.c @@ -7,6 +7,7 @@ #define SECTOR_SIZE 512 +static uint64_t last_sector = -1; static uint8_t sector_buf[512]; static struct { @@ -17,11 +18,11 @@ static struct { uint64_t lba; } dap = { 16, 1, 0, 0, 0 }; -int read_sector(int drive, int lba, int count, void *buffer) { +int read_sector(int drive, void *buffer, uint64_t lba, size_t count) { dap.offset = (uint16_t)(size_t)sector_buf; while (count--) { - dap.lba = lba++; + dap.lba = lba; struct rm_regs r = {0}; r.eax = 0x4200; r.edx = drive; @@ -35,9 +36,38 @@ int read_sector(int drive, int lba, int count, void *buffer) { } memcpy(buffer, sector_buf, SECTOR_SIZE); + last_sector = lba++; buffer += SECTOR_SIZE; } 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, §or_buf[offset], limited_count); + + offset = (offset + limited_count) % SECTOR_SIZE; + buffer += limited_count; + cur_sector++; + } + + return 0; +}