82 lines
2.4 KiB
Rust
82 lines
2.4 KiB
Rust
#![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<CapSlot>)> {
|
|
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<CapSlot> {
|
|
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)
|
|
}
|