Exemple #1
0
class WLFATFS:
    # pylint: disable=too-many-instance-attributes
    CFG_SECTORS_COUNT = 1
    DUMMY_SECTORS_COUNT = 1
    WL_CONFIG_HEADER_SIZE = 48
    WL_STATE_RECORD_SIZE = 16
    WL_STATE_HEADER_SIZE = 64
    WL_STATE_COPY_COUNT = 2
    UINT32_MAX = 4294967295
    WL_SECTOR_SIZE = 0x1000

    WL_STATE_T_DATA = Struct('pos' / Int32ul, 'max_pos' / Int32ul,
                             'move_count' / Int32ul, 'access_count' / Int32ul,
                             'max_count' / Int32ul, 'block_size' / Int32ul,
                             'version' / Int32ul, 'device_id' / Int32ul,
                             'reserved' / Const(28 * b'\x00'))

    WL_CONFIG_T_DATA = Struct('start_addr' / Int32ul,
                              'full_mem_size' / Int32ul, 'page_size' / Int32ul,
                              'sector_size' / Int32ul, 'updaterate' / Int32ul,
                              'wr_size' / Int32ul, 'version' / Int32ul,
                              'temp_buff_size' / Int32ul)
    WL_CONFIG_T_HEADER_SIZE = 48

    def __init__(self,
                 size: int = 1024 * 1024,
                 reserved_sectors_cnt: int = 1,
                 fat_tables_cnt: int = 1,
                 sectors_per_cluster: int = 1,
                 sector_size: int = 0x1000,
                 sectors_per_fat: int = 1,
                 explicit_fat_type: int = None,
                 hidden_sectors: int = 0,
                 long_names_enabled: bool = False,
                 entry_size: int = 32,
                 num_heads: int = 0xff,
                 oem_name: str = 'MSDOS5.0',
                 sec_per_track: int = 0x3f,
                 volume_label: str = 'Espressif',
                 file_sys_type: str = 'FAT',
                 version: int = 2,
                 temp_buff_size: int = 32,
                 update_rate: int = 16,
                 device_id: int = None,
                 root_entry_count: int = 512,
                 media_type: int = 0xf8) -> None:
        if sector_size != WLFATFS.WL_SECTOR_SIZE:
            raise NotImplementedError(
                f'The only supported sector size is currently {WLFATFS.WL_SECTOR_SIZE}'
            )

        self._initialized = False
        self.sector_size = sector_size
        self._version = version
        self._temp_buff_size = temp_buff_size
        self._device_id = device_id
        self._update_rate = update_rate
        self.partition_size = size
        self.total_sectors = self.partition_size // self.sector_size
        self.wl_state_size = WLFATFS.WL_STATE_HEADER_SIZE + WLFATFS.WL_STATE_RECORD_SIZE * self.total_sectors

        # determine the number of required sectors (roundup to sector size)
        self.wl_state_sectors = (self.wl_state_size + self.sector_size -
                                 1) // self.sector_size

        self.boot_sector_start = self.sector_size  # shift by one "dummy" sector
        self.fat_table_start = self.boot_sector_start + reserved_sectors_cnt * self.sector_size

        wl_sectors = WLFATFS.DUMMY_SECTORS_COUNT + WLFATFS.CFG_SECTORS_COUNT + self.wl_state_sectors * 2
        self.plain_fat_sectors = self.total_sectors - wl_sectors

        self.plain_fatfs = FATFS(explicit_fat_type=explicit_fat_type,
                                 size=self.plain_fat_sectors *
                                 self.sector_size,
                                 reserved_sectors_cnt=reserved_sectors_cnt,
                                 fat_tables_cnt=fat_tables_cnt,
                                 sectors_per_cluster=sectors_per_cluster,
                                 sector_size=sector_size,
                                 sectors_per_fat=sectors_per_fat,
                                 root_entry_count=root_entry_count,
                                 hidden_sectors=hidden_sectors,
                                 long_names_enabled=long_names_enabled,
                                 entry_size=entry_size,
                                 num_heads=num_heads,
                                 oem_name=oem_name,
                                 sec_per_track=sec_per_track,
                                 volume_label=volume_label,
                                 file_sys_type=file_sys_type,
                                 media_type=media_type)

        self.fatfs_binary_image = self.plain_fatfs.state.binary_image

    def init_wl(self) -> None:
        self.fatfs_binary_image = self.plain_fatfs.state.binary_image
        self._add_dummy_sector()
        # config must be added after state, do not change the order of these two calls!
        self._add_state_sectors()
        self._add_config_sector()
        self._initialized = True

    def _add_dummy_sector(self) -> None:
        self.fatfs_binary_image = self.sector_size * b'\xff' + self.fatfs_binary_image

    def _add_config_sector(self) -> None:
        wl_config_data = WLFATFS.WL_CONFIG_T_DATA.build(
            dict(start_addr=0,
                 full_mem_size=self.partition_size,
                 page_size=self.sector_size,
                 sector_size=self.sector_size,
                 updaterate=self._update_rate,
                 wr_size=16,
                 version=self._version,
                 temp_buff_size=self._temp_buff_size))

        crc = crc32(list(wl_config_data), WLFATFS.UINT32_MAX)
        wl_config_crc = Int32ul.build(crc)

        # adding three 4 byte zeros to align the structure
        wl_config = wl_config_data + wl_config_crc + Int32ul.build(
            0) + Int32ul.build(0) + Int32ul.build(0)

        self.fatfs_binary_image += (
            wl_config +
            (self.sector_size - WLFATFS.WL_CONFIG_HEADER_SIZE) * b'\xff')

    def _add_state_sectors(self) -> None:
        wl_state_data = WLFATFS.WL_STATE_T_DATA.build(
            dict(
                pos=0,
                max_pos=self.plain_fat_sectors + WLFATFS.DUMMY_SECTORS_COUNT,
                move_count=0,
                access_count=0,
                max_count=self._update_rate,
                block_size=self.sector_size,
                version=self._version,
                device_id=self._device_id or generate_4bytes_random(),
            ))
        crc = crc32(list(wl_state_data), WLFATFS.UINT32_MAX)
        wl_state_crc = Int32ul.build(crc)
        wl_state = wl_state_data + wl_state_crc
        self.fatfs_binary_image += WLFATFS.WL_STATE_COPY_COUNT * (
            (wl_state +
             (self.sector_size - WLFATFS.WL_STATE_HEADER_SIZE) * b'\xff') +
            (self.wl_state_sectors - 1) * self.sector_size * b'\xff')

    def wl_write_filesystem(self, output_path: str) -> None:
        if not self._initialized:
            raise WLNotInitialized(
                'FATFS is not initialized with WL. First call method WLFATFS.init_wl!'
            )
        with open(output_path, 'wb') as output:
            output.write(bytearray(self.fatfs_binary_image))

    def wl_generate(self, input_directory: str) -> None:
        """
        Normalize path to folder and recursively encode folder to binary image
        """
        self.plain_fatfs.generate(input_directory=input_directory)

    def wl_create_file(self,
                       name: str,
                       extension: str = '',
                       path_from_root: Optional[List[str]] = None) -> None:
        self.plain_fatfs.create_file(name, extension, path_from_root)

    def wl_create_directory(
            self,
            name: str,
            path_from_root: Optional[List[str]] = None) -> None:
        self.plain_fatfs.create_directory(name, path_from_root)

    def wl_write_content(self, path_from_root: List[str],
                         content: bytes) -> None:
        self.plain_fatfs.write_content(path_from_root, content)
Exemple #2
0
    def __init__(self,
                 size: int = 1024 * 1024,
                 reserved_sectors_cnt: int = 1,
                 fat_tables_cnt: int = 1,
                 sectors_per_cluster: int = 1,
                 sector_size: int = 0x1000,
                 sectors_per_fat: int = 1,
                 explicit_fat_type: int = None,
                 hidden_sectors: int = 0,
                 long_names_enabled: bool = False,
                 entry_size: int = 32,
                 num_heads: int = 0xff,
                 oem_name: str = 'MSDOS5.0',
                 sec_per_track: int = 0x3f,
                 volume_label: str = 'Espressif',
                 file_sys_type: str = 'FAT',
                 version: int = 2,
                 temp_buff_size: int = 32,
                 update_rate: int = 16,
                 device_id: int = None,
                 root_entry_count: int = 512,
                 media_type: int = 0xf8) -> None:
        if sector_size != WLFATFS.WL_SECTOR_SIZE:
            raise NotImplementedError(
                f'The only supported sector size is currently {WLFATFS.WL_SECTOR_SIZE}'
            )

        self._initialized = False
        self.sector_size = sector_size
        self._version = version
        self._temp_buff_size = temp_buff_size
        self._device_id = device_id
        self._update_rate = update_rate
        self.partition_size = size
        self.total_sectors = self.partition_size // self.sector_size
        self.wl_state_size = WLFATFS.WL_STATE_HEADER_SIZE + WLFATFS.WL_STATE_RECORD_SIZE * self.total_sectors

        # determine the number of required sectors (roundup to sector size)
        self.wl_state_sectors = (self.wl_state_size + self.sector_size -
                                 1) // self.sector_size

        self.boot_sector_start = self.sector_size  # shift by one "dummy" sector
        self.fat_table_start = self.boot_sector_start + reserved_sectors_cnt * self.sector_size

        wl_sectors = WLFATFS.DUMMY_SECTORS_COUNT + WLFATFS.CFG_SECTORS_COUNT + self.wl_state_sectors * 2
        self.plain_fat_sectors = self.total_sectors - wl_sectors

        self.plain_fatfs = FATFS(explicit_fat_type=explicit_fat_type,
                                 size=self.plain_fat_sectors *
                                 self.sector_size,
                                 reserved_sectors_cnt=reserved_sectors_cnt,
                                 fat_tables_cnt=fat_tables_cnt,
                                 sectors_per_cluster=sectors_per_cluster,
                                 sector_size=sector_size,
                                 sectors_per_fat=sectors_per_fat,
                                 root_entry_count=root_entry_count,
                                 hidden_sectors=hidden_sectors,
                                 long_names_enabled=long_names_enabled,
                                 entry_size=entry_size,
                                 num_heads=num_heads,
                                 oem_name=oem_name,
                                 sec_per_track=sec_per_track,
                                 volume_label=volume_label,
                                 file_sys_type=file_sys_type,
                                 media_type=media_type)

        self.fatfs_binary_image = self.plain_fatfs.state.binary_image
Exemple #3
0
def fill_sector(fatfs: fatfsgen.FATFS, file_prefix: str = 'A') -> None:
    for i in range(CFG['sector_size'] // CFG['entry_size']):
        fatfs.create_file(f'{file_prefix}{str(i).upper()}',
                          path_from_root=['TESTFOLD'])