From c8e79a926620e48830778714cfe4b2ea2453fcaf Mon Sep 17 00:00:00 2001 From: jacqueline Date: Fri, 25 Jul 2025 13:33:07 +1000 Subject: Update forked idf components --- lib/fatfs/fatfs_utils/boot_sector.py | 22 +++++++++++----------- lib/fatfs/fatfs_utils/fatfs_state.py | 3 ++- lib/fatfs/fatfs_utils/utils.py | 34 +++++++++++++++++++++++++--------- 3 files changed, 38 insertions(+), 21 deletions(-) (limited to 'lib/fatfs/fatfs_utils') diff --git a/lib/fatfs/fatfs_utils/boot_sector.py b/lib/fatfs/fatfs_utils/boot_sector.py index 615dd065..2809c033 100644 --- a/lib/fatfs/fatfs_utils/boot_sector.py +++ b/lib/fatfs/fatfs_utils/boot_sector.py @@ -1,9 +1,9 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 from inspect import getmembers, isroutine from typing import Optional -from construct import Const, Int8ul, Int16ul, Int32ul, PaddedString, Struct, core +from construct import Bytes, Const, Int8ul, Int16ul, Int32ul, PaddedString, Padding, Struct, core from .exceptions import InconsistentFATAttributes, NotInitialized from .fatfs_state import BootSectorState @@ -29,8 +29,7 @@ class BootSector: BOOT_HEADER_SIZE = 512 BOOT_SECTOR_HEADER = Struct( - # this value reflects BS_jmpBoot used for ESP32 boot sector (any other accepted) - 'BS_jmpBoot' / Const(b'\xeb\xfe\x90'), + 'BS_jmpBoot' / Bytes(3), 'BS_OEMName' / PaddedString(MAX_OEM_NAME_SIZE, SHORT_NAMES_ENCODING), 'BPB_BytsPerSec' / Int16ul, 'BPB_SecPerClus' / Int8ul, @@ -45,12 +44,12 @@ class BootSector: 'BPB_HiddSec' / Int32ul, 'BPB_TotSec32' / Int32ul, # zero if the FAT type is 12/16, otherwise number of sectors 'BS_DrvNum' / Const(b'\x80'), - 'BS_Reserved1' / Const(EMPTY_BYTE), + 'BS_Reserved1' / Padding(1), 'BS_BootSig' / Const(b'\x29'), 'BS_VolID' / Int32ul, 'BS_VolLab' / PaddedString(MAX_VOL_LAB_SIZE, SHORT_NAMES_ENCODING), 'BS_FilSysType' / PaddedString(MAX_FS_TYPE_SIZE, SHORT_NAMES_ENCODING), - 'BS_EMPTY' / Const(448 * EMPTY_BYTE), + 'BS_EMPTY' / Padding(448), 'Signature_word' / Const(FATDefaults.SIGNATURE_WORD) ) assert BOOT_SECTOR_HEADER.sizeof() == BOOT_HEADER_SIZE @@ -65,15 +64,17 @@ class BootSector: raise NotInitialized('The BootSectorState instance is not initialized!') volume_uuid = generate_4bytes_random() pad_header: bytes = (boot_sector_state.sector_size - BootSector.BOOT_HEADER_SIZE) * EMPTY_BYTE - data_content: bytes = boot_sector_state.data_sectors * boot_sector_state.sector_size * FULL_BYTE - root_dir_content: bytes = boot_sector_state.root_dir_sectors_cnt * boot_sector_state.sector_size * EMPTY_BYTE fat_tables_content: bytes = (boot_sector_state.sectors_per_fat_cnt * boot_sector_state.fat_tables_cnt * boot_sector_state.sector_size * EMPTY_BYTE) + root_dir_content: bytes = boot_sector_state.root_dir_sectors_cnt * boot_sector_state.sector_size * EMPTY_BYTE + data_content: bytes = boot_sector_state.data_sectors * boot_sector_state.sector_size * FULL_BYTE + self.boot_sector_state.binary_image = ( BootSector.BOOT_SECTOR_HEADER.build( - dict(BS_OEMName=pad_string(boot_sector_state.oem_name, size=BootSector.MAX_OEM_NAME_SIZE), + dict(BS_jmpBoot=(b'\xeb\xfe\x90'), + BS_OEMName=pad_string(boot_sector_state.oem_name, size=BootSector.MAX_OEM_NAME_SIZE), BPB_BytsPerSec=boot_sector_state.sector_size, BPB_SecPerClus=boot_sector_state.sectors_per_cluster, BPB_RsvdSecCnt=boot_sector_state.reserved_sectors_cnt, @@ -91,8 +92,7 @@ class BootSector: BS_VolLab=pad_string(boot_sector_state.volume_label, size=BootSector.MAX_VOL_LAB_SIZE), BS_FilSysType=pad_string(boot_sector_state.file_sys_type, - size=BootSector.MAX_FS_TYPE_SIZE) - ) + size=BootSector.MAX_FS_TYPE_SIZE)) ) + pad_header + fat_tables_content + root_dir_content + data_content ) diff --git a/lib/fatfs/fatfs_utils/fatfs_state.py b/lib/fatfs/fatfs_utils/fatfs_state.py index 22af7bfb..4ba57132 100644 --- a/lib/fatfs/fatfs_utils/fatfs_state.py +++ b/lib/fatfs/fatfs_utils/fatfs_state.py @@ -152,6 +152,7 @@ class BootSectorState: def non_data_sectors(self) -> int: non_data_sectors_: int = get_non_data_sectors_cnt(self.reserved_sectors_cnt, self.sectors_per_fat_cnt, + self.fat_tables_cnt, self.root_dir_sectors_cnt) return non_data_sectors_ @@ -166,5 +167,5 @@ class BootSectorState: @property def root_directory_start(self) -> int: - root_dir_start: int = (self.reserved_sectors_cnt + self.sectors_per_fat_cnt) * self.sector_size + root_dir_start: int = (self.reserved_sectors_cnt + self.sectors_per_fat_cnt * self.fat_tables_cnt) * self.sector_size return root_dir_start diff --git a/lib/fatfs/fatfs_utils/utils.py b/lib/fatfs/fatfs_utils/utils.py index d2180c76..662586a5 100644 --- a/lib/fatfs/fatfs_utils/utils.py +++ b/lib/fatfs/fatfs_utils/utils.py @@ -1,15 +1,18 @@ -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 - import argparse import binascii import os import re import uuid from datetime import datetime -from typing import List, Optional, Tuple +from typing import List +from typing import Optional +from typing import Tuple -from construct import BitsInteger, BitStruct, Int16ul +from construct import BitsInteger +from construct import BitStruct +from construct import Int16ul # the regex pattern defines symbols that are allowed by long file names but not by short file names INVALID_SFN_CHARS_PATTERN = re.compile(r'[.+,;=\[\]]') @@ -68,8 +71,8 @@ def number_of_clusters(number_of_sectors: int, sectors_per_cluster: int) -> int: return number_of_sectors // sectors_per_cluster -def get_non_data_sectors_cnt(reserved_sectors_cnt: int, sectors_per_fat_cnt: int, root_dir_sectors_cnt: int) -> int: - return reserved_sectors_cnt + sectors_per_fat_cnt + root_dir_sectors_cnt +def get_non_data_sectors_cnt(reserved_sectors_cnt: int, sectors_per_fat_cnt: int, fat_tables_cnt: int, root_dir_sectors_cnt: int) -> int: + return reserved_sectors_cnt + sectors_per_fat_cnt * fat_tables_cnt + root_dir_sectors_cnt def get_fatfs_type(clusters_count: int) -> int: @@ -203,9 +206,19 @@ def get_args_for_partition_generator(desc: str, wl: bool) -> argparse.Namespace: type=int, choices=[FAT12, FAT16, 0], help=""" - Type of fat. Select 12 for fat12, 16 for fat16. Don't set, or set to 0 for automatic - calculation using cluster size and partition size. + Type of the FAT file-system. Select '12' for FAT12, '16' for FAT16. + Leave unset or select 0 for automatic file-system type detection. """) + parser.add_argument('--fat_count', + default=FATDefaults.FAT_TABLES_COUNT, + type=int, + choices=[1, 2], + help='Number of file allocation tables (FATs) in the filesystem.') + parser.add_argument('--wl_mode', + default=None, + type=str, + choices=['safe', 'perf'], + help='Wear levelling mode to use. Safe or performance. Only for sector size of 512') args = parser.parse_args() if args.fat_type == 0: @@ -215,6 +228,9 @@ def get_args_for_partition_generator(desc: str, wl: bool) -> argparse.Namespace: args.partition_size = int(str(args.partition_size), 0) if not os.path.isdir(args.input_directory): raise NotADirectoryError(f'The target directory `{args.input_directory}` does not exist!') + if args.wl_mode is not None: + if args.sector_size != 512: + raise ValueError('Wear levelling mode can be set only for sector size 512') return args @@ -276,7 +292,7 @@ class FATDefaults: # FATFS defaults SIZE: int = 1024 * 1024 RESERVED_SECTORS_COUNT: int = 1 - FAT_TABLES_COUNT: int = 1 + FAT_TABLES_COUNT: int = 2 SECTORS_PER_CLUSTER: int = 1 SECTOR_SIZE: int = 0x1000 HIDDEN_SECTORS: int = 0 -- cgit v1.2.3