From 4b780927d275ffcbb3b5f71d18e4ae23d98f1f0f Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Mon, 2 Jan 2017 08:53:50 -0700 Subject: [PATCH] Fallback in ahci driver when disk: not available, ability to list disk devices --- drivers/ahcid/src/ahci/disk.rs | 4 +- drivers/ahcid/src/ahci/hba.rs | 6 +- drivers/ahcid/src/main.rs | 15 +++- drivers/ahcid/src/scheme.rs | 128 +++++++++++++++++++++++---------- 4 files changed, 109 insertions(+), 44 deletions(-) diff --git a/drivers/ahcid/src/ahci/disk.rs b/drivers/ahcid/src/ahci/disk.rs index f28d5e8..4389425 100644 --- a/drivers/ahcid/src/ahci/disk.rs +++ b/drivers/ahcid/src/ahci/disk.rs @@ -11,7 +11,7 @@ pub struct Disk { size: u64, clb: Dma<[HbaCmdHeader; 32]>, ctbas: [Dma; 32], - fb: Dma<[u8; 256]>, + _fb: Dma<[u8; 256]>, buf: Dma<[u8; 256 * 512]> } @@ -41,7 +41,7 @@ impl Disk { size: size, clb: clb, ctbas: ctbas, - fb: fb, + _fb: fb, buf: buf }) } diff --git a/drivers/ahcid/src/ahci/hba.rs b/drivers/ahcid/src/ahci/hba.rs index 1981847..d22b706 100644 --- a/drivers/ahcid/src/ahci/hba.rs +++ b/drivers/ahcid/src/ahci/hba.rs @@ -389,7 +389,7 @@ pub struct HbaCmdTable { cfis: [Mmio; 64], // Command FIS // 0x40 - acmd: [Mmio; 16], // ATAPI command, 12 or 16 bytes + _acmd: [Mmio; 16], // ATAPI command, 12 or 16 bytes // 0x50 _rsv: [Mmio; 48], // Reserved @@ -402,12 +402,12 @@ pub struct HbaCmdTable { pub struct HbaCmdHeader { // DW0 cfl: Mmio, /* Command FIS length in DWORDS, 2 ~ 16, atapi: 4, write - host to device: 2, prefetchable: 1 */ - pm: Mmio, // Reset - 0x80, bist: 0x40, clear busy on ok: 0x20, port multiplier + _pm: Mmio, // Reset - 0x80, bist: 0x40, clear busy on ok: 0x20, port multiplier prdtl: Mmio, // Physical region descriptor table length in entries // DW1 - prdbc: Mmio, // Physical region descriptor byte count transferred + _prdbc: Mmio, // Physical region descriptor byte count transferred // DW2, 3 ctba: Mmio, // Command table descriptor base address diff --git a/drivers/ahcid/src/main.rs b/drivers/ahcid/src/main.rs index 1cd417c..4e8cbc9 100644 --- a/drivers/ahcid/src/main.rs +++ b/drivers/ahcid/src/main.rs @@ -10,14 +10,23 @@ extern crate syscall; use std::{env, usize}; use std::fs::File; use std::io::{Read, Write}; -use std::os::unix::io::{AsRawFd, FromRawFd}; -use syscall::{EVENT_READ, MAP_WRITE, Event, Packet, Scheme}; +use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use syscall::{EVENT_READ, MAP_WRITE, Event, Packet, Result, Scheme}; use scheme::DiskScheme; pub mod ahci; pub mod scheme; +fn create_scheme_fallback<'a>(name: &'a str, fallback: &'a str) -> Result<(&'a str, RawFd)> { + if let Ok(fd) = syscall::open(&format!(":{}", name), syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) { + Ok((name, fd)) + } else { + syscall::open(&format!(":{}", fallback), syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK) + .map(|fd| (fallback, fd)) + } +} + fn main() { let mut args = env::args().skip(1); @@ -36,7 +45,7 @@ fn main() { if unsafe { syscall::clone(0).unwrap() } == 0 { let address = unsafe { syscall::physmap(bar, 4096, MAP_WRITE).expect("ahcid: failed to map address") }; { - let socket_fd = syscall::open(":disk", syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("ahcid: failed to create disk scheme"); + let (_scheme_name, socket_fd) = create_scheme_fallback("disk", &name).expect("ahcid: failed to create disk scheme"); let mut socket = unsafe { File::from_raw_fd(socket_fd) }; syscall::fevent(socket_fd, EVENT_READ).expect("ahcid: failed to fevent disk scheme"); diff --git a/drivers/ahcid/src/scheme.rs b/drivers/ahcid/src/scheme.rs index 96a7c20..cd35d76 100644 --- a/drivers/ahcid/src/scheme.rs +++ b/drivers/ahcid/src/scheme.rs @@ -1,15 +1,24 @@ use std::collections::BTreeMap; use std::{cmp, str}; +use std::fmt::Write; +use std::io::Read; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use spin::Mutex; -use syscall::{Error, EACCES, EBADF, EINVAL, ENOENT, Result, Scheme, Stat, MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET}; +use syscall::{Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, Result, Scheme, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; use ahci::disk::Disk; +#[derive(Clone)] +enum Handle { + //TODO: Make these enum variants normal tuples (), not nested tuples (()) + List((Vec, usize)), + Disk((Arc>, usize)) +} + pub struct DiskScheme { disks: Box<[Arc>]>, - handles: Mutex>, usize)>>, + handles: Mutex>, next_id: AtomicUsize } @@ -29,18 +38,33 @@ impl DiskScheme { } impl Scheme for DiskScheme { - fn open(&self, path: &[u8], _flags: usize, uid: u32, _gid: u32) -> Result { + fn open(&self, path: &[u8], flags: usize, uid: u32, _gid: u32) -> Result { if uid == 0 { - let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?; + let path_str = str::from_utf8(path).or(Err(Error::new(ENOENT)))?.trim_matches('/'); + if path_str.is_empty() { + if flags & O_DIRECTORY == O_DIRECTORY || flags & O_STAT == O_STAT { + let mut list = String::new(); - let i = path_str.parse::().or(Err(Error::new(ENOENT)))?; + for i in 0..self.disks.len() { + write!(list, "{}\n", i).unwrap(); + } - if let Some(disk) = self.disks.get(i) { - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.lock().insert(id, (disk.clone(), 0)); - Ok(id) + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.lock().insert(id, Handle::List((list.into_bytes(), 0))); + Ok(id) + } else { + Err(Error::new(EISDIR)) + } } else { - Err(Error::new(ENOENT)) + let i = path_str.parse::().or(Err(Error::new(ENOENT)))?; + + if let Some(disk) = self.disks.get(i) { + let id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.lock().insert(id, Handle::Disk((disk.clone(), 0))); + Ok(id) + } else { + Err(Error::new(ENOENT)) + } } } else { Err(Error::new(EACCES)) @@ -61,46 +85,78 @@ impl Scheme for DiskScheme { fn fstat(&self, id: usize, stat: &mut Stat) -> Result { let handles = self.handles.lock(); - let handle = handles.get(&id).ok_or(Error::new(EBADF))?; - - stat.st_mode = MODE_FILE; - stat.st_size = handle.0.lock().size(); - Ok(0) + match *handles.get(&id).ok_or(Error::new(EBADF))? { + Handle::List(ref handle) => { + stat.st_mode = MODE_DIR; + stat.st_size = handle.0.len() as u64; + Ok(0) + }, + Handle::Disk(ref handle) => { + stat.st_mode = MODE_FILE; + stat.st_size = handle.0.lock().size(); + Ok(0) + } + } } fn read(&self, id: usize, buf: &mut [u8]) -> Result { let mut handles = self.handles.lock(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - let mut disk = handle.0.lock(); - let count = disk.read((handle.1 as u64)/512, buf)?; - handle.1 += count; - Ok(count) + match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { + Handle::List(ref mut handle) => { + let count = (&handle.0[handle.1..]).read(buf).unwrap(); + handle.1 += count; + Ok(count) + }, + Handle::Disk(ref mut handle) => { + let mut disk = handle.0.lock(); + let count = disk.read((handle.1 as u64)/512, buf)?; + handle.1 += count; + Ok(count) + } + } } fn write(&self, id: usize, buf: &[u8]) -> Result { let mut handles = self.handles.lock(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; - - let mut disk = handle.0.lock(); - let count = disk.write((handle.1 as u64)/512, buf)?; - handle.1 += count; - Ok(count) + match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { + Handle::List(_) => { + Err(Error::new(EBADF)) + }, + Handle::Disk(ref mut handle) => { + let mut disk = handle.0.lock(); + let count = disk.write((handle.1 as u64)/512, buf)?; + handle.1 += count; + Ok(count) + } + } } fn seek(&self, id: usize, pos: usize, whence: usize) -> Result { let mut handles = self.handles.lock(); - let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; + match *handles.get_mut(&id).ok_or(Error::new(EBADF))? { + Handle::List(ref mut handle) => { + let len = handle.0.len() as usize; + handle.1 = match whence { + SEEK_SET => cmp::min(len, pos), + SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize, + SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, + _ => return Err(Error::new(EINVAL)) + }; - let len = handle.0.lock().size() as usize; - handle.1 = match whence { - SEEK_SET => cmp::min(len, pos), - SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize, - SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, - _ => return Err(Error::new(EINVAL)) - }; + Ok(handle.1) + }, + Handle::Disk(ref mut handle) => { + let len = handle.0.lock().size() as usize; + handle.1 = match whence { + SEEK_SET => cmp::min(len, pos), + SEEK_CUR => cmp::max(0, cmp::min(len as isize, handle.1 as isize + pos as isize)) as usize, + SEEK_END => cmp::max(0, cmp::min(len as isize, len as isize + pos as isize)) as usize, + _ => return Err(Error::new(EINVAL)) + }; - Ok(handle.1) + Ok(handle.1) + } + } } fn close(&self, id: usize) -> Result {