Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added a NVME FS prototype #192

Merged
merged 20 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ members = [
"src/bin/netmgr",
"src/bin/nettest",
"src/bin/pager",
"src/bin/mnemosyne",
"src/kernel",
"src/lib/twizzler-queue-raw",
"src/lib/twizzler-queue",
Expand All @@ -37,6 +38,7 @@ initrd = [
"crate:netmgr",
"crate:nettest",
"crate:pager",
"crate:mnemosyne",
#"lib:twz-rt",
#"lib:monitor",
#"third-party:hello-world-rs"
Expand Down
24 changes: 24 additions & 0 deletions src/bin/mnemosyne/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[package]
name = "mnemosyne"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
twizzler-abi = { path = "../../lib/twizzler-abi", features = ["runtime"] }
twizzler-net = { path = "../../lib/twizzler-net" }
twizzler-object = { path = "../../lib/twizzler-object" }
twizzler-queue = { path = "../../lib/twizzler-queue" }
twizzler-async = { path = "../../lib/twizzler-async" }
twizzler-driver = { path = "../../lib/twizzler-driver" }
nvme = { path = "../../lib/nvme-rs" }
lethe-gadget-fat = { path = "./fat" }
layout = { path = "./fat/layout" }
tickv = { version = "1.0.0" }
async-trait = "0.1.66"
volatile = "0.5"
pci-ids = "0.2.4"

[package.metadata]
twizzler-build = "static"
1 change: 1 addition & 0 deletions src/bin/mnemosyne/fat
Submodule fat added at 08b5e8
170 changes: 170 additions & 0 deletions src/bin/mnemosyne/src/disk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
use std::{
future,
mem::size_of,
sync::{Arc, Mutex, RwLock},
io::Error, io::ErrorKind
};

use std::io;

use layout::{io::SeekFrom, ApplyLayout, Frame, Read, Seek, Write, IO};
use crate::nvme::{init_nvme, NvmeController};

use twizzler_async::block_on;

use layout::{collections::raw::RawBytes, io::StdIO, Encode, SourcedDynamic};
use lethe_gadget_fat::{
filesystem::FileSystem,
schema::{self, FATEntry, Superblock},
};


pub struct Disk {
ctrl: Arc<NvmeController>,
pub pos: usize,
}

impl Disk {
pub fn new() -> Result<Disk, ()> {
Ok(Disk {
ctrl: block_on(init_nvme()),
pos: 0
})
}
}

pub fn setup(data: &mut Disk) {
let super_block = Superblock {
magic: 0,
block_size: 0x200,
block_count: 0x1000,
};

let fat = vec![FATEntry::None; super_block.block_count as usize].into_boxed_slice();

let mut fs = schema::FileSystem {
super_block: super_block.clone(),
fat,
super_block_cp: super_block,
obj_lookup: vec![FATEntry::None; 3].into_boxed_slice(),
rest: RawBytes,
};

let fs_size = fs.sourced_size();
let reserved_blocks = fs_size / fs.super_block.block_size as u64
+ (fs_size % fs.super_block.block_size as u64).min(1);

fs.fat[0] = FATEntry::Block(reserved_blocks);
fs.fat[1..reserved_blocks as usize].fill(FATEntry::Reserved);
for i in reserved_blocks..fs.super_block.block_count - 1 {
fs.fat[i as usize] = FATEntry::Block(i + 1);
}
fs.fat[fs.super_block.block_count as usize - 1] = FATEntry::None;

fs.encode(data).unwrap();
}

const DISK_SIZE: usize = 0x1000000;
const PAGE_SIZE: usize = 4096;
const SECTOR_SIZE: usize = 512;
const PAGE_SHIFT: usize = 12;
const PAGE_MASK: usize = 0xFFF;
const LBA_COUNT: usize = DISK_SIZE / SECTOR_SIZE;

impl Read for Disk {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let mut lba = (self.pos / PAGE_SIZE) * 8;
let mut bytes_written: usize = 0;
let mut read_buffer: [u8; PAGE_SIZE] = [0; PAGE_SIZE];

while bytes_written != buf.len() {
if lba >= LBA_COUNT {
break;
}

let left = self.pos % PAGE_SIZE;
let right = if buf.len() - bytes_written > PAGE_SIZE {PAGE_SIZE} else {left + buf.len() - bytes_written}; // If I want to write more than the boundary of a page
block_on(self.ctrl.read_page(lba as u64, &mut read_buffer, 0));

for p in left..right {
buf[bytes_written] = read_buffer[p];
bytes_written+=1;
}

self.pos += right - left;
lba += PAGE_SIZE / SECTOR_SIZE;
}

Ok(bytes_written)
}

fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> {
self.read(buf);
Ok(())
}
}

impl Write for Disk {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
let mut lba = (self.pos / PAGE_SIZE) * 8;
let mut bytes_read = 0;
let mut write_buffer: [u8; PAGE_SIZE] = [0; PAGE_SIZE];

while bytes_read != buf.len() {
if lba >= LBA_COUNT {
break;
}

let temp_pos: u64 = self.pos.try_into().unwrap();
self.seek(SeekFrom::Start(temp_pos & !PAGE_MASK as u64));
self.read_exact(&mut write_buffer)?;
self.seek(SeekFrom::Start(temp_pos));

let left = self.pos % PAGE_SIZE;
let right = if left + buf.len() - bytes_read > PAGE_SIZE {PAGE_SIZE} else {left + buf.len() - bytes_read};
for p in left..right {
write_buffer[p] = buf[bytes_read];
bytes_read+=1;
}

self.pos += right - left;

block_on(self.ctrl.write_page(lba as u64, &mut write_buffer, 0));
lba += PAGE_SIZE / SECTOR_SIZE;
}

Ok(bytes_read)
}

fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
self.write(buf);

Ok(())
}

fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}

impl Seek for Disk {
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
let new_pos: i64 = match pos {
SeekFrom::Start(x) => x as i64,
SeekFrom::End(x) => (DISK_SIZE as i64) - x,
SeekFrom::Current(x) => (self.pos as i64) + x,
};

if new_pos > DISK_SIZE.try_into().unwrap() || new_pos < 0 {
Err(Error::new(ErrorKind::AddrInUse, "oh no!"))
}
else {
self.pos = new_pos as usize;
Ok(self.pos.try_into().unwrap())
}
}
}

impl IO for Disk {
type Error = io::Error;
}
59 changes: 59 additions & 0 deletions src/bin/mnemosyne/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
extern crate twizzler_abi;

use std::{
future,
mem::size_of,
sync::{Arc, Mutex, RwLock},
};
use twizzler_async::block_on;
use crate::nvme::{init_nvme, NvmeController};
use twizzler_async::Task;
use twizzler_async::Timer;
use std::time::Duration;

use lethe_gadget_fat::filesystem::FileSystem;

use layout::{Seek, Read, Write, io::SeekFrom};
mod disk;
mod nvme;

use disk::Disk;

pub fn main() {
let command = std::env::args().nth(1).unwrap();
let id = std::env::args().nth(2).unwrap().parse::<u128>().unwrap();
let value = std::env::args().nth(3).unwrap();

let mut d = Disk::new().unwrap();
//disk::setup(&mut d);

let mut fs = FileSystem::<Disk>::open(d);

match command.to_string().as_str() {
"create" => {
fs.create_object(id, 512).unwrap();
fs.write_all(id, value.as_bytes(), 0).unwrap();
println!("Done written {}!", value);
}
"read" => {
let size = value.parse::<usize>().unwrap();
let mut buf = Vec::<u8>::with_capacity(size);
for i in 0..size {
buf.push(0);
}
fs.read_exact(id, &mut buf, 0).unwrap();
println!("str: {:?}", &buf);
println!("str: {:?}", String::from_utf8_lossy(&buf));
}
_ => panic!("Command is invalid")
}

/*let str = "Top military secrets";
fs.create_object(id, 0x20).unwrap();

fs.write_all(id, str.as_bytes(), 0).unwrap();

let mut x: [u8; 20] = [0; 20];
fs.read_exact(id, &mut x, 0).unwrap();*/

}
40 changes: 40 additions & 0 deletions src/bin/mnemosyne/src/nvme.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use core::panic;
use std::sync::Arc;

use twizzler_abi::device::BusType;
use twizzler_driver::{bus::pcie::PcieDeviceInfo, DeviceController};

mod controller;
mod dma;
mod requester;

pub use controller::NvmeController;

pub async fn init_nvme() -> Arc<NvmeController> {
let device_root = twizzler_driver::get_bustree_root();
for device in device_root.children() {
if device.is_bus() && device.bus_type() == BusType::Pcie {
for child in device.children() {
let info = unsafe { child.get_info::<PcieDeviceInfo>(0).unwrap() };
if info.get_data().class == 1
&& info.get_data().subclass == 8
&& info.get_data().progif == 2
{
/*println!(
"found nvme controller {:x}.{:x}.{:x}",
info.get_data().bus_nr,
info.get_data().dev_nr,
info.get_data().func_nr
);*/

let mut ctrl = Arc::new(NvmeController::new(
DeviceController::new_from_device(child),
));
controller::init_controller(&mut ctrl).await;
return ctrl;
}
}
}
}
panic!("no nvme controller found");
}
Loading
Loading