#![no_std] #![forbid(unsafe_code)] extern crate alloc; pub mod adapters; pub mod encrypted; pub mod filesystem; pub mod fs; pub mod grants; pub mod protocol; pub mod scope; pub mod server; #[cfg(test)] #[path = "tests/mod.rs"] mod tests; use libkos::syscall; use types::address::VirtualAddress; use types::badge::Badge; use types::bounded::{CapSlot, PageCount}; use types::permission::{Permission, PermissionSet}; /// Client buffers sit high in storage's window, clear of its heap. const BUFFERS_VA: VirtualAddress = VirtualAddress::from_raw(0x0100_0000); const EP: CapSlot = CapSlot::const_new(0); /// Each client's buffer is a region, mapped here and handed to the /// client, which maps the same pages in its own space. Grants are badged /// copies of storage's endpoint. struct Kernel; impl server::Host for Kernel { fn create(&mut self, client: usize) -> Option<(&'static mut [u8], Option)> { let va = VirtualAddress::from_raw(BUFFERS_VA.raw() + client * protocol::BUFFER_SIZE); let region = syscall::create_region(PageCount::new(protocol::BUFFER_PAGES as u16)?).ok()?; // Storage never drops `region`, so the buffer stays mapped. let buf = libkos::window::map_buffer(region, va).ok()?; Some((buf, Some(region))) } fn reclaim(&mut self, buffer: CapSlot) { syscall::revoke(buffer); } /// Call it and pass it on; never Read, which would let the holder /// take other clients' requests. fn mint(&mut self, badge: usize) -> Option { let perms = PermissionSet::empty() .with(Permission::Execute) .with(Permission::Delegate); syscall::mint(EP, Badge::new(badge), perms).ok() } fn revoke(&mut self, grant: CapSlot) { syscall::revoke(grant); syscall::drop_cap(grant); } } pub fn run() -> ! { libkos::println!("storage: started"); let ep = EP; // Init hands over the disk before asking for anything. let Some(device) = libkos::device::receive_device(ep) .mmio .and_then(driver_block_virtio::VirtioBlockDevice::new) else { libkos::println!("storage: no block device, exiting"); syscall::exit(); }; let Some(ext4) = fs::ext4::Ext4::mount(device) else { libkos::println!("storage: no ext4 filesystem it can read, exiting"); syscall::exit(); }; let mut srv = server::StorageServer::new(ext4, Kernel); server_framework::serve(&mut srv, ep) }