⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/fs/
blockdev.rs

1//! Block Device Abstraction
2//!
3//! Provides a common interface for block-level storage devices.
4
5use alloc::vec::Vec;
6
7use crate::error::KernelError;
8
9/// Block device trait
10pub trait BlockDevice: Send + Sync {
11    /// Get device name
12    fn name(&self) -> &str;
13
14    /// Get block size in bytes
15    fn block_size(&self) -> usize;
16
17    /// Get total number of blocks
18    fn block_count(&self) -> u64;
19
20    /// Read blocks from device
21    fn read_blocks(&self, start_block: u64, buffer: &mut [u8]) -> Result<(), KernelError>;
22
23    /// Write blocks to device
24    fn write_blocks(&mut self, start_block: u64, buffer: &[u8]) -> Result<(), KernelError>;
25
26    /// Flush any cached writes
27    fn flush(&mut self) -> Result<(), KernelError> {
28        Ok(()) // Default: no-op
29    }
30}
31
32/// RAM-backed block device (for testing/ramdisk)
33pub struct RamBlockDevice {
34    name: alloc::string::String,
35    block_size: usize,
36    data: Vec<u8>,
37}
38
39impl RamBlockDevice {
40    /// Create a new RAM block device
41    pub fn new(name: alloc::string::String, block_size: usize, block_count: u64) -> Self {
42        let size = block_size * block_count as usize;
43        Self {
44            name,
45            block_size,
46            data: alloc::vec![0u8; size],
47        }
48    }
49
50    /// Get total size in bytes
51    pub fn size(&self) -> usize {
52        self.data.len()
53    }
54}
55
56impl BlockDevice for RamBlockDevice {
57    fn name(&self) -> &str {
58        &self.name
59    }
60
61    fn block_size(&self) -> usize {
62        self.block_size
63    }
64
65    fn block_count(&self) -> u64 {
66        (self.data.len() / self.block_size) as u64
67    }
68
69    fn read_blocks(&self, start_block: u64, buffer: &mut [u8]) -> Result<(), KernelError> {
70        let start_byte = start_block as usize * self.block_size;
71        let end_byte = start_byte + buffer.len();
72
73        if end_byte > self.data.len() {
74            return Err(KernelError::InvalidArgument {
75                name: "block_range",
76                value: "out_of_bounds",
77            });
78        }
79
80        buffer.copy_from_slice(&self.data[start_byte..end_byte]);
81        Ok(())
82    }
83
84    fn write_blocks(&mut self, start_block: u64, buffer: &[u8]) -> Result<(), KernelError> {
85        let start_byte = start_block as usize * self.block_size;
86        let end_byte = start_byte + buffer.len();
87
88        if end_byte > self.data.len() {
89            return Err(KernelError::InvalidArgument {
90                name: "block_range",
91                value: "out_of_bounds",
92            });
93        }
94
95        self.data[start_byte..end_byte].copy_from_slice(buffer);
96        Ok(())
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use alloc::string::String;
103
104    use super::*;
105
106    #[test]
107    fn test_ram_block_device() {
108        let mut dev = RamBlockDevice::new(String::from("test"), 512, 100);
109
110        assert_eq!(dev.block_size(), 512);
111        assert_eq!(dev.block_count(), 100);
112
113        // Write some data
114        let write_data = [0x42u8; 512];
115        dev.write_blocks(0, &write_data).unwrap();
116
117        // Read it back
118        let mut read_data = [0u8; 512];
119        dev.read_blocks(0, &mut read_data).unwrap();
120
121        assert_eq!(read_data, write_data);
122    }
123}