From 20fc821e5dbf05797cd9e66e915e018358eda270 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Wed, 30 Oct 2024 18:56:19 +0000 Subject: [PATCH 1/5] Fix .. entry in new directories. --- src/volume_mgr.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/volume_mgr.rs b/src/volume_mgr.rs index 98b77814..dd930925 100644 --- a/src/volume_mgr.rs +++ b/src/volume_mgr.rs @@ -5,7 +5,7 @@ use byteorder::{ByteOrder, LittleEndian}; use core::convert::TryFrom; -use crate::fat::{self, BlockCache, FatType, OnDiskDirEntry, RESERVED_ENTRIES}; +use crate::fat::{self, BlockCache, OnDiskDirEntry, RESERVED_ENTRIES}; use crate::filesystem::{ Attributes, ClusterId, DirEntry, DirectoryInfo, FileInfo, Mode, RawDirectory, RawFile, @@ -978,16 +978,13 @@ where ctime: now, attributes: att, // point at our parent - cluster: match fat_type { - FatType::Fat16 => { - // On FAT16, indicate parent is root using Cluster(0) - if parent_directory_info.cluster == ClusterId::ROOT_DIR { - ClusterId::EMPTY - } else { - parent_directory_info.cluster - } + cluster: { + // On FAT16, indicate parent is root using Cluster(0) + if parent_directory_info.cluster == ClusterId::ROOT_DIR { + ClusterId::EMPTY + } else { + parent_directory_info.cluster } - FatType::Fat32 => parent_directory_info.cluster, }, size: 0, entry_block: new_dir_start_block, From fa664f465f51e9c5ad856e5857587c1e34e25659 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Wed, 30 Oct 2024 19:05:46 +0000 Subject: [PATCH 2/5] Write to the second FAT. --- src/fat/volume.rs | 31 +++++++++++++++++++++++++++++++ src/volume_mgr.rs | 1 + 2 files changed, 32 insertions(+) diff --git a/src/fat/volume.rs b/src/fat/volume.rs index 8f44c6d9..00d0ed65 100644 --- a/src/fat/volume.rs +++ b/src/fat/volume.rs @@ -55,6 +55,9 @@ pub struct FatVolume { /// The block the FAT starts in. Relative to start of partition (so add /// `self.lba_offset` before passing to volume manager) pub(crate) fat_start: BlockCount, + /// The block the second FAT starts in (if present). Relative to start of + /// partition (so add `self.lba_offset` before passing to volume manager) + pub(crate) second_fat_start: Option, /// Expected number of free clusters pub(crate) free_clusters_count: Option, /// Number of the next expected free cluster @@ -118,10 +121,15 @@ impl FatVolume { { let mut blocks = [Block::new()]; let this_fat_block_num; + let mut second_fat_block_num = None; 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); + if let Some(fat_start) = self.second_fat_start { + second_fat_block_num = + Some(self.lba_start + fat_start.offset_bytes(fat_offset)); + } let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize; block_device .read(&mut blocks, this_fat_block_num, "read_fat") @@ -143,6 +151,10 @@ impl FatVolume { // 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); + if let Some(fat_start) = self.second_fat_start { + second_fat_block_num = + Some(self.lba_start + fat_start.offset_bytes(fat_offset)); + } let this_fat_ent_offset = (fat_offset % Block::LEN_U32) as usize; block_device .read(&mut blocks, this_fat_block_num, "read_fat") @@ -166,6 +178,11 @@ impl FatVolume { block_device .write(&blocks, this_fat_block_num) .map_err(Error::DeviceError)?; + if let Some(second_fat_block_num) = second_fat_block_num { + block_device + .write(&blocks, second_fat_block_num) + .map_err(Error::DeviceError)?; + } Ok(()) } @@ -1098,6 +1115,13 @@ where blocks_per_cluster: bpb.blocks_per_cluster(), first_data_block: (first_data_block), fat_start: BlockCount(u32::from(bpb.reserved_block_count())), + second_fat_start: if bpb.num_fats() == 2 { + Some(BlockCount( + u32::from(bpb.reserved_block_count()) + bpb.fat_size(), + )) + } else { + None + }, free_clusters_count: None, next_free_cluster: None, cluster_count: bpb.total_clusters(), @@ -1135,6 +1159,13 @@ where blocks_per_cluster: bpb.blocks_per_cluster(), first_data_block: BlockCount(first_data_block), fat_start: BlockCount(u32::from(bpb.reserved_block_count())), + second_fat_start: if bpb.num_fats() == 2 { + Some(BlockCount( + u32::from(bpb.reserved_block_count()) + bpb.fat_size(), + )) + } else { + None + }, free_clusters_count: info_sector.free_clusters_count(), next_free_cluster: info_sector.next_free_cluster(), cluster_count: bpb.total_clusters(), diff --git a/src/volume_mgr.rs b/src/volume_mgr.rs index dd930925..20fadd99 100644 --- a/src/volume_mgr.rs +++ b/src/volume_mgr.rs @@ -1381,6 +1381,7 @@ mod tests { blocks_per_cluster: 8, first_data_block: BlockCount(15136), fat_start: BlockCount(32), + second_fat_start: Some(BlockCount(32 + 0x0000_1D80)), name: fat::VolumeName::new(*b"Pictures "), free_clusters_count: None, next_free_cluster: None, From 169bb26a91254a0894e8735bfcc3237389708f52 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Wed, 30 Oct 2024 19:05:57 +0000 Subject: [PATCH 3/5] Write out the update info sector when the volume is closed. --- src/volume_mgr.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/volume_mgr.rs b/src/volume_mgr.rs index 20fadd99..c4fffd38 100644 --- a/src/volume_mgr.rs +++ b/src/volume_mgr.rs @@ -324,6 +324,13 @@ where } let volume_idx = self.get_volume_by_id(volume)?; + + match &mut self.open_volumes[volume_idx].volume_type { + VolumeType::Fat(fat_volume) => { + fat_volume.update_info_sector(&self.block_device)?; + } + } + self.open_volumes.swap_remove(volume_idx); Ok(()) From bbb7374d7f445f5ae7a5d1e25f840e8ef171cddd Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sun, 3 Nov 2024 14:31:22 +0000 Subject: [PATCH 4/5] Bump to v0.8.1. --- CHANGELOG.md | 8 ++++++++ Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecb40f3a..0d242671 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,14 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic - None +## [Version 0.8.1] - 2024-11-03 + +### Changed + +* Second FAT is now updated, if it is present +* When creating a directory `..` now points at the root directory correctly +* The info block containing the free cluster count is now updated when unmounting a FAT32 volume. + ## [Version 0.8.0] - 2024-07-12 ### Changed diff --git a/Cargo.toml b/Cargo.toml index 88412f76..53f6dfa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0" name = "embedded-sdmmc" readme = "README.md" repository = "https://github.com/rust-embedded-community/embedded-sdmmc-rs" -version = "0.8.0" +version = "0.8.1" [dependencies] byteorder = {version = "1", default-features = false} From 4e1b2dcd3dda9040d2ee7bb159f333dc84b0cfc3 Mon Sep 17 00:00:00 2001 From: Jonathan 'theJPster' Pallant Date: Sat, 7 Jun 2025 17:07:26 +0100 Subject: [PATCH 5/5] Update CHANGELOG.md --- CHANGELOG.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d242671..1ea3f62e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -174,13 +174,14 @@ The format is based on [Keep a Changelog] and this project adheres to [Semantic [Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ [Semantic Versioning]: http://semver.org/spec/v2.0.0.html -[Unreleased]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.8.0...develop -[Version 0.8.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.8.0...v0.7.0 -[Version 0.7.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.7.0...v0.6.0 -[Version 0.6.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.6.0...v0.5.0 -[Version 0.5.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.5.0...v0.4.0 -[Version 0.4.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.4.0...v0.3.0 -[Version 0.3.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.3.0...v0.2.1 -[Version 0.2.1]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.2.1...v0.2.0 -[Version 0.2.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.2.0...v0.1.1 +[Unreleased]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.8.1...develop +[Version 0.8.1]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.8.0...v0.8.1 +[Version 0.8.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.7.0...v0.8.0 +[Version 0.7.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.6.0...v0.7.0 +[Version 0.6.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.5.0...v0.6.0 +[Version 0.5.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.4.0...v0.5.0 +[Version 0.4.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.3.0...v0.4.0 +[Version 0.3.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.2.1...v0.3.0 +[Version 0.2.1]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.2.0...v0.2.1 +[Version 0.2.0]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/compare/v0.1.1...v0.2.0 [Version 0.1.1]: https://github.com/rust-embedded-community/embedded-sdmmc-rs/releases/tag/v0.1.1