Merge branch 'ivan/mmc_update_scheme' into 'master'

migrate bcm2835-sdhcid to v2 scheme protocol

See merge request redox-os/drivers!202
This commit is contained in:
Jeremy Soller
2024-09-29 12:51:07 +00:00
3 changed files with 102 additions and 113 deletions
+3 -1
View File
@@ -7,9 +7,11 @@ edition = "2021"
[dependencies]
fdt = "0.1.5"
redox_syscall = "0.5"
common = { path = "../../common" }
driver-block = { path = "../driver-block" }
redox-daemon = "0.1"
libredox = "0.1.3"
redox_syscall = { version = "0.5", features = ["std"] }
redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" }
redox_event = "0.4"
+47 -18
View File
@@ -1,8 +1,12 @@
use std::{fs::File, io::{Read, Write}, process};
use driver_block::Disk;
use event::{EventFlags, RawEventQueue};
use fdt::{Fdt, node::FdtNode};
use syscall::{Packet, SchemeBlockMut};
use redox_scheme::{RequestKind, Response, SignalBehavior, Socket, V2};
use syscall::{
data::{Event, Packet}, error::{Error, ENODEV}, flag::EVENT_READ, io::Io, scheme::SchemeBlockMut, EAGAIN, EINTR, EWOULDBLOCK
};
use crate::scheme::DiskScheme;
@@ -77,39 +81,64 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
}
let scheme_name = ":disk.mmc";
let mut socket = File::create(scheme_name).expect("mmc: failed to create disk scheme");
libredox::call::setrens(0, 0).expect("mmc: failed to enter null namespace");
let scheme_name = "disk.mmc";
let socket_fd = Socket::<V2>::create(&scheme_name).expect("mmcd: failed to create disk scheme");
daemon.ready().expect("mmc: failed to notify parent");
let mut event_queue = RawEventQueue::new().expect("mmcd: failed to open event file");
event_queue.subscribe(socket_fd.inner().raw(), 0, EventFlags::READ).expect("mmcd: failed to event disk scheme");
libredox::call::setrens(0, 0).expect("mmcd: failed to enter null namespace");
daemon.ready().expect("mmcd: failed to notify parent");
let mut todo = Vec::new();
let mut disks = Vec::new();
disks.push(Box::new(sdhci) as Box<dyn Disk>);
let mut scheme = DiskScheme::new(scheme_name.to_string(), disks);
loop {
let mut packet = Packet::default();
if socket.read(&mut packet).expect("mmc: failed to read event") == 0 {
println!("zero, break");
'outer: loop {
let Some(event) = event_queue.next().transpose().expect("mmcd: failed to read event file") else {
break;
}
if let Some(a) = scheme.handle(&packet) {
packet.a = a;
socket.write(&packet).expect("mmcd: failed to write disk scheme");
};
if event.fd == socket_fd.inner().raw() {
loop {
let req = match socket_fd.next_request(SignalBehavior::Interrupt) {
Ok(None) => break 'outer,
Ok(Some(r)) => if let RequestKind::Call(c) = r.kind() {
c
} else {
continue;
},
Err(err) => if matches!(err.errno, EAGAIN | EWOULDBLOCK | EINTR) {
break;
} else {
panic!("mmcd: failed to read disk scheme: {}", err);
}
};
if let Some(resp) = req.handle_scheme_block_mut(&mut scheme) {
socket_fd.write_response(resp, SignalBehavior::Restart).expect("mmcd: failed to write disk scheme");
} else {
todo.push(req);
}
}
} else {
todo.push(packet);
println!("Unknown event {}", event.fd);
}
// Handle todos to start new packets if possible
let mut i = 0;
while i < todo.len() {
if let Some(a) = scheme.handle(&todo[i]) {
let mut packet = todo.remove(i);
packet.a = a;
socket.write(&packet).expect("mmcd: failed to write disk scheme");
if let Some(resp) = todo[i].handle_scheme_block_mut(&mut scheme) {
socket_fd.write_response(resp, SignalBehavior::Restart).expect("mmcd: failed to write disk scheme");
} else {
i += 1;
}
}
for req in todo.drain(..) {
socket_fd.write_response(Response::new(&req, Err(Error::new(ENODEV))), SignalBehavior::Restart)
.expect("mmcd: failed to write disk scheme");
}
}
process::exit(0);
}
+52 -94
View File
@@ -1,21 +1,22 @@
use std::collections::BTreeMap;
use std::{cmp, str};
use std::convert::{TryFrom};
use std::str;
use std::fmt::Write;
use std::io::prelude::*;
use std::sync::{Arc, Mutex};
use driver_block::{Disk, DiskWrapper};
use syscall::schemev2::NewFdFlags;
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};
Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Stat, MODE_DIR,
MODE_FILE, O_DIRECTORY, O_STAT,
};
use redox_scheme::{CallerCtx, OpenResult, SchemeBlockMut};
#[derive(Clone)]
enum Handle {
List(Vec<u8>, usize), // Dir contents buffer, position
Disk(usize, usize), // Disk index, position
Partition(usize, u32, usize), // Disk index, partition index, position
List(Vec<u8>), // Dir contents buffer
Disk(usize), // Disk index
Partition(usize, u32), // Disk index, partition index
}
pub struct DiskScheme {
@@ -28,7 +29,7 @@ pub struct DiskScheme {
impl DiskScheme {
pub fn new(scheme_name: String, disks: Vec<Box<dyn Disk>>) -> DiskScheme {
DiskScheme {
scheme_name: scheme_name,
scheme_name,
disks: disks.into_iter().map(DiskWrapper::new).collect::<Vec<_>>().into_boxed_slice(),
handles: BTreeMap::new(),
next_id: 0
@@ -39,10 +40,10 @@ impl DiskScheme {
fn check_locks(&self, disk_i: usize, part_i_opt: Option<u32>) -> Result<()> {
for (_, handle) in self.handles.iter() {
match handle {
Handle::Disk(i, _) => if disk_i == *i {
Handle::Disk(i) => if disk_i == *i {
return Err(Error::new(ENOLCK));
},
Handle::Partition(i, p, _) => if disk_i == *i {
Handle::Partition(i, p) => if disk_i == *i {
match part_i_opt {
Some(part_i) => if part_i == *p {
return Err(Error::new(ENOLCK));
@@ -60,8 +61,8 @@ impl DiskScheme {
}
impl SchemeBlockMut for DiskScheme {
fn open(&mut self, path: &str, flags: usize, uid: u32, _gid: u32) -> Result<Option<usize>> {
if uid == 0 {
fn xopen(&mut self, path: &str, flags: usize, ctx: &CallerCtx) -> Result<Option<OpenResult>> {
if ctx.uid == 0 {
let path_str = path.trim_matches('/');
if path_str.is_empty() {
if flags & O_DIRECTORY == O_DIRECTORY || flags & O_STAT == O_STAT {
@@ -80,8 +81,8 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::List(list.into_bytes(), 0));
Ok(Some(id))
self.handles.insert(id, Handle::List(list.into_bytes()));
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
} else {
Err(Error::new(EISDIR))
}
@@ -103,8 +104,8 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Partition(i, p, 0));
Ok(Some(id))
self.handles.insert(id, Handle::Partition(i, p));
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
} else {
Err(Error::new(ENOENT))
}
@@ -116,8 +117,8 @@ impl SchemeBlockMut for DiskScheme {
let id = self.next_id;
self.next_id += 1;
self.handles.insert(id, Handle::Disk(i, 0));
Ok(Some(id))
self.handles.insert(id, Handle::Disk(i));
Ok(Some(OpenResult::ThisScheme { number: id, flags: NewFdFlags::POSITIONED }))
} else {
Err(Error::new(ENOENT))
}
@@ -145,19 +146,19 @@ impl SchemeBlockMut for DiskScheme {
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<Option<usize>> {
match *self.handles.get(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref data, _) => {
Handle::List(ref data) => {
stat.st_mode = MODE_DIR;
stat.st_size = data.len() as u64;
Ok(Some(0))
},
Handle::Disk(number, _) => {
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
stat.st_mode = MODE_FILE;
stat.st_size = disk.size();
stat.st_blksize = disk.block_length()?;
Ok(Some(0))
}
Handle::Partition(disk_id, part_num, _) => {
Handle::Partition(disk_id, part_num) => {
let disk = self.disks.get_mut(disk_id).ok_or(Error::new(EBADF))?;
let size = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
@@ -193,8 +194,8 @@ impl SchemeBlockMut for DiskScheme {
}
match *handle {
Handle::List(_, _) => (),
Handle::Disk(number, _) => {
Handle::List(_) => (),
Handle::Disk(number) => {
let number_str = format!("{}", number);
let number_bytes = number_str.as_bytes();
j = 0;
@@ -204,7 +205,7 @@ impl SchemeBlockMut for DiskScheme {
j += 1;
}
}
Handle::Partition(disk_num, part_num, _) => {
Handle::Partition(disk_num, part_num) => {
let path = format!("{}p{}", disk_num, part_num);
let path_bytes = path.as_bytes();
j = 0;
@@ -219,29 +220,25 @@ impl SchemeBlockMut for DiskScheme {
Ok(Some(i))
}
fn read(&mut self, id: usize, buf: &mut [u8]) -> Result<Option<usize>> {
fn read(&mut self, id: usize, buf: &mut [u8], offset: u64, _flags: u32) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref handle, ref mut size) => {
let count = (&handle[*size..]).read(buf).unwrap();
*size += count;
Ok(Some(count))
Handle::List(ref handle) => {
let src = usize::try_from(offset).ok().and_then(|o| handle.get(o..)).unwrap_or(&[]);
let bytes = src.len().min(buf.len());
buf[..bytes].copy_from_slice(&src[..bytes]);
Ok(Some(bytes))
},
Handle::Disk(number, ref mut size) => {
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
if let Some(count) = disk.read((*size as u64)/(blk_len as u64), buf)? {
*size += count;
Ok(Some(count))
} else {
Ok(None)
}
disk.read(offset / u64::from(blk_len), buf)
}
Handle::Partition(disk_num, part_num, ref mut position) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let blksize = disk.block_length()?;
// validate that we're actually reading within the bounds of the partition
let rel_block = *position as u64 / blksize as u64;
let rel_block = offset / u64::from(blksize);
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
@@ -254,36 +251,27 @@ impl SchemeBlockMut for DiskScheme {
abs_block
};
if let Some(count) = disk.read(abs_block, buf)? {
Ok(Some(count))
} else {
Ok(None)
}
disk.read(abs_block, buf)
}
}
}
fn write(&mut self, id: usize, buf: &[u8]) -> Result<Option<usize>> {
fn write(&mut self, id: usize, buf: &[u8], offset: u64, _flags: u32) -> Result<Option<usize>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(_, _) => {
Handle::List(_) => {
Err(Error::new(EBADF))
},
Handle::Disk(number, ref mut size) => {
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let blk_len = disk.block_length()?;
if let Some(count) = disk.write((*size as u64)/(blk_len as u64), buf)? {
*size += count;
Ok(Some(count))
} else {
Ok(None)
}
disk.write(offset / u64::from(blk_len), buf)
}
Handle::Partition(disk_num, part_num, ref mut position) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let blksize = disk.block_length()?;
// validate that we're actually reading within the bounds of the partition
let rel_block = *position as u64 / blksize as u64;
let rel_block = offset / u64::from(blksize as u64);
let abs_block = {
let pt = disk.pt.as_ref().ok_or(Error::new(EBADF))?;
@@ -296,54 +284,24 @@ impl SchemeBlockMut for DiskScheme {
abs_block
};
if let Some(count) = disk.write(abs_block, buf)? {
Ok(Some(count))
} else {
Ok(None)
}
disk.write(abs_block, buf)
}
}
}
fn seek(&mut self, id: usize, pos: isize, whence: usize) -> Result<Option<isize>> {
let pos = pos as usize;
fn fsize(&mut self, id: usize) -> Result<Option<u64>> {
match *self.handles.get_mut(&id).ok_or(Error::new(EBADF))? {
Handle::List(ref mut handle, ref mut size) => {
let len = handle.len() as usize;
*size = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => cmp::max(0, cmp::min(len as isize, *size 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(Some(*size as isize))
Handle::List(ref mut handle) => {
Ok(Some(handle.len() as u64))
},
Handle::Disk(number, ref mut size) => {
Handle::Disk(number) => {
let disk = self.disks.get_mut(number).ok_or(Error::new(EBADF))?;
let len = disk.size() as usize;
*size = match whence {
SEEK_SET => cmp::min(len, pos),
SEEK_CUR => cmp::max(0, cmp::min(len as isize, *size 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(Some(*size as isize))
Ok(Some(disk.size()))
}
Handle::Partition(disk_num, part_num, ref mut position) => {
Handle::Partition(disk_num, part_num) => {
let disk = self.disks.get_mut(disk_num).ok_or(Error::new(EBADF))?;
let block_count = disk.pt.as_ref().ok_or(Error::new(EBADF))?.partitions.get(part_num as usize).ok_or(Error::new(EBADF))?.size;
let len = u64::from(disk.block_length()?) * block_count;
*position = match whence {
SEEK_SET => cmp::min(len as usize, pos) as usize, // Why isn't pos u64?
SEEK_CUR => cmp::max(0, cmp::min(len as isize, *position 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(Some(*position as isize))
Ok(Some(u64::from(disk.block_length()?) * block_count))
}
}
}