diff --git a/Cargo.lock b/Cargo.lock index da45912c2c..f95e8e00f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -42,11 +42,10 @@ name = "ahcid" version = "0.1.0" dependencies = [ "bitflags 1.3.2", - "block-io-wrapper", "byteorder", "common", + "driver-block", "log", - "partitionlib", "pcid", "redox-daemon", "redox-log", @@ -149,10 +148,9 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" name = "bcm2835-sdhcid" version = "0.1.0" dependencies = [ - "block-io-wrapper", "common", + "driver-block", "fdt", - "partitionlib", "redox-daemon", "redox_syscall 0.4.1", ] @@ -206,10 +204,6 @@ dependencies = [ "wyz", ] -[[package]] -name = "block-io-wrapper" -version = "0.1.0" - [[package]] name = "bumpalo" version = "3.13.0" @@ -350,6 +344,14 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "driver-block" +version = "0.1.0" +dependencies = [ + "partitionlib", + "redox_syscall 0.4.1", +] + [[package]] name = "driver-network" version = "0.1.0" @@ -570,10 +572,9 @@ dependencies = [ name = "ided" version = "0.1.0" dependencies = [ - "block-io-wrapper", "common", + "driver-block", "log", - "partitionlib", "pcid", "redox-daemon", "redox-log", @@ -758,9 +759,9 @@ version = "0.1.0" dependencies = [ "arrayvec", "bitflags 1.3.2", - "block-io-wrapper", "common", "crossbeam-channel", + "driver-block", "futures", "log", "partitionlib", @@ -1591,8 +1592,8 @@ name = "virtio-blkd" version = "0.1.0" dependencies = [ "anyhow", - "block-io-wrapper", "common", + "driver-block", "futures", "log", "partitionlib", diff --git a/Cargo.toml b/Cargo.toml index b489a829a7..ec66f52ad5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ members = [ "storage/ahcid", "storage/bcm2835-sdhcid", - "storage/block-io-wrapper", + "storage/driver-block", "storage/ided", "storage/lived", # TODO: not really a driver... "storage/nvmed", diff --git a/net/driver-network/src/lib.rs b/net/driver-network/src/lib.rs index 6c10a352d0..3790b33ba5 100644 --- a/net/driver-network/src/lib.rs +++ b/net/driver-network/src/lib.rs @@ -50,7 +50,7 @@ impl NetworkScheme { format!(":{scheme_name}"), syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK, ) - .expect("e1000d: failed to create network scheme"); + .expect("failed to create network scheme"); let scheme = unsafe { File::from_raw_fd(scheme_fd as RawFd) }; NetworkScheme { diff --git a/storage/ahcid/Cargo.toml b/storage/ahcid/Cargo.toml index 03fd054a25..4c84077667 100644 --- a/storage/ahcid/Cargo.toml +++ b/storage/ahcid/Cargo.toml @@ -7,11 +7,10 @@ edition = "2018" bitflags = "1.2" byteorder = "1.2" log = "0.4" -partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } redox-daemon = "0.1" redox-log = "0.1" redox_syscall = "0.4" -block-io-wrapper = { path = "../block-io-wrapper" } common = { path = "../../common" } +driver-block = { path = "../driver-block" } pcid = { path = "../../pcid" } diff --git a/storage/ahcid/src/ahci/mod.rs b/storage/ahcid/src/ahci/mod.rs index 2036189d24..3f63ca235e 100644 --- a/storage/ahcid/src/ahci/mod.rs +++ b/storage/ahcid/src/ahci/mod.rs @@ -1,6 +1,6 @@ +use driver_block::Disk; use log::{error, info}; use syscall::io::Io; -use syscall::error::Result; use self::disk_ata::DiskATA; use self::disk_atapi::DiskATAPI; @@ -11,14 +11,6 @@ pub mod disk_atapi; pub mod fis; pub mod hba; -pub trait Disk { - fn id(&self) -> usize; - fn size(&mut self) -> u64; - fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result>; - fn write(&mut self, block: u64, buffer: &[u8]) -> Result>; - fn block_length(&mut self) -> Result; -} - pub fn disks(base: usize, name: &str) -> (&'static mut HbaMem, Vec>) { let hba_mem = unsafe { &mut *(base as *mut HbaMem) }; hba_mem.init(); diff --git a/storage/ahcid/src/scheme.rs b/storage/ahcid/src/scheme.rs index 77b36972a3..ae7bb32573 100644 --- a/storage/ahcid/src/scheme.rs +++ b/storage/ahcid/src/scheme.rs @@ -3,19 +3,15 @@ use std::{cmp, str}; use std::convert::{TryFrom}; use std::fmt::Write; use std::io::prelude::*; -use std::io::SeekFrom; -use std::io; +use driver_block::{Disk, DiskWrapper}; use syscall::{ Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; -use crate::ahci::Disk; use crate::ahci::hba::HbaMem; -use partitionlib::{LogicalBlockSize, PartitionTable}; - #[derive(Clone)] enum Handle { List(Vec, usize), // Dir contents buffer, position @@ -23,89 +19,6 @@ enum Handle { Partition(usize, u32, usize), // Disk index, partition index, position } -pub struct DiskWrapper { - disk: Box, - pt: Option, -} - -impl DiskWrapper { - fn pt(disk: &mut dyn Disk) -> Option { - let bs = match disk.block_length() { - Ok(512) => LogicalBlockSize::Lb512, - Ok(4096) => LogicalBlockSize::Lb4096, - _ => return None, - }; - struct Device<'a, 'b> { disk: &'a mut dyn Disk, offset: u64, block_bytes: &'b mut [u8] } - - impl<'a, 'b> Seek for Device<'a, 'b> { - fn seek(&mut self, from: SeekFrom) -> io::Result { - let size = i64::try_from(self.disk.size()).or(Err(io::Error::new(io::ErrorKind::Other, "Disk larger than 2^63 - 1 bytes")))?; - - self.offset = match from { - SeekFrom::Start(new_pos) => cmp::min(self.disk.size(), new_pos), - SeekFrom::Current(new_pos) => cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64, - SeekFrom::End(new_pos) => cmp::max(0, cmp::min(size + new_pos, size)) as u64, - }; - - Ok(self.offset) - } - } - // TODO: Perhaps this impl should be used in the rest of the scheme. - impl<'a, 'b> Read for Device<'a, 'b> { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let blksize = self.disk.block_length().map_err(|err| io::Error::from_raw_os_error(err.errno))?; - let size_in_blocks = self.disk.size() / u64::from(blksize); - - let disk = &mut self.disk; - - let read_block = |block: u64, block_bytes: &mut [u8]| { - if block >= size_in_blocks { - return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW)); - } - loop { - match disk.read(block, block_bytes) { - Ok(Some(bytes)) => { - assert_eq!(bytes, block_bytes.len()); - assert_eq!(bytes, blksize as usize); - return Ok(()); - } - Ok(None) => { std::thread::yield_now(); continue } - Err(err) => return Err(io::Error::from_raw_os_error(err.errno)), - } - } - }; - let bytes_read = block_io_wrapper::read(self.offset, blksize, buf, self.block_bytes, read_block)?; - - self.offset += bytes_read as u64; - Ok(bytes_read) - } - } - - let mut block_bytes = [0u8; 4096]; - - partitionlib::get_partitions(&mut Device { disk, offset: 0, block_bytes: &mut block_bytes[..bs.into()] }, bs).ok().flatten() - } - fn new(mut disk: Box) -> Self { - Self { - pt: Self::pt(&mut *disk), - disk, - } - } -} - -impl std::ops::Deref for DiskWrapper { - type Target = dyn Disk; - - fn deref(&self) -> &Self::Target { - &*self.disk - } -} -impl std::ops::DerefMut for DiskWrapper { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut *self.disk - } -} - pub struct DiskScheme { scheme_name: String, hba_mem: &'static mut HbaMem, diff --git a/storage/bcm2835-sdhcid/Cargo.toml b/storage/bcm2835-sdhcid/Cargo.toml index f9bce4ae2b..d92d58d3fa 100644 --- a/storage/bcm2835-sdhcid/Cargo.toml +++ b/storage/bcm2835-sdhcid/Cargo.toml @@ -8,8 +8,7 @@ edition = "2021" [dependencies] fdt = "0.1.5" redox_syscall = "0.4" -partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } -block-io-wrapper = { path = "../block-io-wrapper" } common = { path = "../../common" } +driver-block = { path = "../driver-block" } redox-daemon = "0.1" diff --git a/storage/bcm2835-sdhcid/src/main.rs b/storage/bcm2835-sdhcid/src/main.rs index f70e8cca4a..7a815a64e2 100644 --- a/storage/bcm2835-sdhcid/src/main.rs +++ b/storage/bcm2835-sdhcid/src/main.rs @@ -1,15 +1,15 @@ use std::{fs::File, io::{Read, Write}, process}; +use driver_block::Disk; use fdt::{Fdt, node::FdtNode}; use syscall::{Packet, SchemeBlockMut}; -use crate::sd::Disk; use crate::scheme::DiskScheme; mod sd; mod scheme; -#[cfg(target_os = "redox")] +#[cfg(target_os = "redox")] fn get_dtb() -> Vec { std::fs::read("kernel.dtb:").unwrap() } @@ -48,7 +48,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { }; println!("ioremap 0x{:08x} to 0x{:08x} 2222", reg.starting_address as usize, addr); let mut sdhci = sd::SdHostCtrl::new(addr); - unsafe { + unsafe { sdhci.init(); /* let mut buf1 = [0u32; 512]; diff --git a/storage/bcm2835-sdhcid/src/scheme.rs b/storage/bcm2835-sdhcid/src/scheme.rs index fce64bb363..7f0e9f6e22 100644 --- a/storage/bcm2835-sdhcid/src/scheme.rs +++ b/storage/bcm2835-sdhcid/src/scheme.rs @@ -3,19 +3,14 @@ use std::{cmp, str}; use std::convert::{TryFrom}; use std::fmt::Write; use std::io::prelude::*; -use std::io::SeekFrom; -use std::io; use std::sync::{Arc, Mutex}; +use driver_block::{Disk, DiskWrapper}; use syscall::{ Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; -use crate::sd::Disk; - -use partitionlib::{LogicalBlockSize, PartitionTable}; - #[derive(Clone)] enum Handle { List(Vec, usize), // Dir contents buffer, position @@ -23,88 +18,6 @@ enum Handle { Partition(usize, u32, usize), // Disk index, partition index, position } -pub struct DiskWrapper { - disk: Box, - pt: Option, -} - -impl DiskWrapper { - fn pt(disk: &mut dyn Disk) -> Option { - let bs = match disk.block_length() { - Ok(512) => LogicalBlockSize::Lb512, - _ => return None, - }; - struct Device<'a, 'b> { disk: &'a mut dyn Disk, offset: u64, block_bytes: &'b mut [u8] } - - impl<'a, 'b> Seek for Device<'a, 'b> { - fn seek(&mut self, from: SeekFrom) -> io::Result { - let size = i64::try_from(self.disk.size()).or(Err(io::Error::new(io::ErrorKind::Other, "Disk larger than 2^63 - 1 bytes")))?; - - self.offset = match from { - SeekFrom::Start(new_pos) => cmp::min(self.disk.size(), new_pos), - SeekFrom::Current(new_pos) => cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64, - SeekFrom::End(new_pos) => cmp::max(0, cmp::min(size + new_pos, size)) as u64, - }; - - Ok(self.offset) - } - } - // TODO: Perhaps this impl should be used in the rest of the scheme. - impl<'a, 'b> Read for Device<'a, 'b> { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let blksize = self.disk.block_length().map_err(|err| io::Error::from_raw_os_error(err.errno))?; - let size_in_blocks = self.disk.size() / u64::from(blksize); - - let disk = &mut self.disk; - - let read_block = |block: u64, block_bytes: &mut [u8]| { - if block >= size_in_blocks { - return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW)); - } - loop { - match disk.read(block, block_bytes) { - Ok(Some(bytes)) => { - assert_eq!(bytes, block_bytes.len()); - assert_eq!(bytes, blksize as usize); - return Ok(()); - } - Ok(None) => { std::thread::yield_now(); continue } - Err(err) => return Err(io::Error::from_raw_os_error(err.errno)), - } - } - }; - let bytes_read = block_io_wrapper::read(self.offset, blksize, buf, self.block_bytes, read_block)?; - - self.offset += bytes_read as u64; - Ok(bytes_read) - } - } - - let mut block_bytes = [0u8; 4096]; - - partitionlib::get_partitions(&mut Device { disk, offset: 0, block_bytes: &mut block_bytes[..bs.into()] }, bs).ok().flatten() - } - fn new(mut disk: Box) -> Self { - Self { - pt: Self::pt(&mut *disk), - disk, - } - } -} - -impl std::ops::Deref for DiskWrapper { - type Target = dyn Disk; - - fn deref(&self) -> &Self::Target { - &*self.disk - } -} -impl std::ops::DerefMut for DiskWrapper { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut *self.disk - } -} - pub struct DiskScheme { scheme_name: String, disks: Box<[DiskWrapper]>, diff --git a/storage/bcm2835-sdhcid/src/sd/mod.rs b/storage/bcm2835-sdhcid/src/sd/mod.rs index be5c37df7b..ece800a329 100644 --- a/storage/bcm2835-sdhcid/src/sd/mod.rs +++ b/storage/bcm2835-sdhcid/src/sd/mod.rs @@ -1,6 +1,6 @@ use std::{sync::{Mutex, RwLock}, time::{self, Duration}, thread}; use syscall::{io::Mmio, Io, Error, Result, EINVAL}; -use core::ptr::{read_volatile, write_volatile}; +use driver_block::Disk; #[cfg(target_arch = "aarch64")] #[inline(always)] @@ -17,7 +17,7 @@ pub(crate) unsafe fn wait_cycles(mut n: usize) { #[inline(always)] pub(crate) unsafe fn wait_msec(mut n: usize) { use core::arch::asm; - + let mut f: usize; let mut t: usize; let mut r: usize; @@ -185,7 +185,7 @@ pub struct SdHostCtrl { impl SdHostCtrl { pub fn new(address: usize) -> Self { SdHostCtrl { - regs: RwLock::new(unsafe { &mut *(address as *mut SdHostCtrlRegs)}), + regs: RwLock::new(unsafe { &mut *(address as *mut SdHostCtrlRegs)}), host_spec_ver: 0, cid: [0; 4], csd: [0; 4], @@ -228,7 +228,7 @@ impl SdHostCtrl { return ; } } - + let regs = self.regs.get_mut().unwrap(); regs.irpt_en.write(0xffff_ffff); regs.irpt_mask.write(0xffff_ffff); @@ -518,7 +518,7 @@ impl SdHostCtrl { self.cid[1] = regs.resp1.read(); self.cid[2] = regs.resp2.read(); self.cid[3] = regs.resp3.read(); - + //FIXME: wrong implement, see CMD_SEND_CSD for detail return Ok(reg_val); } else if code == CMD_SEND_CSD { @@ -526,7 +526,7 @@ impl SdHostCtrl { let tmp1 = regs.resp1.read(); let tmp2 = regs.resp2.read(); let tmp3 = regs.resp3.read(); - + self.csd[0] = tmp3 << 8 | tmp2 >> 24; self.csd[1] = tmp2 << 8 | tmp1 >> 24; self.csd[2] = tmp1 << 8 | tmp0 >> 24; @@ -713,14 +713,6 @@ impl SdHostCtrl { } } -pub trait Disk { - fn id(&self) -> usize; - fn size(&mut self) -> u64; - fn read(&mut self, block:u64, buffer: &mut [u8]) -> syscall::error::Result>; - fn write(&mut self, block:u64, buffer: &[u8]) -> syscall::error::Result>; - fn block_length(&mut self) -> syscall::error::Result; -} - impl Disk for SdHostCtrl { fn id(&self) -> usize { 0xdead_dead diff --git a/storage/block-io-wrapper/.gitignore b/storage/block-io-wrapper/.gitignore deleted file mode 100644 index ea8c4bf7f3..0000000000 --- a/storage/block-io-wrapper/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target diff --git a/storage/block-io-wrapper/Cargo.toml b/storage/block-io-wrapper/Cargo.toml deleted file mode 100644 index b5de7fa458..0000000000 --- a/storage/block-io-wrapper/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "block-io-wrapper" -version = "0.1.0" -authors = ["4lDO2 <4lDO2@protonmail.com>"] -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/storage/block-io-wrapper/src/lib.rs b/storage/block-io-wrapper/src/lib.rs deleted file mode 100644 index bf56b788a0..0000000000 --- a/storage/block-io-wrapper/src/lib.rs +++ /dev/null @@ -1,49 +0,0 @@ -use std::cmp::min; -use std::io::Error; - -/// Split the read operation into a series of block reads. -/// `read_fn` will be called with a block number to be read, and a buffer to be filled. -/// The buffer must be large enough to hold `blksize` of data. -/// `read_fn` must return a full block of data. -/// Result will be the number of bytes read. -pub fn read( - offset: u64, - blksize: u32, - buf: &mut [u8], - block_bytes: &mut [u8], - mut read_fn: impl FnMut(u64, &mut [u8]) -> Result<(), Error>, -) -> Result { - // TODO: Yield sometimes, perhaps after a few blocks or something. - - if buf.len() == 0 { - return Ok(0); - } - let to_copy = usize::try_from( - offset.saturating_add(u64::try_from(buf.len()).expect("buf.len() larger than u64")) - - offset, - ) - .expect("bytes to copy larger than usize"); - let mut curr_buf = &mut buf[..to_copy]; - let mut curr_offset = offset; - let blk_size = usize::try_from(blksize).expect("blksize larger than usize"); - let mut total_read = 0; - - while curr_buf.len() > 0 { - // TODO: Async/await? I mean, shouldn't AHCI be async? - - let blk_offset = - usize::try_from(curr_offset % u64::from(blksize)).expect("usize smaller than blksize"); - let to_copy = min(curr_buf.len(), blk_size - blk_offset); - assert!(blk_offset + to_copy <= blk_size); - - read_fn(curr_offset / u64::from(blksize), block_bytes)?; - - let src_buf = &block_bytes[blk_offset..]; - - curr_buf[..to_copy].copy_from_slice(&src_buf[..to_copy]); - curr_buf = &mut curr_buf[to_copy..]; - curr_offset += u64::try_from(to_copy).expect("bytes to copy larger than u64"); - total_read += to_copy; - } - Ok(total_read) -} diff --git a/storage/driver-block/Cargo.toml b/storage/driver-block/Cargo.toml new file mode 100644 index 0000000000..710b5efd5d --- /dev/null +++ b/storage/driver-block/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "driver-block" +version = "0.1.0" +edition = "2021" + +[dependencies] +partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } + +redox_syscall = "0.4" diff --git a/storage/driver-block/src/lib.rs b/storage/driver-block/src/lib.rs new file mode 100644 index 0000000000..e9ac6c5dc0 --- /dev/null +++ b/storage/driver-block/src/lib.rs @@ -0,0 +1,175 @@ +use std::cmp; +use std::io::Error; +use std::io::{self, Read, Seek, SeekFrom}; + +use partitionlib::{LogicalBlockSize, PartitionTable}; + +/// Split the read operation into a series of block reads. +/// `read_fn` will be called with a block number to be read, and a buffer to be filled. +/// The buffer must be large enough to hold `blksize` of data. +/// `read_fn` must return a full block of data. +/// Result will be the number of bytes read. +// FIXME make private once nvmed uses the DiskWrapper defined in this crate +pub fn block_read( + offset: u64, + blksize: u32, + buf: &mut [u8], + block_bytes: &mut [u8], + mut read_fn: impl FnMut(u64, &mut [u8]) -> Result<(), Error>, +) -> Result { + // TODO: Yield sometimes, perhaps after a few blocks or something. + + if buf.len() == 0 { + return Ok(0); + } + let to_copy = usize::try_from( + offset.saturating_add(u64::try_from(buf.len()).expect("buf.len() larger than u64")) + - offset, + ) + .expect("bytes to copy larger than usize"); + let mut curr_buf = &mut buf[..to_copy]; + let mut curr_offset = offset; + let blk_size = usize::try_from(blksize).expect("blksize larger than usize"); + let mut total_read = 0; + + while curr_buf.len() > 0 { + // TODO: Async/await? I mean, shouldn't AHCI be async? + + let blk_offset = + usize::try_from(curr_offset % u64::from(blksize)).expect("usize smaller than blksize"); + let to_copy = cmp::min(curr_buf.len(), blk_size - blk_offset); + assert!(blk_offset + to_copy <= blk_size); + + read_fn(curr_offset / u64::from(blksize), block_bytes)?; + + let src_buf = &block_bytes[blk_offset..]; + + curr_buf[..to_copy].copy_from_slice(&src_buf[..to_copy]); + curr_buf = &mut curr_buf[to_copy..]; + curr_offset += u64::try_from(to_copy).expect("bytes to copy larger than u64"); + total_read += to_copy; + } + Ok(total_read) +} + +pub trait Disk { + fn id(&self) -> usize; + fn block_length(&mut self) -> syscall::error::Result; + fn size(&mut self) -> u64; + + fn read(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result>; + fn write(&mut self, block: u64, buffer: &[u8]) -> syscall::Result>; +} + +pub struct DiskWrapper { + pub disk: Box, + pub pt: Option, +} + +impl DiskWrapper { + fn pt(disk: &mut dyn Disk) -> Option { + let bs = match disk.block_length() { + Ok(512) => LogicalBlockSize::Lb512, + _ => return None, + }; + struct Device<'a, 'b> { + disk: &'a mut dyn Disk, + offset: u64, + block_bytes: &'b mut [u8], + } + + impl<'a, 'b> Seek for Device<'a, 'b> { + fn seek(&mut self, from: SeekFrom) -> io::Result { + let size = i64::try_from(self.disk.size()).or(Err(io::Error::new( + io::ErrorKind::Other, + "Disk larger than 2^63 - 1 bytes", + )))?; + + self.offset = match from { + SeekFrom::Start(new_pos) => cmp::min(self.disk.size(), new_pos), + SeekFrom::Current(new_pos) => { + cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64 + } + SeekFrom::End(new_pos) => cmp::max(0, cmp::min(size + new_pos, size)) as u64, + }; + + Ok(self.offset) + } + } + // TODO: Perhaps this impl should be used in the rest of the scheme. + impl<'a, 'b> Read for Device<'a, 'b> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + let blksize = self + .disk + .block_length() + .map_err(|err| io::Error::from_raw_os_error(err.errno))?; + let size_in_blocks = self.disk.size() / u64::from(blksize); + + let disk = &mut self.disk; + + let read_block = |block: u64, block_bytes: &mut [u8]| { + if block >= size_in_blocks { + return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW)); + } + loop { + match disk.read(block, block_bytes) { + Ok(Some(bytes)) => { + assert_eq!(bytes, block_bytes.len()); + assert_eq!(bytes, blksize as usize); + return Ok(()); + } + Ok(None) => { + std::thread::yield_now(); + continue; + } + Err(err) => return Err(io::Error::from_raw_os_error(err.errno)), + } + } + }; + let bytes_read = block_read( + self.offset, + blksize, + buf, + self.block_bytes, + read_block, + )?; + + self.offset += bytes_read as u64; + Ok(bytes_read) + } + } + + let mut block_bytes = [0u8; 4096]; + + partitionlib::get_partitions( + &mut Device { + disk, + offset: 0, + block_bytes: &mut block_bytes[..bs.into()], + }, + bs, + ) + .ok() + .flatten() + } + + pub fn new(mut disk: Box) -> Self { + Self { + pt: Self::pt(&mut *disk), + disk, + } + } +} + +impl std::ops::Deref for DiskWrapper { + type Target = dyn Disk; + + fn deref(&self) -> &Self::Target { + &*self.disk + } +} +impl std::ops::DerefMut for DiskWrapper { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut *self.disk + } +} diff --git a/storage/ided/Cargo.toml b/storage/ided/Cargo.toml index c580881d9e..1df0416b7b 100644 --- a/storage/ided/Cargo.toml +++ b/storage/ided/Cargo.toml @@ -4,10 +4,9 @@ version = "0.1.0" edition = "2018" [dependencies] -block-io-wrapper = { path = "../block-io-wrapper" } common = { path = "../../common" } +driver-block = { path = "../driver-block" } log = "0.4" -partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } pcid = { path = "../../pcid" } redox-daemon = "0.1" redox-log = "0.1" diff --git a/storage/ided/src/ide.rs b/storage/ided/src/ide.rs index 259997ab7d..8428d92b60 100644 --- a/storage/ided/src/ide.rs +++ b/storage/ided/src/ide.rs @@ -5,6 +5,7 @@ use std::{ time::{Duration, Instant}, }; +use driver_block::Disk; use syscall::{ error::{Error, Result, EIO}, io::{Io, Pio, ReadOnly, WriteOnly}, @@ -153,14 +154,6 @@ impl Channel { } } -pub trait Disk { - fn id(&self) -> usize; - fn size(&mut self) -> u64; - fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result>; - fn write(&mut self, block: u64, buffer: &[u8]) -> Result>; - fn block_length(&mut self) -> Result; -} - pub struct AtaDisk { pub chan: Arc>, pub chan_i: usize, diff --git a/storage/ided/src/main.rs b/storage/ided/src/main.rs index bf176e4986..ca27ab7e60 100644 --- a/storage/ided/src/main.rs +++ b/storage/ided/src/main.rs @@ -1,3 +1,4 @@ +use driver_block::Disk; use log::{error, info}; use pcid_interface::{PciBar, PcidServerHandle}; use redox_log::{OutputBuilder, RedoxLogger}; @@ -18,7 +19,7 @@ use syscall::{ }; use crate::{ - ide::{AtaCommand, AtaDisk, Channel, Disk}, + ide::{AtaCommand, AtaDisk, Channel}, scheme::DiskScheme, }; diff --git a/storage/ided/src/scheme.rs b/storage/ided/src/scheme.rs index a5fe20b309..31032d4a9a 100644 --- a/storage/ided/src/scheme.rs +++ b/storage/ided/src/scheme.rs @@ -3,18 +3,15 @@ use std::{cmp, str}; use std::convert::{TryFrom}; use std::fmt::Write; use std::io::prelude::*; -use std::io::SeekFrom; -use std::io; use std::sync::{Arc, Mutex}; +use driver_block::{Disk, DiskWrapper}; use syscall::{ Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; -use crate::ide::{Channel, Disk}; - -use partitionlib::{LogicalBlockSize, PartitionTable}; +use crate::ide::Channel; #[derive(Clone)] enum Handle { @@ -23,89 +20,6 @@ enum Handle { Partition(usize, u32, usize), // Disk index, partition index, position } -pub struct DiskWrapper { - disk: Box, - pt: Option, -} - -impl DiskWrapper { - fn pt(disk: &mut dyn Disk) -> Option { - let bs = match disk.block_length() { - Ok(512) => LogicalBlockSize::Lb512, - Ok(4096) => LogicalBlockSize::Lb4096, - _ => return None, - }; - struct Device<'a, 'b> { disk: &'a mut dyn Disk, offset: u64, block_bytes: &'b mut [u8] } - - impl<'a, 'b> Seek for Device<'a, 'b> { - fn seek(&mut self, from: SeekFrom) -> io::Result { - let size = i64::try_from(self.disk.size()).or(Err(io::Error::new(io::ErrorKind::Other, "Disk larger than 2^63 - 1 bytes")))?; - - self.offset = match from { - SeekFrom::Start(new_pos) => cmp::min(self.disk.size(), new_pos), - SeekFrom::Current(new_pos) => cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64, - SeekFrom::End(new_pos) => cmp::max(0, cmp::min(size + new_pos, size)) as u64, - }; - - Ok(self.offset) - } - } - // TODO: Perhaps this impl should be used in the rest of the scheme. - impl<'a, 'b> Read for Device<'a, 'b> { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let blksize = self.disk.block_length().map_err(|err| io::Error::from_raw_os_error(err.errno))?; - let size_in_blocks = self.disk.size() / u64::from(blksize); - - let disk = &mut self.disk; - - let read_block = |block: u64, block_bytes: &mut [u8]| { - if block >= size_in_blocks { - return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW)); - } - loop { - match disk.read(block, block_bytes) { - Ok(Some(bytes)) => { - assert_eq!(bytes, block_bytes.len()); - assert_eq!(bytes, blksize as usize); - return Ok(()); - } - Ok(None) => { std::thread::yield_now(); continue } - Err(err) => return Err(io::Error::from_raw_os_error(err.errno)), - } - } - }; - let bytes_read = block_io_wrapper::read(self.offset, blksize, buf, self.block_bytes, read_block)?; - - self.offset += bytes_read as u64; - Ok(bytes_read) - } - } - - let mut block_bytes = [0u8; 4096]; - - partitionlib::get_partitions(&mut Device { disk, offset: 0, block_bytes: &mut block_bytes[..bs.into()] }, bs).ok().flatten() - } - fn new(mut disk: Box) -> Self { - Self { - pt: Self::pt(&mut *disk), - disk, - } - } -} - -impl std::ops::Deref for DiskWrapper { - type Target = dyn Disk; - - fn deref(&self) -> &Self::Target { - &*self.disk - } -} -impl std::ops::DerefMut for DiskWrapper { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut *self.disk - } -} - pub struct DiskScheme { scheme_name: String, chans: Box<[Arc>]>, diff --git a/storage/nvmed/Cargo.toml b/storage/nvmed/Cargo.toml index ce52f43752..59c9c36935 100644 --- a/storage/nvmed/Cargo.toml +++ b/storage/nvmed/Cargo.toml @@ -15,8 +15,8 @@ redox_syscall = "0.4" partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } smallvec = "1" -block-io-wrapper = { path = "../block-io-wrapper" } common = { path = "../../common" } +driver-block = { path = "../driver-block" } pcid = { path = "../../pcid" } [features] diff --git a/storage/nvmed/src/scheme.rs b/storage/nvmed/src/scheme.rs index 654044aba0..638b426ae4 100644 --- a/storage/nvmed/src/scheme.rs +++ b/storage/nvmed/src/scheme.rs @@ -96,7 +96,7 @@ impl DiskWrapper { } } }; - let bytes_read = block_io_wrapper::read( + let bytes_read = driver_block::block_read( self.offset, blksize .try_into() diff --git a/storage/virtio-blkd/Cargo.toml b/storage/virtio-blkd/Cargo.toml index c9ec28ced1..690454263d 100644 --- a/storage/virtio-blkd/Cargo.toml +++ b/storage/virtio-blkd/Cargo.toml @@ -17,7 +17,7 @@ redox-log = "0.1" redox_syscall = "0.4" partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } -block-io-wrapper = { path = "../block-io-wrapper" } common = { path = "../../common" } +driver-block = { path = "../driver-block" } pcid = { path = "../../pcid" } virtio-core = { path = "../../virtio-core" } diff --git a/storage/virtio-blkd/src/scheme.rs b/storage/virtio-blkd/src/scheme.rs index a92f084444..e981de0369 100644 --- a/storage/virtio-blkd/src/scheme.rs +++ b/storage/virtio-blkd/src/scheme.rs @@ -148,7 +148,7 @@ impl<'a> DiskScheme<'a> { }; let bytes_read = - block_io_wrapper::read(self.offset, 512, buf, self.block_bytes, read_block) + driver_block::block_read(self.offset, 512, buf, self.block_bytes, read_block) .unwrap(); self.offset += bytes_read as u64; Ok(bytes_read) diff --git a/virtio-core/src/probe.rs b/virtio-core/src/probe.rs index 4f7d48719d..aebd065d04 100644 --- a/virtio-core/src/probe.rs +++ b/virtio-core/src/probe.rs @@ -71,7 +71,7 @@ pub fn probe_device(pcid_handle: &mut PcidServerHandle) -> Result let mut notify_addr = None; let mut device_addr = None; - for capability in pcid_handle + for raw_capability in pcid_handle .get_capabilities()? .iter() .filter_map(|capability| { @@ -83,7 +83,7 @@ pub fn probe_device(pcid_handle: &mut PcidServerHandle) -> Result }) { // SAFETY: We have verified that the length of the data is correct. - let capability = unsafe { &*(capability.data.as_ptr() as *const PciCapability) }; + let capability = unsafe { &*(raw_capability.data.as_ptr() as *const PciCapability) }; match capability.cfg_type { CfgType::Common | CfgType::Notify | CfgType::Device => {} @@ -123,7 +123,7 @@ pub fn probe_device(pcid_handle: &mut PcidServerHandle) -> Result // SAFETY: The capability type is `Notify`, so its safe to access // the `notify_multiplier` field. let multiplier = unsafe { - (&*(capability as *const PciCapability as *const PciCapabilityNotify)) + (&*(raw_capability.data.as_ptr() as *const PciCapability as *const PciCapabilityNotify)) .notify_off_multiplier() }; notify_addr = Some((address, multiplier));