2021-03-02 12:23:43 +03:00
|
|
|
#if defined(bios)
|
|
|
|
|
2019-06-02 00:34:24 +03:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
2019-06-02 00:48:33 +03:00
|
|
|
#include <drivers/disk.h>
|
2020-11-02 12:17:20 +03:00
|
|
|
#include <lib/libc.h>
|
2019-06-02 00:34:24 +03:00
|
|
|
#include <lib/real.h>
|
2020-01-22 07:02:12 +03:00
|
|
|
#include <lib/blib.h>
|
2020-05-10 01:38:27 +03:00
|
|
|
#include <lib/print.h>
|
2020-09-20 13:03:44 +03:00
|
|
|
#include <mm/pmm.h>
|
2019-06-02 00:34:24 +03:00
|
|
|
|
2020-09-25 23:36:26 +03:00
|
|
|
struct dap {
|
2019-06-02 00:48:33 +03:00
|
|
|
uint16_t size;
|
|
|
|
uint16_t count;
|
|
|
|
uint16_t offset;
|
|
|
|
uint16_t segment;
|
|
|
|
uint64_t lba;
|
2020-09-25 23:36:26 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct dap *dap = NULL;
|
2019-06-02 00:34:24 +03:00
|
|
|
|
2021-03-03 22:53:26 +03:00
|
|
|
#define XFER_BUF_SIZE 16384
|
|
|
|
static void *xfer_buf = NULL;
|
|
|
|
|
|
|
|
bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t count) {
|
|
|
|
if (count * volume->sector_size > XFER_BUF_SIZE)
|
|
|
|
panic("XFER");
|
2019-06-03 01:14:32 +03:00
|
|
|
|
2021-03-03 22:53:26 +03:00
|
|
|
if (xfer_buf == NULL)
|
|
|
|
xfer_buf = conv_mem_alloc_aligned(XFER_BUF_SIZE, 16);
|
|
|
|
|
|
|
|
if (dap == NULL) {
|
2020-09-25 23:36:26 +03:00
|
|
|
dap = conv_mem_alloc(sizeof(struct dap));
|
|
|
|
dap->size = 16;
|
|
|
|
}
|
|
|
|
|
2021-03-03 22:53:26 +03:00
|
|
|
dap->count = count;
|
2020-03-28 06:02:26 +03:00
|
|
|
|
2021-03-03 22:53:26 +03:00
|
|
|
dap->segment = rm_seg(xfer_buf);
|
|
|
|
dap->offset = rm_off(xfer_buf);
|
|
|
|
dap->lba = block;
|
2019-06-03 01:14:32 +03:00
|
|
|
|
|
|
|
struct rm_regs r = {0};
|
|
|
|
r.eax = 0x4200;
|
2021-03-03 22:53:26 +03:00
|
|
|
r.edx = volume->drive;
|
2020-09-25 23:36:26 +03:00
|
|
|
r.esi = (uint32_t)rm_off(dap);
|
|
|
|
r.ds = rm_seg(dap);
|
2019-06-03 01:14:32 +03:00
|
|
|
|
|
|
|
rm_int(0x13, &r, &r);
|
|
|
|
|
|
|
|
if (r.eflags & EFLAGS_CF) {
|
|
|
|
int ah = (r.eax >> 8) & 0xff;
|
2021-03-03 23:40:55 +03:00
|
|
|
switch (ah) {
|
|
|
|
case 0x0c:
|
|
|
|
return false;
|
|
|
|
default:
|
|
|
|
panic("Disk error %x. Drive %x, LBA %x.",
|
|
|
|
ah, volume->drive, dap->lba);
|
|
|
|
}
|
2019-06-03 01:14:32 +03:00
|
|
|
}
|
|
|
|
|
2021-03-03 23:40:55 +03:00
|
|
|
if (buf != NULL)
|
|
|
|
memcpy(buf, xfer_buf, count * volume->sector_size);
|
2019-06-02 12:17:49 +03:00
|
|
|
|
2021-03-03 22:53:26 +03:00
|
|
|
return true;
|
2019-06-02 12:17:49 +03:00
|
|
|
}
|
2021-03-02 12:23:43 +03:00
|
|
|
|
|
|
|
size_t disk_create_index(struct volume **ret) {
|
|
|
|
struct volume *volume_index;
|
|
|
|
size_t volume_count = 0, volume_index_i = 0;
|
|
|
|
|
|
|
|
for (uint8_t drive = 0x80; drive; drive++) {
|
|
|
|
struct rm_regs r = {0};
|
|
|
|
struct bios_drive_params drive_params;
|
|
|
|
|
|
|
|
r.eax = 0x4800;
|
|
|
|
r.edx = drive;
|
|
|
|
r.ds = rm_seg(&drive_params);
|
|
|
|
r.esi = rm_off(&drive_params);
|
|
|
|
|
|
|
|
drive_params.buf_size = sizeof(struct bios_drive_params);
|
|
|
|
|
|
|
|
rm_int(0x13, &r, &r);
|
|
|
|
|
|
|
|
if (r.eflags & EFLAGS_CF)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
print("Found BIOS drive %x\n", drive);
|
|
|
|
print(" ... %X total %u-byte sectors\n",
|
|
|
|
drive_params.lba_count, drive_params.bytes_per_sect);
|
|
|
|
|
|
|
|
volume_count++;
|
|
|
|
|
|
|
|
struct volume block;
|
|
|
|
|
|
|
|
block.drive = drive;
|
|
|
|
block.sector_size = drive_params.bytes_per_sect;
|
|
|
|
block.first_sect = 0;
|
|
|
|
block.sect_count = drive_params.lba_count;
|
|
|
|
|
2021-03-03 23:40:55 +03:00
|
|
|
// The medium could not be present (e.g.: CD-ROMs)
|
|
|
|
// Do a test run to see if we can actually read it
|
|
|
|
if (!disk_read_sectors(&block, NULL, 0, 1)) {
|
|
|
|
print(" ... Ignoring drive...\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-03-02 12:23:43 +03:00
|
|
|
for (int part = 0; ; part++) {
|
|
|
|
struct volume p;
|
|
|
|
int ret = part_get(&p, &block, part);
|
|
|
|
|
|
|
|
if (ret == END_OF_TABLE || ret == INVALID_TABLE)
|
|
|
|
break;
|
|
|
|
if (ret == NO_PARTITION)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
volume_count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
volume_index = ext_mem_alloc(sizeof(struct volume) * volume_count);
|
|
|
|
|
|
|
|
for (uint8_t drive = 0x80; drive; drive++) {
|
|
|
|
struct rm_regs r = {0};
|
|
|
|
struct bios_drive_params drive_params;
|
|
|
|
|
|
|
|
r.eax = 0x4800;
|
|
|
|
r.edx = drive;
|
|
|
|
r.ds = rm_seg(&drive_params);
|
|
|
|
r.esi = rm_off(&drive_params);
|
|
|
|
|
|
|
|
drive_params.buf_size = sizeof(struct bios_drive_params);
|
|
|
|
|
|
|
|
rm_int(0x13, &r, &r);
|
|
|
|
|
|
|
|
if (r.eflags & EFLAGS_CF)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
struct volume *block = &volume_index[volume_index_i++];
|
|
|
|
|
|
|
|
block->drive = drive;
|
|
|
|
block->partition = -1;
|
|
|
|
block->sector_size = drive_params.bytes_per_sect;
|
|
|
|
block->first_sect = 0;
|
|
|
|
block->sect_count = drive_params.lba_count;
|
|
|
|
|
2021-03-03 23:40:55 +03:00
|
|
|
// The medium could not be present (e.g.: CD-ROMs)
|
|
|
|
// Do a test run to see if we can actually read it
|
|
|
|
if (!disk_read_sectors(block, NULL, 0, 1)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-03-02 12:23:43 +03:00
|
|
|
if (gpt_get_guid(&block->guid, block)) {
|
|
|
|
block->guid_valid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int part = 0; ; part++) {
|
|
|
|
struct volume p;
|
|
|
|
int ret = part_get(&p, block, part);
|
|
|
|
|
|
|
|
if (ret == END_OF_TABLE || ret == INVALID_TABLE)
|
|
|
|
break;
|
|
|
|
if (ret == NO_PARTITION)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
volume_index[volume_index_i++] = p;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*ret = volume_index;
|
|
|
|
return volume_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|