1use core::cell::RefCell;
2
3use alloc::{rc::Rc, vec, vec::Vec};
4use embedded_sdmmc::{
5 Block, BlockCount, BlockDevice, BlockIdx, TimeSource, Timestamp, VolumeManager,
6};
7
8use crate::mbr;
9
10#[derive(Default, Clone)]
12pub struct Device {
13 bytes: Rc<RefCell<Vec<u8>>>,
14 resize_chunk: usize,
15 min_len: usize,
16 max_blocks: usize,
17}
18
19impl Device {
20 pub const MIN_SIZE: usize = 2_141_184;
22
23 pub const MAX_SIZE: usize = 2 * 1024 * 1024 * 1024;
25
26 pub fn new(size: usize) -> anyhow::Result<Self> {
28 anyhow::ensure!(
29 Self::MIN_SIZE <= size,
30 "the provided amount of bytes `{size}` is below the lower limit of `{}`",
31 Self::MIN_SIZE
32 );
33
34 anyhow::ensure!(
35 size <= Self::MAX_SIZE,
36 "the provided amount of bytes `{size}` is above the upper limit of `{}`",
37 Self::MAX_SIZE
38 );
39
40 let bytes = mbr::create_mbr_with_fat(size)?;
41
42 Ok(Self {
43 bytes: Rc::new(RefCell::new(bytes)),
44 resize_chunk: 0,
45 min_len: 0,
46 max_blocks: 0,
47 })
48 }
49
50 pub fn try_to_raw_bytes(&self) -> anyhow::Result<Vec<u8>> {
54 Ok(self.bytes.try_borrow()?.clone())
55 }
56
57 pub fn from_raw_bytes_unchecked(bytes: Vec<u8>) -> Self {
61 Self {
62 bytes: Rc::new(RefCell::new(bytes)),
63 resize_chunk: 0,
64 min_len: 0,
65 max_blocks: 0,
66 }
67 }
68
69 pub fn try_to_bytes(&self) -> anyhow::Result<Vec<u8>> {
71 let bytes = self.bytes.try_borrow()?;
72 let mut buffer = vec![0u8; bytes.len() + 24];
73
74 buffer[0..8].copy_from_slice(&(self.resize_chunk as u64).to_le_bytes());
75 buffer[8..16].copy_from_slice(&(self.min_len as u64).to_le_bytes());
76 buffer[16..24].copy_from_slice(&(self.max_blocks as u64).to_le_bytes());
77 buffer[24..].copy_from_slice(&bytes);
78
79 Ok(buffer)
80 }
81
82 pub fn try_from_bytes(buffer: &[u8]) -> anyhow::Result<Self> {
84 anyhow::ensure!(buffer.len() > 24, "buffer is too small.");
85
86 let mut resize_chunk = [0u8; 8];
87 let mut min_len = [0u8; 8];
88 let mut max_blocks = [0u8; 8];
89
90 resize_chunk.copy_from_slice(&buffer[..8]);
91 min_len.copy_from_slice(&buffer[8..16]);
92 max_blocks.copy_from_slice(&buffer[16..24]);
93
94 let bytes = buffer[24..].to_vec();
95
96 Ok(Self {
97 bytes: Rc::new(RefCell::new(bytes)),
98 resize_chunk: u64::from_le_bytes(resize_chunk) as usize,
99 min_len: u64::from_le_bytes(min_len) as usize,
100 max_blocks: u64::from_le_bytes(max_blocks) as usize,
101 })
102 }
103
104 pub fn with_min_len(mut self, min_len: usize) -> Self {
106 self.min_len = min_len;
107 self
108 }
109
110 pub fn with_max_len(mut self, max_len: usize) -> Self {
112 self.max_blocks = max_len / Block::LEN;
113 self
114 }
115
116 pub fn with_resize_chunk(mut self, resize_chunk: usize) -> Self {
118 self.resize_chunk = resize_chunk;
119 self
120 }
121
122 pub fn open(self) -> VolumeManager<Self, Clock> {
124 VolumeManager::new(self, Clock::default())
125 }
126}
127
128impl BlockDevice for Device {
129 type Error = anyhow::Error;
130
131 fn read(
132 &self,
133 blocks: &mut [Block],
134 start_block_idx: BlockIdx,
135 reason: &str,
136 ) -> anyhow::Result<()> {
137 let idx = start_block_idx.0 as usize;
138 let idx = idx
139 .checked_mul(Block::LEN)
140 .ok_or_else(|| anyhow::anyhow!("block idx overflow: {reason}"))?;
141
142 let bytes = self
143 .bytes
144 .try_borrow()
145 .map_err(|e| anyhow::anyhow!("device blocked `{e}`: {reason}"))?;
146
147 for i in 0..blocks.len() {
148 let ofs = idx + i * Block::LEN;
149 let end = ofs + Block::LEN;
150
151 if end <= bytes.len() {
152 blocks[i].contents.copy_from_slice(&bytes[ofs..end]);
153 } else {
154 blocks[i].contents.fill(0);
155 }
156 }
157
158 Ok(())
159 }
160
161 fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> anyhow::Result<()> {
162 let idx = start_block_idx.0 as usize;
163 let idx = idx
164 .checked_mul(Block::LEN)
165 .ok_or_else(|| anyhow::anyhow!("block idx overflow"))?;
166
167 let len = blocks
168 .len()
169 .checked_mul(Block::LEN)
170 .ok_or_else(|| anyhow::anyhow!("block len overflow"))?;
171
172 let last = idx
173 .checked_add(len)
174 .ok_or_else(|| anyhow::anyhow!("block last overflow"))?;
175
176 let mut bytes = self.bytes.try_borrow_mut()?;
177
178 if last > bytes.len() {
179 anyhow::ensure!(
180 self.max_blocks == 0 || last <= self.max_blocks * Block::LEN,
181 "write attempt to overflow maximum length"
182 );
183
184 let last = last.max(self.min_len).max(bytes.len() + self.resize_chunk);
185
186 bytes.resize(last, 0);
187 }
188
189 for i in 0..blocks.len() {
190 let ofs = idx + i * Block::LEN;
191
192 bytes[ofs..ofs + Block::LEN].copy_from_slice(&blocks[i].contents);
193 }
194
195 Ok(())
196 }
197
198 fn num_blocks(&self) -> anyhow::Result<BlockCount> {
199 let len = self.bytes.try_borrow()?.len();
200 let len = len / Block::LEN;
201
202 Ok(BlockCount(len as u32))
203 }
204}
205
206#[derive(Debug)]
210pub struct Clock {
211 ts: RefCell<Timestamp>,
212 def: Timestamp,
213}
214
215impl Default for Clock {
216 fn default() -> Self {
217 let ts = Timestamp::from_calendar(1980, 01, 01, 13, 30, 05).expect("invalid initial ts");
218
219 Self {
220 ts: RefCell::new(ts),
221 def: ts,
222 }
223 }
224}
225
226impl TimeSource for Clock {
227 fn get_timestamp(&self) -> Timestamp {
228 let ts = { self.ts.try_borrow().map(|t| *t).unwrap_or(self.def) };
229
230 {
231 let mut tsp = ts;
232
233 tsp.seconds += 1;
234 if tsp.seconds == 60 {
235 tsp.minutes += 1;
236 tsp.seconds = 0;
237 }
238 if tsp.minutes == 60 {
239 tsp.hours += 1;
240 tsp.minutes = 0;
241 }
242 if tsp.hours == 24 {
243 tsp.zero_indexed_day += 1;
244 tsp.hours = 0;
245 }
246 if tsp.zero_indexed_day == 27 {
247 tsp.zero_indexed_month += 1;
248 tsp.zero_indexed_day = 0;
249 }
250 if tsp.zero_indexed_month == 12 {
251 tsp.year_since_1970 += 1;
252 tsp.zero_indexed_month = 0;
253 }
254
255 if let Ok(mut t) = self.ts.try_borrow_mut() {
256 *t = tsp;
257 }
258 }
259
260 ts
261 }
262}