| 
3 | 3 | //! Generic code for handling block devices, such as types for identifying  | 
4 | 4 | //! a particular block on a block device by its index.  | 
5 | 5 | 
  | 
 | 6 | +use embedded_storage::block::{BlockCount, BlockDevice, BlockIdx};  | 
 | 7 | + | 
6 | 8 | /// A standard 512 byte block (also known as a sector).  | 
7 | 9 | ///  | 
8 | 10 | /// IBM PC formatted 5.25" and 3.5" floppy disks, IDE/SATA Hard Drives up to  | 
9 | 11 | /// about 2 TiB, and almost all SD/MMC cards have 512 byte blocks.  | 
10 | 12 | ///  | 
11 | 13 | /// This library does not support devices with a block size other than 512  | 
12 | 14 | /// bytes.  | 
13 |  | -#[derive(Clone)]  | 
14 |  | -pub struct Block {  | 
15 |  | -    /// The 512 bytes in this block (or sector).  | 
16 |  | -    pub contents: [u8; Block::LEN],  | 
17 |  | -}  | 
18 |  | - | 
19 |  | -impl Block {  | 
20 |  | -    /// All our blocks are a fixed length of 512 bytes. We do not support  | 
21 |  | -    /// 'Advanced Format' Hard Drives with 4 KiB blocks, nor weird old  | 
22 |  | -    /// pre-3.5-inch floppy disk formats.  | 
23 |  | -    pub const LEN: usize = 512;  | 
24 |  | - | 
25 |  | -    /// Sometimes we want `LEN` as a `u32` and the casts don't look nice.  | 
26 |  | -    pub const LEN_U32: u32 = 512;  | 
 | 15 | +pub type Block = [u8; BLOCK_LEN];  | 
27 | 16 | 
 
  | 
28 |  | -    /// Create a new block full of zeros.  | 
29 |  | -    pub fn new() -> Block {  | 
30 |  | -        Block {  | 
31 |  | -            contents: [0u8; Self::LEN],  | 
32 |  | -        }  | 
33 |  | -    }  | 
34 |  | -}  | 
 | 17 | +/// All our blocks are a fixed length of 512 bytes. We do not support  | 
 | 18 | +/// 'Advanced Format' Hard Drives with 4 KiB blocks, nor weird old  | 
 | 19 | +/// pre-3.5-inch floppy disk formats.  | 
 | 20 | +pub const BLOCK_LEN: usize = 512;  | 
35 | 21 | 
 
  | 
36 |  | -impl core::ops::Deref for Block {  | 
37 |  | -    type Target = [u8; 512];  | 
38 |  | -    fn deref(&self) -> &[u8; 512] {  | 
39 |  | -        &self.contents  | 
40 |  | -    }  | 
41 |  | -}  | 
 | 22 | +/// Sometimes we want `LEN` as a `u32` and the casts don't look nice.  | 
 | 23 | +pub const BLOCK_LEN_U32: u32 = 512;  | 
42 | 24 | 
 
  | 
43 |  | -impl core::ops::DerefMut for Block {  | 
44 |  | -    fn deref_mut(&mut self) -> &mut [u8; 512] {  | 
45 |  | -        &mut self.contents  | 
46 |  | -    }  | 
47 |  | -}  | 
48 |  | - | 
49 |  | -impl core::fmt::Debug for Block {  | 
50 |  | -    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {  | 
51 |  | -        writeln!(fmt, "Block:")?;  | 
52 |  | -        for line in self.contents.chunks(32) {  | 
53 |  | -            for b in line {  | 
54 |  | -                write!(fmt, "{:02x}", b)?;  | 
55 |  | -            }  | 
56 |  | -            write!(fmt, " ")?;  | 
57 |  | -            for &b in line {  | 
58 |  | -                if (0x20..=0x7F).contains(&b) {  | 
59 |  | -                    write!(fmt, "{}", b as char)?;  | 
60 |  | -                } else {  | 
61 |  | -                    write!(fmt, ".")?;  | 
62 |  | -                }  | 
63 |  | -            }  | 
64 |  | -            writeln!(fmt)?;  | 
65 |  | -        }  | 
66 |  | -        Ok(())  | 
67 |  | -    }  | 
68 |  | -}  | 
69 |  | - | 
70 |  | -impl Default for Block {  | 
71 |  | -    fn default() -> Self {  | 
72 |  | -        Self::new()  | 
73 |  | -    }  | 
74 |  | -}  | 
75 |  | - | 
76 |  | -/// A block device - a device which can read and write blocks (or  | 
77 |  | -/// sectors). Only supports devices which are <= 2 TiB in size.  | 
78 |  | -pub trait BlockDevice {  | 
79 |  | -    /// The errors that the `BlockDevice` can return. Must be debug formattable.  | 
80 |  | -    type Error: core::fmt::Debug;  | 
81 |  | -    /// Read one or more blocks, starting at the given block index.  | 
82 |  | -    fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>;  | 
83 |  | -    /// Write one or more blocks, starting at the given block index.  | 
84 |  | -    fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>;  | 
85 |  | -    /// Determine how many blocks this device can hold.  | 
86 |  | -    fn num_blocks(&self) -> Result<BlockCount, Self::Error>;  | 
87 |  | -}  | 
 | 25 | +/// Sometimes we want `LEN` as a `u64` and the casts don't look nice.  | 
 | 26 | +pub const BLOCK_LEN_U64: u64 = 512;  | 
88 | 27 | 
 
  | 
89 | 28 | /// A caching layer for block devices  | 
90 | 29 | ///  | 
 | 
104 | 43 |     pub fn new(block_device: D) -> BlockCache<D> {  | 
105 | 44 |         BlockCache {  | 
106 | 45 |             block_device,  | 
107 |  | -            block: [Block::new()],  | 
 | 46 | +            block: [[0; BLOCK_LEN]],  | 
108 | 47 |             block_idx: None,  | 
109 | 48 |         }  | 
110 | 49 |     }  | 
@@ -160,112 +99,36 @@ where  | 
160 | 99 |     }  | 
161 | 100 | }  | 
162 | 101 | 
 
  | 
163 |  | -/// The linear numeric address of a block (or sector).  | 
164 |  | -///  | 
165 |  | -/// The first block on a disk gets `BlockIdx(0)` (which usually contains the  | 
166 |  | -/// Master Boot Record).  | 
167 |  | -#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]  | 
168 |  | -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]  | 
169 |  | -pub struct BlockIdx(pub u32);  | 
170 |  | - | 
171 |  | -impl BlockIdx {  | 
172 |  | -    /// Convert a block index into a 64-bit byte offset from the start of the  | 
173 |  | -    /// volume. Useful if your underlying block device actually works in  | 
174 |  | -    /// bytes, like `open("/dev/mmcblk0")` does on Linux.  | 
175 |  | -    pub fn into_bytes(self) -> u64 {  | 
176 |  | -        (u64::from(self.0)) * (Block::LEN as u64)  | 
177 |  | -    }  | 
178 |  | - | 
179 |  | -    /// Create an iterator from the current `BlockIdx` through the given  | 
180 |  | -    /// number of blocks.  | 
181 |  | -    pub fn range(self, num: BlockCount) -> BlockIter {  | 
182 |  | -        BlockIter::new(self, self + BlockCount(num.0))  | 
183 |  | -    }  | 
184 |  | -}  | 
185 |  | - | 
186 |  | -impl core::ops::Add<BlockCount> for BlockIdx {  | 
187 |  | -    type Output = BlockIdx;  | 
188 |  | -    fn add(self, rhs: BlockCount) -> BlockIdx {  | 
189 |  | -        BlockIdx(self.0 + rhs.0)  | 
190 |  | -    }  | 
191 |  | -}  | 
192 |  | - | 
193 |  | -impl core::ops::AddAssign<BlockCount> for BlockIdx {  | 
194 |  | -    fn add_assign(&mut self, rhs: BlockCount) {  | 
195 |  | -        self.0 += rhs.0  | 
196 |  | -    }  | 
197 |  | -}  | 
198 |  | - | 
199 |  | -impl core::ops::Sub<BlockCount> for BlockIdx {  | 
200 |  | -    type Output = BlockIdx;  | 
201 |  | -    fn sub(self, rhs: BlockCount) -> BlockIdx {  | 
202 |  | -        BlockIdx(self.0 - rhs.0)  | 
203 |  | -    }  | 
 | 102 | +/// Convert a block index into a 64-bit byte offset from the start of the  | 
 | 103 | +/// volume. Useful if your underlying block device actually works in  | 
 | 104 | +/// bytes, like `open("/dev/mmcblk0")` does on Linux.  | 
 | 105 | +pub fn block_index_into_bytes(block_index: BlockIdx) -> u64 {  | 
 | 106 | +    block_index.0 * BLOCK_LEN_U64  | 
204 | 107 | }  | 
205 | 108 | 
 
  | 
206 |  | -impl core::ops::SubAssign<BlockCount> for BlockIdx {  | 
207 |  | -    fn sub_assign(&mut self, rhs: BlockCount) {  | 
208 |  | -        self.0 -= rhs.0  | 
209 |  | -    }  | 
210 |  | -}  | 
211 |  | - | 
212 |  | -/// The a number of blocks (or sectors).  | 
 | 109 | +/// How many blocks are required to hold this many bytes.  | 
213 | 110 | ///  | 
214 |  | -/// Add this to a `BlockIdx` to get an actual address on disk.  | 
215 |  | -#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]  | 
216 |  | -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]  | 
217 |  | -pub struct BlockCount(pub u32);  | 
218 |  | - | 
219 |  | -impl core::ops::Add<BlockCount> for BlockCount {  | 
220 |  | -    type Output = BlockCount;  | 
221 |  | -    fn add(self, rhs: BlockCount) -> BlockCount {  | 
222 |  | -        BlockCount(self.0 + rhs.0)  | 
223 |  | -    }  | 
224 |  | -}  | 
225 |  | - | 
226 |  | -impl core::ops::AddAssign<BlockCount> for BlockCount {  | 
227 |  | -    fn add_assign(&mut self, rhs: BlockCount) {  | 
228 |  | -        self.0 += rhs.0  | 
229 |  | -    }  | 
230 |  | -}  | 
231 |  | - | 
232 |  | -impl core::ops::Sub<BlockCount> for BlockCount {  | 
233 |  | -    type Output = BlockCount;  | 
234 |  | -    fn sub(self, rhs: BlockCount) -> BlockCount {  | 
235 |  | -        BlockCount(self.0 - rhs.0)  | 
236 |  | -    }  | 
237 |  | -}  | 
238 |  | - | 
239 |  | -impl core::ops::SubAssign<BlockCount> for BlockCount {  | 
240 |  | -    fn sub_assign(&mut self, rhs: BlockCount) {  | 
241 |  | -        self.0 -= rhs.0  | 
242 |  | -    }  | 
243 |  | -}  | 
244 |  | - | 
245 |  | -impl BlockCount {  | 
246 |  | -    /// How many blocks are required to hold this many bytes.  | 
247 |  | -    ///  | 
248 |  | -    /// ```  | 
249 |  | -    /// # use embedded_sdmmc::BlockCount;  | 
250 |  | -    /// assert_eq!(BlockCount::from_bytes(511), BlockCount(1));  | 
251 |  | -    /// assert_eq!(BlockCount::from_bytes(512), BlockCount(1));  | 
252 |  | -    /// assert_eq!(BlockCount::from_bytes(513), BlockCount(2));  | 
253 |  | -    /// assert_eq!(BlockCount::from_bytes(1024), BlockCount(2));  | 
254 |  | -    /// assert_eq!(BlockCount::from_bytes(1025), BlockCount(3));  | 
255 |  | -    /// ```  | 
256 |  | -    pub const fn from_bytes(byte_count: u32) -> BlockCount {  | 
257 |  | -        let mut count = byte_count / Block::LEN_U32;  | 
258 |  | -        if (count * Block::LEN_U32) != byte_count {  | 
259 |  | -            count += 1;  | 
260 |  | -        }  | 
261 |  | -        BlockCount(count)  | 
262 |  | -    }  | 
263 |  | - | 
264 |  | -    /// Take a number of blocks and increment by the integer number of blocks  | 
265 |  | -    /// required to get to the block that holds the byte at the given offset.  | 
266 |  | -    pub fn offset_bytes(self, offset: u32) -> Self {  | 
267 |  | -        BlockCount(self.0 + (offset / Block::LEN_U32))  | 
268 |  | -    }  | 
 | 111 | +/// ```  | 
 | 112 | +/// # use embedded_sdmmc::blockdevice::{block_count_from_bytes};  | 
 | 113 | +/// # use embedded_storage::block::BlockCount;  | 
 | 114 | +/// assert_eq!(block_count_from_bytes(511), BlockCount(1));  | 
 | 115 | +/// assert_eq!(block_count_from_bytes(512), BlockCount(1));  | 
 | 116 | +/// assert_eq!(block_count_from_bytes(513), BlockCount(2));  | 
 | 117 | +/// assert_eq!(block_count_from_bytes(1024), BlockCount(2));  | 
 | 118 | +/// assert_eq!(block_count_from_bytes(1025), BlockCount(3));  | 
 | 119 | +/// ```  | 
 | 120 | +pub const fn block_count_from_bytes(byte_count: u64) -> BlockCount {  | 
 | 121 | +    let mut count = byte_count / BLOCK_LEN_U64;  | 
 | 122 | +    if (count * BLOCK_LEN_U64) != byte_count {  | 
 | 123 | +        count += 1;  | 
 | 124 | +    }  | 
 | 125 | +    BlockCount(count)  | 
 | 126 | +}  | 
 | 127 | + | 
 | 128 | +/// Take a number of blocks and increment by the integer number of blocks  | 
 | 129 | +/// required to get to the block that holds the byte at the given offset.  | 
 | 130 | +pub fn block_count_offset_bytes(base: BlockCount, offset: u64) -> BlockCount {  | 
 | 131 | +    BlockCount(base.0 + (offset / BLOCK_LEN_U64))  | 
269 | 132 | }  | 
270 | 133 | 
 
  | 
271 | 134 | /// An iterator returned from `Block::range`.  | 
 | 
0 commit comments