Skip to content
Snippets Groups Projects
disk.rs 2.27 KiB
Newer Older
Jeremy Soller's avatar
Jeremy Soller committed
use core::{mem, ptr};
use redoxfs::{BLOCK_SIZE, Disk};
Jeremy Soller's avatar
Jeremy Soller committed
use syscall::error::{Error, Result, EIO};

Jeremy Soller's avatar
Jeremy Soller committed
use crate::{DISK_ADDRESS_PACKET_ADDR, DISK_BIOS_ADDR, ThunkData};
Jeremy Soller's avatar
Jeremy Soller committed

#[derive(Clone, Copy)]
#[repr(packed)]
pub struct DiskAddressPacket {
    size: u8,
    reserved: u8,
    blocks: u16,
    buffer: u16,
    segment: u16,
    address: u64,
}

impl DiskAddressPacket {
    pub fn from_block(block: u64) -> DiskAddressPacket {
        let blocks = BLOCK_SIZE / 512;
        DiskAddressPacket {
Jeremy Soller's avatar
Jeremy Soller committed
            size: mem::size_of::<DiskAddressPacket>() as u8,
Jeremy Soller's avatar
Jeremy Soller committed
            reserved: 0,
Jeremy Soller's avatar
Jeremy Soller committed
            blocks: blocks as u16,
            buffer: DISK_BIOS_ADDR as u16,
Jeremy Soller's avatar
Jeremy Soller committed
            segment: 0,
            address: block * blocks,
        }
    }
}

pub struct DiskBios {
    boot_disk: u8,
Jeremy Soller's avatar
Jeremy Soller committed
    thunk13: extern "C" fn(),
}

impl DiskBios {
    pub fn new(boot_disk: u8, thunk13: extern "C" fn()) -> Self {
        Self { boot_disk, thunk13 }
Jeremy Soller's avatar
Jeremy Soller committed
    }
}

impl Disk for DiskBios {
Jeremy Soller's avatar
Jeremy Soller committed
    fn read_at(&mut self, block: u64, buffer: &mut [u8]) -> Result<usize> {
Jeremy Soller's avatar
Jeremy Soller committed
        for (i, chunk) in buffer.chunks_mut(BLOCK_SIZE as usize).enumerate() {
Jeremy Soller's avatar
Jeremy Soller committed
            unsafe {
                let mut dap = DiskAddressPacket::from_block(block);
                ptr::write(DISK_ADDRESS_PACKET_ADDR as *mut DiskAddressPacket, dap);
Jeremy Soller's avatar
Jeremy Soller committed

Jeremy Soller's avatar
Jeremy Soller committed
                let mut data = ThunkData::new();
                data.eax = 0x4200;
                data.edx = self.boot_disk as u32;
                data.esi = DISK_ADDRESS_PACKET_ADDR as u32;
Jeremy Soller's avatar
Jeremy Soller committed
                data.with(self.thunk13);
Jeremy Soller's avatar
Jeremy Soller committed
                //TODO: return result on error
                assert_eq!(data.eax, 0);
Jeremy Soller's avatar
Jeremy Soller committed
                //TODO: check blocks transferred
                dap = ptr::read(DISK_ADDRESS_PACKET_ADDR as *mut DiskAddressPacket);
Jeremy Soller's avatar
Jeremy Soller committed
                ptr::copy(DISK_BIOS_ADDR as *const u8, chunk.as_mut_ptr(), chunk.len());
            }
Jeremy Soller's avatar
Jeremy Soller committed
        }

        Ok(buffer.len())
Jeremy Soller's avatar
Jeremy Soller committed
    }

Jeremy Soller's avatar
Jeremy Soller committed
    fn write_at(&mut self, block: u64, buffer: &[u8]) -> Result<usize> {
        log::error!(
            "DiskBios::write_at(0x{:X}, 0x{:X}:0x{:X}) not allowed",
            block,
            buffer.as_ptr() as usize,
            buffer.len()
        );
        Err(Error::new(EIO))
Jeremy Soller's avatar
Jeremy Soller committed
    }

    fn size(&mut self) -> Result<u64> {
        log::error!("DiskBios::size not implemented");
        Err(Error::new(EIO))
Jeremy Soller's avatar
Jeremy Soller committed
    }
}