Skip to main content

ax_driver_block/partition/
device.rs

1use super::PartitionRegion;
2use crate::{BaseDriverOps, BlockDriverOps, DevError, DevResult, DeviceType};
3
4pub struct PartitionBlockDevice<T> {
5    inner: T,
6    region: PartitionRegion,
7}
8
9impl<T: BlockDriverOps> PartitionBlockDevice<T> {
10    pub const fn new(inner: T, region: PartitionRegion) -> Self {
11        Self { inner, region }
12    }
13
14    pub const fn region(&self) -> PartitionRegion {
15        self.region
16    }
17
18    fn check_io_bounds(&self, block_id: u64, buf_len: usize) -> DevResult {
19        let block_size = self.inner.block_size();
20        if block_size == 0 || !buf_len.is_multiple_of(block_size) {
21            return Err(DevError::InvalidParam);
22        }
23
24        let blocks = u64::try_from(buf_len / block_size).map_err(|_| DevError::BadState)?;
25        let end_block = block_id.checked_add(blocks).ok_or(DevError::BadState)?;
26        if end_block > self.num_blocks() {
27            return Err(DevError::InvalidParam);
28        }
29
30        Ok(())
31    }
32}
33
34impl<T: BlockDriverOps> BaseDriverOps for PartitionBlockDevice<T> {
35    fn device_name(&self) -> &str {
36        self.inner.device_name()
37    }
38
39    fn device_type(&self) -> DeviceType {
40        self.inner.device_type()
41    }
42
43    fn irq_num(&self) -> Option<usize> {
44        self.inner.irq_num()
45    }
46}
47
48impl<T: BlockDriverOps> BlockDriverOps for PartitionBlockDevice<T> {
49    fn num_blocks(&self) -> u64 {
50        self.region.num_blocks()
51    }
52
53    fn block_size(&self) -> usize {
54        self.inner.block_size()
55    }
56
57    fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> DevResult {
58        self.check_io_bounds(block_id, buf.len())?;
59        self.inner.read_block(self.region.start_lba + block_id, buf)
60    }
61
62    fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DevResult {
63        self.check_io_bounds(block_id, buf.len())?;
64        self.inner
65            .write_block(self.region.start_lba + block_id, buf)
66    }
67
68    fn flush(&mut self) -> DevResult {
69        self.inner.flush()
70    }
71}