Skip to main content

proka_kernel/drivers/block/
ramblk.rs

1use crate::drivers::device::{BlockDevice, DeviceError, DeviceType, SharedDeviceOps};
2extern crate alloc;
3use alloc::string::{String, ToString};
4use alloc::vec;
5use alloc::vec::Vec;
6use spin::RwLock;
7
8#[allow(dead_code)]
9pub struct RamBlockDevice {
10    name: String,
11    storage: RwLock<Vec<u8>>,
12    block_size: usize,
13}
14
15impl RamBlockDevice {
16    #[allow(dead_code)]
17    pub fn new(num_blocks: usize, block_size: usize) -> Self {
18        Self {
19            name: "ramdisk".to_string(),
20            storage: RwLock::new(vec![0; num_blocks * block_size]),
21            block_size,
22        }
23    }
24}
25
26impl SharedDeviceOps for RamBlockDevice {
27    fn name(&self) -> &str {
28        &self.name
29    }
30
31    fn device_type(&self) -> DeviceType {
32        DeviceType::Block
33    }
34
35    fn open(&self) -> Result<(), DeviceError> {
36        Ok(())
37    }
38
39    fn close(&self) -> Result<(), DeviceError> {
40        Ok(())
41    }
42
43    fn ioctl(&self, _cmd: u64, _arg: u64) -> Result<u64, DeviceError> {
44        Err(DeviceError::NotSupported)
45    }
46}
47
48impl BlockDevice for RamBlockDevice {
49    fn block_size(&self) -> usize {
50        self.block_size
51    }
52
53    fn num_blocks(&self) -> usize {
54        self.storage.read().len() / self.block_size
55    }
56
57    fn read_blocks(
58        &self,
59        block_idx: usize,
60        num_blocks: usize,
61        buf: &mut [u8],
62    ) -> Result<usize, DeviceError> {
63        let start = block_idx * self.block_size;
64        let end = start + num_blocks * self.block_size;
65        let storage = self.storage.read();
66
67        if end > storage.len() {
68            return Err(DeviceError::AddressOutOfRange);
69        }
70
71        if buf.len() < end - start {
72            return Err(DeviceError::BufferTooSmall);
73        }
74
75        buf[..end - start].copy_from_slice(&storage[start..end]);
76        Ok(num_blocks)
77    }
78
79    fn write_blocks(
80        &self,
81        block_idx: usize,
82        num_blocks: usize,
83        buf: &[u8],
84    ) -> Result<usize, DeviceError> {
85        let start = block_idx * self.block_size;
86        let end = start + num_blocks * self.block_size;
87        let mut storage = self.storage.write();
88
89        if end > storage.len() {
90            return Err(DeviceError::AddressOutOfRange);
91        }
92
93        if buf.len() < end - start {
94            return Err(DeviceError::InvalidParam);
95        }
96
97        storage[start..end].copy_from_slice(&buf[..end - start]);
98        Ok(num_blocks)
99    }
100}