From ef719bea1d5a3a9fe6653ae5d5d5f2d6198d7d76 Mon Sep 17 00:00:00 2001 From: Martin Vychodil Date: Tue, 3 Jun 2025 11:20:10 +0200 Subject: [PATCH] fix(storage/fatfs): Fix rootdir entry count handling in fatfsgen.py script (FAT12/FAT16) FatFS generator script now uses de-facto limits for Root directory items count when generating FAT12 or FAT16 image. Also, Root directory is not required to occupy whole sector (number of items can be anything from the range from 1 to given limit). --- components/fatfs/fatfs_utils/utils.py | 2 ++ components/fatfs/fatfsgen.py | 21 +++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/components/fatfs/fatfs_utils/utils.py b/components/fatfs/fatfs_utils/utils.py index 662586a50b6..3d84ee59222 100644 --- a/components/fatfs/fatfs_utils/utils.py +++ b/components/fatfs/fatfs_utils/utils.py @@ -303,6 +303,8 @@ class FATDefaults: VOLUME_LABEL: str = 'Espressif' FILE_SYS_TYPE: str = 'FAT' ROOT_ENTRIES_COUNT: int = 512 # number of entries in the root directory, recommended 512 + FAT12_MAX_ROOT_ENTRIES: int = 224 # maximum number of entries in FAT12 root directory + FAT16_MAX_ROOT_ENTRIES: int = 512 # maximum number of entries in FAT16 root directory MEDIA_TYPE: int = 0xf8 SIGNATURE_WORD: bytes = b'\x55\xAA' diff --git a/components/fatfs/fatfsgen.py b/components/fatfs/fatfsgen.py index 30d274f5260..c52346259d2 100755 --- a/components/fatfs/fatfsgen.py +++ b/components/fatfs/fatfsgen.py @@ -57,8 +57,7 @@ class FATFS: root_entry_count: int = FATDefaults.ROOT_ENTRIES_COUNT, explicit_fat_type: Optional[int] = None, media_type: int = FATDefaults.MEDIA_TYPE) -> None: - # root directory bytes should be aligned by sector size - assert (int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) % sector_size == 0 + # number of bytes in the root dir must be even multiple of BPB_BytsPerSec if (int(root_entry_count) > 128): assert ((int(root_entry_count) * BYTES_PER_DIRECTORY_ENTRY) // sector_size) % 2 == 0 @@ -251,10 +250,24 @@ def calculate_min_space(path: List[str], def main() -> None: args = get_args_for_partition_generator('Create a FAT filesystem and populate it with directory content', wl=False) + # 0 == default (512 items) + root_dir_count = args.root_entry_count + if root_dir_count == 0: + root_dir_count = FATDefaults.ROOT_ENTRIES_COUNT + + # apply de-facto limits based on FAT type + if args.fat_type == 12: + if root_dir_count > FATDefaults.FAT12_MAX_ROOT_ENTRIES: + root_dir_count = FATDefaults.FAT12_MAX_ROOT_ENTRIES + + if args.fat_type == 16: + if root_dir_count > FATDefaults.FAT16_MAX_ROOT_ENTRIES: + root_dir_count = FATDefaults.FAT16_MAX_ROOT_ENTRIES + if args.partition_size == -1: clusters = calculate_min_space([], args.input_directory, args.sector_size, long_file_names=True, is_root=True) fats = get_fat_sectors_count(clusters, args.sector_size) - root_dir_sectors = (FATDefaults.ROOT_ENTRIES_COUNT * FATDefaults.ENTRY_SIZE) // args.sector_size + root_dir_sectors = max((root_dir_count * FATDefaults.ENTRY_SIZE // args.sector_size), 1) args.partition_size = max(FATFS_MIN_ALLOC_UNIT * args.sector_size, (clusters + fats + get_non_data_sectors_cnt(RESERVED_CLUSTERS_COUNT, fats, @@ -269,7 +282,7 @@ def main() -> None: sector_size=args.sector_size, long_names_enabled=args.long_name_support, use_default_datetime=args.use_default_datetime, - root_entry_count=args.root_entry_count, + root_entry_count=root_dir_count, explicit_fat_type=args.fat_type) fatfs.generate(args.input_directory)