33//! Generic code for handling block devices, such as types for identifying
44//! a particular block on a block device by its index.
55
6+ use embedded_storage:: block:: { BlockCount , BlockDevice , BlockIdx } ;
7+
68/// A standard 512 byte block (also known as a sector).
79///
810/// IBM PC formatted 5.25" and 3.5" floppy disks, IDE/SATA Hard Drives up to
911/// about 2 TiB, and almost all SD/MMC cards have 512 byte blocks.
1012///
1113/// This library does not support devices with a block size other than 512
1214/// 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 ;
27-
28- /// Create a new block full of zeros.
29- pub fn new ( ) -> Block {
30- Block {
31- contents : [ 0u8 ; Self :: LEN ] ,
32- }
33- }
34- }
35-
36- impl core:: ops:: Deref for Block {
37- type Target = [ u8 ; 512 ] ;
38- fn deref ( & self ) -> & [ u8 ; 512 ] {
39- & self . contents
40- }
41- }
42-
43- impl core:: ops:: DerefMut for Block {
44- fn deref_mut ( & mut self ) -> & mut [ u8 ; 512 ] {
45- & mut self . contents
46- }
47- }
15+ pub type Block = [ u8 ; BLOCK_LEN ] ;
4816
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- }
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 ;
6921
70- impl Default for Block {
71- fn default ( ) -> Self {
72- Self :: new ( )
73- }
74- }
22+ /// Sometimes we want `LEN` as a `u32` and the casts don't look nice.
23+ pub const BLOCK_LEN_U32 : u32 = 512 ;
7524
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 ;
8827
8928/// A caching layer for block devices
9029///
10443 pub fn new ( block_device : D ) -> BlockCache < D > {
10544 BlockCache {
10645 block_device,
107- block : [ Block :: new ( ) ] ,
46+ block : [ [ 0 ; BLOCK_LEN ] ] ,
10847 block_idx : None ,
10948 }
11049 }
11352 pub fn read ( & mut self , block_idx : BlockIdx ) -> Result < & Block , D :: Error > {
11453 if self . block_idx != Some ( block_idx) {
11554 self . block_idx = None ;
116- self . block_device . read ( & mut self . block , block_idx ) ?;
55+ self . block_device . read ( block_idx , & mut self . block ) ?;
11756 self . block_idx = Some ( block_idx) ;
11857 }
11958 Ok ( & self . block [ 0 ] )
12362 pub fn read_mut ( & mut self , block_idx : BlockIdx ) -> Result < & mut Block , D :: Error > {
12463 if self . block_idx != Some ( block_idx) {
12564 self . block_idx = None ;
126- self . block_device . read ( & mut self . block , block_idx ) ?;
65+ self . block_device . read ( block_idx , & mut self . block ) ?;
12766 self . block_idx = Some ( block_idx) ;
12867 }
12968 Ok ( & mut self . block [ 0 ] )
13271 /// Write back a block you read with [`Self::read_mut`] and then modified.
13372 pub fn write_back ( & mut self ) -> Result < ( ) , D :: Error > {
13473 self . block_device . write (
135- & self . block ,
13674 self . block_idx . expect ( "write_back with no read" ) ,
75+ & self . block ,
13776 )
13877 }
13978
@@ -160,112 +99,36 @@ where
16099 }
161100}
162101
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- }
204- }
205-
206- impl core:: ops:: SubAssign < BlockCount > for BlockIdx {
207- fn sub_assign ( & mut self , rhs : BlockCount ) {
208- self . 0 -= rhs. 0
209- }
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
210107}
211108
212- /// The a number of blocks (or sectors) .
109+ /// How many blocks are required to hold this many bytes .
213110///
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 ) )
269132}
270133
271134/// An iterator returned from `Block::range`.
0 commit comments