diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml new file mode 100644 index 0000000..bf7a604 --- /dev/null +++ b/.forgejo/workflows/ci.yml @@ -0,0 +1,42 @@ +name: Check + +on: + push: + branches: [main] + pull_request: + branches: [main] + +env: + # Should speed up builds. + CARGO_INCREMENTAL: 0 + # Should reduce the size of ./target to improve cache load/store. + CARGO_PROFILE_TEST_DEBUG: 0 + +jobs: + check: + name: Check Rust + runs-on: docker + + steps: + - name: Checkout Repo + uses: actions/checkout@v4 + + - name: Install Rust + uses: https://codeberg.org/wackbyte/rust-toolchain@trunk + with: + toolchain: nightly-2025-10-02 + components: rustfmt, clippy, rust-src + - name: Cache + uses: https://github.com/Swatinem/rust-cache@v2 + with: + # Don't cache ~/.cargo/bin since we restore the cache after we install things there + cache-bin: "false" + workspaces: "backend" + - name: "Check Format" + run: cargo fmt --check + working-directory: rust + - name: "Lint" + run: | + rustup component add clippy + cargo clippy --locked -- -D warnings + working-directory: rust diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 66768f4..f7acab6 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] channel = "nightly-2025-10-02" -components = ["rustfmt", "rust-analyzer"] +components = ["rustfmt", "rust-analyzer", "clippy", "rust-src"] diff --git a/rust/lib/client/voyageurs_client/src/listener.rs b/rust/lib/client/voyageurs_client/src/listener.rs index 1912b88..89e40b6 100644 --- a/rust/lib/client/voyageurs_client/src/listener.rs +++ b/rust/lib/client/voyageurs_client/src/listener.rs @@ -7,7 +7,7 @@ use mammoth::thread; #[allow(dead_code)] #[derive(PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] enum Keycode { - UnknownKeycode = 0x0, + Unknown = 0x0, A = 0x1, B = 0x2, @@ -135,7 +135,7 @@ impl Keycode { 0x37 => Keycode::Period, 0x38 => Keycode::FSlash, 0x39 => Keycode::Esc, - _ => Keycode::UnknownKeycode, + _ => Keycode::Unknown, } } } diff --git a/rust/lib/fs/ext2/src/ext2_driver.rs b/rust/lib/fs/ext2/src/ext2_driver.rs index 96bb858..0997b62 100644 --- a/rust/lib/fs/ext2/src/ext2_driver.rs +++ b/rust/lib/fs/ext2/src/ext2_driver.rs @@ -94,7 +94,7 @@ impl Ext2Driver { /// Updates the cached inode tables to contain the inode table for /// a specific group. fn populate_inode_table_if_none(&mut self, block_group_num: usize) { - if let None = self.inode_table_map[block_group_num] { + if self.inode_table_map[block_group_num].is_none() { debug!( "Cache MISS on inode table for block_group {}", block_group_num @@ -148,17 +148,15 @@ impl Ext2Driver { let dbl_indr_block_mem = MemoryRegion::from_cap(self.reader.read(block_num, 1).unwrap()).unwrap(); - let dbl_indr_blocks: &[u32] = dbl_indr_block_mem.slice(); + let dbl_indr_blocks: &[u32] = &dbl_indr_block_mem.slice()[0..num_dbl_indr]; let mut blocks_to_read = Vec::new(); - for i in 0..num_dbl_indr { + for (i, dbl_indr_block) in dbl_indr_blocks.iter().enumerate() { let num_blocks_in_single = min(num_blocks - (256 * i), 256); blocks_to_read.append( - &mut self.get_blocks_from_single_indirect( - dbl_indr_blocks[i] as u64, - num_blocks_in_single, - ), + &mut self + .get_blocks_from_single_indirect(*dbl_indr_block as u64, num_blocks_in_single), ); } @@ -176,7 +174,7 @@ impl Ext2Driver { let mut blocks = Vec::new(); - while let Some(block) = iter.next() { + for block in iter { if block as u64 == (curr_block.lba + curr_block.size) { curr_block.size += 1; } else { diff --git a/rust/lib/fs/ext2/src/types.rs b/rust/lib/fs/ext2/src/types.rs index 7aa3d2b..fd1f59b 100644 --- a/rust/lib/fs/ext2/src/types.rs +++ b/rust/lib/fs/ext2/src/types.rs @@ -111,7 +111,9 @@ pub struct Inode { const _: () = assert!(size_of::() == 128); +#[allow(dead_code)] pub const EXT2_FT_FILE: u8 = 0x1; +#[allow(dead_code)] pub const EXT2_FT_DIR: u8 = 0x2; #[repr(C, packed)] diff --git a/rust/lib/mammoth/src/cap_syscall.rs b/rust/lib/mammoth/src/cap_syscall.rs index eb9567a..b820bdc 100644 --- a/rust/lib/mammoth/src/cap_syscall.rs +++ b/rust/lib/mammoth/src/cap_syscall.rs @@ -2,7 +2,6 @@ use core::ffi::c_void; use crate::zion::{self, z_cap_t, ZError}; -#[must_use] fn syscall(id: u64, req: &T) -> Result<(), ZError> { unsafe { let resp = zion::SysCall1(id, req as *const T as *const c_void); diff --git a/rust/lib/mammoth/src/elf.rs b/rust/lib/mammoth/src/elf.rs index dd33876..28b636f 100644 --- a/rust/lib/mammoth/src/elf.rs +++ b/rust/lib/mammoth/src/elf.rs @@ -1,5 +1,4 @@ use crate::cap::Capability; -use crate::debug; use crate::init; use crate::syscall; use crate::zion::ZError; @@ -237,7 +236,7 @@ fn load_program_segment( let page_offset = prog_header.vaddr & 0xFFF; let mem_size = page_offset + prog_header.mem_size; - let mem_object = crate::mem::MemoryRegion::new(mem_size)?; + let mut mem_object = crate::mem::MemoryRegion::new(mem_size)?; mem_object.zero_region(); diff --git a/rust/lib/mammoth/src/init.rs b/rust/lib/mammoth/src/init.rs index 556cf24..c190ad1 100644 --- a/rust/lib/mammoth/src/init.rs +++ b/rust/lib/mammoth/src/init.rs @@ -28,7 +28,7 @@ pub fn parse_init_port(port_cap: z_cap_t) { let mut caps: [u64; 1] = [0]; let resp = syscall::port_poll(&init_port, &mut bytes, &mut caps); - if let Err(_) = resp { + if resp.is_err() { break; } diff --git a/rust/lib/mammoth/src/macros.rs b/rust/lib/mammoth/src/macros.rs index c977a91..3fc64c5 100644 --- a/rust/lib/mammoth/src/macros.rs +++ b/rust/lib/mammoth/src/macros.rs @@ -2,21 +2,20 @@ use alloc::string::String; use alloc::vec::Vec; use core::fmt; +#[derive(Default)] pub struct Writer { int_vec: Vec, } impl Writer { pub fn new() -> Self { - Self { - int_vec: Vec::new(), - } + Writer::default() } } -impl Into for Writer { - fn into(self) -> String { - String::from_utf8(self.int_vec).expect("Failed to convert") +impl From for String { + fn from(value: Writer) -> Self { + String::from_utf8(value.int_vec).expect("Failed to convert") } } diff --git a/rust/lib/mammoth/src/mem.rs b/rust/lib/mammoth/src/mem.rs index a203c74..d10e65d 100644 --- a/rust/lib/mammoth/src/mem.rs +++ b/rust/lib/mammoth/src/mem.rs @@ -3,7 +3,6 @@ use crate::syscall; use crate::zion::ZError; use alloc::slice; use core::fmt::Debug; -use core::ops::Deref; use core::ptr::{addr_of, addr_of_mut, read_volatile, write_volatile, NonNull}; #[cfg(feature = "hosted")] @@ -91,7 +90,7 @@ impl MemoryRegion { } } - pub fn mut_slice(&self) -> &mut [T] { + pub fn mut_slice(&mut self) -> &mut [T] { unsafe { slice::from_raw_parts_mut( self.virt_addr as *mut T, @@ -100,7 +99,7 @@ impl MemoryRegion { } } - pub fn zero_region(&self) { + pub fn zero_region(&mut self) { for i in self.mut_slice() { *i = 0; } @@ -118,8 +117,9 @@ impl MemoryRegion { /// Creates a reference from a given offset. /// - /// SAFETY: Caller must ensure that the memory pointed to by this - /// pointer must not get mutated while the reference exists. + /// # Safety + /// - Caller must ensure that the memory pointed to by this + /// pointer must not get mutated while the reference exists. pub unsafe fn as_ref_at_offset(&self, offset: usize) -> &T { let ptr: *const T = self.raw_ptr_at_offset(offset as u64); assert!(ptr.is_aligned(), ""); @@ -132,9 +132,10 @@ impl MemoryRegion { /// Creates a reference from a given offset. /// - /// SAFETY: Caller must ensure that this is the only reference to the memory pointed - /// to by this pointer. - pub unsafe fn as_mut_ref_at_offset(&self, offset: usize) -> &mut T { + /// # Safety + /// - Caller must ensure that this is the only reference to the memory pointed + /// to by this pointer. + pub unsafe fn as_mut_ref_at_offset(&mut self, offset: usize) -> &mut T { let ptr: *const T = self.raw_ptr_at_offset(offset as u64); assert!(ptr.is_aligned(), ""); // SAFETY: diff --git a/rust/lib/mammoth/src/physical_box.rs b/rust/lib/mammoth/src/physical_box.rs index 963b6ec..af68cba 100644 --- a/rust/lib/mammoth/src/physical_box.rs +++ b/rust/lib/mammoth/src/physical_box.rs @@ -89,7 +89,7 @@ impl PhysicalBox<[T]> { } } - pub fn from_vec(mut vec: Vec) -> Self { + pub fn from_vec(vec: Vec) -> Self { let len = vec.len(); let layout = core::alloc::Layout::array::(len).expect("Layout overflow"); @@ -117,6 +117,10 @@ impl PhysicalBox<[T]> { pub fn len(&self) -> usize { (**self).len() } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } impl Index for PhysicalBox<[T]> diff --git a/rust/lib/mammoth/src/sync.rs b/rust/lib/mammoth/src/sync.rs index 0ee5fea..f435e32 100644 --- a/rust/lib/mammoth/src/sync.rs +++ b/rust/lib/mammoth/src/sync.rs @@ -50,7 +50,7 @@ impl DerefMut for MutexGuard<'_, T> { } } -impl Mutex { +impl<'a, T> Mutex { pub fn new(data: T) -> Mutex { Mutex { cap: syscall::mutex_create().unwrap(), @@ -58,7 +58,7 @@ impl Mutex { } } - pub fn lock(&self) -> MutexGuard { + pub fn lock(&'a self) -> MutexGuard<'a, T> { syscall::mutex_lock(&self.cap).unwrap(); MutexGuard { mutex: self } @@ -70,3 +70,12 @@ impl Drop for MutexGuard<'_, T> { syscall::mutex_release(&self.mutex.cap).unwrap(); } } + +impl Default for Mutex +where + T: Default, +{ + fn default() -> Self { + Self::new(T::default()) + } +} diff --git a/rust/lib/mammoth/src/syscall.rs b/rust/lib/mammoth/src/syscall.rs index 2691458..bab76ca 100644 --- a/rust/lib/mammoth/src/syscall.rs +++ b/rust/lib/mammoth/src/syscall.rs @@ -9,7 +9,6 @@ use core::ffi::c_void; #[cfg(feature = "hosted")] use core::panic::PanicInfo; -#[must_use] fn syscall(id: u64, req: &T) -> Result<(), ZError> { unsafe { let resp = zion::SysCall1(id, req as *const T as *const c_void); diff --git a/rust/lib/mammoth/src/task/mod.rs b/rust/lib/mammoth/src/task/mod.rs index 92164ec..fee1a9d 100644 --- a/rust/lib/mammoth/src/task/mod.rs +++ b/rust/lib/mammoth/src/task/mod.rs @@ -48,7 +48,7 @@ struct TaskWaker { } impl TaskWaker { - fn new(task_id: TaskId, task_queue: Arc>>) -> Waker { + fn create_waker(task_id: TaskId, task_queue: Arc>>) -> Waker { Waker::from(Arc::new(TaskWaker { task_id, task_queue, @@ -69,6 +69,7 @@ impl Wake for TaskWaker { } } +#[derive(Default)] pub struct Executor { tasks: Arc>>, // TODO: Consider a better datastructure for this. @@ -78,11 +79,7 @@ pub struct Executor { impl Executor { pub fn new() -> Executor { - Executor { - tasks: Arc::new(Mutex::new(BTreeMap::new())), - task_queue: Arc::new(Mutex::new(VecDeque::new())), - waker_cache: BTreeMap::new(), - } + Executor::default() } pub fn spawn(&mut self, task: Task) { @@ -100,7 +97,7 @@ impl Executor { let waker = self .waker_cache .entry(task_id) - .or_insert_with(|| TaskWaker::new(task_id, self.task_queue.clone())); + .or_insert_with(|| TaskWaker::create_waker(task_id, self.task_queue.clone())); let mut ctx = Context::from_waker(waker); match task.poll(&mut ctx) { Poll::Ready(()) => { diff --git a/rust/lib/mammoth/src/thread.rs b/rust/lib/mammoth/src/thread.rs index 99032be..aeb4b27 100644 --- a/rust/lib/mammoth/src/thread.rs +++ b/rust/lib/mammoth/src/thread.rs @@ -40,7 +40,7 @@ where let raw_main = Box::into_raw(Box::new(main)); let proc_cap = Capability::take_copy(unsafe { crate::init::SELF_PROC_CAP }).unwrap(); let cap = syscall::thread_create(&proc_cap).unwrap(); - syscall::thread_start(&cap, entry_point as u64, raw_main as u64, 0).unwrap(); + syscall::thread_start(&cap, entry_point as usize as u64, raw_main as u64, 0).unwrap(); JoinHandle { cap } } diff --git a/rust/lib/pci/src/device.rs b/rust/lib/pci/src/device.rs index 948cd04..d74cb82 100644 --- a/rust/lib/pci/src/device.rs +++ b/rust/lib/pci/src/device.rs @@ -2,8 +2,7 @@ use alloc::vec::Vec; use mammoth::{cap::Capability, mem::MemoryRegion, syscall, zion::ZError}; use crate::header::{ - PciCapabilityPointer, PciDeviceHeader, PciHeaderType, PciMsiCapability, PciMsiControl, - get_header_type, + PciCapabilityPointer, PciDeviceHeader, PciHeaderType, PciMsiCapability, get_header_type, }; pub struct PciDevice { @@ -11,7 +10,7 @@ pub struct PciDevice { } impl PciDevice { - pub fn from(mut memory_region: MemoryRegion) -> Result { + pub fn from(memory_region: MemoryRegion) -> Result { match get_header_type(&memory_region)? { PciHeaderType::Device => {} t => { diff --git a/rust/lib/yellowstone/src/lib.rs b/rust/lib/yellowstone/src/lib.rs index 76659ef..ffdc267 100644 --- a/rust/lib/yellowstone/src/lib.rs +++ b/rust/lib/yellowstone/src/lib.rs @@ -10,10 +10,12 @@ static mut YELLOWSTONE_INIT: Option = None; pub fn from_init_endpoint() -> &'static mut YellowstoneClient { unsafe { - if let None = YELLOWSTONE_INIT { + #[allow(static_mut_refs)] + if YELLOWSTONE_INIT.is_none() { YELLOWSTONE_INIT = Some(YellowstoneClient::new(Capability::take(INIT_ENDPOINT))); } + #[allow(static_mut_refs)] YELLOWSTONE_INIT.as_mut().unwrap() } } diff --git a/rust/lib/yunq-test/src/lib.rs b/rust/lib/yunq-test/src/lib.rs index 1a3c3ec..9af3d55 100644 --- a/rust/lib/yunq-test/src/lib.rs +++ b/rust/lib/yunq-test/src/lib.rs @@ -12,7 +12,11 @@ mod tests { #[test] fn basic_serialization() -> Result<(), ZError> { - let basic = Basic { unsigned_int: 82, signed_int: -1234, strn: "abc".to_string() }; + let basic = Basic { + unsigned_int: 82, + signed_int: -1234, + strn: "abc".to_string(), + }; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); @@ -27,13 +31,17 @@ mod tests { #[test] fn basic_serialization_as_request() -> Result<(), ZError> { - let basic = Basic { unsigned_int: 82, signed_int: -1234, strn: "abc".to_string() }; + let basic = Basic { + unsigned_int: 82, + signed_int: -1234, + strn: "abc".to_string(), + }; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); let req_id = 12; basic.serialize_as_request(req_id, &mut buf, &mut caps)?; - + assert!(buf.at::(8)? == req_id); let parsed = Basic::parse_from_request(&buf, &caps)?; @@ -50,7 +58,7 @@ mod tests { let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); cap.serialize(&mut buf, 0, &mut caps)?; - + assert!(caps.len() == 1); assert!(caps[0] == cap_id); @@ -63,12 +71,14 @@ mod tests { #[test] fn repeated_serialization() -> Result<(), ZError> { - let rep = Repeated { unsigned_ints: vec![0, 1, 3],}; + let rep = Repeated { + unsigned_ints: vec![0, 1, 3], + }; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); rep.serialize(&mut buf, 0, &mut caps)?; - + let parsed = Repeated::parse(&buf, 0, &caps)?; assert!(parsed == rep); @@ -79,17 +89,20 @@ mod tests { #[test] fn nested_serialization() -> Result<(), ZError> { let nested = Nested { - basic: Basic { unsigned_int: 82, signed_int: -1234, strn: "abc".to_string() }, - cap1: Cap { cap: 37}, - cap2: Cap { cap: 39}, + basic: Basic { + unsigned_int: 82, + signed_int: -1234, + strn: "abc".to_string(), + }, + cap1: Cap { cap: 37 }, + cap2: Cap { cap: 39 }, }; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); nested.serialize(&mut buf, 0, &mut caps)?; - - let parsed = Nested::parse(&buf, 0, &caps)?; + let parsed = Nested::parse(&buf, 0, &caps)?; assert!(parsed == nested); @@ -99,23 +112,29 @@ mod tests { #[test] fn repeated_nested_serialization() -> Result<(), ZError> { let nested = RepeatedNested { - basics: vec![Basic { unsigned_int: 82, signed_int: -1234, strn: "abc".to_string(),}, - Basic { unsigned_int: 21, signed_int: -8, strn: "def".to_string(), },], - caps: vec![Cap{ cap: 123}, Cap {cap: 12343}], + basics: vec![ + Basic { + unsigned_int: 82, + signed_int: -1234, + strn: "abc".to_string(), + }, + Basic { + unsigned_int: 21, + signed_int: -8, + strn: "def".to_string(), + }, + ], + caps: vec![Cap { cap: 123 }, Cap { cap: 12343 }], }; let mut buf = ByteBuffer::<1024>::new(); let mut caps = Vec::new(); nested.serialize(&mut buf, 0, &mut caps)?; - - let parsed = RepeatedNested::parse(&buf, 0, &caps)?; + let parsed = RepeatedNested::parse(&buf, 0, &caps)?; assert!(parsed == nested); - Ok(()) } - - } diff --git a/rust/lib/yunq/src/buffer.rs b/rust/lib/yunq/src/buffer.rs index c3b0b18..7966337 100644 --- a/rust/lib/yunq/src/buffer.rs +++ b/rust/lib/yunq/src/buffer.rs @@ -5,12 +5,19 @@ pub struct ByteBuffer { buffer: Box<[u8; N]>, } -impl ByteBuffer { - pub fn new() -> Self { +impl Default for ByteBuffer { + fn default() -> Self { Self { buffer: Box::new([0; N]), } } +} + +impl ByteBuffer { + pub fn new() -> Self { + ByteBuffer::default() + } + pub fn size(&self) -> u64 { N as u64 } @@ -54,7 +61,7 @@ impl ByteBuffer { if (len + offset) > N { return Err(ZError::BUFFER_SIZE); } - Ok(alloc::str::from_utf8(&self.buffer[offset..offset + len]) - .map_err(|_| ZError::INVALID_ARGUMENT)?) + alloc::str::from_utf8(&self.buffer[offset..offset + len]) + .map_err(|_| ZError::INVALID_ARGUMENT) } } diff --git a/rust/lib/yunq/src/client.rs b/rust/lib/yunq/src/client.rs index e90698e..c4c45b8 100644 --- a/rust/lib/yunq/src/client.rs +++ b/rust/lib/yunq/src/client.rs @@ -34,5 +34,5 @@ pub fn call_endpoint( return Err(ZError::from(resp_code)); } - Ok(Resp::parse_from_request(&byte_buffer, &cap_buffer)?) + Resp::parse_from_request(byte_buffer, &cap_buffer) } diff --git a/rust/lib/yunq/src/message.rs b/rust/lib/yunq/src/message.rs index d1fc6a5..568916f 100644 --- a/rust/lib/yunq/src/message.rs +++ b/rust/lib/yunq/src/message.rs @@ -28,7 +28,7 @@ pub fn parse_repeated_message( buf: &ByteBuffer, mut offset: usize, len: usize, - caps: &Vec, + caps: &[z_cap_t], ) -> Result, ZError> { let mut repeated = Vec::new(); for _ in 0..len { @@ -43,18 +43,18 @@ pub fn parse_repeated_message( pub fn serialize_repeated( buf: &mut ByteBuffer, offset: usize, - data: &Vec, + data: &[T], ) -> Result { - for i in 0..data.len() { - buf.write_at(offset + (i * size_of::()), data[i])?; + for (i, val) in data.iter().enumerate() { + buf.write_at(offset + (i * size_of::()), val)?; } - Ok(offset + (data.len() * size_of::())) + Ok(offset + size_of_val(data)) } pub fn serialize_repeated_message( buf: &mut ByteBuffer, mut offset: usize, - data: &Vec, + data: &[T], caps: &mut Vec, ) -> Result { for item in data { @@ -76,14 +76,14 @@ pub trait YunqMessage { fn parse( buf: &ByteBuffer, offset: usize, - caps: &Vec, + caps: &[z_cap_t], ) -> Result where Self: Sized; fn parse_from_request( buf: &ByteBuffer, - caps: &Vec, + caps: &[z_cap_t], ) -> Result where Self: Sized, @@ -92,7 +92,7 @@ pub trait YunqMessage { return Err(ZError::INVALID_RESPONSE); } - Ok(Self::parse(&buf, 16, &caps)?) + Self::parse(buf, 16, caps) } fn serialize( @@ -109,7 +109,7 @@ pub trait YunqMessage { caps: &mut Vec, ) -> Result { buf.write_at(0, SENTINEL)?; - buf.write_at(8, request_id as u64)?; + buf.write_at(8, request_id)?; let length = self.serialize(buf, 16, caps)?; @@ -125,7 +125,7 @@ impl YunqMessage for Empty { fn parse( _buf: &ByteBuffer, _offset: usize, - _caps: &Vec, + _caps: &[z_cap_t], ) -> Result where Self: Sized, diff --git a/rust/lib/yunq/src/server.rs b/rust/lib/yunq/src/server.rs index a5ded0b..cdfe418 100644 --- a/rust/lib/yunq/src/server.rs +++ b/rust/lib/yunq/src/server.rs @@ -37,7 +37,7 @@ pub trait YunqServer { .expect("Failed to reply"), Err(err) => { crate::message::serialize_error(&mut byte_buffer, err); - syscall::reply_port_send(reply_port_cap, &byte_buffer.slice(0x10), &[]) + syscall::reply_port_send(reply_port_cap, byte_buffer.slice(0x10), &[]) .expect("Failed to reply w/ error") } } @@ -84,11 +84,11 @@ where .at::(8) .expect("Failed to access request length."); let self_clone = self.clone(); - spawner.spawn(Task::new((async move || { + spawner.spawn(Task::new(async move { self_clone .handle_request_and_response(method, byte_buffer, cap_buffer, reply_port_cap) - .await; - })())); + .await + })); } } @@ -113,12 +113,10 @@ where .expect("Failed to reply"), Err(err) => { crate::message::serialize_error(&mut byte_buffer, err); - syscall::reply_port_send(reply_port_cap, &byte_buffer.slice(0x10), &[]) + syscall::reply_port_send(reply_port_cap, byte_buffer.slice(0x10), &[]) .expect("Failed to reply w/ error") } } - - () } } diff --git a/rust/sys/denali/src/ahci/command.rs b/rust/sys/denali/src/ahci/command.rs index 947082e..c827bb1 100644 --- a/rust/sys/denali/src/ahci/command.rs +++ b/rust/sys/denali/src/ahci/command.rs @@ -95,7 +95,7 @@ impl Command { command: SataCommand::DmaReadExt, lba, sector_cnt: lba_count, - paddr: paddr, + paddr, memory_region: None, } } diff --git a/rust/sys/denali/src/ahci/port_controller.rs b/rust/sys/denali/src/ahci/port_controller.rs index 556e8f7..42dfa00 100644 --- a/rust/sys/denali/src/ahci/port_controller.rs +++ b/rust/sys/denali/src/ahci/port_controller.rs @@ -44,9 +44,8 @@ impl PortController { }; // This leaves space for 8 prdt entries. - for i in 0..32 { - command_list[i].command_table_base_addr = - (command_paddr + 0x500) + (0x100 * (i as u64)); + for (i, header) in command_list.iter_mut().enumerate() { + header.command_table_base_addr = (command_paddr + 0x500) + (0x100 * (i as u64)); } let command_slots = array::from_fn(|_| Arc::new(Mutex::new(CommandStatus::Empty))); diff --git a/rust/sys/teton/src/framebuffer.rs b/rust/sys/teton/src/framebuffer.rs index dad4099..f083367 100644 --- a/rust/sys/teton/src/framebuffer.rs +++ b/rust/sys/teton/src/framebuffer.rs @@ -16,15 +16,16 @@ impl Framebuffer { }) } - fn draw_pixel(&self, row: u32, col: u32, pixel: u32) { + fn draw_pixel(&mut self, row: u32, col: u32, pixel: u32) { let index = row * (self.fb_info.pitch as u32 / 4) + col; self.memory_region.mut_slice()[index as usize] = pixel; } - pub fn draw_glyph(&self, glyph: &[u8], row: u32, col: u32) { + pub fn draw_glyph(&mut self, glyph: &[u8], row: u32, col: u32) { let gl_width = 8; let gl_height = 16; + #[allow(clippy::needless_range_loop)] for r in 0..gl_height { for c in 0..gl_width { if ((glyph[r] >> c) % 2) == 1 { diff --git a/rust/sys/teton/src/psf.rs b/rust/sys/teton/src/psf.rs index f6a75a6..3f99f65 100644 --- a/rust/sys/teton/src/psf.rs +++ b/rust/sys/teton/src/psf.rs @@ -23,7 +23,7 @@ pub struct Psf { impl Psf { pub fn new(path: &str) -> Result { - let file = File::open(&path)?; + let file = File::open(path)?; let header = file.slice()[0..core::mem::size_of::()] .as_ptr() diff --git a/rust/sys/teton/src/terminal.rs b/rust/sys/teton/src/terminal.rs index 2cd46ce..20b7ee0 100644 --- a/rust/sys/teton/src/terminal.rs +++ b/rust/sys/teton/src/terminal.rs @@ -62,10 +62,8 @@ impl Terminal { } fn write_line(&mut self, line: &str) { - let mut col = 0; - for c in line.chars() { - self.console.write_char(c, self.row, col); - col += 1; + for (col, c) in line.chars().enumerate() { + self.console.write_char(c, self.row, col as u32); } self.row += 1 diff --git a/rust/sys/victoriafalls/src/lib.rs b/rust/sys/victoriafalls/src/lib.rs index b7b9ca3..a213a8b 100644 --- a/rust/sys/victoriafalls/src/lib.rs +++ b/rust/sys/victoriafalls/src/lib.rs @@ -12,7 +12,8 @@ static mut VFS_CLIENT: Option = None; fn get_client() -> &'static mut VFSClient { unsafe { - if let None = VFS_CLIENT { + #[allow(static_mut_refs)] + if VFS_CLIENT.is_none() { let endpoint_cap = yellowstone_yunq::from_init_endpoint() .get_endpoint(&yellowstone_yunq::GetEndpointRequest { endpoint_name: "victoriafalls".to_string(), @@ -21,6 +22,7 @@ fn get_client() -> &'static mut VFSClient { VFS_CLIENT = Some(VFSClient::new(Capability::take(endpoint_cap.endpoint))); } + #[allow(static_mut_refs)] VFS_CLIENT.as_mut().unwrap() } } diff --git a/rust/sys/victoriafalls/src/server.rs b/rust/sys/victoriafalls/src/server.rs index 0c2edb8..a901ea9 100644 --- a/rust/sys/victoriafalls/src/server.rs +++ b/rust/sys/victoriafalls/src/server.rs @@ -35,7 +35,7 @@ impl VFSServerHandler for VictoriaFallsServerImpl { let mut inode_num = 2; // Start with root. - while let Some(path_token) = tokens.next() { + for path_token in tokens { inode_num = self.find_path_in_dir(inode_num, path_token)?; } @@ -57,7 +57,7 @@ impl VFSServerHandler for VictoriaFallsServerImpl { let mut inode_num = 2; // Start with root. - while let Some(path_token) = tokens.next() { + for path_token in tokens { inode_num = self.find_path_in_dir(inode_num, path_token)?; } diff --git a/rust/sys/voyageurs/src/xhci/data_structures/command_trb.rs b/rust/sys/voyageurs/src/xhci/data_structures/command_trb.rs new file mode 100644 index 0000000..d55b85a --- /dev/null +++ b/rust/sys/voyageurs/src/xhci/data_structures/command_trb.rs @@ -0,0 +1,71 @@ +use bitfield_struct::bitfield; + +use crate::xhci::data_structures::{TransferRequestBlock, TrbType}; + +pub struct EnableSlotTrb {} + +#[bitfield(u128)] +pub struct EnableSlotCommand { + __: u64, + __: u32, + #[bits(10)] + __: u16, + #[bits(6, default=TrbType::EnableSlotCommand)] + trb_type: TrbType, + #[bits(5)] + slot_type: u8, + #[bits(11)] + __: u16, +} + +impl From for CommandTrb { + fn from(value: EnableSlotCommand) -> Self { + Self(value.into_bits().into()) + } +} + +#[bitfield(u128)] +pub struct AddressDeviceCommand { + pub input_context_pointer: u64, + __: u32, + #[bits(9)] + __: u16, + pub block_set_address_request: bool, + #[bits(6, default=TrbType::AddressDeviceCommand)] + trb_typ: TrbType, + __: u8, + pub slot_id: u8, +} + +impl From for CommandTrb { + fn from(value: AddressDeviceCommand) -> Self { + Self(value.into_bits().into()) + } +} + +#[bitfield(u128)] +pub struct NoOpCommand { + __: u64, + __: u32, + cycle: bool, + #[bits(9)] + __: u16, + #[bits(6, default = TrbType::NoOpCommand)] + trb_type: TrbType, + __: u16, +} + +impl From for CommandTrb { + fn from(value: NoOpCommand) -> Self { + Self(value.into_bits().into()) + } +} + +/// Simple type to ensure we are only sending commands to command rings. +pub struct CommandTrb(TransferRequestBlock); + +impl From for TransferRequestBlock { + fn from(value: CommandTrb) -> Self { + value.0 + } +} diff --git a/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs b/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs index e4985d8..4902da2 100644 --- a/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs +++ b/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs @@ -18,10 +18,10 @@ pub struct EventRingSegmentTableEntry { } impl EventRingSegmentTableEntry { - pub fn from_trb_ring(&mut self, trb_ring: &TrbRingSegment) { + pub fn update_from_trb_ring(&mut self, trb_ring: &TrbRingSegment) { mammoth::debug!("RSTE: {:0x}", self as *const _ as usize); self.ring_segment_base_address = trb_ring.physical_address() as u64; - assert!(self.ring_segment_base_address % 64 == 0); + assert!(self.ring_segment_base_address.is_multiple_of(64)); unsafe { core::ptr::write_volatile( &mut self.ring_segment_size as *mut u64, diff --git a/rust/sys/voyageurs/src/xhci/data_structures/event_trb.rs b/rust/sys/voyageurs/src/xhci/data_structures/event_trb.rs new file mode 100644 index 0000000..4754e7a --- /dev/null +++ b/rust/sys/voyageurs/src/xhci/data_structures/event_trb.rs @@ -0,0 +1,139 @@ +use bitfield_struct::{bitenum, bitfield}; + +use crate::xhci::data_structures::{TransferRequestBlock, TrbType}; + +#[bitenum] +#[repr(u8)] +#[derive(Debug, Eq, PartialEq)] +pub enum CommandCompletionCode { + #[fallback] + #[allow(dead_code)] + Invalid = 0, + Success = 1, +} + +#[bitfield(u128)] +pub struct TransferEvent { + pub transfer_trb_pointer: u64, + + #[bits(24)] + pub trb_transfer_lenght: u32, + + /// Completion Code. This field encodes the completion status of the command that generated the + /// event. Refer to the respective command definition for a list of the possible Completion Codes + /// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error + /// conditions. + #[bits(8)] + pub completion_code: CommandCompletionCode, + #[bits(10)] + __: u16, + /// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the + /// Command Completion Event TRB type ID + #[bits(6, default=TrbType::TransferEvent)] + pub trb_type: TrbType, + + #[bits(5)] + pub endpoint_id: u8, + #[bits(3)] + __: u8, + + pub slot_id: u8, +} + +#[bitfield(u128)] +pub struct CommandCompletionEvent { + /// Command TRB Pointer Hi and Lo. This field represents the high order bits of the 64-bit address + /// of the Command TRB that generated this event. Note that this field is not valid for some + /// Completion Code values. Refer to Table 6-90 for specific cases. + /// + /// The memory structure referenced by this physical memory pointer shall be aligned on a 16-byte + /// address boundary. + pub command_trb_pointer: u64, + /// Command Completion Parameter. This field may optionally be set by a command. Refer to + /// section 4.6.6.1 for specific usage. If a command does not utilize this field it shall be treated as + /// RsvdZ. + #[bits(24)] + pub command_completion_parameter: u64, + /// Completion Code. This field encodes the completion status of the command that generated the + /// event. Refer to the respective command definition for a list of the possible Completion Codes + /// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error + /// conditions. + #[bits(8)] + pub completion_code: CommandCompletionCode, + /// Cycle bit (C). This bit is used to mark the Dequeue Pointer of an Event Ring + pub cycle_bit: bool, + #[bits(9)] + __: u16, + /// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the + /// Command Completion Event TRB type ID + #[bits(6, default=TrbType::CommandCompletionEvent)] + pub trb_type: TrbType, + /// VF ID. The ID of the Virtual Function that generated the event. Note that this field is valid only if + /// Virtual Functions are enabled. If they are not enabled this field shall be cleared to ‘0’. + pub vf_id: u8, + /// Slot ID. The Slot ID field shall be updated by the xHC to reflect the slot associated with the + /// command that generated the event, with the following exceptions: + /// + /// - The Slot ID shall be cleared to ‘0’ for No Op, Set Latency Tolerance Value, Get Port Bandwidth, + /// and Force Event Commands. + /// + /// - The Slot ID shall be set to the ID of the newly allocated Device Slot for the Enable Slot + /// Command. + /// + /// - The value of Slot ID shall be vendor defined when generated by a vendor defined command. + /// + /// This value is used as an index in the Device Context Base Address Array to select the Device + /// Context of the source device. If this Event is due to a Host Controller Command, then this field + /// shall be cleared to ‘0’. + pub slot_id: u8, +} + +#[bitfield(u128)] +pub struct PortStatusChangeEvent { + #[bits(24)] + __: u32, + pub port_id: u8, + __: u32, + #[bits(24)] + __: u32, + #[bits(8)] + pub completion_code: CommandCompletionCode, + #[bits(10)] + __: u16, + #[bits(6, default=TrbType::PortStatusChangeEvent)] + trb_type: TrbType, + __: u16, +} + +pub enum EventTrb { + Transfer(TransferEvent), + CommandCompletion(CommandCompletionEvent), + PortStatusChange(PortStatusChangeEvent), + BandwidthRequest(TransferRequestBlock), + Doorbell(TransferRequestBlock), + HostController(TransferRequestBlock), + DeviceNotification(TransferRequestBlock), + MFINDEXWrap(TransferRequestBlock), +} + +impl From for EventTrb { + fn from(value: TransferRequestBlock) -> Self { + match value.trb_type() { + TrbType::TransferEvent => { + EventTrb::Transfer(TransferEvent::from_bits(value.into_bits())) + } + TrbType::CommandCompletionEvent => { + EventTrb::CommandCompletion(CommandCompletionEvent::from_bits(value.into_bits())) + } + TrbType::PortStatusChangeEvent => { + EventTrb::PortStatusChange(PortStatusChangeEvent::from_bits(value.into_bits())) + } + TrbType::BandwidthRequestEvent => EventTrb::BandwidthRequest(value), + TrbType::DoorbellEvent => EventTrb::Doorbell(value), + TrbType::HostControllerEvent => EventTrb::HostController(value), + TrbType::DeviceNotificationEvent => EventTrb::DeviceNotification(value), + TrbType::MFINDEXWrapEvent => EventTrb::MFINDEXWrap(value), + t => panic!("Unknown trb type on event ring: {:?}", t), + } + } +} diff --git a/rust/sys/voyageurs/src/xhci/data_structures/mod.rs b/rust/sys/voyageurs/src/xhci/data_structures/mod.rs index 6b33f73..5069bf6 100644 --- a/rust/sys/voyageurs/src/xhci/data_structures/mod.rs +++ b/rust/sys/voyageurs/src/xhci/data_structures/mod.rs @@ -1,14 +1,18 @@ +mod command_trb; mod device_context; mod endpoint_context; mod event_ring_segment_table; +mod event_trb; mod input_context; mod slot_context; mod trb; mod trb_ring_segment; +pub use command_trb::*; pub use device_context::*; pub use endpoint_context::*; pub use event_ring_segment_table::*; +pub use event_trb::*; pub use input_context::*; pub use slot_context::*; pub use trb::*; diff --git a/rust/sys/voyageurs/src/xhci/data_structures/trb.rs b/rust/sys/voyageurs/src/xhci/data_structures/trb.rs index e84afe7..7cb0338 100644 --- a/rust/sys/voyageurs/src/xhci/data_structures/trb.rs +++ b/rust/sys/voyageurs/src/xhci/data_structures/trb.rs @@ -75,29 +75,6 @@ where } } -#[bitfield(u128)] -pub struct TrbNoOp { - __: u64, - #[bits(22)] - __: u32, - #[bits(10, default = 0)] - interrupter_target: u16, - cycle: bool, - evaluate_next: bool, - __: bool, - __: bool, - chain: bool, - #[bits(default = true)] - interrupt_on_completion: bool, - #[bits(4)] - __: u8, - #[bits(6, default = TrbType::NoOpCommand)] - trb_type: TrbType, - __: u16, -} - -impl TypedTrb for TrbNoOp {} - #[bitfield(u128)] pub struct TrbLink { /// Ring Segment Pointer Hi and Lo. These fields represent the high order bits of the 64-bit base @@ -141,138 +118,3 @@ pub struct TrbLink { } impl TypedTrb for TrbLink {} - -#[bitfield(u128)] -pub struct TrbTransferEvent { - pub transfer_trb_pointer: u64, - - #[bits(24)] - pub trb_transfer_lenght: u32, - - /// Completion Code. This field encodes the completion status of the command that generated the - /// event. Refer to the respective command definition for a list of the possible Completion Codes - /// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error - /// conditions. - pub completion_code: u8, - #[bits(10)] - __: u16, - /// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the - /// Command Completion Event TRB type ID - #[bits(6, default=TrbType::TransferEvent)] - pub trb_type: TrbType, - - #[bits(5)] - pub endpoint_id: u8, - #[bits(3)] - __: u8, - - pub slot_id: u8, -} - -impl TypedTrb for TrbTransferEvent {} - -#[bitenum] -#[repr(u8)] -pub enum CommandCompletionCode { - #[fallback] - Invalid = 0, - Success = 1, -} - -#[bitfield(u128)] -pub struct TrbCommandCompletion { - /// Command TRB Pointer Hi and Lo. This field represents the high order bits of the 64-bit address - /// of the Command TRB that generated this event. Note that this field is not valid for some - /// Completion Code values. Refer to Table 6-90 for specific cases. - /// - /// The memory structure referenced by this physical memory pointer shall be aligned on a 16-byte - /// address boundary. - pub command_trb_pointer: u64, - /// Command Completion Parameter. This field may optionally be set by a command. Refer to - /// section 4.6.6.1 for specific usage. If a command does not utilize this field it shall be treated as - /// RsvdZ. - #[bits(24)] - pub command_completion_parameter: u64, - /// Completion Code. This field encodes the completion status of the command that generated the - /// event. Refer to the respective command definition for a list of the possible Completion Codes - /// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error - /// conditions. - pub completion_code: u8, - /// Cycle bit (C). This bit is used to mark the Dequeue Pointer of an Event Ring - pub cycle_bit: bool, - #[bits(9)] - __: u16, - /// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the - /// Command Completion Event TRB type ID - #[bits(6, default=TrbType::CommandCompletionEvent)] - pub trb_type: TrbType, - /// VF ID. The ID of the Virtual Function that generated the event. Note that this field is valid only if - /// Virtual Functions are enabled. If they are not enabled this field shall be cleared to ‘0’. - pub vf_id: u8, - /// Slot ID. The Slot ID field shall be updated by the xHC to reflect the slot associated with the - /// command that generated the event, with the following exceptions: - /// - /// - The Slot ID shall be cleared to ‘0’ for No Op, Set Latency Tolerance Value, Get Port Bandwidth, - /// and Force Event Commands. - /// - /// - The Slot ID shall be set to the ID of the newly allocated Device Slot for the Enable Slot - /// Command. - /// - /// - The value of Slot ID shall be vendor defined when generated by a vendor defined command. - /// - /// This value is used as an index in the Device Context Base Address Array to select the Device - /// Context of the source device. If this Event is due to a Host Controller Command, then this field - /// shall be cleared to ‘0’. - pub slot_id: u8, -} - -impl TypedTrb for TrbCommandCompletion {} - -#[bitfield(u128)] -pub struct TrbPortStatusChangeEvent { - #[bits(24)] - __: u32, - pub port_id: u8, - __: u32, - #[bits(24)] - __: u32, - pub completion_code: u8, - #[bits(10)] - __: u16, - #[bits(6, default=TrbType::PortStatusChangeEvent)] - trb_type: TrbType, - __: u16, -} - -impl TypedTrb for TrbPortStatusChangeEvent {} - -#[bitfield(u128)] -pub struct TrbEnableSlotCommand { - __: u64, - __: u32, - #[bits(10)] - __: u16, - #[bits(6, default=TrbType::EnableSlotCommand)] - trb_type: TrbType, - #[bits(5)] - slot_type: u8, - #[bits(11)] - __: u16, -} - -impl TypedTrb for TrbEnableSlotCommand {} - -#[bitfield(u128)] -pub struct TrbAddressDeviceCommand { - pub input_context_pointer: u64, - __: u32, - #[bits(9)] - __: u16, - pub block_set_address_request: bool, - #[bits(6, default=TrbType::AddressDeviceCommand)] - trb_typ: TrbType, - __: u8, - pub slot_id: u8, -} - -impl TypedTrb for TrbAddressDeviceCommand {} diff --git a/rust/sys/voyageurs/src/xhci/device_context_base_array.rs b/rust/sys/voyageurs/src/xhci/device_context_base_array.rs index 6c32179..d69497c 100644 --- a/rust/sys/voyageurs/src/xhci/device_context_base_array.rs +++ b/rust/sys/voyageurs/src/xhci/device_context_base_array.rs @@ -4,7 +4,7 @@ use mammoth::physical_box::PhysicalBox; use crate::xhci::{ data_structures::{ DeviceContext, EndpointContextFields, EndpointState, EndpointType, InputContext, - TRDequeuePointer, TrbTransferEvent, + TRDequeuePointer, TransferEvent, }, registers::DoorbellPointer, trb_ring::TrbRing, @@ -20,22 +20,27 @@ impl DeviceContextBaseArray { pub struct DeviceSlot { device_context: PhysicalBox, - endpoint_0_transfer_ring: TrbRing, + endpoint_0_transfer_ring: TrbRing, + doorbell: DoorbellPointer, } impl DeviceSlot { - fn new() -> Self { + fn new(doorbell: DoorbellPointer) -> Self { Self { device_context: PhysicalBox::new(DeviceContext::default()), endpoint_0_transfer_ring: TrbRing::new(), + doorbell, } } + pub fn send_control_command(&mut self) { + self.doorbell.ring(1); + } } pub struct DeviceSlotManager { device_context_base_array: DeviceContextBaseArray, slots: Box<[Option]>, - doorbells: Box<[DoorbellPointer]>, + doorbells: Box<[Option]>, } impl DeviceSlotManager { @@ -49,7 +54,7 @@ impl DeviceSlotManager { slots: core::iter::repeat_with(|| None) .take(max_slots as usize) .collect(), - doorbells, + doorbells: doorbells.into_iter().map(|d| Some(d)).collect(), } } @@ -66,7 +71,11 @@ impl DeviceSlotManager { port_number: u8, ) -> PhysicalBox { // TODO: Ensure alignment - let device_slot = DeviceSlot::new(); + let device_slot = DeviceSlot::new( + self.doorbells[(slot_id - 1) as usize] + .take() + .expect("Slot already allocated."), + ); let mut input_context = PhysicalBox::new(InputContext::default()); // The Add Context flags for the Slot Context and the Endpoint 0 Context shall be set to ‘1’. diff --git a/rust/sys/voyageurs/src/xhci/driver.rs b/rust/sys/voyageurs/src/xhci/driver.rs index 6f69b63..1a0fc0e 100644 --- a/rust/sys/voyageurs/src/xhci/driver.rs +++ b/rust/sys/voyageurs/src/xhci/driver.rs @@ -1,20 +1,17 @@ -use alloc::boxed::Box; use alloc::sync::Arc; -use mammoth::cap::Capability; use mammoth::sync::Mutex; use mammoth::task::Spawner; use mammoth::task::Task; use super::registers::{self}; +use crate::xhci::data_structures::AddressDeviceCommand; use crate::xhci::data_structures::CommandCompletionCode; -use crate::xhci::data_structures::TransferRequestBlock; -use crate::xhci::data_structures::TrbAddressDeviceCommand; -use crate::xhci::data_structures::TrbCommandCompletion; -use crate::xhci::data_structures::TrbEnableSlotCommand; -use crate::xhci::data_structures::TrbNoOp; -use crate::xhci::data_structures::TrbPortStatusChangeEvent; -use crate::xhci::data_structures::TrbType; -use crate::xhci::data_structures::TypedTrb; +use crate::xhci::data_structures::CommandCompletionEvent; +use crate::xhci::data_structures::CommandTrb; +use crate::xhci::data_structures::EnableSlotCommand; +use crate::xhci::data_structures::EventTrb; +use crate::xhci::data_structures::NoOpCommand; +use crate::xhci::data_structures::PortStatusChangeEvent; use crate::xhci::device_context_base_array::DeviceSlotManager; use crate::xhci::interrupter::Interrupter; use crate::xhci::registers::DoorbellPointer; @@ -40,7 +37,7 @@ impl XHCIDriver { ((pci_device.header().bars[1] as usize) << 32) | (pci_device.header().bars[0] as usize); let irq_port_cap = pci_device.register_msi().unwrap(); - let (operational, capabilities) = HostControllerOperationalWrapper::new(address as usize); + let (operational, capabilities) = HostControllerOperationalWrapper::new(address); let max_slots = capabilities.params_1.max_device_slots(); let doorbell_physical = address + capabilities.doorbell_offset as usize; @@ -153,38 +150,49 @@ impl XHCIDriver { } pub fn interrupt_loop(self: Arc, spawner: Spawner) { - let completion_handler = |trb: TransferRequestBlock| { + let completion_handler = |trb| { self.clone().handle_completion(spawner.clone(), trb); }; self.interrupter.lock().interrupt_loop(completion_handler); } - fn handle_completion(self: Arc, spawner: Spawner, trb: TransferRequestBlock) { - match trb.trb_type() { - TrbType::TransferEvent => { - todo!("Handle Transfer") + fn handle_completion(self: Arc, spawner: Spawner, trb: EventTrb) { + match trb { + EventTrb::Transfer(trb) => { + mammoth::debug!("Unhandled transfer event: {:?}", trb); } - TrbType::CommandCompletionEvent => { + EventTrb::CommandCompletion(trb) => { self.command_ring .lock() .trb_ring - .handle_completion(TrbCommandCompletion::from_trb(trb)); + .handle_completion(trb, trb.command_trb_pointer() as usize); } - TrbType::PortStatusChangeEvent => { - let trb = TrbPortStatusChangeEvent::from_trb(trb); + EventTrb::PortStatusChange(trb) => { let self_clone = self.clone(); spawner.spawn(Task::new(async move { self_clone.port_status_change(trb).await })); } - _ => { - panic!("Unhandled event type: {:?}", trb.trb_type()); + EventTrb::BandwidthRequest(trb) => { + mammoth::debug!("Unhandled bandwidth request event: {:?}", trb); + } + EventTrb::Doorbell(trb) => { + mammoth::debug!("Unhandled doorbell event: {:?}", trb); + } + EventTrb::HostController(trb) => { + mammoth::debug!("Unhandled host controller event: {:?}", trb); + } + EventTrb::DeviceNotification(trb) => { + mammoth::debug!("Unhandled device notification event: {:?}", trb); + } + EventTrb::MFINDEXWrap(trb) => { + mammoth::debug!("Unhandled MFINDEX wrap event: {:?}", trb); } } } - async fn send_command(&self, trb: impl TypedTrb) -> TrbCommandCompletion { + async fn send_command(&self, trb: CommandTrb) -> CommandCompletionEvent { // Split the future and the await so the lock is dropped before we await. let future = { self.command_ring.lock().enqueue_command(trb) }; future.await @@ -194,9 +202,9 @@ impl XHCIDriver { #[cfg(feature = "debug")] mammoth::debug!("Sending no op command."); - let result = self.send_command(TrbNoOp::new()).await; + let result = self.send_command(NoOpCommand::new().into()).await; - assert!(result.completion_code() == CommandCompletionCode::Success.into_bits()); + assert_eq!(result.completion_code(), CommandCompletionCode::Success); #[cfg(feature = "debug")] mammoth::debug!("Successfully tested no op command."); @@ -221,15 +229,12 @@ impl XHCIDriver { } } - async fn port_status_change(self: Arc, status_change: TrbPortStatusChangeEvent) { + async fn port_status_change(self: Arc, status_change: PortStatusChangeEvent) { // Ports are indexed from 1. let port_id = status_change.port_id(); let port_index = (port_id - 1) as usize; - let port_status = self - .operational - .get_port(port_index as usize) - .status_and_control; + let port_status = self.operational.get_port(port_index).status_and_control; #[cfg(feature = "debug")] mammoth::debug!("Port status change for port {}", port_id); @@ -248,8 +253,8 @@ impl XHCIDriver { #[cfg(feature = "debug")] mammoth::debug!("Enabling slot."); - let resp = self.send_command(TrbEnableSlotCommand::new()).await; - assert!(resp.completion_code() == CommandCompletionCode::Success.into_bits()); + let resp = self.send_command(EnableSlotCommand::new().into()).await; + assert_eq!(resp.completion_code(), CommandCompletionCode::Success); let slot = resp.slot_id(); @@ -266,11 +271,12 @@ impl XHCIDriver { let resp = self .send_command( - TrbAddressDeviceCommand::new() + AddressDeviceCommand::new() .with_slot_id(slot) - .with_input_context_pointer(input_context.physical_address() as u64), + .with_input_context_pointer(input_context.physical_address() as u64) + .into(), ) .await; - assert!(resp.completion_code() == CommandCompletionCode::Success.into_bits()); + assert_eq!(resp.completion_code(), CommandCompletionCode::Success); } } diff --git a/rust/sys/voyageurs/src/xhci/event_ring.rs b/rust/sys/voyageurs/src/xhci/event_ring.rs index 58e5d75..116f27e 100644 --- a/rust/sys/voyageurs/src/xhci/event_ring.rs +++ b/rust/sys/voyageurs/src/xhci/event_ring.rs @@ -1,7 +1,7 @@ use alloc::vec::Vec; use crate::xhci::{ - data_structures::{EventRingSegmentTable, TransferRequestBlock, TrbRingSegment}, + data_structures::{EventRingSegmentTable, EventTrb, TransferRequestBlock, TrbRingSegment}, trb_ring::TrbPointer, }; @@ -24,7 +24,7 @@ impl EventRing { trb_pointer: TrbPointer::default(), }; - event_ring.segment_table[0].from_trb_ring(&event_ring.segments[0]); + event_ring.segment_table[0].update_from_trb_ring(&event_ring.segments[0]); event_ring } @@ -58,13 +58,13 @@ impl EventRing { } } - pub fn get_next(&mut self) -> Option { + pub fn get_next(&mut self) -> Option { let curr = self.current_trb(); if curr.cycle() != self.cycle_bit { None } else { self.increment_pointer(); - Some(curr) + Some(curr.into()) } } } diff --git a/rust/sys/voyageurs/src/xhci/interrupter.rs b/rust/sys/voyageurs/src/xhci/interrupter.rs index 483dc54..05fca51 100644 --- a/rust/sys/voyageurs/src/xhci/interrupter.rs +++ b/rust/sys/voyageurs/src/xhci/interrupter.rs @@ -1,10 +1,9 @@ use core::ptr::NonNull; -use alloc::boxed::Box; use mammoth::cap::Capability; use crate::xhci::{ - data_structures::TransferRequestBlock, + data_structures::{EventTrb, TransferRequestBlock}, event_ring::EventRing, registers::{InterrupterModeration, InterrupterRegisterSet, InterrupterRegisters}, }; @@ -48,17 +47,14 @@ impl Interrupter { self.register_set.enable_interrupts(); } - pub fn interrupt_loop(&mut self, completion_handler: impl Fn(TransferRequestBlock) -> ()) { + pub fn interrupt_loop(&mut self, completion_handler: impl Fn(EventTrb)) { loop { let _ = mammoth::syscall::port_recv(&self.irq_port_cap, &mut [], &mut []).unwrap(); - #[cfg(feature = "debug")] - mammoth::debug!("Received Interrupt."); - while let Some(trb) = self.event_ring.get_next() { completion_handler(trb); - self.register_set - .update_dequeue_pointer_clearing_busy(self.event_ring.erdp_physical_address()); } + self.register_set + .update_dequeue_pointer_clearing_busy(self.event_ring.erdp_physical_address()); } } } diff --git a/rust/sys/voyageurs/src/xhci/registers/doorbell.rs b/rust/sys/voyageurs/src/xhci/registers/doorbell.rs index 0ffbe80..9427efe 100644 --- a/rust/sys/voyageurs/src/xhci/registers/doorbell.rs +++ b/rust/sys/voyageurs/src/xhci/registers/doorbell.rs @@ -1,6 +1,6 @@ use core::ptr::NonNull; -use alloc::{boxed::Box, vec::Vec}; +use alloc::boxed::Box; use bitfield_struct::bitfield; use volatile::VolatileRef; diff --git a/rust/sys/voyageurs/src/xhci/registers/host_controller.rs b/rust/sys/voyageurs/src/xhci/registers/host_controller.rs index 6d32703..34037d6 100644 --- a/rust/sys/voyageurs/src/xhci/registers/host_controller.rs +++ b/rust/sys/voyageurs/src/xhci/registers/host_controller.rs @@ -341,7 +341,7 @@ pub struct UsbConfigure { /// XHCI Spec Section 5.4 /// -/// > The base address of this register space is referred to as Operational Base. The +/// The base address of this register space is referred to as Operational Base. The /// Operational Base shall be Dword aligned and is calculated by adding the value /// of the Capability Registers Length (CAPLENGTH) register (refer to Section 5.3.1) /// to the Capability Base address. All registers are multiples of 32 bits in length diff --git a/rust/sys/voyageurs/src/xhci/trb_ring.rs b/rust/sys/voyageurs/src/xhci/trb_ring.rs index e5789da..34cdb47 100644 --- a/rust/sys/voyageurs/src/xhci/trb_ring.rs +++ b/rust/sys/voyageurs/src/xhci/trb_ring.rs @@ -5,7 +5,7 @@ use mammoth::sync::Mutex; use crate::xhci::{ data_structures::{ - TransferRequestBlock, TrbCommandCompletion, TrbLink, TrbRingSegment, TypedTrb, + CommandCompletionEvent, CommandTrb, TransferRequestBlock, TrbLink, TrbRingSegment, TypedTrb, }, registers::DoorbellPointer, }; @@ -20,11 +20,11 @@ struct TrbFutureState { } #[derive(Clone)] -pub struct TrbFuture { +pub struct TrbFuture { state: Arc>>, } -impl TrbFuture { +impl TrbFuture { fn new(paddr: usize) -> Self { Self { state: Arc::new(Mutex::new(TrbFutureState { @@ -36,7 +36,7 @@ impl TrbFuture { } } -impl Future for TrbFuture { +impl Future for TrbFuture { type Output = T; fn poll( @@ -70,14 +70,14 @@ impl TrbPointer { } } -pub struct TrbRing { +pub struct TrbRing { segments: Vec, enqueue_pointer: TrbPointer, cycle_bit: bool, pending_futures: VecDeque>, } -impl TrbRing { +impl TrbRing { pub fn new() -> Self { Self { // TODO: What size and count should this be. @@ -147,17 +147,15 @@ impl TrbRing { } } - pub fn handle_completion(&mut self, completion_trb: T) { - let trb = completion_trb.to_trb(); - let paddr = trb.parameter() as usize; + pub fn handle_completion(&mut self, completion_trb: T, physical_address: usize) { let completion = self.pending_futures.pop_front().unwrap(); let mut completion = completion.state.lock(); // TODO: Handle recovery scenarios here. assert!( - completion.physical_address == paddr, + completion.physical_address == physical_address, "Got an unexpected command completion. Expected: {:0x}, Got: {:0x}", completion.physical_address, - paddr + physical_address ); completion.response = Some(completion_trb); @@ -168,7 +166,7 @@ impl TrbRing { } pub struct CommandRing { - pub trb_ring: TrbRing, + pub trb_ring: TrbRing, doorbell: DoorbellPointer, } @@ -181,8 +179,8 @@ impl CommandRing { } // We have to explicitly return a future her - pub fn enqueue_command(&mut self, command: impl TypedTrb) -> TrbFuture { - let fut = self.trb_ring.enqueue_trb(command.to_trb()); + pub fn enqueue_command(&mut self, command: CommandTrb) -> TrbFuture { + let fut = self.trb_ring.enqueue_trb(command.into()); // Command Doorbell is always 0. self.doorbell.ring(0); fut diff --git a/rust/sys/yellowstone/src/server.rs b/rust/sys/yellowstone/src/server.rs index 8cc4a4b..a6d5fa1 100644 --- a/rust/sys/yellowstone/src/server.rs +++ b/rust/sys/yellowstone/src/server.rs @@ -57,9 +57,8 @@ impl YellowstoneServerContext { pub fn wait(&self, service: &str) -> Result<(), ZError> { loop { - match self.service_map.lock().get(service) { - Some(_) => return Ok(()), - None => {} + if self.service_map.lock().get(service).is_some() { + return Ok(()); } self.registration_semaphore.wait().unwrap(); } diff --git a/scripts/build.sh b/scripts/build.sh index 5cee593..9b64905 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -19,11 +19,11 @@ CARGO_SYS_ROOT="${DIR}/../sysroot/" pushd "${DIR}/../rust" for BIN in ${DIR}/../rust/usr/*/; do - cargo install --offline --force --path "${BIN}" --root $CARGO_USR_ROOT + cargo install --force --path "${BIN}" --root $CARGO_USR_ROOT done for BIN in ${DIR}/../rust/sys/*/; do - cargo install --offline --all-features --force --path "${BIN}" --root $CARGO_SYS_ROOT + cargo install --all-features --force --path "${BIN}" --root $CARGO_SYS_ROOT done popd diff --git a/yunq/rust/src/codegen.rs b/yunq/rust/src/codegen.rs index 7eefb66..9462f4b 100644 --- a/yunq/rust/src/codegen.rs +++ b/yunq/rust/src/codegen.rs @@ -122,7 +122,7 @@ fn parse_field(field: &Field) -> TokenStream { let rep_offset = buf.at::(yunq::message::field_offset(offset, #ind))?; let rep_len = buf.at::(yunq::message::field_offset(offset, #ind) + 4)?; - yunq::message::parse_repeated_message(buf, offset + rep_offset as usize, rep_len as usize, &caps)? + yunq::message::parse_repeated_message(buf, offset + rep_offset as usize, rep_len as usize, caps)? }; }, } @@ -174,7 +174,7 @@ fn generate_serialize(message: &Message) -> TokenStream { &self, buf: &mut yunq::ByteBuffer, offset: usize, - caps: &mut alloc::vec::Vec, + caps: &mut Vec, ) -> Result { let num_fields = #num_fields; let core_size: u32 = (yunq::message::MESSAGE_HEADER_SIZE + 8 * num_fields) as u32; @@ -183,10 +183,10 @@ fn generate_serialize(message: &Message) -> TokenStream { #(#serializers)* - buf.write_at(offset + 0, yunq::message::MESSAGE_IDENT)?; + buf.write_at(offset, yunq::message::MESSAGE_IDENT)?; buf.write_at(offset + 4, core_size)?; buf.write_at(offset + 8, next_extension)?; - buf.write_at(offset + 12, 0 as u32)?; + buf.write_at(offset + 12, 0_u32)?; Ok(next_extension as usize) } } @@ -200,12 +200,12 @@ fn generate_parse(message: &Message) -> TokenStream { fn parse( buf: &yunq::ByteBuffer, offset: usize, - caps: &alloc::vec::Vec, + caps: &[z_cap_t], ) -> Result where Self: Sized, { - if buf.at::(offset + 0)? != yunq::message::MESSAGE_IDENT { + if buf.at::(offset)? != yunq::message::MESSAGE_IDENT { mammoth::debug!("Expected IDENT at offest {:#x}, got {:#x}", offset, buf.at::(offset)?); return Err(ZError::INVALID_ARGUMENT); } @@ -303,7 +303,7 @@ fn generate_server_case(method: &Method) -> TokenStream { #id => { let req = #req::parse_from_request(byte_buffer, cap_buffer)?; let resp = self.handler.#name(req)?; - cap_buffer.resize(0, 0); + cap_buffer.clear(); let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?; Ok(resp_len) }, @@ -312,7 +312,7 @@ fn generate_server_case(method: &Method) -> TokenStream { #id => { let req = #req::parse_from_request(byte_buffer, cap_buffer)?; self.handler.#name(req)?; - cap_buffer.resize(0, 0); + cap_buffer.clear(); // TODO: Implement serialization for EmptyMessage so this is less hacky. yunq::message::serialize_error(byte_buffer, ZError::from(0)); Ok(0x10) @@ -321,7 +321,7 @@ fn generate_server_case(method: &Method) -> TokenStream { (None, Some(_)) => quote! { #id => { let resp = self.handler.#name()?; - cap_buffer.resize(0, 0); + cap_buffer.clear(); let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?; Ok(resp_len) }, @@ -403,7 +403,7 @@ fn generate_async_server_case(method: &Method) -> TokenStream { #id => { let req = #req::parse_from_request(byte_buffer, cap_buffer)?; let resp = self.handler.#name(req).await?; - cap_buffer.resize(0, 0); + cap_buffer.clear(); let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?; Ok(resp_len) }, @@ -412,7 +412,7 @@ fn generate_async_server_case(method: &Method) -> TokenStream { #id => { let req = #req::parse_from_request(byte_buffer, cap_buffer)?; self.handler.#name(req).await?; - cap_buffer.resize(0, 0); + cap_buffer.clear(); // TODO: Implement serialization for EmptyMessage so this is less hacky. yunq::message::serialize_error(byte_buffer, ZError::from(0)); Ok(0x10) @@ -421,7 +421,7 @@ fn generate_async_server_case(method: &Method) -> TokenStream { (None, Some(_)) => quote! { #id => { let resp = self.handler.#name().await?; - cap_buffer.resize(0, 0); + cap_buffer.clear(); let resp_len = resp.serialize_as_request(0, byte_buffer, cap_buffer)?; Ok(resp_len) }, @@ -547,6 +547,7 @@ pub fn generate_code(ast: &[Decl]) -> String { use alloc::vec::Vec; use mammoth::zion::z_cap_t; use mammoth::zion::ZError; + #[allow(unused_imports)] use yunq::ByteBuffer; use yunq::YunqMessage;