ax_driver_block/partition/
device.rs1use 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}