I'm getting rather a lot further this time, and am almost at the point where I can read in a file from its path, the longer way around (as in, enumerate ACPI, emumerate PCI bus, find and initialise IDE controllers, and so forth), giving me a solid foundation to build upon.
I'm experiencing some strangeness around LBA addresses. For addresses <255, I have to add 1 to it for some reason - attempting to read LBA 0 gives me an ABORT, but reading LBA 1 gives me the first sector.
For addresses >255, things seem to get all kinds of muddled. Attempting to read sector 465 (+1 when programming = 466) instead yields sector 1217, verified by outputting the hex, and comparing the disk image manually in a hex editor to find that particular string.
Neither of these things seem like they should be true, yet here we are, and for the life of me I can't work out what I've done wrong.
The device reports on the PCI bus as a PIIX3 IDE controller. Using debug printing I can confirm the sector I'm reading is indeed sector 466, taken 1 indexed, when programming the LBA registers.
The command line I'm using is:
Code: Select all
qemu-system-x86_64 -bios $OVMF_PURE_EFI -drive format=raw,file=uefi.img -accel kvm
Code: Select all
const IDE_CTL_HOB: u8 = 1 << 7;
const IDE_CTL_REG: u16 = 0;
const IDE_REG_LBA0: u16 = 3;
const IDE_REG_LBA1: u16 = 4;
const IDE_REG_LBA2: u16 = 5;
const IDE_REG_SECCOUNT: u16 = 2;
impl IdeDrive {
fn select_drive_and_set_xfer_params(&self, ctl: &RwLockWriteGuard<'_, IdeController>, offset: u64, size: u64) {
self.select(&ctl);
// debug to confirm I'm trying to read the sector I think I should be
log::info!("Reading {}", offset);
if self.ident.is_lba48() {
unsafe {
let mut lba3_reg = Port::<u8>::new(ctl.io_base + IDE_REG_LBA0);
let mut lba4_reg = Port::<u8>::new(ctl.io_base + IDE_REG_LBA1);
let mut lba5_reg = Port::<u8>::new(ctl.io_base + IDE_REG_LBA2);
let mut seccount1_reg = Port::<u8>::new(ctl.io_base + IDE_REG_SECCOUNT);
let mut ctl_reg = Port::<u8>::new(ctl.control_base + IDE_CTL_REG);
let control_word_high_order = ctl_reg.read() | IDE_CTL_HOB;
ctl_reg.write(control_word_high_order);
lba3_reg.write((offset >> 24) as u8);
lba4_reg.write((offset >> 32) as u8);
lba5_reg.write((offset >> 40) as u8);
seccount1_reg.write((size >> 8) as u8);
let control_word_low_order = ctl_reg.read() & !IDE_CTL_HOB;
ctl_reg.write(control_word_low_order);
}
}
unsafe {
let mut lba0_reg = Port::<u8>::new(ctl.io_base + IDE_REG_LBA0);
let mut lba1_reg = Port::<u8>::new(ctl.io_base + IDE_REG_LBA1);
let mut lba2_reg = Port::<u8>::new(ctl.io_base + IDE_REG_LBA2);
let mut seccount0_reg = Port::<u8>::new(ctl.io_base + IDE_REG_SECCOUNT);
lba0_reg.write(offset as u8);
lba1_reg.write((offset >> 8) as u8);
lba2_reg.write((offset >> 16) as u8);
seccount0_reg.write(size as u8);
}
}
}
Help would be greatly appreciated, as I'm at a genuine loss as to why it's behaving the way that it is.
Kind regards,
Venos :3