mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-06 14:14:33 +02:00
fatfsgen.py: Support for detection of minimal partition size
This commit is contained in:
@@ -14,6 +14,7 @@ from construct import BitsInteger, BitStruct, Int16ul
|
|||||||
# the regex pattern defines symbols that are allowed by long file names but not by short file names
|
# 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'[.+,;=\[\]]')
|
INVALID_SFN_CHARS_PATTERN = re.compile(r'[.+,;=\[\]]')
|
||||||
|
|
||||||
|
FATFS_MIN_ALLOC_UNIT: int = 128
|
||||||
FAT12_MAX_CLUSTERS: int = 4085
|
FAT12_MAX_CLUSTERS: int = 4085
|
||||||
FAT16_MAX_CLUSTERS: int = 65525
|
FAT16_MAX_CLUSTERS: int = 65525
|
||||||
RESERVED_CLUSTERS_COUNT: int = 2
|
RESERVED_CLUSTERS_COUNT: int = 2
|
||||||
@@ -174,7 +175,9 @@ def get_args_for_partition_generator(desc: str, wl: bool) -> argparse.Namespace:
|
|||||||
help='Filename of the generated fatfs image')
|
help='Filename of the generated fatfs image')
|
||||||
parser.add_argument('--partition_size',
|
parser.add_argument('--partition_size',
|
||||||
default=FATDefaults.SIZE,
|
default=FATDefaults.SIZE,
|
||||||
help='Size of the partition in bytes')
|
help='Size of the partition in bytes.' +
|
||||||
|
('' if wl else ' Use `--partition_size detect` for detecting the minimal partition size.')
|
||||||
|
)
|
||||||
parser.add_argument('--sector_size',
|
parser.add_argument('--sector_size',
|
||||||
default=FATDefaults.SECTOR_SIZE,
|
default=FATDefaults.SECTOR_SIZE,
|
||||||
type=int,
|
type=int,
|
||||||
@@ -207,6 +210,8 @@ def get_args_for_partition_generator(desc: str, wl: bool) -> argparse.Namespace:
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
if args.fat_type == 0:
|
if args.fat_type == 0:
|
||||||
args.fat_type = None
|
args.fat_type = None
|
||||||
|
if args.partition_size == 'detect' and not wl:
|
||||||
|
args.partition_size = -1
|
||||||
args.partition_size = int(str(args.partition_size), 0)
|
args.partition_size = int(str(args.partition_size), 0)
|
||||||
if not os.path.isdir(args.input_directory):
|
if not os.path.isdir(args.input_directory):
|
||||||
raise NotADirectoryError(f'The target directory `{args.input_directory}` does not exist!')
|
raise NotADirectoryError(f'The target directory `{args.input_directory}` does not exist!')
|
||||||
|
@@ -7,11 +7,15 @@ from datetime import datetime
|
|||||||
from typing import Any, List, Optional
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
from fatfs_utils.boot_sector import BootSector
|
from fatfs_utils.boot_sector import BootSector
|
||||||
|
from fatfs_utils.exceptions import NoFreeClusterException
|
||||||
from fatfs_utils.fat import FAT
|
from fatfs_utils.fat import FAT
|
||||||
from fatfs_utils.fatfs_state import FATFSState
|
from fatfs_utils.fatfs_state import FATFSState
|
||||||
from fatfs_utils.fs_object import Directory
|
from fatfs_utils.fs_object import Directory
|
||||||
from fatfs_utils.utils import (BYTES_PER_DIRECTORY_ENTRY, FATFS_INCEPTION, FATDefaults,
|
from fatfs_utils.long_filename_utils import get_required_lfn_entries_count
|
||||||
get_args_for_partition_generator, read_filesystem)
|
from fatfs_utils.utils import (BYTES_PER_DIRECTORY_ENTRY, FATFS_INCEPTION, FATFS_MIN_ALLOC_UNIT,
|
||||||
|
RESERVED_CLUSTERS_COUNT, FATDefaults, get_args_for_partition_generator,
|
||||||
|
get_fat_sectors_count, get_non_data_sectors_cnt, read_filesystem,
|
||||||
|
required_clusters_count)
|
||||||
|
|
||||||
|
|
||||||
class FATFS:
|
class FATFS:
|
||||||
@@ -184,8 +188,47 @@ class FATFS:
|
|||||||
self._generate_partition_from_folder(folder_name, folder_path=path_to_folder, is_dir=True)
|
self._generate_partition_from_folder(folder_name, folder_path=path_to_folder, is_dir=True)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_min_space(path: List[str],
|
||||||
|
fs_entity: str,
|
||||||
|
sector_size: int = 0x1000,
|
||||||
|
long_file_names: bool = False,
|
||||||
|
is_root: bool = False) -> int:
|
||||||
|
if os.path.isfile(os.path.join(*path, fs_entity)):
|
||||||
|
with open(os.path.join(*path, fs_entity), 'rb') as file_:
|
||||||
|
content = file_.read()
|
||||||
|
res: int = required_clusters_count(sector_size, content)
|
||||||
|
return res
|
||||||
|
buff: int = 0
|
||||||
|
dir_size = 2 * FATDefaults.ENTRY_SIZE # record for symlinks "." and ".."
|
||||||
|
for file in sorted(os.listdir(os.path.join(*path, fs_entity))):
|
||||||
|
if long_file_names and True:
|
||||||
|
# LFN entries + one short entry
|
||||||
|
dir_size += (get_required_lfn_entries_count(fs_entity) + 1) * FATDefaults.ENTRY_SIZE
|
||||||
|
else:
|
||||||
|
dir_size += FATDefaults.ENTRY_SIZE
|
||||||
|
buff += calculate_min_space(path + [fs_entity], file, sector_size, long_file_names, is_root=False)
|
||||||
|
if is_root and dir_size // FATDefaults.ENTRY_SIZE > FATDefaults.ROOT_ENTRIES_COUNT:
|
||||||
|
raise NoFreeClusterException('Not enough space in root!')
|
||||||
|
|
||||||
|
# roundup sectors, at least one is required
|
||||||
|
buff += (dir_size + sector_size - 1) // sector_size
|
||||||
|
return buff
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
args = get_args_for_partition_generator('Create a FAT filesystem and populate it with directory content', wl=False)
|
args = get_args_for_partition_generator('Create a FAT filesystem and populate it with directory content', wl=False)
|
||||||
|
|
||||||
|
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
|
||||||
|
args.partition_size = max(FATFS_MIN_ALLOC_UNIT * args.sector_size,
|
||||||
|
(clusters + fats + get_non_data_sectors_cnt(RESERVED_CLUSTERS_COUNT,
|
||||||
|
fats,
|
||||||
|
root_dir_sectors)
|
||||||
|
) * args.sector_size
|
||||||
|
)
|
||||||
|
|
||||||
fatfs = FATFS(sector_size=args.sector_size,
|
fatfs = FATFS(sector_size=args.sector_size,
|
||||||
sectors_per_cluster=args.sectors_per_cluster,
|
sectors_per_cluster=args.sectors_per_cluster,
|
||||||
size=args.partition_size,
|
size=args.partition_size,
|
||||||
|
Reference in New Issue
Block a user