From 48890b0abdef9bbac6f7f259a0e148a3f34d3bdf Mon Sep 17 00:00:00 2001 From: Andrew Walbran Date: Tue, 29 Oct 2024 17:32:07 +0000 Subject: [PATCH] Use embedded-storage BlockDevice trait. This will allow both the SD card driver and the FAT32 implementation to be used with filesystem or block device drivers respectively. --- Cargo.toml | 1 + examples/linux/mod.rs | 26 +-- src/blockdevice.rs | 221 +++++-------------------- src/fat/bpb.rs | 11 +- src/fat/volume.rs | 158 ++++++++++-------- src/filesystem/directory.rs | 9 +- src/filesystem/files.rs | 28 +++- src/lib.rs | 9 +- src/sdcard/mod.rs | 51 +++--- src/volume_mgr.rs | 317 ++++++++++++++++++------------------ tests/utils/mod.rs | 26 +-- 11 files changed, 405 insertions(+), 452 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 45276c1..0b45a68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ byteorder = {version = "1", default-features = false} defmt = {version = "0.3", optional = true} embedded-hal = "1.0.0" embedded-io = "0.6.1" +embedded-storage = { git = "https://github.com/qwandor/embedded-storage", branch = "block" } heapless = "^0.8" log = {version = "0.4", default-features = false, optional = true} diff --git a/examples/linux/mod.rs b/examples/linux/mod.rs index 6eefe23..22a0967 100644 --- a/examples/linux/mod.rs +++ b/examples/linux/mod.rs @@ -1,7 +1,9 @@ //! Helpers for using embedded-sdmmc on Linux use chrono::Timelike; -use embedded_sdmmc::{Block, BlockCount, BlockDevice, BlockIdx, TimeSource, Timestamp}; +use embedded_sdmmc::{ + blockdevice::BLOCK_LEN_U64, Block, BlockCount, BlockDevice, BlockIdx, TimeSource, Timestamp, +}; use std::cell::RefCell; use std::fs::{File, OpenOptions}; use std::io::prelude::*; @@ -34,25 +36,29 @@ impl LinuxBlockDevice { impl BlockDevice for LinuxBlockDevice { type Error = std::io::Error; - fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> { + fn read( + &mut self, + first_block_index: BlockIdx, + blocks: &mut [Block], + ) -> Result<(), Self::Error> { self.file .borrow_mut() - .seek(SeekFrom::Start(start_block_idx.into_bytes()))?; + .seek(SeekFrom::Start(first_block_index.0 * BLOCK_LEN_U64))?; for block in blocks.iter_mut() { - self.file.borrow_mut().read_exact(&mut block.contents)?; + self.file.borrow_mut().read_exact(block)?; if self.print_blocks { - println!("Read block {:?}: {:?}", start_block_idx, &block); + println!("Read block {:?}: {:?}", first_block_index, &block); } } Ok(()) } - fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> { + fn write(&mut self, first_block_index: BlockIdx, blocks: &[Block]) -> Result<(), Self::Error> { self.file .borrow_mut() - .seek(SeekFrom::Start(start_block_idx.into_bytes()))?; + .seek(SeekFrom::Start(first_block_index.0 * BLOCK_LEN_U64))?; for block in blocks.iter() { - self.file.borrow_mut().write_all(&block.contents)?; + self.file.borrow_mut().write_all(block)?; if self.print_blocks { println!("Wrote: {:?}", &block); } @@ -60,9 +66,9 @@ impl BlockDevice for LinuxBlockDevice { Ok(()) } - fn num_blocks(&self) -> Result { + fn block_count(&self) -> Result { let num_blocks = self.file.borrow().metadata().unwrap().len() / 512; - Ok(BlockCount(num_blocks as u32)) + Ok(BlockCount(num_blocks)) } } diff --git a/src/blockdevice.rs b/src/blockdevice.rs index 618eda2..d309e02 100644 --- a/src/blockdevice.rs +++ b/src/blockdevice.rs @@ -3,6 +3,8 @@ //! Generic code for handling block devices, such as types for identifying //! a particular block on a block device by its index. +use embedded_storage::block::{BlockCount, BlockDevice, BlockIdx}; + /// A standard 512 byte block (also known as a sector). /// /// IBM PC formatted 5.25" and 3.5" floppy disks, IDE/SATA Hard Drives up to @@ -10,81 +12,18 @@ /// /// This library does not support devices with a block size other than 512 /// bytes. -#[derive(Clone)] -pub struct Block { - /// The 512 bytes in this block (or sector). - pub contents: [u8; Block::LEN], -} - -impl Block { - /// All our blocks are a fixed length of 512 bytes. We do not support - /// 'Advanced Format' Hard Drives with 4 KiB blocks, nor weird old - /// pre-3.5-inch floppy disk formats. - pub const LEN: usize = 512; - - /// Sometimes we want `LEN` as a `u32` and the casts don't look nice. - pub const LEN_U32: u32 = 512; - - /// Create a new block full of zeros. - pub fn new() -> Block { - Block { - contents: [0u8; Self::LEN], - } - } -} - -impl core::ops::Deref for Block { - type Target = [u8; 512]; - fn deref(&self) -> &[u8; 512] { - &self.contents - } -} - -impl core::ops::DerefMut for Block { - fn deref_mut(&mut self) -> &mut [u8; 512] { - &mut self.contents - } -} +pub type Block = [u8; BLOCK_LEN]; -impl core::fmt::Debug for Block { - fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { - writeln!(fmt, "Block:")?; - for line in self.contents.chunks(32) { - for b in line { - write!(fmt, "{:02x}", b)?; - } - write!(fmt, " ")?; - for &b in line { - if (0x20..=0x7F).contains(&b) { - write!(fmt, "{}", b as char)?; - } else { - write!(fmt, ".")?; - } - } - writeln!(fmt)?; - } - Ok(()) - } -} +/// All our blocks are a fixed length of 512 bytes. We do not support +/// 'Advanced Format' Hard Drives with 4 KiB blocks, nor weird old +/// pre-3.5-inch floppy disk formats. +pub const BLOCK_LEN: usize = 512; -impl Default for Block { - fn default() -> Self { - Self::new() - } -} +/// Sometimes we want `LEN` as a `u32` and the casts don't look nice. +pub const BLOCK_LEN_U32: u32 = 512; -/// A block device - a device which can read and write blocks (or -/// sectors). Only supports devices which are <= 2 TiB in size. -pub trait BlockDevice { - /// The errors that the `BlockDevice` can return. Must be debug formattable. - type Error: core::fmt::Debug; - /// Read one or more blocks, starting at the given block index. - fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>; - /// Write one or more blocks, starting at the given block index. - fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error>; - /// Determine how many blocks this device can hold. - fn num_blocks(&self) -> Result; -} +/// Sometimes we want `LEN` as a `u64` and the casts don't look nice. +pub const BLOCK_LEN_U64: u64 = 512; /// A caching layer for block devices /// @@ -104,7 +43,7 @@ where pub fn new(block_device: D) -> BlockCache { BlockCache { block_device, - block: [Block::new()], + block: [[0; BLOCK_LEN]], block_idx: None, } } @@ -113,7 +52,7 @@ where pub fn read(&mut self, block_idx: BlockIdx) -> Result<&Block, D::Error> { if self.block_idx != Some(block_idx) { self.block_idx = None; - self.block_device.read(&mut self.block, block_idx)?; + self.block_device.read(block_idx, &mut self.block)?; self.block_idx = Some(block_idx); } Ok(&self.block[0]) @@ -123,7 +62,7 @@ where pub fn read_mut(&mut self, block_idx: BlockIdx) -> Result<&mut Block, D::Error> { if self.block_idx != Some(block_idx) { self.block_idx = None; - self.block_device.read(&mut self.block, block_idx)?; + self.block_device.read(block_idx, &mut self.block)?; self.block_idx = Some(block_idx); } Ok(&mut self.block[0]) @@ -132,8 +71,8 @@ where /// Write back a block you read with [`Self::read_mut`] and then modified. pub fn write_back(&mut self) -> Result<(), D::Error> { self.block_device.write( - &self.block, self.block_idx.expect("write_back with no read"), + &self.block, ) } @@ -160,112 +99,36 @@ where } } -/// The linear numeric address of a block (or sector). -/// -/// The first block on a disk gets `BlockIdx(0)` (which usually contains the -/// Master Boot Record). -#[cfg_attr(feature = "defmt-log", derive(defmt::Format))] -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct BlockIdx(pub u32); - -impl BlockIdx { - /// Convert a block index into a 64-bit byte offset from the start of the - /// volume. Useful if your underlying block device actually works in - /// bytes, like `open("/dev/mmcblk0")` does on Linux. - pub fn into_bytes(self) -> u64 { - (u64::from(self.0)) * (Block::LEN as u64) - } - - /// Create an iterator from the current `BlockIdx` through the given - /// number of blocks. - pub fn range(self, num: BlockCount) -> BlockIter { - BlockIter::new(self, self + BlockCount(num.0)) - } -} - -impl core::ops::Add for BlockIdx { - type Output = BlockIdx; - fn add(self, rhs: BlockCount) -> BlockIdx { - BlockIdx(self.0 + rhs.0) - } -} - -impl core::ops::AddAssign for BlockIdx { - fn add_assign(&mut self, rhs: BlockCount) { - self.0 += rhs.0 - } -} - -impl core::ops::Sub for BlockIdx { - type Output = BlockIdx; - fn sub(self, rhs: BlockCount) -> BlockIdx { - BlockIdx(self.0 - rhs.0) - } -} - -impl core::ops::SubAssign for BlockIdx { - fn sub_assign(&mut self, rhs: BlockCount) { - self.0 -= rhs.0 - } +/// Convert a block index into a 64-bit byte offset from the start of the +/// volume. Useful if your underlying block device actually works in +/// bytes, like `open("/dev/mmcblk0")` does on Linux. +pub fn block_index_into_bytes(block_index: BlockIdx) -> u64 { + block_index.0 * BLOCK_LEN_U64 } -/// The a number of blocks (or sectors). +/// How many blocks are required to hold this many bytes. /// -/// Add this to a `BlockIdx` to get an actual address on disk. -#[cfg_attr(feature = "defmt-log", derive(defmt::Format))] -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct BlockCount(pub u32); - -impl core::ops::Add for BlockCount { - type Output = BlockCount; - fn add(self, rhs: BlockCount) -> BlockCount { - BlockCount(self.0 + rhs.0) - } -} - -impl core::ops::AddAssign for BlockCount { - fn add_assign(&mut self, rhs: BlockCount) { - self.0 += rhs.0 - } -} - -impl core::ops::Sub for BlockCount { - type Output = BlockCount; - fn sub(self, rhs: BlockCount) -> BlockCount { - BlockCount(self.0 - rhs.0) - } -} - -impl core::ops::SubAssign for BlockCount { - fn sub_assign(&mut self, rhs: BlockCount) { - self.0 -= rhs.0 - } -} - -impl BlockCount { - /// How many blocks are required to hold this many bytes. - /// - /// ``` - /// # use embedded_sdmmc::BlockCount; - /// assert_eq!(BlockCount::from_bytes(511), BlockCount(1)); - /// assert_eq!(BlockCount::from_bytes(512), BlockCount(1)); - /// assert_eq!(BlockCount::from_bytes(513), BlockCount(2)); - /// assert_eq!(BlockCount::from_bytes(1024), BlockCount(2)); - /// assert_eq!(BlockCount::from_bytes(1025), BlockCount(3)); - /// ``` - pub const fn from_bytes(byte_count: u32) -> BlockCount { - let mut count = byte_count / Block::LEN_U32; - if (count * Block::LEN_U32) != byte_count { - count += 1; - } - BlockCount(count) - } - - /// Take a number of blocks and increment by the integer number of blocks - /// required to get to the block that holds the byte at the given offset. - pub fn offset_bytes(self, offset: u32) -> Self { - BlockCount(self.0 + (offset / Block::LEN_U32)) - } +/// ``` +/// # use embedded_sdmmc::blockdevice::{block_count_from_bytes}; +/// # use embedded_storage::block::BlockCount; +/// assert_eq!(block_count_from_bytes(511), BlockCount(1)); +/// assert_eq!(block_count_from_bytes(512), BlockCount(1)); +/// assert_eq!(block_count_from_bytes(513), BlockCount(2)); +/// assert_eq!(block_count_from_bytes(1024), BlockCount(2)); +/// assert_eq!(block_count_from_bytes(1025), BlockCount(3)); +/// ``` +pub const fn block_count_from_bytes(byte_count: u64) -> BlockCount { + let mut count = byte_count / BLOCK_LEN_U64; + if (count * BLOCK_LEN_U64) != byte_count { + count += 1; + } + BlockCount(count) +} + +/// Take a number of blocks and increment by the integer number of blocks +/// required to get to the block that holds the byte at the given offset. +pub fn block_count_offset_bytes(base: BlockCount, offset: u64) -> BlockCount { + BlockCount(base.0 + (offset / BLOCK_LEN_U64)) } /// An iterator returned from `Block::range`. diff --git a/src/fat/bpb.rs b/src/fat/bpb.rs index c7e83b6..5cee2db 100644 --- a/src/fat/bpb.rs +++ b/src/fat/bpb.rs @@ -1,10 +1,11 @@ //! Boot Parameter Block use crate::{ - blockdevice::BlockCount, + blockdevice::block_count_from_bytes, fat::{FatType, OnDiskDirEntry}, }; use byteorder::{ByteOrder, LittleEndian}; +use embedded_storage::block::BlockCount; /// A Boot Parameter Block. /// @@ -30,8 +31,10 @@ impl<'a> Bpb<'a> { return Err("Bad BPB footer"); } - let root_dir_blocks = - BlockCount::from_bytes(u32::from(bpb.root_entries_count()) * OnDiskDirEntry::LEN_U32).0; + let root_dir_blocks = block_count_from_bytes( + u64::from(bpb.root_entries_count()) * u64::from(OnDiskDirEntry::LEN_U32), + ) + .0 as u32; let non_data_blocks = u32::from(bpb.reserved_block_count()) + (u32::from(bpb.num_fats()) * bpb.fat_size()) + root_dir_blocks; @@ -101,7 +104,7 @@ impl<'a> Bpb<'a> { pub fn fs_info_block(&self) -> Option { match self.fat_type { FatType::Fat16 => None, - FatType::Fat32 => Some(BlockCount(u32::from(self.fs_info()))), + FatType::Fat32 => Some(BlockCount(self.fs_info().into())), } } diff --git a/src/fat/volume.rs b/src/fat/volume.rs index 5d8307d..65b1b2c 100644 --- a/src/fat/volume.rs +++ b/src/fat/volume.rs @@ -1,17 +1,19 @@ //! FAT-specific volume support. use crate::{ + blockdevice::{block_count_from_bytes, block_count_offset_bytes, BLOCK_LEN, BLOCK_LEN_U32}, debug, fat::{ Bpb, Fat16Info, Fat32Info, FatSpecificInfo, FatType, InfoSector, OnDiskDirEntry, RESERVED_ENTRIES, }, filesystem::FilenameError, - trace, warn, Attributes, Block, BlockCache, BlockCount, BlockDevice, BlockIdx, ClusterId, - DirEntry, DirectoryInfo, Error, LfnBuffer, ShortFileName, TimeSource, VolumeType, + trace, warn, Attributes, BlockCache, BlockCount, BlockIdx, ClusterId, DirEntry, DirectoryInfo, + Error, LfnBuffer, ShortFileName, TimeSource, VolumeType, }; use byteorder::{ByteOrder, LittleEndian}; -use core::convert::TryFrom; +use core::{convert::TryFrom, fmt::Debug}; +use embedded_storage::block::BlockDevice; /// An MS-DOS 11 character volume label. /// @@ -167,6 +169,7 @@ impl FatVolume { ) -> Result<(), Error> where D: BlockDevice, + D::Error: Debug, { match &self.fat_specific_info { FatSpecificInfo::Fat16(_) => { @@ -178,7 +181,7 @@ impl FatVolume { } trace!("Reading info sector"); let block = block_cache - .read_mut(fat32_info.info_location) + .read_mut(fat32_info.info_location.into()) .map_err(Error::DeviceError)?; if let Some(count) = self.free_clusters_count { block[488..492].copy_from_slice(&count.to_le_bytes()); @@ -210,16 +213,18 @@ impl FatVolume { ) -> Result<(), Error> where D: BlockDevice, + D::Error: Debug, { let this_fat_block_num; match &self.fat_specific_info { FatSpecificInfo::Fat16(_fat16_info) => { let fat_offset = cluster.0 * 2; - this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset); - let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize; + this_fat_block_num = + self.lba_start + block_count_offset_bytes(self.fat_start, fat_offset.into()); + let this_fat_ent_offset = (fat_offset % BLOCK_LEN_U32) as usize; trace!("Reading FAT for update"); let block = block_cache - .read_mut(this_fat_block_num) + .read_mut(this_fat_block_num.into()) .map_err(Error::DeviceError)?; // See let entry = match new_value { @@ -237,11 +242,12 @@ impl FatVolume { FatSpecificInfo::Fat32(_fat32_info) => { // FAT32 => 4 bytes per entry let fat_offset = cluster.0 * 4; - this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset); - let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize; + this_fat_block_num = + self.lba_start + block_count_offset_bytes(self.fat_start, fat_offset.into()); + let this_fat_ent_offset = (fat_offset % BLOCK_LEN_U32) as usize; trace!("Reading FAT for update"); let block = block_cache - .read_mut(this_fat_block_num) + .read_mut(this_fat_block_num.into()) .map_err(Error::DeviceError)?; let entry = match new_value { ClusterId::INVALID => 0x0FFF_FFF6, @@ -271,6 +277,7 @@ impl FatVolume { ) -> Result> where D: BlockDevice, + D::Error: Debug, { if cluster.0 > (u32::MAX / 4) { panic!("next_cluster called on invalid cluster {:x?}", cluster); @@ -278,10 +285,11 @@ impl FatVolume { match &self.fat_specific_info { FatSpecificInfo::Fat16(_fat16_info) => { let fat_offset = cluster.0 * 2; - let this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset); - let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize; + let this_fat_block_num = + self.lba_start + block_count_offset_bytes(self.fat_start, fat_offset.into()); + let this_fat_ent_offset = (fat_offset % BLOCK_LEN_U32) as usize; trace!("Walking FAT"); - let block = block_cache.read(this_fat_block_num)?; + let block = block_cache.read(this_fat_block_num.into())?; let fat_entry = LittleEndian::read_u16(&block[this_fat_ent_offset..=this_fat_ent_offset + 1]); match fat_entry { @@ -301,10 +309,11 @@ impl FatVolume { } FatSpecificInfo::Fat32(_fat32_info) => { let fat_offset = cluster.0 * 4; - let this_fat_block_num = self.lba_start + self.fat_start.offset_bytes(fat_offset); - let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize; + let this_fat_block_num = + self.lba_start + block_count_offset_bytes(self.fat_start, fat_offset.into()); + let this_fat_ent_offset = (fat_offset % BLOCK_LEN_U32) as usize; trace!("Walking FAT"); - let block = block_cache.read(this_fat_block_num)?; + let block = block_cache.read(this_fat_block_num.into())?; let fat_entry = LittleEndian::read_u32(&block[this_fat_ent_offset..=this_fat_ent_offset + 3]) & 0x0FFF_FFFF; @@ -332,7 +341,7 @@ impl FatVolume { /// Number of bytes in a cluster. pub(crate) fn bytes_per_cluster(&self) -> u32 { - u32::from(self.blocks_per_cluster) * Block::LEN_U32 + u32::from(self.blocks_per_cluster) * BLOCK_LEN_U32 } /// Converts a cluster number (or `Cluster`) to a block number (or @@ -346,7 +355,7 @@ impl FatVolume { ClusterId(c) => { // FirstSectorofCluster = ((N – 2) * BPB_SecPerClus) + FirstDataSector; let first_block_of_cluster = - BlockCount((c - 2) * u32::from(self.blocks_per_cluster)); + BlockCount((u64::from(c) - 2) * u64::from(self.blocks_per_cluster)); self.first_data_block + first_block_of_cluster } }; @@ -359,7 +368,7 @@ impl FatVolume { }; // FirstSectorofCluster = ((N – 2) * BPB_SecPerClus) + FirstDataSector; let first_block_of_cluster = - BlockCount((cluster_num - 2) * u32::from(self.blocks_per_cluster)); + BlockCount((u64::from(cluster_num) - 2) * u64::from(self.blocks_per_cluster)); self.lba_start + self.first_data_block + first_block_of_cluster } } @@ -377,6 +386,7 @@ impl FatVolume { ) -> Result> where D: BlockDevice, + D::Error: Debug, T: TimeSource, { match &self.fat_specific_info { @@ -394,9 +404,9 @@ impl FatVolume { ClusterId::ROOT_DIR => { let len_bytes = u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32; - BlockCount::from_bytes(len_bytes) + block_count_from_bytes(len_bytes.into()) } - _ => BlockCount(u32::from(self.blocks_per_cluster)), + _ => BlockCount(u64::from(self.blocks_per_cluster)), }; // Walk the directory @@ -404,7 +414,7 @@ impl FatVolume { for block_idx in first_dir_block_num.range(dir_size) { trace!("Reading directory"); let block = block_cache - .read_mut(block_idx) + .read_mut(block_idx.into()) .map_err(Error::DeviceError)?; for (i, dir_entry_bytes) in block.chunks_exact_mut(OnDiskDirEntry::LEN).enumerate() @@ -457,7 +467,7 @@ impl FatVolume { }; let mut first_dir_block_num = self.cluster_to_block(dir_cluster); - let dir_size = BlockCount(u32::from(self.blocks_per_cluster)); + let dir_size = BlockCount(self.blocks_per_cluster.into()); // Walk the cluster chain until we run out of clusters while let Some(cluster) = current_cluster { // Loop through the blocks in the cluster @@ -465,7 +475,7 @@ impl FatVolume { // Read a block of directory entries trace!("Reading directory"); let block = block_cache - .read_mut(block_idx) + .read_mut(block_idx.into()) .map_err(Error::DeviceError)?; // Are any entries in the block we just loaded blank? If so // we can use them. @@ -525,6 +535,7 @@ impl FatVolume { where F: FnMut(&DirEntry), D: BlockDevice, + D::Error: Debug, { match &self.fat_specific_info { FatSpecificInfo::Fat16(fat16_info) => { @@ -550,6 +561,7 @@ impl FatVolume { where F: FnMut(&DirEntry, Option<&str>), D: BlockDevice, + D::Error: Debug, { #[derive(Clone, Copy)] enum SeqState { @@ -657,6 +669,7 @@ impl FatVolume { where F: for<'odde> FnMut(&DirEntry, &OnDiskDirEntry<'odde>), D: BlockDevice, + D::Error: Debug, { // Root directories on FAT16 have a fixed size, because they use // a specially reserved space on disk (see @@ -670,22 +683,22 @@ impl FatVolume { let dir_size = match dir_info.cluster { ClusterId::ROOT_DIR => { let len_bytes = u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32; - BlockCount::from_bytes(len_bytes) + block_count_from_bytes(len_bytes.into()) } - _ => BlockCount(u32::from(self.blocks_per_cluster)), + _ => BlockCount(self.blocks_per_cluster.into()), }; while let Some(cluster) = current_cluster { for block_idx in first_dir_block_num.range(dir_size) { trace!("Reading FAT"); - let block = block_cache.read(block_idx)?; + let block = block_cache.read(block_idx.into())?; for (i, dir_entry_bytes) in block.chunks_exact(OnDiskDirEntry::LEN).enumerate() { let dir_entry = OnDiskDirEntry::new(dir_entry_bytes); if dir_entry.is_end() { // Can quit early return Ok(()); } else if dir_entry.is_valid() { - // Safe, since Block::LEN always fits on a u32 + // Safe, since BLOCK_LEN always fits on a u32 let start = (i * OnDiskDirEntry::LEN) as u32; let entry = dir_entry.get_entry(FatType::Fat16, block_idx, start); func(&entry, &dir_entry); @@ -717,6 +730,7 @@ impl FatVolume { where F: for<'odde> FnMut(&DirEntry, &OnDiskDirEntry<'odde>), D: BlockDevice, + D::Error: Debug, { // All directories on FAT32 have a cluster chain but the root // dir starts in a specified cluster. @@ -726,16 +740,18 @@ impl FatVolume { }; while let Some(cluster) = current_cluster { let start_block_idx = self.cluster_to_block(cluster); - for block_idx in start_block_idx.range(BlockCount(u32::from(self.blocks_per_cluster))) { + for block_idx in start_block_idx.range(BlockCount(self.blocks_per_cluster.into())) { trace!("Reading FAT"); - let block = block_cache.read(block_idx).map_err(Error::DeviceError)?; + let block = block_cache + .read(block_idx.into()) + .map_err(Error::DeviceError)?; for (i, dir_entry_bytes) in block.chunks_exact(OnDiskDirEntry::LEN).enumerate() { let dir_entry = OnDiskDirEntry::new(dir_entry_bytes); if dir_entry.is_end() { // Can quit early return Ok(()); } else if dir_entry.is_valid() { - // Safe, since Block::LEN always fits on a u32 + // Safe, since BLOCK_LEN always fits on a u32 let start = (i * OnDiskDirEntry::LEN) as u32; let entry = dir_entry.get_entry(FatType::Fat32, block_idx, start); func(&entry, &dir_entry); @@ -759,6 +775,7 @@ impl FatVolume { ) -> Result> where D: BlockDevice, + D::Error: Debug, { match &self.fat_specific_info { FatSpecificInfo::Fat16(fat16_info) => { @@ -775,9 +792,9 @@ impl FatVolume { ClusterId::ROOT_DIR => { let len_bytes = u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32; - BlockCount::from_bytes(len_bytes) + block_count_from_bytes(len_bytes.into()) } - _ => BlockCount(u32::from(self.blocks_per_cluster)), + _ => BlockCount(self.blocks_per_cluster.into()), }; while let Some(cluster) = current_cluster { @@ -813,7 +830,7 @@ impl FatVolume { }; while let Some(cluster) = current_cluster { let block_idx = self.cluster_to_block(cluster); - for block in block_idx.range(BlockCount(u32::from(self.blocks_per_cluster))) { + for block in block_idx.range(BlockCount(self.blocks_per_cluster.into())) { match self.find_entry_in_block( block_cache, FatType::Fat32, @@ -844,9 +861,12 @@ impl FatVolume { ) -> Result> where D: BlockDevice, + D::Error: Debug, { trace!("Reading directory"); - let block = block_cache.read(block_idx).map_err(Error::DeviceError)?; + let block = block_cache + .read(block_idx.into()) + .map_err(Error::DeviceError)?; for (i, dir_entry_bytes) in block.chunks_exact(OnDiskDirEntry::LEN).enumerate() { let dir_entry = OnDiskDirEntry::new(dir_entry_bytes); if dir_entry.is_end() { @@ -854,7 +874,7 @@ impl FatVolume { break; } else if dir_entry.matches(match_name) { // Found it - // Block::LEN always fits on a u32 + // BLOCK_LEN always fits on a u32 let start = (i * OnDiskDirEntry::LEN) as u32; return Ok(dir_entry.get_entry(fat_type, block_idx, start)); } @@ -871,6 +891,7 @@ impl FatVolume { ) -> Result<(), Error> where D: BlockDevice, + D::Error: Debug, { match &self.fat_specific_info { FatSpecificInfo::Fat16(fat16_info) => { @@ -887,9 +908,9 @@ impl FatVolume { ClusterId::ROOT_DIR => { let len_bytes = u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32; - BlockCount::from_bytes(len_bytes) + block_count_from_bytes(len_bytes.into()) } - _ => BlockCount(u32::from(self.blocks_per_cluster)), + _ => BlockCount(self.blocks_per_cluster.into()), }; // Walk the directory @@ -934,7 +955,7 @@ impl FatVolume { // Scan the cluster a block at a time let start_block_idx = self.cluster_to_block(cluster); for block_idx in - start_block_idx.range(BlockCount(u32::from(self.blocks_per_cluster))) + start_block_idx.range(BlockCount(self.blocks_per_cluster.into())) { match self.delete_entry_in_block(block_cache, match_name, block_idx) { Err(Error::NotFound) => { @@ -974,10 +995,11 @@ impl FatVolume { ) -> Result<(), Error> where D: BlockDevice, + D::Error: Debug, { trace!("Reading directory"); let block = block_cache - .read_mut(block_idx) + .read_mut(block_idx.into()) .map_err(Error::DeviceError)?; for (i, dir_entry_bytes) in block.chunks_exact_mut(OnDiskDirEntry::LEN).enumerate() { let dir_entry = OnDiskDirEntry::new(dir_entry_bytes); @@ -1004,6 +1026,7 @@ impl FatVolume { ) -> Result> where D: BlockDevice, + D::Error: Debug, { let mut current_cluster = start_cluster; match &self.fat_specific_info { @@ -1016,16 +1039,16 @@ impl FatVolume { ); let fat_offset = current_cluster.0 * 2; trace!("fat_offset = {:?}", fat_offset); - let this_fat_block_num = - self.lba_start + self.fat_start.offset_bytes(fat_offset); + let this_fat_block_num = self.lba_start + + block_count_offset_bytes(self.fat_start, fat_offset.into()); trace!("this_fat_block_num = {:?}", this_fat_block_num); - let mut this_fat_ent_offset = usize::try_from(fat_offset % Block::LEN_U32) + let mut this_fat_ent_offset = usize::try_from(fat_offset % BLOCK_LEN_U32) .map_err(|_| Error::ConversionError)?; trace!("Reading block {:?}", this_fat_block_num); let block = block_cache - .read(this_fat_block_num) + .read(this_fat_block_num.into()) .map_err(Error::DeviceError)?; - while this_fat_ent_offset <= Block::LEN - 2 { + while this_fat_ent_offset <= BLOCK_LEN - 2 { let fat_entry = LittleEndian::read_u16( &block[this_fat_ent_offset..=this_fat_ent_offset + 1], ); @@ -1046,16 +1069,16 @@ impl FatVolume { ); let fat_offset = current_cluster.0 * 4; trace!("fat_offset = {:?}", fat_offset); - let this_fat_block_num = - self.lba_start + self.fat_start.offset_bytes(fat_offset); + let this_fat_block_num = self.lba_start + + block_count_offset_bytes(self.fat_start, fat_offset.into()); trace!("this_fat_block_num = {:?}", this_fat_block_num); - let mut this_fat_ent_offset = usize::try_from(fat_offset % Block::LEN_U32) + let mut this_fat_ent_offset = usize::try_from(fat_offset % BLOCK_LEN_U32) .map_err(|_| Error::ConversionError)?; trace!("Reading block {:?}", this_fat_block_num); let block = block_cache - .read(this_fat_block_num) + .read(this_fat_block_num.into()) .map_err(Error::DeviceError)?; - while this_fat_ent_offset <= Block::LEN - 4 { + while this_fat_ent_offset <= BLOCK_LEN - 4 { let fat_entry = LittleEndian::read_u32( &block[this_fat_ent_offset..=this_fat_ent_offset + 3], ) & 0x0FFF_FFFF; @@ -1081,6 +1104,7 @@ impl FatVolume { ) -> Result> where D: BlockDevice, + D::Error: Debug, { debug!("Allocating new cluster, prev_cluster={:?}", prev_cluster); let end_cluster = ClusterId(self.cluster_count + RESERVED_ENTRIES); @@ -1140,14 +1164,14 @@ impl FatVolume { *number_free_cluster -= 1; }; if zero { - let blocks = [Block::new()]; + let blocks = [[0; BLOCK_LEN]]; let start_block_idx = self.cluster_to_block(new_cluster); - let num_blocks = BlockCount(u32::from(self.blocks_per_cluster)); + let num_blocks = BlockCount(self.blocks_per_cluster.into()); for block_idx in start_block_idx.range(num_blocks) { trace!("Zeroing cluster"); block_cache .block_device() - .write(&blocks, block_idx) + .write(block_idx.into(), &blocks) .map_err(Error::DeviceError)?; } } @@ -1163,6 +1187,7 @@ impl FatVolume { ) -> Result<(), Error> where D: BlockDevice, + D::Error: Debug, { if cluster.0 < RESERVED_ENTRIES { // file doesn't have any valid cluster allocated, there is nothing to do @@ -1210,6 +1235,7 @@ impl FatVolume { ) -> Result<(), Error> where D: BlockDevice, + D::Error: Debug, { let fat_type = match self.fat_specific_info { FatSpecificInfo::Fat16(_) => FatType::Fat16, @@ -1217,7 +1243,7 @@ impl FatVolume { }; trace!("Reading directory for update"); let block = block_cache - .read_mut(entry.entry_block) + .read_mut(entry.entry_block.into()) .map_err(Error::DeviceError)?; let start = usize::try_from(entry.entry_offset).map_err(|_| Error::ConversionError)?; @@ -1241,21 +1267,23 @@ where D::Error: core::fmt::Debug, { trace!("Reading BPB"); - let block = block_cache.read(lba_start).map_err(Error::DeviceError)?; + let block = block_cache + .read(lba_start.into()) + .map_err(Error::DeviceError)?; let bpb = Bpb::create_from_bytes(block).map_err(Error::FormatError)?; match bpb.fat_type { FatType::Fat16 => { - if bpb.bytes_per_block() as usize != Block::LEN { + if bpb.bytes_per_block() as usize != BLOCK_LEN { return Err(Error::BadBlockSize(bpb.bytes_per_block())); } // FirstDataSector = BPB_ResvdSecCnt + (BPB_NumFATs * FATSz) + RootDirSectors; let root_dir_blocks = ((u32::from(bpb.root_entries_count()) * OnDiskDirEntry::LEN_U32) - + (Block::LEN_U32 - 1)) - / Block::LEN_U32; - let fat_start = BlockCount(u32::from(bpb.reserved_block_count())); + + (BLOCK_LEN_U32 - 1)) + / BLOCK_LEN_U32; + let fat_start = BlockCount(bpb.reserved_block_count().into()); let first_root_dir_block = - fat_start + BlockCount(u32::from(bpb.num_fats()) * bpb.fat_size()); - let first_data_block = first_root_dir_block + BlockCount(root_dir_blocks); + fat_start + BlockCount(u64::from(bpb.num_fats()) * u64::from(bpb.fat_size())); + let first_data_block = first_root_dir_block + BlockCount(root_dir_blocks.into()); let volume = FatVolume { lba_start, num_blocks, @@ -1264,7 +1292,7 @@ where }, blocks_per_cluster: bpb.blocks_per_cluster(), first_data_block: (first_data_block), - fat_start: BlockCount(u32::from(bpb.reserved_block_count())), + fat_start: BlockCount(bpb.reserved_block_count().into()), free_clusters_count: None, next_free_cluster: None, cluster_count: bpb.total_clusters(), @@ -1289,8 +1317,8 @@ where contents: bpb.volume_label(), }, blocks_per_cluster: bpb.blocks_per_cluster(), - first_data_block: BlockCount(first_data_block), - fat_start: BlockCount(u32::from(bpb.reserved_block_count())), + first_data_block: BlockCount(first_data_block.into()), + fat_start: BlockCount(bpb.reserved_block_count().into()), free_clusters_count: None, next_free_cluster: None, cluster_count: bpb.total_clusters(), @@ -1303,7 +1331,7 @@ where // Now we don't need the BPB, update the volume with data from the info sector trace!("Reading info block"); let info_block = block_cache - .read(lba_start + info_location) + .read((lba_start + info_location).into()) .map_err(Error::DeviceError)?; let info_sector = InfoSector::create_from_bytes(info_block).map_err(Error::FormatError)?; diff --git a/src/filesystem/directory.rs b/src/filesystem/directory.rs index 527807b..03e8eb0 100644 --- a/src/filesystem/directory.rs +++ b/src/filesystem/directory.rs @@ -1,7 +1,8 @@ -use crate::blockdevice::BlockIdx; use crate::fat::{FatType, OnDiskDirEntry}; use crate::filesystem::{Attributes, ClusterId, Handle, LfnBuffer, ShortFileName, Timestamp}; use crate::{Error, RawVolume, VolumeManager}; +use core::fmt::Debug; +use embedded_storage::block::BlockIdx; use super::ToShortFileName; @@ -61,6 +62,7 @@ impl RawDirectory { ) -> Directory where D: crate::BlockDevice, + D::Error: Debug, T: crate::TimeSource, { Directory::new(self, volume_mgr) @@ -84,6 +86,7 @@ pub struct Directory< const MAX_VOLUMES: usize, > where D: crate::BlockDevice, + D::Error: Debug, T: crate::TimeSource, { raw_directory: RawDirectory, @@ -94,6 +97,7 @@ impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: Directory<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> where D: crate::BlockDevice, + D::Error: Debug, T: crate::TimeSource, { /// Create a new `Directory` from a `RawDirectory` @@ -241,6 +245,7 @@ impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: for Directory<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> where D: crate::BlockDevice, + D::Error: Debug, T: crate::TimeSource, { fn drop(&mut self) { @@ -252,6 +257,7 @@ impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: core::fmt::Debug for Directory<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> where D: crate::BlockDevice, + D::Error: Debug, T: crate::TimeSource, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -264,6 +270,7 @@ impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: defmt::Format for Directory<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> where D: crate::BlockDevice, + D::Error: Debug, T: crate::TimeSource, { fn format(&self, fmt: defmt::Formatter) { diff --git a/src/filesystem/files.rs b/src/filesystem/files.rs index 870d85d..cb4161b 100644 --- a/src/filesystem/files.rs +++ b/src/filesystem/files.rs @@ -1,9 +1,11 @@ use super::TimeSource; use crate::{ filesystem::{ClusterId, DirEntry, Handle}, - BlockDevice, Error, RawVolume, VolumeManager, + Error, RawVolume, VolumeManager, }; +use core::fmt::Debug; use embedded_io::{ErrorType, Read, Seek, SeekFrom, Write}; +use embedded_storage::block::BlockDevice; /// A handle for an open file on disk. /// @@ -32,7 +34,8 @@ impl RawFile { volume_mgr: &VolumeManager, ) -> File where - D: crate::BlockDevice, + D: BlockDevice, + D::Error: Debug, T: crate::TimeSource, { File::new(self, volume_mgr) @@ -49,7 +52,8 @@ impl RawFile { /// the [`File::close`] method. pub struct File<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> where - D: crate::BlockDevice, + D: BlockDevice, + D::Error: Debug, T: crate::TimeSource, { raw_file: RawFile, @@ -59,7 +63,8 @@ where impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> File<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> where - D: crate::BlockDevice, + D: BlockDevice, + D::Error: Debug, T: crate::TimeSource, { /// Create a new `File` from a `RawFile` @@ -148,7 +153,8 @@ where impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> Drop for File<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> where - D: crate::BlockDevice, + D: BlockDevice, + D::Error: Debug, T: crate::TimeSource, { fn drop(&mut self) { @@ -159,7 +165,8 @@ where impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: usize> core::fmt::Debug for File<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> where - D: crate::BlockDevice, + D: BlockDevice, + D::Error: Debug, T: crate::TimeSource, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -174,6 +181,8 @@ impl< const MAX_FILES: usize, const MAX_VOLUMES: usize, > ErrorType for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> +where + D::Error: Debug, { type Error = crate::Error; } @@ -185,6 +194,8 @@ impl< const MAX_FILES: usize, const MAX_VOLUMES: usize, > Read for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> +where + D::Error: Debug, { fn read(&mut self, buf: &mut [u8]) -> Result { if buf.is_empty() { @@ -202,6 +213,8 @@ impl< const MAX_FILES: usize, const MAX_VOLUMES: usize, > Write for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> +where + D::Error: Debug, { fn write(&mut self, buf: &[u8]) -> Result { if buf.is_empty() { @@ -224,6 +237,8 @@ impl< const MAX_FILES: usize, const MAX_VOLUMES: usize, > Seek for File<'_, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> +where + D::Error: Debug, { fn seek(&mut self, pos: SeekFrom) -> Result { match pos { @@ -246,6 +261,7 @@ impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: defmt::Format for File<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> where D: crate::BlockDevice, + D::Error: Debug, T: crate::TimeSource, { fn format(&self, fmt: defmt::Formatter) { diff --git a/src/lib.rs b/src/lib.rs index 434808d..4daa780 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,7 +78,8 @@ use embedded_io::ErrorKind; use filesystem::Handle; #[doc(inline)] -pub use crate::blockdevice::{Block, BlockCache, BlockCount, BlockDevice, BlockIdx}; +pub use crate::blockdevice::{Block, BlockCache}; +pub use embedded_storage::block::{BlockCount, BlockDevice, BlockIdx}; #[doc(inline)] pub use crate::fat::{FatVolume, VolumeName}; @@ -282,6 +283,7 @@ impl RawVolume { where D: crate::BlockDevice, T: crate::TimeSource, + D::Error: Debug, { Volume::new(self, volume_mgr) } @@ -299,6 +301,7 @@ pub struct Volume<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const where D: crate::BlockDevice, T: crate::TimeSource, + D::Error: Debug, { raw_volume: RawVolume, volume_mgr: &'a VolumeManager, @@ -309,6 +312,7 @@ impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: where D: crate::BlockDevice, T: crate::TimeSource, + D::Error: Debug, { /// Create a new `Volume` from a `RawVolume` pub fn new( @@ -355,6 +359,7 @@ impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: where D: crate::BlockDevice, T: crate::TimeSource, + D::Error: Debug, { fn drop(&mut self) { _ = self.volume_mgr.close_volume(self.raw_volume) @@ -366,6 +371,7 @@ impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: where D: crate::BlockDevice, T: crate::TimeSource, + D::Error: Debug, { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "Volume({})", self.raw_volume.0 .0) @@ -377,6 +383,7 @@ impl<'a, D, T, const MAX_DIRS: usize, const MAX_FILES: usize, const MAX_VOLUMES: defmt::Format for Volume<'a, D, T, MAX_DIRS, MAX_FILES, MAX_VOLUMES> where D: crate::BlockDevice, + D::Error: Debug, T: crate::TimeSource, { fn format(&self, fmt: defmt::Formatter) { diff --git a/src/sdcard/mod.rs b/src/sdcard/mod.rs index 5c3c038..0e1c26e 100644 --- a/src/sdcard/mod.rs +++ b/src/sdcard/mod.rs @@ -5,8 +5,9 @@ pub mod proto; -use crate::{trace, Block, BlockCount, BlockDevice, BlockIdx}; +use crate::{trace, Block}; use core::cell::RefCell; +use embedded_storage::block::{BlockCount, BlockDevice, BlockIdx}; use proto::*; // **************************************************************************** @@ -162,27 +163,31 @@ where /// Read one or more blocks, starting at the given block index. /// /// This will trigger card (re-)initialisation. - fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> { + fn read( + &mut self, + first_block_index: BlockIdx, + blocks: &mut [Block], + ) -> Result<(), Self::Error> { let mut inner = self.inner.borrow_mut(); - debug!("Read {} blocks @ {}", blocks.len(), start_block_idx.0,); + debug!("Read {} blocks @ {}", blocks.len(), first_block_index.0); inner.check_init()?; - inner.read(blocks, start_block_idx) + inner.read(first_block_index, blocks) } /// Write one or more blocks, starting at the given block index. /// /// This will trigger card (re-)initialisation. - fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> { + fn write(&mut self, first_block_index: BlockIdx, blocks: &[Block]) -> Result<(), Self::Error> { let mut inner = self.inner.borrow_mut(); - debug!("Writing {} blocks @ {}", blocks.len(), start_block_idx.0); + debug!("Writing {} blocks @ {}", blocks.len(), first_block_index.0); inner.check_init()?; - inner.write(blocks, start_block_idx) + inner.write(first_block_index, blocks) } /// Determine how many blocks this device can hold. /// /// This will trigger card (re-)initialisation. - fn num_blocks(&self) -> Result { + fn block_count(&self) -> Result { let mut inner = self.inner.borrow_mut(); inner.check_init()?; inner.num_blocks() @@ -209,22 +214,25 @@ where DELAYER: embedded_hal::delay::DelayNs, { /// Read one or more blocks, starting at the given block index. - fn read(&mut self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Error> { + fn read(&mut self, first_block_index: BlockIdx, blocks: &mut [Block]) -> Result<(), Error> { let start_idx = match self.card_type { - Some(CardType::SD1 | CardType::SD2) => start_block_idx.0 * 512, - Some(CardType::SDHC) => start_block_idx.0, + Some(CardType::SD1 | CardType::SD2) => first_block_index.0 * 512, + Some(CardType::SDHC) => first_block_index.0, None => return Err(Error::CardNotFound), }; + let start_idx = start_idx + .try_into() + .map_err(|_| Error::BlockOutOfBounds(start_idx))?; if blocks.len() == 1 { // Start a single-block read self.card_command(CMD17, start_idx)?; - self.read_data(&mut blocks[0].contents)?; + self.read_data(&mut blocks[0])?; } else { // Start a multi-block read self.card_command(CMD18, start_idx)?; for block in blocks.iter_mut() { - self.read_data(&mut block.contents)?; + self.read_data(block)?; } // Stop the read self.card_command(CMD12, 0)?; @@ -233,16 +241,19 @@ where } /// Write one or more blocks, starting at the given block index. - fn write(&mut self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Error> { + fn write(&mut self, first_block_index: BlockIdx, blocks: &[Block]) -> Result<(), Error> { let start_idx = match self.card_type { - Some(CardType::SD1 | CardType::SD2) => start_block_idx.0 * 512, - Some(CardType::SDHC) => start_block_idx.0, + Some(CardType::SD1 | CardType::SD2) => first_block_index.0 * 512, + Some(CardType::SDHC) => first_block_index.0, None => return Err(Error::CardNotFound), }; + let start_idx = start_idx + .try_into() + .map_err(|_| Error::BlockOutOfBounds(start_idx))?; if blocks.len() == 1 { // Start a single-block write self.card_command(CMD24, start_idx)?; - self.write_data(DATA_START_BLOCK, &blocks[0].contents)?; + self.write_data(DATA_START_BLOCK, &blocks[0])?; self.wait_not_busy(Delay::new_write())?; if self.card_command(CMD13, 0)? != 0x00 { return Err(Error::WriteError); @@ -262,7 +273,7 @@ where self.card_command(CMD25, start_idx)?; for block in blocks.iter() { self.wait_not_busy(Delay::new_write())?; - self.write_data(WRITE_MULTIPLE_TOKEN, &block.contents)?; + self.write_data(WRITE_MULTIPLE_TOKEN, block)?; } // Stop the write self.wait_not_busy(Delay::new_write())?; @@ -279,7 +290,7 @@ where Csd::V1(ref contents) => contents.card_capacity_blocks(), Csd::V2(ref contents) => contents.card_capacity_blocks(), }; - Ok(BlockCount(num_blocks)) + Ok(BlockCount(num_blocks.into())) } /// Return the usable size of this SD card in bytes. @@ -624,6 +635,8 @@ pub enum Error { CardNotFound, /// Couldn't set a GPIO pin GpioError, + /// Tried to read or write a block out of bounds. + BlockOutOfBounds(u64), } /// The different types of card we support. diff --git a/src/volume_mgr.rs b/src/volume_mgr.rs index f359460..da3f580 100644 --- a/src/volume_mgr.rs +++ b/src/volume_mgr.rs @@ -4,19 +4,21 @@ use core::cell::RefCell; use core::convert::TryFrom; +use core::fmt::Debug; use core::ops::DerefMut; use byteorder::{ByteOrder, LittleEndian}; use heapless::Vec; use crate::{ + blockdevice::{BLOCK_LEN, BLOCK_LEN_U32, BLOCK_LEN_U64}, debug, fat, filesystem::{ Attributes, ClusterId, DirEntry, DirectoryInfo, FileInfo, HandleGenerator, LfnBuffer, Mode, RawDirectory, RawFile, TimeSource, ToShortFileName, MAX_FILE_SIZE, }, - trace, Block, BlockCache, BlockCount, BlockDevice, BlockIdx, Error, RawVolume, ShortFileName, - Volume, VolumeIdx, VolumeInfo, VolumeType, PARTITION_ID_FAT16, PARTITION_ID_FAT16_LBA, + trace, BlockCache, BlockCount, BlockDevice, BlockIdx, Error, RawVolume, ShortFileName, Volume, + VolumeIdx, VolumeInfo, VolumeType, PARTITION_ID_FAT16, PARTITION_ID_FAT16_LBA, PARTITION_ID_FAT32_CHS_LBA, PARTITION_ID_FAT32_LBA, }; @@ -187,8 +189,8 @@ where ); ( partition[PARTITION_INFO_TYPE_INDEX], - BlockIdx(lba_start), - BlockCount(num_blocks), + BlockIdx(lba_start.into()), + BlockCount(num_blocks.into()), ) }; match part_type { @@ -1130,7 +1132,7 @@ where data.block_cache.write_back()?; for block_idx in new_dir_start_block - .range(BlockCount(u32::from(fat.blocks_per_cluster))) + .range(BlockCount(fat.blocks_per_cluster.into())) .skip(1) { let _block = data.block_cache.blank_mut(block_idx); @@ -1237,6 +1239,7 @@ where ) -> Result<(BlockIdx, usize, usize), Error> where D: BlockDevice, + D::Error: Debug, { let bytes_per_cluster = match &self.open_volumes[volume_idx].volume_type { VolumeType::Fat(fat) => fat.bytes_per_cluster(), @@ -1261,12 +1264,12 @@ where // How many blocks in are we now? let offset_from_cluster = desired_offset - start.0; assert!(offset_from_cluster < bytes_per_cluster); - let num_blocks = BlockCount(offset_from_cluster / Block::LEN_U32); + let num_blocks = BlockCount(u64::from(offset_from_cluster) / BLOCK_LEN_U64); let block_idx = match &self.open_volumes[volume_idx].volume_type { VolumeType::Fat(fat) => fat.cluster_to_block(start.1), } + num_blocks; - let block_offset = (desired_offset % Block::LEN_U32) as usize; - let available = Block::LEN - block_offset; + let block_offset = (desired_offset % BLOCK_LEN_U32) as usize; + let available = BLOCK_LEN - block_offset; Ok((block_idx, block_offset, available)) } } @@ -1301,7 +1304,7 @@ fn solve_mode_variant(mode: Mode, dir_entry_is_some: bool) -> Mode { mod tests { use super::*; use crate::filesystem::Handle; - use crate::Timestamp; + use crate::{Block, Timestamp}; struct DummyBlockDevice; @@ -1330,148 +1333,147 @@ mod tests { type Error = Error; /// Read one or more blocks, starting at the given block index. - fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> { + fn read( + &mut self, + first_block_index: BlockIdx, + blocks: &mut [Block], + ) -> Result<(), Self::Error> { // Actual blocks taken from an SD card, except I've changed the start and length of partition 0. static BLOCKS: [Block; 3] = [ - Block { - contents: [ - 0xfa, 0xb8, 0x00, 0x10, 0x8e, 0xd0, 0xbc, 0x00, 0xb0, 0xb8, 0x00, 0x00, - 0x8e, 0xd8, 0x8e, 0xc0, // 0x000 - 0xfb, 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x06, 0xb9, 0x00, 0x02, 0xf3, 0xa4, - 0xea, 0x21, 0x06, 0x00, // 0x010 - 0x00, 0xbe, 0xbe, 0x07, 0x38, 0x04, 0x75, 0x0b, 0x83, 0xc6, 0x10, 0x81, - 0xfe, 0xfe, 0x07, 0x75, // 0x020 - 0xf3, 0xeb, 0x16, 0xb4, 0x02, 0xb0, 0x01, 0xbb, 0x00, 0x7c, 0xb2, 0x80, - 0x8a, 0x74, 0x01, 0x8b, // 0x030 - 0x4c, 0x02, 0xcd, 0x13, 0xea, 0x00, 0x7c, 0x00, 0x00, 0xeb, 0xfe, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x040 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x050 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x060 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x070 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x080 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x090 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x0A0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x0B0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x0C0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x0D0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x0E0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x0F0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x100 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x110 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x120 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x130 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x140 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x150 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x160 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x170 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x180 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x190 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x1A0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0xca, 0xde, 0x06, - 0x00, 0x00, 0x00, 0x04, // 0x1B0 - 0x01, 0x04, 0x0c, 0xfe, 0xc2, 0xff, 0x01, 0x00, 0x00, 0x00, 0x33, 0x22, - 0x11, 0x00, 0x00, 0x00, // 0x1C0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x1D0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x1E0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x55, 0xaa, // 0x1F0 - ], - }, - Block { - contents: [ - 0xeb, 0x58, 0x90, 0x6d, 0x6b, 0x66, 0x73, 0x2e, 0x66, 0x61, 0x74, 0x00, - 0x02, 0x08, 0x20, 0x00, // 0x000 - 0x02, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, - 0x00, 0x08, 0x00, 0x00, // 0x010 - 0x00, 0x20, 0x76, 0x00, 0x80, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, // 0x020 - 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x030 - 0x80, 0x01, 0x29, 0x0b, 0xa8, 0x89, 0x27, 0x50, 0x69, 0x63, 0x74, 0x75, - 0x72, 0x65, 0x73, 0x20, // 0x040 - 0x20, 0x20, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20, 0x0e, 0x1f, - 0xbe, 0x77, 0x7c, 0xac, // 0x050 - 0x22, 0xc0, 0x74, 0x0b, 0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, - 0x5e, 0xeb, 0xf0, 0x32, // 0x060 - 0xe4, 0xcd, 0x16, 0xcd, 0x19, 0xeb, 0xfe, 0x54, 0x68, 0x69, 0x73, 0x20, - 0x69, 0x73, 0x20, 0x6e, // 0x070 - 0x6f, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x20, 0x64, 0x69, // 0x080 - 0x73, 0x6b, 0x2e, 0x20, 0x20, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, - 0x69, 0x6e, 0x73, 0x65, // 0x090 - 0x72, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, - 0x65, 0x20, 0x66, 0x6c, // 0x0A0 - 0x6f, 0x70, 0x70, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x20, // 0x0B0 - 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, - 0x72, 0x79, 0x20, 0x61, // 0x0C0 - 0x67, 0x61, 0x69, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x0d, 0x0a, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x0D0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x0E0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x0F0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x100 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x110 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x120 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x130 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x140 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x150 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x160 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x170 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x180 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x190 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x1A0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x1B0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x1C0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x1D0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, // 0x1E0 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x55, 0xaa, // 0x1F0 - ], - }, - Block { - contents: hex!( - "52 52 61 41 00 00 00 00 00 00 00 00 00 00 00 00 + [ + 0xfa, 0xb8, 0x00, 0x10, 0x8e, 0xd0, 0xbc, 0x00, 0xb0, 0xb8, 0x00, 0x00, 0x8e, + 0xd8, 0x8e, 0xc0, // 0x000 + 0xfb, 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x06, 0xb9, 0x00, 0x02, 0xf3, 0xa4, 0xea, + 0x21, 0x06, 0x00, // 0x010 + 0x00, 0xbe, 0xbe, 0x07, 0x38, 0x04, 0x75, 0x0b, 0x83, 0xc6, 0x10, 0x81, 0xfe, + 0xfe, 0x07, 0x75, // 0x020 + 0xf3, 0xeb, 0x16, 0xb4, 0x02, 0xb0, 0x01, 0xbb, 0x00, 0x7c, 0xb2, 0x80, 0x8a, + 0x74, 0x01, 0x8b, // 0x030 + 0x4c, 0x02, 0xcd, 0x13, 0xea, 0x00, 0x7c, 0x00, 0x00, 0xeb, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x040 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x050 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x060 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x070 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x080 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x090 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x0A0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x0B0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x0C0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x0D0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x0E0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x0F0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x100 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x110 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x120 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x130 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x140 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x150 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x160 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x170 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x180 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x190 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x1A0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0xca, 0xde, 0x06, 0x00, + 0x00, 0x00, 0x04, // 0x1B0 + 0x01, 0x04, 0x0c, 0xfe, 0xc2, 0xff, 0x01, 0x00, 0x00, 0x00, 0x33, 0x22, 0x11, + 0x00, 0x00, 0x00, // 0x1C0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x1D0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x1E0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x55, 0xaa, // 0x1F0 + ], + [ + 0xeb, 0x58, 0x90, 0x6d, 0x6b, 0x66, 0x73, 0x2e, 0x66, 0x61, 0x74, 0x00, 0x02, + 0x08, 0x20, 0x00, // 0x000 + 0x02, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x10, 0x00, 0x04, 0x00, 0x00, + 0x08, 0x00, 0x00, // 0x010 + 0x00, 0x20, 0x76, 0x00, 0x80, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, // 0x020 + 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x030 + 0x80, 0x01, 0x29, 0x0b, 0xa8, 0x89, 0x27, 0x50, 0x69, 0x63, 0x74, 0x75, 0x72, + 0x65, 0x73, 0x20, // 0x040 + 0x20, 0x20, 0x46, 0x41, 0x54, 0x33, 0x32, 0x20, 0x20, 0x20, 0x0e, 0x1f, 0xbe, + 0x77, 0x7c, 0xac, // 0x050 + 0x22, 0xc0, 0x74, 0x0b, 0x56, 0xb4, 0x0e, 0xbb, 0x07, 0x00, 0xcd, 0x10, 0x5e, + 0xeb, 0xf0, 0x32, // 0x060 + 0xe4, 0xcd, 0x16, 0xcd, 0x19, 0xeb, 0xfe, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, + 0x73, 0x20, 0x6e, // 0x070 + 0x6f, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x20, 0x64, 0x69, // 0x080 + 0x73, 0x6b, 0x2e, 0x20, 0x20, 0x50, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x69, + 0x6e, 0x73, 0x65, // 0x090 + 0x72, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6f, 0x6f, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x20, 0x66, 0x6c, // 0x0A0 + 0x6f, 0x70, 0x70, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x0d, 0x0a, 0x70, 0x72, 0x65, + 0x73, 0x73, 0x20, // 0x0B0 + 0x61, 0x6e, 0x79, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x72, + 0x79, 0x20, 0x61, // 0x0C0 + 0x67, 0x61, 0x69, 0x6e, 0x20, 0x2e, 0x2e, 0x2e, 0x20, 0x0d, 0x0a, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x0D0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x0E0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x0F0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x100 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x110 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x120 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x130 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x140 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x150 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x160 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x170 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x180 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x190 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x1A0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x1B0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x1C0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x1D0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, // 0x1E0 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x55, 0xaa, // 0x1F0 + ], + hex!( + "52 52 61 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -1503,16 +1505,15 @@ mod tests { 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 72 72 41 61 FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA" - ), - }, + ), ]; println!( "Reading block {} to {}", - start_block_idx.0, - start_block_idx.0 as usize + blocks.len() + first_block_index.0, + first_block_index.0 as usize + blocks.len() ); for (idx, block) in blocks.iter_mut().enumerate() { - let block_idx = start_block_idx.0 as usize + idx; + let block_idx = first_block_index.0 as usize + idx; if block_idx < BLOCKS.len() { *block = BLOCKS[block_idx].clone(); } else { @@ -1523,12 +1524,16 @@ mod tests { } /// Write one or more blocks, starting at the given block index. - fn write(&self, _blocks: &[Block], _start_block_idx: BlockIdx) -> Result<(), Self::Error> { + fn write( + &mut self, + _first_block_index: BlockIdx, + _blocks: &[Block], + ) -> Result<(), Self::Error> { unimplemented!(); } /// Determine how many blocks this device can hold. - fn num_blocks(&self) -> Result { + fn block_count(&self) -> Result { Ok(BlockCount(2)) } } diff --git a/tests/utils/mod.rs b/tests/utils/mod.rs index 3f89a0e..a467c37 100644 --- a/tests/utils/mod.rs +++ b/tests/utils/mod.rs @@ -85,13 +85,17 @@ where { type Error = Error; - fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> { + fn read( + &mut self, + first_block_index: BlockIdx, + blocks: &mut [Block], + ) -> Result<(), Self::Error> { let borrow = self.contents.borrow(); let contents: &[u8] = borrow.as_ref(); - let mut block_idx = start_block_idx; + let mut block_idx = first_block_index; for block in blocks.iter_mut() { - let start_offset = block_idx.0 as usize * embedded_sdmmc::Block::LEN; - let end_offset = start_offset + embedded_sdmmc::Block::LEN; + let start_offset = block_idx.0 as usize * embedded_sdmmc::blockdevice::BLOCK_LEN; + let end_offset = start_offset + embedded_sdmmc::blockdevice::BLOCK_LEN; if end_offset > contents.len() { return Err(Error::OutOfBounds(block_idx)); } @@ -103,13 +107,13 @@ where Ok(()) } - fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> { + fn write(&mut self, first_block_index: BlockIdx, blocks: &[Block]) -> Result<(), Self::Error> { let mut borrow = self.contents.borrow_mut(); let contents: &mut [u8] = borrow.as_mut(); - let mut block_idx = start_block_idx; + let mut block_idx = first_block_index; for block in blocks.iter() { - let start_offset = block_idx.0 as usize * embedded_sdmmc::Block::LEN; - let end_offset = start_offset + embedded_sdmmc::Block::LEN; + let start_offset = block_idx.0 as usize * embedded_sdmmc::blockdevice::BLOCK_LEN; + let end_offset = start_offset + embedded_sdmmc::blockdevice::BLOCK_LEN; if end_offset > contents.len() { return Err(Error::OutOfBounds(block_idx)); } @@ -119,14 +123,14 @@ where Ok(()) } - fn num_blocks(&self) -> Result { + fn block_count(&self) -> Result { let borrow = self.contents.borrow(); let contents: &[u8] = borrow.as_ref(); - let len_blocks = contents.len() / embedded_sdmmc::Block::LEN; + let len_blocks = contents.len() / embedded_sdmmc::blockdevice::BLOCK_LEN; if len_blocks > u32::MAX as usize { panic!("Test disk too large! Only 2**32 blocks allowed"); } - Ok(BlockCount(len_blocks as u32)) + Ok(BlockCount(len_blocks as u64)) } }