| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- # SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
- # SPDX-License-Identifier: Apache-2.0
- from textwrap import dedent
- from typing import Optional
- from .exceptions import InconsistentFATAttributes
- from .utils import (ALLOWED_SECTOR_SIZES, FAT12, FAT12_MAX_CLUSTERS, FAT16, FAT16_MAX_CLUSTERS,
- RESERVED_CLUSTERS_COUNT, FATDefaults, get_fat_sectors_count, get_fatfs_type,
- get_non_data_sectors_cnt, number_of_clusters)
- class FATFSState:
- """
- The class represents the state and the configuration of the FATFS.
- """
- def __init__(self,
- sector_size: int,
- reserved_sectors_cnt: int,
- root_dir_sectors_cnt: int,
- size: int,
- media_type: int,
- sectors_per_cluster: int,
- volume_label: str,
- oem_name: str,
- fat_tables_cnt: int,
- sec_per_track: int,
- num_heads: int,
- hidden_sectors: int,
- file_sys_type: str,
- use_default_datetime: bool,
- explicit_fat_type: Optional[int] = None,
- long_names_enabled: bool = False):
- self.boot_sector_state = BootSectorState(oem_name=oem_name,
- sector_size=sector_size,
- sectors_per_cluster=sectors_per_cluster,
- reserved_sectors_cnt=reserved_sectors_cnt,
- fat_tables_cnt=fat_tables_cnt,
- root_dir_sectors_cnt=root_dir_sectors_cnt,
- sectors_count=size // sector_size,
- media_type=media_type,
- sec_per_track=sec_per_track,
- num_heads=num_heads,
- hidden_sectors=hidden_sectors,
- volume_label=volume_label,
- file_sys_type=file_sys_type,
- volume_uuid=-1)
- self._explicit_fat_type: Optional[int] = explicit_fat_type
- self.long_names_enabled: bool = long_names_enabled
- self.use_default_datetime: bool = use_default_datetime
- if (size // sector_size) * sectors_per_cluster in (FAT12_MAX_CLUSTERS, FAT16_MAX_CLUSTERS):
- print('WARNING: It is not recommended to create FATFS with bounding '
- f'count of clusters: {FAT12_MAX_CLUSTERS} or {FAT16_MAX_CLUSTERS}')
- self.check_fat_type()
- @property
- def binary_image(self) -> bytearray:
- return self.boot_sector_state.binary_image
- @binary_image.setter
- def binary_image(self, value: bytearray) -> None:
- self.boot_sector_state.binary_image = value
- def check_fat_type(self) -> None:
- _type = self.boot_sector_state.fatfs_type
- if self._explicit_fat_type is not None and self._explicit_fat_type != _type:
- raise InconsistentFATAttributes(dedent(
- f"""FAT type you specified is inconsistent with other attributes of the system.
- The specified FATFS type: FAT{self._explicit_fat_type}
- The actual FATFS type: FAT{_type}"""))
- if _type not in (FAT12, FAT16):
- raise NotImplementedError('FAT32 is currently not supported.')
- class BootSectorState:
- # pylint: disable=too-many-instance-attributes
- def __init__(self,
- oem_name: str,
- sector_size: int,
- sectors_per_cluster: int,
- reserved_sectors_cnt: int,
- fat_tables_cnt: int,
- root_dir_sectors_cnt: int,
- sectors_count: int,
- media_type: int,
- sec_per_track: int,
- num_heads: int,
- hidden_sectors: int,
- volume_label: str,
- file_sys_type: str,
- volume_uuid: int = -1) -> None:
- self.oem_name: str = oem_name
- self.sector_size: int = sector_size
- assert self.sector_size in ALLOWED_SECTOR_SIZES
- self.sectors_per_cluster: int = sectors_per_cluster
- self.reserved_sectors_cnt: int = reserved_sectors_cnt
- self.fat_tables_cnt: int = fat_tables_cnt
- self.root_dir_sectors_cnt: int = root_dir_sectors_cnt
- self.sectors_count: int = sectors_count
- self.media_type: int = media_type
- self.sectors_per_fat_cnt = get_fat_sectors_count(self.size // self.sector_size, self.sector_size)
- self.sec_per_track: int = sec_per_track
- self.num_heads: int = num_heads
- self.hidden_sectors: int = hidden_sectors
- self.volume_label: str = volume_label
- self.file_sys_type: str = file_sys_type
- self.volume_uuid: int = volume_uuid
- self._binary_image: bytearray = bytearray(b'')
- @property
- def binary_image(self) -> bytearray:
- return self._binary_image
- @binary_image.setter
- def binary_image(self, value: bytearray) -> None:
- self._binary_image = value
- @property
- def size(self) -> int:
- return self.sector_size * self.sectors_count
- @property
- def data_region_start(self) -> int:
- return self.non_data_sectors * self.sector_size
- @property
- def fatfs_type(self) -> int:
- # variable typed_fatfs_type must be explicitly typed to avoid mypy error
- typed_fatfs_type: int = get_fatfs_type(self.clusters)
- return typed_fatfs_type
- @property
- def clusters(self) -> int:
- """
- The actual number of clusters is calculated by `number_of_clusters`,
- however, the initial two blocks of FAT are reserved (device type and root directory),
- despite they don't refer to the data region.
- Since that, two clusters are added to use the full potential of the FAT file system partition.
- """
- clusters_cnt_: int = number_of_clusters(self.data_sectors, self.sectors_per_cluster) + RESERVED_CLUSTERS_COUNT
- return clusters_cnt_
- @property
- def data_sectors(self) -> int:
- # self.sector_size is checked in constructor if has one of allowed values (ALLOWED_SECTOR_SIZES)
- return (self.size // self.sector_size) - self.non_data_sectors
- @property
- 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.root_dir_sectors_cnt)
- return non_data_sectors_
- @property
- def fat_table_start_address(self) -> int:
- return self.sector_size * self.reserved_sectors_cnt
- @property
- def entries_root_count(self) -> int:
- entries_root_count_: int = (self.root_dir_sectors_cnt * self.sector_size) // FATDefaults.ENTRY_SIZE
- return entries_root_count_
- @property
- def root_directory_start(self) -> int:
- root_dir_start: int = (self.reserved_sectors_cnt + self.sectors_per_fat_cnt) * self.sector_size
- return root_dir_start
|