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 ;
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 ] ;
48
16
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 ;
69
21
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 ;
75
24
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
}
113
52
pub fn read ( & mut self , block_idx : BlockIdx ) -> Result < & Block , D :: Error > {
114
53
if self . block_idx != Some ( block_idx) {
115
54
self . block_idx = None ;
116
- self . block_device . read ( & mut self . block , block_idx ) ?;
55
+ self . block_device . read ( block_idx , & mut self . block ) ?;
117
56
self . block_idx = Some ( block_idx) ;
118
57
}
119
58
Ok ( & self . block [ 0 ] )
123
62
pub fn read_mut ( & mut self , block_idx : BlockIdx ) -> Result < & mut Block , D :: Error > {
124
63
if self . block_idx != Some ( block_idx) {
125
64
self . block_idx = None ;
126
- self . block_device . read ( & mut self . block , block_idx ) ?;
65
+ self . block_device . read ( block_idx , & mut self . block ) ?;
127
66
self . block_idx = Some ( block_idx) ;
128
67
}
129
68
Ok ( & mut self . block [ 0 ] )
132
71
/// Write back a block you read with [`Self::read_mut`] and then modified.
133
72
pub fn write_back ( & mut self ) -> Result < ( ) , D :: Error > {
134
73
self . block_device . write (
135
- & self . block ,
136
74
self . block_idx . expect ( "write_back with no read" ) ,
75
+ & self . block ,
137
76
)
138
77
}
139
78
@@ -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
- }
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
210
107
}
211
108
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