Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
bbdc273
fix fatfs to use arc
Koichi98 Jun 12, 2025
58c3daa
add vfs
Koichi98 Jun 13, 2025
5a3b202
asyncfilesystem trait compile success
Koichi98 Jun 16, 2025
3677c8b
init_filesystem WIP
Koichi98 Jun 16, 2025
43e0b03
complete implementing wrapper
Koichi98 Jun 17, 2025
12d3d7d
refactor
Koichi98 Jun 17, 2025
d545165
use AsyncVfsPath
Koichi98 Jun 18, 2025
bbdec4a
cargo fmt
Koichi98 Jun 18, 2025
ef9355d
delete embedded_io_async from Cargo.toml
Koichi98 Jun 18, 2025
2f5860c
fix make test
Koichi98 Jun 18, 2025
762c8ec
delete unneeded struct
Koichi98 Jun 18, 2025
9d12b45
fix error for Vfs
Koichi98 Jun 18, 2025
a642242
fix for test
Koichi98 Jun 18, 2025
344f1de
delete simple_copy() since unneeded
Koichi98 Jun 18, 2025
a48436b
Merge branch 'main' into fatfs_wrapper
Koichi98 Jun 23, 2025
8d633cd
delete comment
Koichi98 Jun 23, 2025
9ed4470
delete comment
Koichi98 Jun 23, 2025
42dc6d5
fix filesystem trait unpin
Koichi98 Jun 25, 2025
9b99ba5
fix fatfs wrapper not to use poll_fn and fix exists,metadata func
Koichi98 Jun 26, 2025
61ce72f
fix
Koichi98 Jun 26, 2025
e94c311
fix
Koichi98 Jun 26, 2025
192745d
add async vfs path
Koichi98 Jun 26, 2025
86da4ad
Merge branch 'main' into feat/async_vfs_path
Koichi98 Jun 26, 2025
0676469
fix for unpin
Koichi98 Jun 27, 2025
aa09abf
fix for unpin
Koichi98 Jun 27, 2025
94cc80b
delete WalkDirIterator related
Koichi98 Jun 27, 2025
a6dbceb
arrange errors
Koichi98 Jun 27, 2025
88808e0
Merge branch 'fix/Vfserror_for_nostd' into feat/async_vfs_path
Koichi98 Jun 28, 2025
b8549ca
merge with feat/async_vfs_path
Koichi98 Jun 28, 2025
4607f36
rename Error to IOError in AsyncFIlesystem
Koichi98 Jun 28, 2025
1b5069f
fix clippy
Koichi98 Jun 28, 2025
40d5e50
fix clippy
Koichi98 Jun 28, 2025
5951930
fix error mapping between FatfsError and VfsError
Koichi98 Jul 1, 2025
8d2933b
fix error handling fatfs
Koichi98 Jul 1, 2025
4295f3f
add trait bound IoError for VfsError,VfsErrorKind
Koichi98 Jul 1, 2025
650839a
merge with main
Koichi98 Jul 1, 2025
5eaa1f7
fix comment
Koichi98 Jul 1, 2025
fb37660
minor fix
Koichi98 Jul 1, 2025
b43d719
delete Fatfs related from path.rs
Koichi98 Jul 1, 2025
f6e6f5d
add trait bound for IoError
Koichi98 Jul 1, 2025
f9ccfae
merge main
Koichi98 Jul 2, 2025
31f0e3e
delete once_cell from Cargo.toml
Koichi98 Jul 2, 2025
79b6c8c
add VfsIoError
Koichi98 Jul 2, 2025
999facd
delete generic E from AsycFs,AsyncVfsPath
Koichi98 Jul 2, 2025
e3d6b48
fix conflict
Koichi98 Jul 2, 2025
8c7a1cc
fix for deleting generic type E from VfsError
Koichi98 Jul 2, 2025
c32ae75
fix
Koichi98 Jul 2, 2025
b87be67
fix
Koichi98 Jul 2, 2025
d74f4ee
Merge branch 'fix/introduce_vfsioerror' into feat/async_vfs_path
Koichi98 Jul 2, 2025
edea2a8
fix comment
Koichi98 Jul 2, 2025
a408137
delete unnecessary changes
Koichi98 Jul 2, 2025
6c8273e
fix clippy
Koichi98 Jul 2, 2025
a3b8250
Merge branch 'main' into feat/async_vfs_path
Koichi98 Jul 3, 2025
dd2457b
fix
Koichi98 Jul 3, 2025
477f0ee
Merge branch 'feat/async_vfs_path' of github.com:tier4/awkernel into …
Koichi98 Jul 3, 2025
437408e
cargo fmt
Koichi98 Jul 3, 2025
480c7e3
fix clippy
Koichi98 Jul 3, 2025
84a7d9b
Merge branch 'feat/async_vfs_path' into fatfs_wrapper
Koichi98 Jul 3, 2025
1e00847
delete empty line
Koichi98 Jul 3, 2025
d196abb
Merge branch 'feat/async_vfs_path' into fatfs_wrapper
Koichi98 Jul 3, 2025
a971c07
delete empty line
Koichi98 Jul 3, 2025
0554156
delete Unpin
Koichi98 Jul 3, 2025
520a2de
merge main
Koichi98 Jul 3, 2025
80e4c3d
fix
Koichi98 Jul 3, 2025
1c47375
fix
Koichi98 Jul 3, 2025
427dd09
add Debug trait
Koichi98 Jul 4, 2025
98a8dba
impl Debug for Filesystem
Koichi98 Jul 4, 2025
df475c9
delete unnecessary change
Koichi98 Jul 4, 2025
6e8dc91
add Debug for fatfs
Koichi98 Jul 4, 2025
2f9f13b
fix error
Koichi98 Jul 4, 2025
bdd1a3a
add init in memory fatfs
Koichi98 Jul 4, 2025
dfdc500
Merge branch 'feat/init_inmemory_fatfs' into fatfs_wrapper
Koichi98 Jul 4, 2025
e3df04f
fix
Koichi98 Jul 4, 2025
bbf950e
Merge branch 'fatfs_wrapper' of github.com:tier4/awkernel into fatfs_…
Koichi98 Jul 4, 2025
a8834df
merge with main
Koichi98 Jul 7, 2025
2b15e1b
fix
Koichi98 Jul 7, 2025
b038bda
Merge branch 'feat/init_inmemory_fatfs' into fatfs_wrapper
Koichi98 Jul 8, 2025
eb4dd56
Merge branch 'main' into fatfs_wrapper
Koichi98 Jul 8, 2025
19100a3
fix comment
Koichi98 Jul 8, 2025
9f4b746
Merge branch 'fatfs_wrapper' of github.com:tier4/awkernel into fatfs_…
Koichi98 Jul 8, 2025
43e41af
fix app
Koichi98 Jul 9, 2025
3110319
refactor
Koichi98 Jul 9, 2025
fbf5a09
Merge branch 'main' into fatfs_wrapper
Koichi98 Jul 22, 2025
f232595
fix clippy
Koichi98 Jul 22, 2025
fe42b71
Merge branch 'main' into fatfs_wrapper
Koichi98 Jul 24, 2025
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
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ QEMU_X86_ARGS+= -numa node,memdev=m0,cpus=0-3,nodeid=0
QEMU_X86_ARGS+= -numa node,memdev=m1,cpus=4-7,nodeid=1
QEMU_X86_ARGS+= -numa node,memdev=m2,cpus=8-11,nodeid=2
QEMU_X86_ARGS+= -numa node,memdev=m3,cpus=12-15,nodeid=3
QEMU_X86_ARGS+= -nographic
# QEMU_X86_ARGS+= -d int # debug interrupt
# QEMU_X86_ARGS+= --trace apic_mem_writel # debug APIC
# QEMU_X86_ARGS+= --trace "e1000e_irq_*" --trace "pci_cfg_*" # debug e1000e and PCI
Expand Down
15 changes: 15 additions & 0 deletions applications/tests/test_memfatfs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "test_memfatfs"
version = "0.1.0"
edition = "2024"

[dependencies]
log = "0.4"

[dependencies.awkernel_async_lib]
path = "../../../awkernel_async_lib"
default-features = false

[dependencies.awkernel_lib]
path = "../../../awkernel_lib"
default-features = false
91 changes: 91 additions & 0 deletions applications/tests/test_memfatfs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#![no_std]

extern crate alloc;

use alloc::vec;
use awkernel_async_lib::file::path::AsyncVfsPath;
use awkernel_lib::file::fatfs::init_memory_fatfs;

pub async fn run() {
awkernel_async_lib::spawn(
"test fatfs".into(),
memfatfs_test(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;
}

async fn memfatfs_test() {
// TODO - Remove this when the filesystem is fully ready. This will be done in the kernel initialization.
match init_memory_fatfs() {
Ok(_) => log::info!("In-memory FAT filesystem initialized successfully."),
Err(e) => {
log::error!("Failed to initialize in-memory FAT filesystem: {e:?}");
return;
}
}

let root_path = AsyncVfsPath::new_in_memory_fatfs();
let file_name = "test.txt";
let data_to_write = b"Hello from the in-memory FAT filesystem!";
let bytes_written;

let file_path = root_path.join(file_name).unwrap();
log::info!("Attempting to create and write to file '{file_name}'");

match file_path.create_file().await {
Ok(mut file) => match file.write(data_to_write).await {
Ok(len) => {
bytes_written = len;
log::info!("Successfully wrote {bytes_written} bytes to '{file_name}'.");
}
Err(e) => {
log::error!("Failed to write to file '{file_name}': {e:?}");
return;
}
},
Err(e) => {
log::error!("Failed to create file '{file_name}': {e:?}");
return;
}
};

log::info!("Attempting to open and read from file '{file_name}'");
if bytes_written == 0 {
log::warn!("No bytes were written, skipping file read operation.");
return;
}

match file_path.open_file().await {
Ok(mut file) => {
let mut read_buffer = vec![0; bytes_written];
match file.read(&mut read_buffer).await {
Ok(bytes_read) => {
log::info!("Successfully read {bytes_read} bytes from '{file_name}'.");
if bytes_read != bytes_written {
log::warn!(
"Bytes read ({bytes_read}) does not match bytes written ({bytes_written})."
);
}

match core::str::from_utf8(&read_buffer[..bytes_read]) {
Ok(s) => log::info!("Content of '{file_name}': \"{s}\""),
Err(_) => log::warn!(
"Content of '{}' is not valid UTF-8. Raw bytes: {:?}",
file_name,
&read_buffer[..bytes_read]
),
}
}
Err(e) => {
log::error!("Failed to read from file '{file_name}': {e:?}");
}
}
}
Err(e) => {
log::error!("Failed to open file '{file_name}': {e:?}");
}
}

log::info!("FAT filesystem test completed.");
}
1 change: 1 addition & 0 deletions awkernel_async_lib/src/file.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod fatfs;
pub mod filesystem;
pub mod path;
255 changes: 255 additions & 0 deletions awkernel_async_lib/src/file/fatfs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
use super::filesystem::{AsyncFileSystem, AsyncSeekAndRead, AsyncSeekAndWrite};
use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
use async_trait::async_trait;
use awkernel_lib::{
file::{
fatfs::{
error::Error,
file::File,
fs::{FileSystem, LossyOemCpConverter, OemCpConverter, ReadWriteSeek},
get_memory_fatfs,
time::{Date, DateTime, NullTimeProvider, TimeProvider},
},
io::{Read, Seek, SeekFrom, Write},
memfs::InMemoryDisk,
vfs::{
error::{VfsError, VfsErrorKind, VfsIoError, VfsResult},
path::{VfsFileType, VfsMetadata},
},
},
sync::{mcs::MCSNode, mutex::Mutex},
time::Time,
};
use core::fmt::Debug;
use futures::stream::{self, Stream};

struct AsyncFile<IO, TP, OCC>
where
IO: ReadWriteSeek + Send + Debug + Sync,
TP: TimeProvider + Send + Sync,
OCC: OemCpConverter + Send + Sync,
{
file: Mutex<File<IO, TP, OCC>>,
}

#[async_trait]
impl<IO, TP, OCC> AsyncSeekAndRead for AsyncFile<IO, TP, OCC>
where
IO: ReadWriteSeek + Send + Sync + Debug,
IO::Error: Into<VfsIoError>,
TP: TimeProvider + Send + Sync,
OCC: OemCpConverter + Send + Sync,
{
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, VfsError> {
let mut node = MCSNode::new();
let mut file_guard = self.file.lock(&mut node);
(*file_guard)
.read(buf)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))
}

async fn seek(&mut self, pos: SeekFrom) -> Result<u64, VfsError> {
let mut node = MCSNode::new();
let mut file_guard = self.file.lock(&mut node);
(*file_guard)
.seek(pos)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))
}
}

#[async_trait]
impl<IO, TP, OCC> AsyncSeekAndWrite for AsyncFile<IO, TP, OCC>
where
IO: ReadWriteSeek + Send + Debug + Sync,
IO::Error: Into<VfsIoError>,
TP: TimeProvider + Send + Sync,
OCC: OemCpConverter + Send + Sync,
{
async fn write(&mut self, buf: &[u8]) -> Result<usize, VfsError> {
let mut node = MCSNode::new();
let mut file_guard = self.file.lock(&mut node);
(*file_guard)
.write(buf)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))
}

async fn write_all(&mut self, buf: &[u8]) -> Result<(), VfsError> {
let mut node = MCSNode::new();
let mut file_guard = self.file.lock(&mut node);
(*file_guard)
.write_all(buf)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))
}

async fn flush(&mut self) -> Result<(), VfsError> {
let mut node = MCSNode::new();
let mut file_guard = self.file.lock(&mut node);
(*file_guard)
.flush()
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))
}

async fn seek(&mut self, pos: SeekFrom) -> Result<u64, VfsError> {
<Self as AsyncSeekAndRead>::seek(self, pos).await
}
}

#[derive(Debug)]
pub struct AsyncFatFs<IO, TP, OCC>
where
IO: ReadWriteSeek + Send + Sync + Debug,
TP: TimeProvider + Send + Sync,
OCC: OemCpConverter + Send + Sync,
{
fs: Arc<FileSystem<IO, TP, OCC>>,
}

impl AsyncFatFs<InMemoryDisk, NullTimeProvider, LossyOemCpConverter> {
pub fn new_in_memory() -> Self {
Self {
fs: get_memory_fatfs(),
}
}
}

#[async_trait]
impl<IO, TP, OCC> AsyncFileSystem for AsyncFatFs<IO, TP, OCC>
where
IO: ReadWriteSeek + Send + Sync + Debug + 'static,
IO::Error: Into<VfsIoError>,
TP: TimeProvider + Send + Sync + 'static,
OCC: OemCpConverter + Send + Sync + 'static,
{
async fn read_dir(
&self,
path: &str,
) -> VfsResult<Box<dyn Unpin + Stream<Item = String> + Send>> {
let dir = FileSystem::root_dir(&self.fs)
.open_dir(path)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))?;
let entries: Result<Vec<String>, _> = dir
.iter()
.map(|entry_res| {
entry_res
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))
.map(|entry| entry.file_name())
})
.collect();
entries.map(|names| {
Box::new(stream::iter(names)) as Box<dyn Unpin + Stream<Item = String> + Send>
})
}

async fn create_dir(&self, path: &str) -> VfsResult<()> {
FileSystem::root_dir(&self.fs)
.create_dir(path)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))?;
Ok(())
}

async fn open_file(&self, path: &str) -> VfsResult<Box<dyn AsyncSeekAndRead + Send + Unpin>> {
let file = FileSystem::root_dir(&self.fs)
.open_file(path)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))?;

Ok(Box::new(AsyncFile {
file: Mutex::new(file),
}))
}

async fn create_file(
&self,
path: &str,
) -> VfsResult<Box<dyn AsyncSeekAndWrite + Send + Unpin>> {
let file = FileSystem::root_dir(&self.fs)
.create_file(path)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))?;

Ok(Box::new(AsyncFile {
file: Mutex::new(file),
}))
}

async fn append_file(
&self,
path: &str,
) -> VfsResult<Box<dyn AsyncSeekAndWrite + Send + Unpin>> {
let file = {
let result: Result<File<IO, TP, OCC>, Error<IO::Error>> = (|| {
let mut file = FileSystem::root_dir(&self.fs).open_file(path)?;
file.seek(SeekFrom::End(0))?;
Ok(file)
})();
result
}
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))?;

Ok(Box::new(AsyncFile {
file: Mutex::new(file),
}))
}

async fn metadata(&self, path: &str) -> VfsResult<VfsMetadata> {
if path.is_empty() {
return Ok(VfsMetadata {
file_type: VfsFileType::Directory,
len: 0,
created: None,
modified: None,
accessed: None,
});
}
let entry = FileSystem::root_dir(&self.fs)
.find_entry(path, None, None)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))?;
let metadata = VfsMetadata {
file_type: if entry.is_dir() {
VfsFileType::Directory
} else {
VfsFileType::File
},
len: entry.len(),
created: to_vfs_datetime(entry.created()),
modified: to_vfs_datetime(entry.modified()),
accessed: to_vfs_date(entry.accessed()),
};
Ok(metadata)
}

async fn exists(&self, path: &str) -> VfsResult<bool> {
if path.is_empty() {
return Ok(true);
}
Ok(FileSystem::root_dir(&self.fs)
.find_entry(path, None, None)
.is_ok())
}

async fn remove_file(&self, path: &str) -> VfsResult<()> {
FileSystem::root_dir(&self.fs)
.remove(path)
.map_err(|e| VfsError::from(VfsErrorKind::from(e)))?;

Ok(())
}

async fn remove_dir(&self, path: &str) -> VfsResult<()> {
self.remove_file(path).await
}
}

fn to_vfs_datetime(_date_time: DateTime) -> Option<Time> {
// TODO - Currently, we use NullTimeProvider which does not provide actual time.
// Once we implement a proper time provider, we can convert DateTime to Time.
// For now, we return None to indicate that the conversion is not implemented.
// This is a placeholder for the actual implementation.
todo!()
}

fn to_vfs_date(_date: Date) -> Option<Time> {
// TODO - Currently, we use NullTimeProvider which does not provide actual time.
// Once we implement a proper time provider, we can convert DateTime to Time.
// For now, we return None to indicate that the conversion is not implemented.
// This is a placeholder for the actual implementation.
None
}
8 changes: 8 additions & 0 deletions awkernel_async_lib/src/file/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//! different VirtualFileSystem implementations (i.e. an in memory implementation for unit tests)

use super::filesystem::{AsyncFileSystem, AsyncSeekAndRead, AsyncSeekAndWrite};
use crate::file::fatfs::AsyncFatFs;
use awkernel_lib::{
file::vfs::{
error::{VfsError, VfsErrorKind, VfsResult},
Expand Down Expand Up @@ -53,6 +54,13 @@ impl PartialEq for AsyncVfsPath {

impl Eq for AsyncVfsPath {}

impl AsyncVfsPath {
pub fn new_in_memory_fatfs() -> Self {
let fs = AsyncFatFs::new_in_memory();
AsyncVfsPath::from(Box::new(fs) as Box<dyn AsyncFileSystem>)
}
}

impl AsyncVfsPath {
/// Creates a root path for the given filesystem
pub fn new(filesystem: Box<dyn AsyncFileSystem + Send + Sync>) -> Self {
Expand Down
Loading