1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//! Device wrappers that implement `rcore_fs::dev::Device`, which can loaded
//! file systems on (e.g. `rcore_fs_sfs::SimpleFileSystem::open()`).

use alloc::sync::Arc;

extern crate rcore_fs;

use kernel_hal::drivers::scheme::BlockScheme;
use lock::RwLock;
use rcore_fs::dev::{BlockDevice, DevError, Device, Result};

/// A naive LRU cache layer for `BlockDevice`, re-exported from `rcore-fs`.
pub use rcore_fs::dev::block_cache::BlockCache;

/// Memory buffer for device.
pub struct MemBuf(RwLock<&'static mut [u8]>);

impl MemBuf {
    /// create a [`MemBuf`] struct.
    pub fn new(buf: &'static mut [u8]) -> Self {
        MemBuf(RwLock::new(buf))
    }
}

impl Device for MemBuf {
    fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result<usize> {
        let slice = self.0.read();
        let len = buf.len().min(slice.len() - offset);
        buf[..len].copy_from_slice(&slice[offset..offset + len]);
        Ok(len)
    }
    fn write_at(&self, offset: usize, buf: &[u8]) -> Result<usize> {
        let mut slice = self.0.write();
        let len = buf.len().min(slice.len() - offset);
        slice[offset..offset + len].copy_from_slice(&buf[..len]);
        Ok(len)
    }
    fn sync(&self) -> Result<()> {
        Ok(())
    }
}

/// Block device implements [`BlockScheme`].
pub struct Block(Arc<dyn BlockScheme>);

impl Block {
    /// create a [`Block`] struct.
    pub fn new(block: Arc<dyn BlockScheme>) -> Self {
        Self(block)
    }
}

impl BlockDevice for Block {
    const BLOCK_SIZE_LOG2: u8 = 9; // 512

    fn read_at(&self, block_id: usize, buf: &mut [u8]) -> Result<()> {
        self.0.read_block(block_id, buf).map_err(|_| DevError)
    }

    fn write_at(&self, block_id: usize, buf: &[u8]) -> Result<()> {
        self.0.write_block(block_id, buf).map_err(|_| DevError)
    }

    fn sync(&self) -> Result<()> {
        self.0.flush().map_err(|_| DevError)
    }
}