mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/enable-fat16' into 'master'
Enable FAT16 for FATFS generator Closes IDF-4046 See merge request espressif/esp-idf!16283
This commit is contained in:
commit
52bdfa6c74
@ -7,6 +7,46 @@ menu "FAT Filesystem support"
|
|||||||
help
|
help
|
||||||
Number of volumes (logical drives) to use.
|
Number of volumes (logical drives) to use.
|
||||||
|
|
||||||
|
choice FATFS_SECTOR_SIZE
|
||||||
|
prompt "Sector size"
|
||||||
|
default FATFS_SECTOR_4096
|
||||||
|
help
|
||||||
|
Specify the size of the sector in bytes for FATFS partition generator.
|
||||||
|
|
||||||
|
config FATFS_SECTOR_512
|
||||||
|
bool "512"
|
||||||
|
config FATFS_SECTOR_1024
|
||||||
|
bool "1024"
|
||||||
|
config FATFS_SECTOR_2048
|
||||||
|
bool "2048"
|
||||||
|
config FATFS_SECTOR_4096
|
||||||
|
bool "4096"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice FATFS_SECTORS_PER_CLUSTER
|
||||||
|
prompt "Sectors per cluster"
|
||||||
|
default FATFS_SECTORS_PER_CLUSTER_1
|
||||||
|
help
|
||||||
|
This value specifies how many sectors there are in one cluster.
|
||||||
|
|
||||||
|
config FATFS_SECTORS_PER_CLUSTER_1
|
||||||
|
bool "1"
|
||||||
|
config FATFS_SECTORS_PER_CLUSTER_2
|
||||||
|
bool "2"
|
||||||
|
config FATFS_SECTORS_PER_CLUSTER_4
|
||||||
|
bool "4"
|
||||||
|
config FATFS_SECTORS_PER_CLUSTER_8
|
||||||
|
bool "8"
|
||||||
|
config FATFS_SECTORS_PER_CLUSTER_16
|
||||||
|
bool "16"
|
||||||
|
config FATFS_SECTORS_PER_CLUSTER_32
|
||||||
|
bool "32"
|
||||||
|
config FATFS_SECTORS_PER_CLUSTER_64
|
||||||
|
bool "64"
|
||||||
|
config FATFS_SECTORS_PER_CLUSTER_128
|
||||||
|
bool "128"
|
||||||
|
endchoice
|
||||||
|
|
||||||
choice FATFS_CHOOSE_CODEPAGE
|
choice FATFS_CHOOSE_CODEPAGE
|
||||||
prompt "OEM Code Page"
|
prompt "OEM Code Page"
|
||||||
default FATFS_CODEPAGE_437
|
default FATFS_CODEPAGE_437
|
||||||
@ -64,6 +104,21 @@ menu "FAT Filesystem support"
|
|||||||
|
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
|
choice FATFS_CHOOSE_TYPE
|
||||||
|
prompt "FAT type"
|
||||||
|
default FATFS_AUTO_TYPE
|
||||||
|
help
|
||||||
|
If user specifies automatic detection of the FAT type,
|
||||||
|
the FATFS generator will determine the type by the size.
|
||||||
|
|
||||||
|
config FATFS_AUTO_TYPE
|
||||||
|
bool "Select a suitable FATFS type automatically."
|
||||||
|
config FATFS_FAT12
|
||||||
|
bool "FAT12"
|
||||||
|
config FATFS_FAT16
|
||||||
|
bool "FAT16"
|
||||||
|
endchoice
|
||||||
|
|
||||||
config FATFS_CODEPAGE
|
config FATFS_CODEPAGE
|
||||||
int
|
int
|
||||||
default 0 if FATFS_CODEPAGE_DYNAMIC
|
default 0 if FATFS_CODEPAGE_DYNAMIC
|
||||||
@ -96,7 +151,7 @@ menu "FAT Filesystem support"
|
|||||||
help
|
help
|
||||||
Support long filenames in FAT. Long filename data increases
|
Support long filenames in FAT. Long filename data increases
|
||||||
memory usage. FATFS can be configured to store the buffer for
|
memory usage. FATFS can be configured to store the buffer for
|
||||||
long filename data in stack or heap.
|
long filename data in stack or heap (Currently not supported by FATFS partition generator).
|
||||||
|
|
||||||
config FATFS_LFN_NONE
|
config FATFS_LFN_NONE
|
||||||
bool "No long filenames"
|
bool "No long filenames"
|
||||||
|
@ -5,11 +5,12 @@
|
|||||||
import os
|
import os
|
||||||
from typing import Any, List, Optional
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
from construct import Const, Int8ul, Int16ul, Int32ul, PaddedString, Struct
|
|
||||||
from fatfsgen_utils.fat import FAT
|
from fatfsgen_utils.fat import FAT
|
||||||
|
from fatfsgen_utils.fatfs_parser import FATFSParser
|
||||||
from fatfsgen_utils.fatfs_state import FATFSState
|
from fatfsgen_utils.fatfs_state import FATFSState
|
||||||
from fatfsgen_utils.fs_object import Directory
|
from fatfsgen_utils.fs_object import Directory
|
||||||
from fatfsgen_utils.utils import generate_4bytes_random, get_args_for_partition_generator, pad_string
|
from fatfsgen_utils.utils import (BYTES_PER_DIRECTORY_ENTRY, FAT32, generate_4bytes_random,
|
||||||
|
get_args_for_partition_generator, pad_string, read_filesystem)
|
||||||
|
|
||||||
|
|
||||||
class FATFS:
|
class FATFS:
|
||||||
@ -17,35 +18,6 @@ class FATFS:
|
|||||||
The class FATFS provides API for generating FAT file system.
|
The class FATFS provides API for generating FAT file system.
|
||||||
It contains reference to the FAT table and to the root directory.
|
It contains reference to the FAT table and to the root directory.
|
||||||
"""
|
"""
|
||||||
MAX_VOL_LAB_SIZE = 11
|
|
||||||
MAX_OEM_NAME_SIZE = 8
|
|
||||||
MAX_FS_TYPE_SIZE = 8
|
|
||||||
BOOT_HEADER_SIZE = 512
|
|
||||||
|
|
||||||
BOOT_SECTOR_HEADER = Struct(
|
|
||||||
'BS_jmpBoot' / Const(b'\xeb\xfe\x90'),
|
|
||||||
'BS_OEMName' / PaddedString(MAX_OEM_NAME_SIZE, 'utf-8'),
|
|
||||||
'BPB_BytsPerSec' / Int16ul,
|
|
||||||
'BPB_SecPerClus' / Int8ul,
|
|
||||||
'BPB_RsvdSecCnt' / Int16ul,
|
|
||||||
'BPB_NumFATs' / Int8ul,
|
|
||||||
'BPB_RootEntCnt' / Int16ul,
|
|
||||||
'BPB_TotSec16' / Int16ul,
|
|
||||||
'BPB_Media' / Int8ul,
|
|
||||||
'BPB_FATSz16' / Int16ul,
|
|
||||||
'BPB_SecPerTrk' / Int16ul,
|
|
||||||
'BPB_NumHeads' / Int16ul,
|
|
||||||
'BPB_HiddSec' / Int32ul,
|
|
||||||
'BPB_TotSec32' / Int32ul,
|
|
||||||
'BS_DrvNum' / Const(b'\x80'),
|
|
||||||
'BS_Reserved1' / Const(b'\x00'),
|
|
||||||
'BS_BootSig' / Const(b'\x29'),
|
|
||||||
'BS_VolID' / Int32ul,
|
|
||||||
'BS_VolLab' / PaddedString(MAX_VOL_LAB_SIZE, 'utf-8'),
|
|
||||||
'BS_FilSysType' / PaddedString(MAX_FS_TYPE_SIZE, 'utf-8'),
|
|
||||||
'BS_EMPTY' / Const(448 * b'\x00'),
|
|
||||||
'Signature_word' / Const(b'\x55\xAA')
|
|
||||||
)
|
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
binary_image_path: Optional[str] = None,
|
binary_image_path: Optional[str] = None,
|
||||||
@ -55,7 +27,6 @@ class FATFS:
|
|||||||
sectors_per_cluster: int = 1,
|
sectors_per_cluster: int = 1,
|
||||||
sector_size: int = 0x1000,
|
sector_size: int = 0x1000,
|
||||||
sectors_per_fat: int = 1,
|
sectors_per_fat: int = 1,
|
||||||
root_dir_sectors_cnt: int = 4,
|
|
||||||
hidden_sectors: int = 0,
|
hidden_sectors: int = 0,
|
||||||
long_names_enabled: bool = False,
|
long_names_enabled: bool = False,
|
||||||
entry_size: int = 32,
|
entry_size: int = 32,
|
||||||
@ -64,10 +35,18 @@ class FATFS:
|
|||||||
sec_per_track: int = 0x3f,
|
sec_per_track: int = 0x3f,
|
||||||
volume_label: str = 'Espressif',
|
volume_label: str = 'Espressif',
|
||||||
file_sys_type: str = 'FAT',
|
file_sys_type: str = 'FAT',
|
||||||
|
root_entry_count: int = 512,
|
||||||
|
explicit_fat_type: int = None,
|
||||||
media_type: int = 0xf8) -> None:
|
media_type: int = 0xf8) -> None:
|
||||||
|
|
||||||
|
assert (root_entry_count * BYTES_PER_DIRECTORY_ENTRY) % sector_size == 0
|
||||||
|
assert ((root_entry_count * BYTES_PER_DIRECTORY_ENTRY) // sector_size) % 2 == 0
|
||||||
|
|
||||||
|
root_dir_sectors_cnt = (root_entry_count * BYTES_PER_DIRECTORY_ENTRY) // sector_size
|
||||||
|
|
||||||
self.state = FATFSState(entry_size=entry_size,
|
self.state = FATFSState(entry_size=entry_size,
|
||||||
sector_size=sector_size,
|
sector_size=sector_size,
|
||||||
|
explicit_fat_type=explicit_fat_type,
|
||||||
reserved_sectors_cnt=reserved_sectors_cnt,
|
reserved_sectors_cnt=reserved_sectors_cnt,
|
||||||
root_dir_sectors_cnt=root_dir_sectors_cnt,
|
root_dir_sectors_cnt=root_dir_sectors_cnt,
|
||||||
size=size,
|
size=size,
|
||||||
@ -83,13 +62,13 @@ class FATFS:
|
|||||||
volume_label=volume_label,
|
volume_label=volume_label,
|
||||||
oem_name=oem_name)
|
oem_name=oem_name)
|
||||||
binary_image = bytearray(
|
binary_image = bytearray(
|
||||||
self.read_filesystem(binary_image_path) if binary_image_path else self.create_empty_fatfs())
|
read_filesystem(binary_image_path) if binary_image_path else self.create_empty_fatfs())
|
||||||
self.state.binary_image = binary_image
|
self.state.binary_image = binary_image
|
||||||
|
|
||||||
self.fat = FAT(fatfs_state=self.state,
|
self.fat = FAT(fatfs_state=self.state,
|
||||||
reserved_sectors_cnt=self.state.reserved_sectors_cnt)
|
reserved_sectors_cnt=self.state.reserved_sectors_cnt)
|
||||||
|
|
||||||
self.root_directory = Directory(name='A', # the name is not important
|
self.root_directory = Directory(name='A', # the name is not important, must be string
|
||||||
size=self.state.root_dir_sectors_cnt * self.state.sector_size,
|
size=self.state.root_dir_sectors_cnt * self.state.sector_size,
|
||||||
fat=self.fat,
|
fat=self.fat,
|
||||||
cluster=self.fat.clusters[1],
|
cluster=self.fat.clusters[1],
|
||||||
@ -105,6 +84,7 @@ class FATFS:
|
|||||||
parent_dir = self.root_directory
|
parent_dir = self.root_directory
|
||||||
if path_from_root:
|
if path_from_root:
|
||||||
parent_dir = self.root_directory.recursive_search(path_from_root, self.root_directory)
|
parent_dir = self.root_directory.recursive_search(path_from_root, self.root_directory)
|
||||||
|
|
||||||
self.root_directory.new_directory(name=name, parent=parent_dir, path_from_root=path_from_root)
|
self.root_directory.new_directory(name=name, parent=parent_dir, path_from_root=path_from_root)
|
||||||
|
|
||||||
def write_content(self, path_from_root: List[str], content: bytes) -> None:
|
def write_content(self, path_from_root: List[str], content: bytes) -> None:
|
||||||
@ -117,36 +97,31 @@ class FATFS:
|
|||||||
sectors_count = self.state.size // self.state.sector_size
|
sectors_count = self.state.size // self.state.sector_size
|
||||||
volume_uuid = generate_4bytes_random()
|
volume_uuid = generate_4bytes_random()
|
||||||
return (
|
return (
|
||||||
FATFS.BOOT_SECTOR_HEADER.build(
|
FATFSParser.BOOT_SECTOR_HEADER.build(
|
||||||
dict(BS_OEMName=pad_string(self.state.oem_name, size=FATFS.MAX_OEM_NAME_SIZE),
|
dict(BS_OEMName=pad_string(self.state.oem_name, size=FATFSParser.MAX_OEM_NAME_SIZE),
|
||||||
BPB_BytsPerSec=self.state.sectors_per_cluster * self.state.sector_size,
|
BPB_BytsPerSec=self.state.sector_size,
|
||||||
BPB_SecPerClus=self.state.sectors_per_cluster,
|
BPB_SecPerClus=self.state.sectors_per_cluster,
|
||||||
BPB_RsvdSecCnt=self.state.reserved_sectors_cnt,
|
BPB_RsvdSecCnt=self.state.reserved_sectors_cnt,
|
||||||
BPB_NumFATs=self.state.fat_tables_cnt,
|
BPB_NumFATs=self.state.fat_tables_cnt,
|
||||||
BPB_RootEntCnt=self.state.entries_root_count,
|
BPB_RootEntCnt=self.state.entries_root_count,
|
||||||
BPB_TotSec16=0x00 if self.state.fatfs_type == FATFSState.FAT32 else sectors_count,
|
BPB_TotSec16=0x00 if self.state.fatfs_type == FAT32 else sectors_count,
|
||||||
BPB_Media=self.state.media_type,
|
BPB_Media=self.state.media_type,
|
||||||
BPB_FATSz16=self.state.sectors_per_fat_cnt,
|
BPB_FATSz16=self.state.sectors_per_fat_cnt,
|
||||||
BPB_SecPerTrk=self.state.sec_per_track,
|
BPB_SecPerTrk=self.state.sec_per_track,
|
||||||
BPB_NumHeads=self.state.num_heads,
|
BPB_NumHeads=self.state.num_heads,
|
||||||
BPB_HiddSec=self.state.hidden_sectors,
|
BPB_HiddSec=self.state.hidden_sectors,
|
||||||
BPB_TotSec32=sectors_count if self.state.fatfs_type == FATFSState.FAT32 else 0x00,
|
BPB_TotSec32=sectors_count if self.state.fatfs_type == FAT32 else 0x00,
|
||||||
BS_VolID=volume_uuid,
|
BS_VolID=volume_uuid,
|
||||||
BS_VolLab=pad_string(self.state.volume_label, size=FATFS.MAX_VOL_LAB_SIZE),
|
BS_VolLab=pad_string(self.state.volume_label, size=FATFSParser.MAX_VOL_LAB_SIZE),
|
||||||
BS_FilSysType=pad_string(self.state.file_sys_type, size=FATFS.MAX_FS_TYPE_SIZE)
|
BS_FilSysType=pad_string(self.state.file_sys_type, size=FATFSParser.MAX_FS_TYPE_SIZE)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
+ (self.state.sector_size - FATFS.BOOT_HEADER_SIZE) * b'\x00'
|
+ (self.state.sector_size - FATFSParser.BOOT_HEADER_SIZE) * b'\x00'
|
||||||
+ self.state.sectors_per_fat_cnt * self.state.fat_tables_cnt * self.state.sector_size * b'\x00'
|
+ self.state.sectors_per_fat_cnt * self.state.fat_tables_cnt * self.state.sector_size * b'\x00'
|
||||||
+ self.state.root_dir_sectors_cnt * self.state.sector_size * b'\x00'
|
+ self.state.root_dir_sectors_cnt * self.state.sector_size * b'\x00'
|
||||||
+ self.state.data_sectors * self.state.sector_size * b'\xff'
|
+ self.state.data_sectors * self.state.sector_size * b'\xff'
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def read_filesystem(path: str) -> bytearray:
|
|
||||||
with open(path, 'rb') as fs_file:
|
|
||||||
return bytearray(fs_file.read())
|
|
||||||
|
|
||||||
def write_filesystem(self, output_path: str) -> None:
|
def write_filesystem(self, output_path: str) -> None:
|
||||||
with open(output_path, 'wb') as output:
|
with open(output_path, 'wb') as output:
|
||||||
output.write(bytearray(self.state.binary_image))
|
output.write(bytearray(self.state.binary_image))
|
||||||
@ -190,13 +165,17 @@ 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)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
def main() -> None:
|
||||||
args = get_args_for_partition_generator('Create a FAT filesystem and populate it with directory content')
|
args = get_args_for_partition_generator('Create a FAT filesystem and populate it with directory content')
|
||||||
input_dir = args.input_directory
|
fatfs = FATFS(sector_size=args.sector_size,
|
||||||
|
sectors_per_cluster=args.sectors_per_cluster,
|
||||||
|
size=args.partition_size,
|
||||||
|
root_entry_count=args.root_entry_count,
|
||||||
|
explicit_fat_type=args.fat_type)
|
||||||
|
|
||||||
partition_size = int(str(args.partition_size), 0)
|
fatfs.generate(args.input_directory)
|
||||||
sector_size_bytes = int(str(args.sector_size), 0)
|
|
||||||
|
|
||||||
fatfs = FATFS(size=partition_size, sector_size=sector_size_bytes)
|
|
||||||
fatfs.generate(input_dir)
|
|
||||||
fatfs.write_filesystem(args.output_file)
|
fatfs.write_filesystem(args.output_file)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
from construct import Int16ul
|
||||||
|
|
||||||
from .fatfs_state import FATFSState
|
from .fatfs_state import FATFSState
|
||||||
from .utils import build_byte, clean_first_half_byte, clean_second_half_byte, split_by_half_byte_12_bit_little_endian
|
from .utils import (FAT12, FAT16, build_byte, clean_first_half_byte, clean_second_half_byte,
|
||||||
|
split_by_half_byte_12_bit_little_endian)
|
||||||
|
|
||||||
|
|
||||||
class Cluster:
|
class Cluster:
|
||||||
@ -13,7 +16,10 @@ class Cluster:
|
|||||||
"""
|
"""
|
||||||
RESERVED_BLOCK_ID = 0
|
RESERVED_BLOCK_ID = 0
|
||||||
ROOT_BLOCK_ID = 1
|
ROOT_BLOCK_ID = 1
|
||||||
ALLOCATED_BLOCK_VALUE = 0xFFF # for fat 12
|
ALLOCATED_BLOCK_FAT12 = 0xFFF
|
||||||
|
ALLOCATED_BLOCK_FAT16 = 0xFFFF
|
||||||
|
ALLOCATED_BLOCK_SWITCH = {FAT12: ALLOCATED_BLOCK_FAT12, FAT16: ALLOCATED_BLOCK_FAT16}
|
||||||
|
INITIAL_BLOCK_SWITCH = {FAT12: 0xFF8, FAT16: 0xFFF8}
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
cluster_id: int,
|
cluster_id: int,
|
||||||
@ -26,7 +32,7 @@ class Cluster:
|
|||||||
self._next_cluster = None # type: Optional[Cluster]
|
self._next_cluster = None # type: Optional[Cluster]
|
||||||
if self.id == Cluster.RESERVED_BLOCK_ID:
|
if self.id == Cluster.RESERVED_BLOCK_ID:
|
||||||
self.is_empty = False
|
self.is_empty = False
|
||||||
self.set_in_fat(0xff8)
|
self.set_in_fat(self.INITIAL_BLOCK_SWITCH[self.fatfs_state.fatfs_type])
|
||||||
return
|
return
|
||||||
|
|
||||||
self.cluster_data_address = self._compute_cluster_data_address()
|
self.cluster_data_address = self._compute_cluster_data_address()
|
||||||
@ -86,14 +92,16 @@ class Cluster:
|
|||||||
assert value <= (1 << self.fatfs_state.fatfs_type) - 1
|
assert value <= (1 << self.fatfs_state.fatfs_type) - 1
|
||||||
half_bytes = split_by_half_byte_12_bit_little_endian(value)
|
half_bytes = split_by_half_byte_12_bit_little_endian(value)
|
||||||
|
|
||||||
# hardcoded for fat 12
|
if self.fatfs_state.fatfs_type == FAT12:
|
||||||
# IDF-4046 will extend it for fat 16
|
|
||||||
if self.fat_cluster_address % 8 == 0:
|
if self.fat_cluster_address % 8 == 0:
|
||||||
self.fatfs_state.binary_image[self.real_cluster_address] = build_byte(half_bytes[1], half_bytes[0])
|
self.fatfs_state.binary_image[self.real_cluster_address] = build_byte(half_bytes[1], half_bytes[0])
|
||||||
self._set_second_half_byte(self.real_cluster_address + 1, half_bytes[2])
|
self._set_second_half_byte(self.real_cluster_address + 1, half_bytes[2])
|
||||||
elif self.fat_cluster_address % 8 != 0:
|
elif self.fat_cluster_address % 8 != 0:
|
||||||
self._set_first_half_byte(self.real_cluster_address, half_bytes[0])
|
self._set_first_half_byte(self.real_cluster_address, half_bytes[0])
|
||||||
self.fatfs_state.binary_image[self.real_cluster_address + 1] = build_byte(half_bytes[2], half_bytes[1])
|
self.fatfs_state.binary_image[self.real_cluster_address + 1] = build_byte(half_bytes[2], half_bytes[1])
|
||||||
|
elif self.fatfs_state.fatfs_type == FAT16:
|
||||||
|
self.fatfs_state.binary_image[self.real_cluster_address:self.real_cluster_address + 2] = Int16ul.build(
|
||||||
|
value)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_root(self) -> bool:
|
def is_root(self) -> bool:
|
||||||
@ -104,7 +112,7 @@ class Cluster:
|
|||||||
This method sets bits in FAT table to `allocated` and clean the corresponding sector(s)
|
This method sets bits in FAT table to `allocated` and clean the corresponding sector(s)
|
||||||
"""
|
"""
|
||||||
self.is_empty = False
|
self.is_empty = False
|
||||||
self.set_in_fat(Cluster.ALLOCATED_BLOCK_VALUE)
|
self.set_in_fat(self.ALLOCATED_BLOCK_SWITCH[self.fatfs_state.fatfs_type])
|
||||||
|
|
||||||
cluster_start = self.cluster_data_address
|
cluster_start = self.cluster_data_address
|
||||||
dir_size = self.fatfs_state.get_dir_size(self.is_root)
|
dir_size = self.fatfs_state.get_dir_size(self.is_root)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
class WriteDirectoryException(Exception):
|
class WriteDirectoryException(Exception):
|
||||||
@ -38,3 +38,7 @@ class WLNotInitialized(Exception):
|
|||||||
|
|
||||||
class FatalError(Exception):
|
class FatalError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InconsistentFATAttributes(Exception):
|
||||||
|
pass
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
from .cluster import Cluster
|
from .cluster import Cluster
|
||||||
@ -18,7 +18,7 @@ class FAT:
|
|||||||
self.reserved_sectors_cnt = reserved_sectors_cnt
|
self.reserved_sectors_cnt = reserved_sectors_cnt
|
||||||
|
|
||||||
self.clusters = [Cluster(cluster_id=i, fatfs_state=self.fatfs_state) for i in
|
self.clusters = [Cluster(cluster_id=i, fatfs_state=self.fatfs_state) for i in
|
||||||
range(1, self.fatfs_state.max_clusters)]
|
range(1, self.fatfs_state.clusters)]
|
||||||
|
|
||||||
# update root directory record
|
# update root directory record
|
||||||
self.clusters[0].allocate_cluster()
|
self.clusters[0].allocate_cluster()
|
||||||
|
67
components/fatfs/fatfsgen_utils/fatfs_parser.py
Normal file
67
components/fatfs/fatfsgen_utils/fatfs_parser.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
from construct import Const, Int8ul, Int16ul, Int32ul, PaddedString, Struct
|
||||||
|
|
||||||
|
from .utils import (BYTES_PER_DIRECTORY_ENTRY, get_fatfs_type, get_non_data_sectors_cnt, number_of_clusters,
|
||||||
|
read_filesystem)
|
||||||
|
|
||||||
|
|
||||||
|
class FATFSParser:
|
||||||
|
MAX_VOL_LAB_SIZE = 11
|
||||||
|
MAX_OEM_NAME_SIZE = 8
|
||||||
|
MAX_FS_TYPE_SIZE = 8
|
||||||
|
|
||||||
|
# the FAT specification defines 512 bytes for the boot sector header
|
||||||
|
BOOT_HEADER_SIZE = 512
|
||||||
|
|
||||||
|
BOOT_SECTOR_HEADER = Struct(
|
||||||
|
'BS_jmpBoot' / Const(b'\xeb\xfe\x90'),
|
||||||
|
'BS_OEMName' / PaddedString(MAX_OEM_NAME_SIZE, 'utf-8'),
|
||||||
|
'BPB_BytsPerSec' / Int16ul,
|
||||||
|
'BPB_SecPerClus' / Int8ul,
|
||||||
|
'BPB_RsvdSecCnt' / Int16ul,
|
||||||
|
'BPB_NumFATs' / Int8ul,
|
||||||
|
'BPB_RootEntCnt' / Int16ul,
|
||||||
|
'BPB_TotSec16' / Int16ul,
|
||||||
|
'BPB_Media' / Int8ul,
|
||||||
|
'BPB_FATSz16' / Int16ul,
|
||||||
|
'BPB_SecPerTrk' / Int16ul,
|
||||||
|
'BPB_NumHeads' / Int16ul,
|
||||||
|
'BPB_HiddSec' / Int32ul,
|
||||||
|
'BPB_TotSec32' / Int32ul,
|
||||||
|
'BS_DrvNum' / Const(b'\x80'),
|
||||||
|
'BS_Reserved1' / Const(b'\x00'),
|
||||||
|
'BS_BootSig' / Const(b'\x29'),
|
||||||
|
'BS_VolID' / Int32ul,
|
||||||
|
'BS_VolLab' / PaddedString(MAX_VOL_LAB_SIZE, 'utf-8'),
|
||||||
|
'BS_FilSysType' / PaddedString(MAX_FS_TYPE_SIZE, 'utf-8'),
|
||||||
|
'BS_EMPTY' / Const(448 * b'\x00'),
|
||||||
|
'Signature_word' / Const(b'\x55\xAA')
|
||||||
|
)
|
||||||
|
assert BOOT_SECTOR_HEADER.sizeof() == BOOT_HEADER_SIZE
|
||||||
|
|
||||||
|
def __init__(self, image_file_path: str, wl_support: bool = False) -> None:
|
||||||
|
if wl_support:
|
||||||
|
raise NotImplementedError('Parser is not implemented for WL yet.')
|
||||||
|
self.fatfs = read_filesystem(image_file_path)
|
||||||
|
|
||||||
|
# when wl is not supported we expect boot sector to be the first
|
||||||
|
self.parsed_header = FATFSParser.BOOT_SECTOR_HEADER.parse(self.fatfs[:FATFSParser.BOOT_HEADER_SIZE])
|
||||||
|
|
||||||
|
def print(self) -> None:
|
||||||
|
print('Properties of the FATFS:')
|
||||||
|
for key in self.parsed_header.keys():
|
||||||
|
if key in ('_io', 'BS_EMPTY', 'Signature_word'):
|
||||||
|
continue
|
||||||
|
print(' {}: {}'.format(key.replace('BPB_', '').replace('BS_', ''), self.parsed_header[key]))
|
||||||
|
root_dir_cnt = (self.parsed_header['BPB_RootEntCnt'] * BYTES_PER_DIRECTORY_ENTRY) // self.parsed_header[
|
||||||
|
'BPB_BytsPerSec']
|
||||||
|
non_data_sectors = get_non_data_sectors_cnt(self.parsed_header['BPB_RsvdSecCnt'],
|
||||||
|
# this has to be changed when FAT32 is supported
|
||||||
|
self.parsed_header['BPB_FATSz16'], root_dir_cnt)
|
||||||
|
data_clusters = self.parsed_header['BPB_TotSec16'] - non_data_sectors
|
||||||
|
clusters_num = number_of_clusters(data_clusters, self.parsed_header['BPB_SecPerClus'])
|
||||||
|
assert self.parsed_header['BPB_BytsPerSec'] in (512, 1024, 2048, 4096)
|
||||||
|
assert self.parsed_header['BPB_SecPerClus'] in (1, 2, 4, 8, 16, 32, 64, 128)
|
||||||
|
print(f' Clusters number: {clusters_num}')
|
||||||
|
print(f' FATFS type: FAT{get_fatfs_type(clusters_num)}')
|
@ -1,16 +1,17 @@
|
|||||||
# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
from .exceptions import InconsistentFATAttributes
|
||||||
|
from .utils import (FAT12, FAT12_MAX_CLUSTERS, FAT16, FAT16_MAX_CLUSTERS, get_fatfs_type, get_non_data_sectors_cnt,
|
||||||
|
number_of_clusters)
|
||||||
|
|
||||||
|
|
||||||
class FATFSState:
|
class FATFSState:
|
||||||
"""
|
"""
|
||||||
The class represents the state and the configuration of the FATFS.
|
The class represents the state and the configuration of the FATFS.
|
||||||
"""
|
"""
|
||||||
FAT12_MAX_CLUSTERS = 4085
|
|
||||||
FAT16_MAX_CLUSTERS = 65525
|
|
||||||
FAT12 = 12
|
|
||||||
FAT16 = 16
|
|
||||||
FAT32 = 32
|
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
entry_size: int,
|
entry_size: int,
|
||||||
@ -28,7 +29,10 @@ class FATFSState:
|
|||||||
num_heads: int,
|
num_heads: int,
|
||||||
hidden_sectors: int,
|
hidden_sectors: int,
|
||||||
file_sys_type: str,
|
file_sys_type: str,
|
||||||
|
explicit_fat_type: int = None,
|
||||||
long_names_enabled: bool = False):
|
long_names_enabled: bool = False):
|
||||||
|
|
||||||
|
self._explicit_fat_type = explicit_fat_type
|
||||||
self._binary_image: bytearray = bytearray(b'')
|
self._binary_image: bytearray = bytearray(b'')
|
||||||
self.fat_tables_cnt: int = fat_tables_cnt
|
self.fat_tables_cnt: int = fat_tables_cnt
|
||||||
self.oem_name: str = oem_name
|
self.oem_name: str = oem_name
|
||||||
@ -47,6 +51,11 @@ class FATFSState:
|
|||||||
self.sectors_per_fat_cnt: int = sectors_per_fat
|
self.sectors_per_fat_cnt: int = sectors_per_fat
|
||||||
self.sectors_per_cluster: int = sectors_per_cluster
|
self.sectors_per_cluster: int = sectors_per_cluster
|
||||||
|
|
||||||
|
if self.clusters 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
|
@property
|
||||||
def binary_image(self) -> bytearray:
|
def binary_image(self) -> bytearray:
|
||||||
return self._binary_image
|
return self._binary_image
|
||||||
@ -68,28 +77,36 @@ class FATFSState:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def non_data_sectors(self) -> int:
|
def non_data_sectors(self) -> int:
|
||||||
return self.reserved_sectors_cnt + self.sectors_per_fat_cnt + self.root_dir_sectors_cnt
|
return get_non_data_sectors_cnt(self.reserved_sectors_cnt, self.sectors_per_fat_cnt, # type: ignore
|
||||||
|
self.root_dir_sectors_cnt)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def data_region_start(self) -> int:
|
def data_region_start(self) -> int:
|
||||||
return self.non_data_sectors * self.sector_size
|
return self.non_data_sectors * self.sector_size
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def max_clusters(self) -> int:
|
def clusters(self) -> int:
|
||||||
return self.data_sectors // self.sectors_per_cluster
|
return number_of_clusters(self.data_sectors, self.sectors_per_cluster) # type: ignore
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def root_directory_start(self) -> int:
|
def root_directory_start(self) -> int:
|
||||||
return (self.reserved_sectors_cnt + self.sectors_per_fat_cnt) * self.sector_size
|
return (self.reserved_sectors_cnt + self.sectors_per_fat_cnt) * self.sector_size
|
||||||
|
|
||||||
|
def check_fat_type(self) -> None:
|
||||||
|
_type = self.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.')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fatfs_type(self) -> int:
|
def fatfs_type(self) -> int:
|
||||||
if self.max_clusters < FATFSState.FAT12_MAX_CLUSTERS:
|
# variable typed_fatfs_type must be explicitly typed to avoid mypy error
|
||||||
return FATFSState.FAT12
|
typed_fatfs_type: int = get_fatfs_type(self.clusters)
|
||||||
elif self.max_clusters < FATFSState.FAT16_MAX_CLUSTERS:
|
return typed_fatfs_type
|
||||||
return FATFSState.FAT16
|
|
||||||
# fat is FAT.FAT32, not supported now
|
|
||||||
raise NotImplementedError('FAT32 is currently not supported.')
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def entries_root_count(self) -> int:
|
def entries_root_count(self) -> int:
|
||||||
|
@ -9,6 +9,13 @@ from typing import List, Optional, Tuple
|
|||||||
|
|
||||||
from construct import Int16ul
|
from construct import Int16ul
|
||||||
|
|
||||||
|
FAT12_MAX_CLUSTERS: int = 4085
|
||||||
|
FAT16_MAX_CLUSTERS: int = 65525
|
||||||
|
FAT12: int = 12
|
||||||
|
FAT16: int = 16
|
||||||
|
FAT32: int = 32
|
||||||
|
BYTES_PER_DIRECTORY_ENTRY = 32
|
||||||
|
|
||||||
|
|
||||||
def crc32(input_values: List[int], crc: int) -> int:
|
def crc32(input_values: List[int], crc: int) -> int:
|
||||||
"""
|
"""
|
||||||
@ -18,6 +25,22 @@ def crc32(input_values: List[int], crc: int) -> int:
|
|||||||
return binascii.crc32(bytearray(input_values), crc)
|
return binascii.crc32(bytearray(input_values), crc)
|
||||||
|
|
||||||
|
|
||||||
|
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_fatfs_type(clusters_count: int) -> int:
|
||||||
|
if clusters_count < FAT12_MAX_CLUSTERS:
|
||||||
|
return FAT12
|
||||||
|
if clusters_count < FAT16_MAX_CLUSTERS:
|
||||||
|
return FAT16
|
||||||
|
return FAT32
|
||||||
|
|
||||||
|
|
||||||
def required_clusters_count(cluster_size: int, content: bytes) -> int:
|
def required_clusters_count(cluster_size: int, content: bytes) -> int:
|
||||||
# compute number of required clusters for file text
|
# compute number of required clusters for file text
|
||||||
return (len(content) + cluster_size - 1) // cluster_size
|
return (len(content) + cluster_size - 1) // cluster_size
|
||||||
@ -88,8 +111,35 @@ def get_args_for_partition_generator(desc: str) -> argparse.Namespace:
|
|||||||
help='Size of the partition in bytes')
|
help='Size of the partition in bytes')
|
||||||
parser.add_argument('--sector_size',
|
parser.add_argument('--sector_size',
|
||||||
default=4096,
|
default=4096,
|
||||||
|
type=int,
|
||||||
|
choices=[512, 1024, 2048, 4096],
|
||||||
help='Size of the partition in bytes')
|
help='Size of the partition in bytes')
|
||||||
|
parser.add_argument('--sectors_per_cluster',
|
||||||
|
default=1,
|
||||||
|
type=int,
|
||||||
|
choices=[1, 2, 4, 8, 16, 32, 64, 128],
|
||||||
|
help='Number of sectors per cluster')
|
||||||
|
parser.add_argument('--root_entry_count',
|
||||||
|
default=512,
|
||||||
|
help='Number of entries in the root directory')
|
||||||
|
parser.add_argument('--fat_type',
|
||||||
|
default=0,
|
||||||
|
type=int,
|
||||||
|
choices=[12, 16, 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.
|
||||||
|
""")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
if args.fat_type == 0:
|
||||||
|
args.fat_type = None
|
||||||
|
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!')
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
def read_filesystem(path: str) -> bytearray:
|
||||||
|
with open(path, 'rb') as fs_file:
|
||||||
|
return bytearray(fs_file.read())
|
||||||
|
@ -16,6 +16,43 @@ function(fatfs_create_partition_image partition base_dir)
|
|||||||
set(fatfsgen_py ${python} ${idf_path}/components/fatfs/fatfsgen.py)
|
set(fatfsgen_py ${python} ${idf_path}/components/fatfs/fatfsgen.py)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if("${CONFIG_FATFS_SECTORS_PER_CLUSTER_1}")
|
||||||
|
set(sectors_per_cluster 1)
|
||||||
|
elseif("${CONFIG_FATFS_SECTORS_PER_CLUSTER_2}")
|
||||||
|
set(sectors_per_cluster 2)
|
||||||
|
elseif("${CONFIG_FATFS_SECTORS_PER_CLUSTER_4}")
|
||||||
|
set(sectors_per_cluster 4)
|
||||||
|
elseif("${CONFIG_FATFS_SECTORS_PER_CLUSTER_8}")
|
||||||
|
set(sectors_per_cluster 8)
|
||||||
|
elseif("${CONFIG_FATFS_SECTORS_PER_CLUSTER_16}")
|
||||||
|
set(sectors_per_cluster 16)
|
||||||
|
elseif("${CONFIG_FATFS_SECTORS_PER_CLUSTER_32}")
|
||||||
|
set(sectors_per_cluster 32)
|
||||||
|
elseif("${CONFIG_FATFS_SECTORS_PER_CLUSTER_64}")
|
||||||
|
set(sectors_per_cluster 64)
|
||||||
|
elseif("${CONFIG_FATFS_SECTORS_PER_CLUSTER_128}")
|
||||||
|
set(sectors_per_cluster 128)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${CONFIG_FATFS_SECTOR_512}")
|
||||||
|
set(fatfs_sector_size 512)
|
||||||
|
elseif("${CONFIG_FATFS_SECTOR_1024}")
|
||||||
|
set(fatfs_sector_size 1024)
|
||||||
|
elseif("${CONFIG_FATFS_SECTOR_2048}")
|
||||||
|
set(fatfs_sector_size 2048)
|
||||||
|
else()
|
||||||
|
set(fatfs_sector_size 4096)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
if("${CONFIG_FATFS_AUTO_TYPE}")
|
||||||
|
set(fatfs_explicit_type 0)
|
||||||
|
elseif("${CONFIG_FATFS_FAT12}")
|
||||||
|
set(fatfs_explicit_type 12)
|
||||||
|
elseif("${CONFIG_FATFS_FAT16}")
|
||||||
|
set(fatfs_explicit_type 16)
|
||||||
|
endif()
|
||||||
|
|
||||||
get_filename_component(base_dir_full_path ${base_dir} ABSOLUTE)
|
get_filename_component(base_dir_full_path ${base_dir} ABSOLUTE)
|
||||||
partition_table_get_partition_info(size "--partition-name ${partition}" "size")
|
partition_table_get_partition_info(size "--partition-name ${partition}" "size")
|
||||||
partition_table_get_partition_info(offset "--partition-name ${partition}" "offset")
|
partition_table_get_partition_info(offset "--partition-name ${partition}" "offset")
|
||||||
@ -28,6 +65,9 @@ function(fatfs_create_partition_image partition base_dir)
|
|||||||
COMMAND ${fatfsgen_py} ${base_dir_full_path}
|
COMMAND ${fatfsgen_py} ${base_dir_full_path}
|
||||||
--partition_size ${size}
|
--partition_size ${size}
|
||||||
--output_file ${image_file}
|
--output_file ${image_file}
|
||||||
|
--sector_size "${fatfs_sector_size}"
|
||||||
|
--sectors_per_cluster "${sectors_per_cluster}"
|
||||||
|
--fat_type "${fatfs_explicit_type}"
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
|
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
|
||||||
|
@ -7,12 +7,14 @@ import shutil
|
|||||||
import sys
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from test_utils import CFG, generate_test_dir_1, generate_test_dir_2
|
from test_utils import CFG, fill_sector, generate_test_dir_1, generate_test_dir_2
|
||||||
|
|
||||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
import fatfsgen # noqa E402
|
import fatfsgen # noqa E402 # pylint: disable=C0413
|
||||||
from fatfsgen_utils.exceptions import WriteDirectoryException # noqa E402
|
from fatfsgen_utils.exceptions import TooLongNameException # noqa E402 # pylint: disable=C0413
|
||||||
from fatfsgen_utils.exceptions import LowerCaseException, NoFreeClusterException, TooLongNameException # noqa E402
|
from fatfsgen_utils.exceptions import WriteDirectoryException # noqa E402 # pylint: disable=C0413
|
||||||
|
from fatfsgen_utils.exceptions import LowerCaseException, NoFreeClusterException # noqa E402 # pylint: disable=C0413
|
||||||
|
from fatfsgen_utils.utils import read_filesystem # noqa E402 # pylint: disable=C0413
|
||||||
|
|
||||||
|
|
||||||
class FatFSGen(unittest.TestCase):
|
class FatFSGen(unittest.TestCase):
|
||||||
@ -27,8 +29,9 @@ class FatFSGen(unittest.TestCase):
|
|||||||
def test_empty_file_sn_fat12(self) -> None:
|
def test_empty_file_sn_fat12(self) -> None:
|
||||||
fatfs = fatfsgen.FATFS()
|
fatfs = fatfsgen.FATFS()
|
||||||
fatfs.create_file('TESTFILE')
|
fatfs.create_file('TESTFILE')
|
||||||
|
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
|
||||||
self.assertEqual(file_system[0x2000:0x200c], b'TESTFILE \x20') # check entry name and type
|
self.assertEqual(file_system[0x2000:0x200c], b'TESTFILE \x20') # check entry name and type
|
||||||
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
|
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
|
||||||
@ -37,7 +40,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs = fatfsgen.FATFS()
|
fatfs = fatfsgen.FATFS()
|
||||||
fatfs.create_directory('TESTFOLD')
|
fatfs.create_directory('TESTFOLD')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
|
||||||
self.assertEqual(file_system[0x2000:0x200c], b'TESTFOLD \x10') # check entry name and type
|
self.assertEqual(file_system[0x2000:0x200c], b'TESTFOLD \x10') # check entry name and type
|
||||||
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
|
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
|
||||||
@ -48,7 +51,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs = fatfsgen.FATFS()
|
fatfs = fatfsgen.FATFS()
|
||||||
fatfs.create_file('TESTF', extension='TXT')
|
fatfs.create_file('TESTF', extension='TXT')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
self.assertEqual(file_system[0x2000:0x200c], b'TESTF TXT\x20') # check entry name and type
|
self.assertEqual(file_system[0x2000:0x200c], b'TESTF TXT\x20') # check entry name and type
|
||||||
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
|
self.assertEqual(file_system[0x1000:0x1006], b'\xf8\xff\xff\xff\x0f\x00') # check fat
|
||||||
|
|
||||||
@ -57,7 +60,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs.create_file('WRITEF', extension='TXT')
|
fatfs.create_file('WRITEF', extension='TXT')
|
||||||
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=b'testcontent')
|
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=b'testcontent')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
|
||||||
self.assertEqual(file_system[0x2000:0x200c], b'WRITEF TXT\x20') # check entry name and type
|
self.assertEqual(file_system[0x2000:0x200c], b'WRITEF TXT\x20') # check entry name and type
|
||||||
self.assertEqual(file_system[0x201a:0x2020], b'\x02\x00\x0b\x00\x00\x00') # check size and cluster ref
|
self.assertEqual(file_system[0x201a:0x2020], b'\x02\x00\x0b\x00\x00\x00') # check size and cluster ref
|
||||||
@ -70,7 +73,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD'])
|
fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD'])
|
||||||
fatfs.write_content(path_from_root=['TESTFOLD', 'WRITEF.TXT'], content=b'testcontent')
|
fatfs.write_content(path_from_root=['TESTFOLD', 'WRITEF.TXT'], content=b'testcontent')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
|
||||||
self.assertEqual(file_system[0x2000:0x200c], b'TESTFOLD \x10')
|
self.assertEqual(file_system[0x2000:0x200c], b'TESTFOLD \x10')
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -91,7 +94,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs.fat.clusters[3].set_in_fat(4)
|
fatfs.fat.clusters[3].set_in_fat(4)
|
||||||
fatfs.fat.clusters[4].set_in_fat(5)
|
fatfs.fat.clusters[4].set_in_fat(5)
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
file_system[0x1000:0x1010],
|
file_system[0x1000:0x1010],
|
||||||
b'\xf8\xff\xff\xe8\x43\x00\x05\xf0\xff\xff\x0f\x00\x00\x00\x00\x00')
|
b'\xf8\xff\xff\xe8\x43\x00\x05\xf0\xff\xff\x0f\x00\x00\x00\x00\x00')
|
||||||
@ -101,7 +104,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs.create_file('WRITEF', extension='TXT')
|
fatfs.create_file('WRITEF', extension='TXT')
|
||||||
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a')
|
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\xff\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\xff\x0f\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||||
self.assertEqual(file_system[0x6000: 0x7000], CFG['sector_size'] * b'a')
|
self.assertEqual(file_system[0x6000: 0x7000], CFG['sector_size'] * b'a')
|
||||||
|
|
||||||
@ -110,7 +113,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs.create_file('WRITEF', extension='TXT')
|
fatfs.create_file('WRITEF', extension='TXT')
|
||||||
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a')
|
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\x03\xf0\xff\x00\x00\x00\x00\x00\x00\x00\x00')
|
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\x03\xf0\xff\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||||
self.assertEqual(file_system[0x7000: 0x8000], b'a' + (CFG['sector_size'] - 1) * b'\x00')
|
self.assertEqual(file_system[0x7000: 0x8000], b'a' + (CFG['sector_size'] - 1) * b'\x00')
|
||||||
|
|
||||||
@ -118,12 +121,11 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs = fatfsgen.FATFS()
|
fatfs = fatfsgen.FATFS()
|
||||||
fatfs.create_directory('TESTFOLD')
|
fatfs.create_directory('TESTFOLD')
|
||||||
|
|
||||||
for i in range(CFG['sector_size'] // CFG['entry_size']):
|
fill_sector(fatfs)
|
||||||
fatfs.create_file(f'A{str(i).upper()}', path_from_root=['TESTFOLD'])
|
|
||||||
fatfs.write_content(path_from_root=['TESTFOLD', 'A0'], content=b'first')
|
fatfs.write_content(path_from_root=['TESTFOLD', 'A0'], content=b'first')
|
||||||
fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later')
|
fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
self.assertEqual(file_system[0x1000: 0x10d0],
|
self.assertEqual(file_system[0x1000: 0x10d0],
|
||||||
b'\xf8\xff\xff\x82\xf0\xff' + 192 * b'\xff' + 10 * b'\x00')
|
b'\xf8\xff\xff\x82\xf0\xff' + 192 * b'\xff' + 10 * b'\x00')
|
||||||
self.assertEqual(file_system[0x85000:0x85005], b'later')
|
self.assertEqual(file_system[0x85000:0x85005], b'later')
|
||||||
@ -162,7 +164,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs.write_content(path_from_root=['TESTFOLD', 'A253'], content=b'later')
|
fatfs.write_content(path_from_root=['TESTFOLD', 'A253'], content=b'later')
|
||||||
fatfs.write_content(path_from_root=['TESTFOLD', 'A255'], content=b'last')
|
fatfs.write_content(path_from_root=['TESTFOLD', 'A255'], content=b'last')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
self.assertEqual(file_system[0x105000:0x105010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
self.assertEqual(file_system[0x105000:0x105010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||||
self.assertEqual(file_system[0x108000:0x108010], b'last\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
self.assertEqual(file_system[0x108000:0x108010], b'last\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||||
|
|
||||||
@ -193,7 +195,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD', 'TESTFOLL', 'TESTFOLO'])
|
fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD', 'TESTFOLL', 'TESTFOLO'])
|
||||||
fatfs.write_content(path_from_root=['TESTFOLD', 'TESTFOLL', 'TESTFOLO', 'WRITEF.TXT'], content=b'later')
|
fatfs.write_content(path_from_root=['TESTFOLD', 'TESTFOLL', 'TESTFOLO', 'WRITEF.TXT'], content=b'later')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
|
||||||
self.assertEqual(file_system[0x9000:0x9010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
self.assertEqual(file_system[0x9000:0x9010], b'later\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||||
|
|
||||||
@ -205,7 +207,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD', 'TESTFOLD', 'TESTFOLD'])
|
fatfs.create_file('WRITEF', extension='TXT', path_from_root=['TESTFOLD', 'TESTFOLD', 'TESTFOLD'])
|
||||||
fatfs.write_content(path_from_root=['TESTFOLD', 'TESTFOLD', 'TESTFOLD', 'WRITEF.TXT'], content=b'later')
|
fatfs.write_content(path_from_root=['TESTFOLD', 'TESTFOLD', 'TESTFOLD', 'WRITEF.TXT'], content=b'later')
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
|
||||||
self.assertEqual(file_system[0x2000:0x2010], b'TESTFOLD \x10\x00\x00\x01\x00')
|
self.assertEqual(file_system[0x2000:0x2010], b'TESTFOLD \x10\x00\x00\x01\x00')
|
||||||
self.assertEqual(file_system[0x2010:0x2020], b'!\x00\x00\x00\x00\x00\x01\x00\x01\x00\x02\x00\x00\x00\x00\x00')
|
self.assertEqual(file_system[0x2010:0x2020], b'!\x00\x00\x00\x00\x00\x01\x00\x01\x00\x02\x00\x00\x00\x00\x00')
|
||||||
@ -220,7 +222,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs = fatfsgen.FATFS()
|
fatfs = fatfsgen.FATFS()
|
||||||
fatfs.generate(CFG['test_dir'])
|
fatfs.generate(CFG['test_dir'])
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
self.assertEqual(file_system[0x6060:0x6070], b'TESTFIL2 \x00\x00\x01\x00')
|
self.assertEqual(file_system[0x6060:0x6070], b'TESTFIL2 \x00\x00\x01\x00')
|
||||||
self.assertEqual(file_system[0x6070:0x6080], b'!\x00\x00\x00\x00\x00\x01\x00\x01\x00\x05\x00\x0b\x00\x00\x00')
|
self.assertEqual(file_system[0x6070:0x6080], b'!\x00\x00\x00\x00\x00\x01\x00\x01\x00\x05\x00\x0b\x00\x00\x00')
|
||||||
self.assertEqual(file_system[0x7040:0x7050], b'LASTFILE \x00\x00\x01\x00')
|
self.assertEqual(file_system[0x7040:0x7050], b'LASTFILE \x00\x00\x01\x00')
|
||||||
@ -232,7 +234,7 @@ class FatFSGen(unittest.TestCase):
|
|||||||
fatfs = fatfsgen.FATFS()
|
fatfs = fatfsgen.FATFS()
|
||||||
fatfs.generate(CFG['test_dir2'])
|
fatfs.generate(CFG['test_dir2'])
|
||||||
fatfs.write_filesystem(CFG['output_file'])
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
file_system = fatfs.read_filesystem(CFG['output_file'])
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
|
||||||
self.assertEqual(file_system[0x2020:0x2030], b'TESTFILE \x00\x00\x01\x00')
|
self.assertEqual(file_system[0x2020:0x2030], b'TESTFILE \x00\x00\x01\x00')
|
||||||
self.assertEqual(file_system[0x6060:0x6070], b'TESTFIL2 \x00\x00\x01\x00')
|
self.assertEqual(file_system[0x6060:0x6070], b'TESTFIL2 \x00\x00\x01\x00')
|
||||||
@ -243,6 +245,43 @@ class FatFSGen(unittest.TestCase):
|
|||||||
self.assertEqual(file_system[0xa000:0xa010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
self.assertEqual(file_system[0xa000:0xa010], b'ahoj\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||||
self.assertEqual(file_system[0xb000:0xb009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')
|
self.assertEqual(file_system[0xb000:0xb009], b'\xff\xff\xff\xff\xff\xff\xff\xff\xff')
|
||||||
|
|
||||||
|
def test_empty_fat16(self) -> None:
|
||||||
|
fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024)
|
||||||
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
self.assertEqual(file_system[0x1000:0x1007], b'\xf8\xff\xff\xff\x00\x00\x00')
|
||||||
|
|
||||||
|
def test_simple_fat16(self) -> None:
|
||||||
|
fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024)
|
||||||
|
fatfs.create_directory('TESTFOLD')
|
||||||
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
self.assertEqual(file_system[0x1000:0x1007], b'\xf8\xff\xff\xff\xff\xff\x00')
|
||||||
|
|
||||||
|
def test_chaining_fat16(self) -> None:
|
||||||
|
fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024)
|
||||||
|
fatfs.create_file('WRITEF', extension='TXT')
|
||||||
|
fatfs.write_content(path_from_root=['WRITEF.TXT'], content=CFG['sector_size'] * b'a' + b'a')
|
||||||
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
self.assertEqual(file_system[0x1000: 0x100e], b'\xf8\xff\xff\xff\x03\x00\xff\xff\x00\x00\x00\x00\x00\x00')
|
||||||
|
self.assertEqual(file_system[0x7000: 0x8000], b'a' + (CFG['sector_size'] - 1) * b'\x00')
|
||||||
|
|
||||||
|
def test_full_sector_folder_fat16(self) -> None:
|
||||||
|
fatfs = fatfsgen.FATFS(size=17 * 1024 * 1024)
|
||||||
|
fatfs.create_directory('TESTFOLD')
|
||||||
|
|
||||||
|
fill_sector(fatfs)
|
||||||
|
fatfs.write_content(path_from_root=['TESTFOLD', 'A0'], content=b'first')
|
||||||
|
fatfs.write_content(path_from_root=['TESTFOLD', 'A126'], content=b'later')
|
||||||
|
fatfs.write_filesystem(CFG['output_file'])
|
||||||
|
file_system = read_filesystem(CFG['output_file'])
|
||||||
|
self.assertEqual(file_system[0x1000: 0x1110],
|
||||||
|
b'\xf8\xff\xff\xff\x82\x00' + 258 * b'\xff' + 8 * b'\x00')
|
||||||
|
self.assertEqual(file_system[0x85000:0x85005], b'later')
|
||||||
|
self.assertEqual(file_system[0x86000:0x86010], b'A126 \x00\x00\x01\x00')
|
||||||
|
self.assertEqual(file_system[0x86020:0x86030], b'A127 \x00\x00\x01\x00')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from typing import Any, Dict, Union
|
from typing import Any, Dict, Union
|
||||||
|
|
||||||
|
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
|
import fatfsgen # noqa E402 # pylint: disable=C0413
|
||||||
|
|
||||||
CFG = dict(
|
CFG = dict(
|
||||||
sector_size=4096,
|
sector_size=4096,
|
||||||
entry_size=32,
|
entry_size=32,
|
||||||
@ -33,3 +37,8 @@ def generate_test_dir_2() -> None:
|
|||||||
file.write('thisistest\n')
|
file.write('thisistest\n')
|
||||||
with open(os.path.join(CFG['test_dir2'], 'testfile'), 'w') as file:
|
with open(os.path.join(CFG['test_dir2'], 'testfile'), 'w') as file:
|
||||||
file.write('ahoj\n')
|
file.write('ahoj\n')
|
||||||
|
|
||||||
|
|
||||||
|
def fill_sector(fatfs: fatfsgen.FATFS) -> None:
|
||||||
|
for i in range(CFG['sector_size'] // CFG['entry_size']):
|
||||||
|
fatfs.create_file(f'A{str(i).upper()}', path_from_root=['TESTFOLD'])
|
||||||
|
@ -52,7 +52,7 @@ class WLFATFS:
|
|||||||
sectors_per_cluster: int = 1,
|
sectors_per_cluster: int = 1,
|
||||||
sector_size: int = 0x1000,
|
sector_size: int = 0x1000,
|
||||||
sectors_per_fat: int = 1,
|
sectors_per_fat: int = 1,
|
||||||
root_dir_sectors_cnt: int = 4,
|
explicit_fat_type: int = None,
|
||||||
hidden_sectors: int = 0,
|
hidden_sectors: int = 0,
|
||||||
long_names_enabled: bool = False,
|
long_names_enabled: bool = False,
|
||||||
entry_size: int = 32,
|
entry_size: int = 32,
|
||||||
@ -63,8 +63,9 @@ class WLFATFS:
|
|||||||
file_sys_type: str = 'FAT',
|
file_sys_type: str = 'FAT',
|
||||||
version: int = 2,
|
version: int = 2,
|
||||||
temp_buff_size: int = 32,
|
temp_buff_size: int = 32,
|
||||||
updaterate: int = 16,
|
update_rate: int = 16,
|
||||||
device_id: int = None,
|
device_id: int = None,
|
||||||
|
root_entry_count: int = 512,
|
||||||
media_type: int = 0xf8) -> None:
|
media_type: int = 0xf8) -> None:
|
||||||
if sector_size != WLFATFS.WL_SECTOR_SIZE:
|
if sector_size != WLFATFS.WL_SECTOR_SIZE:
|
||||||
raise NotImplementedError(f'The only supported sector size is currently {WLFATFS.WL_SECTOR_SIZE}')
|
raise NotImplementedError(f'The only supported sector size is currently {WLFATFS.WL_SECTOR_SIZE}')
|
||||||
@ -74,7 +75,7 @@ class WLFATFS:
|
|||||||
self._version = version
|
self._version = version
|
||||||
self._temp_buff_size = temp_buff_size
|
self._temp_buff_size = temp_buff_size
|
||||||
self._device_id = device_id
|
self._device_id = device_id
|
||||||
self._updaterate = updaterate
|
self._update_rate = update_rate
|
||||||
self.partition_size = size
|
self.partition_size = size
|
||||||
self.total_sectors = self.partition_size // self.sector_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
|
self.wl_state_size = WLFATFS.WL_STATE_HEADER_SIZE + WLFATFS.WL_STATE_RECORD_SIZE * self.total_sectors
|
||||||
@ -89,13 +90,14 @@ class WLFATFS:
|
|||||||
self.plain_fat_sectors = self.total_sectors - wl_sectors
|
self.plain_fat_sectors = self.total_sectors - wl_sectors
|
||||||
|
|
||||||
self.plain_fatfs = FATFS(
|
self.plain_fatfs = FATFS(
|
||||||
|
explicit_fat_type=explicit_fat_type,
|
||||||
size=self.plain_fat_sectors * self.sector_size,
|
size=self.plain_fat_sectors * self.sector_size,
|
||||||
reserved_sectors_cnt=reserved_sectors_cnt,
|
reserved_sectors_cnt=reserved_sectors_cnt,
|
||||||
fat_tables_cnt=fat_tables_cnt,
|
fat_tables_cnt=fat_tables_cnt,
|
||||||
sectors_per_cluster=sectors_per_cluster,
|
sectors_per_cluster=sectors_per_cluster,
|
||||||
sector_size=sector_size,
|
sector_size=sector_size,
|
||||||
sectors_per_fat=sectors_per_fat,
|
sectors_per_fat=sectors_per_fat,
|
||||||
root_dir_sectors_cnt=root_dir_sectors_cnt,
|
root_entry_count=root_entry_count,
|
||||||
hidden_sectors=hidden_sectors,
|
hidden_sectors=hidden_sectors,
|
||||||
long_names_enabled=long_names_enabled,
|
long_names_enabled=long_names_enabled,
|
||||||
entry_size=entry_size,
|
entry_size=entry_size,
|
||||||
@ -127,7 +129,7 @@ class WLFATFS:
|
|||||||
full_mem_size=self.partition_size,
|
full_mem_size=self.partition_size,
|
||||||
page_size=self.sector_size,
|
page_size=self.sector_size,
|
||||||
sector_size=self.sector_size,
|
sector_size=self.sector_size,
|
||||||
updaterate=self._updaterate,
|
updaterate=self._update_rate,
|
||||||
wr_size=16,
|
wr_size=16,
|
||||||
version=self._version,
|
version=self._version,
|
||||||
temp_buff_size=self._temp_buff_size
|
temp_buff_size=self._temp_buff_size
|
||||||
@ -149,7 +151,7 @@ class WLFATFS:
|
|||||||
max_pos=self.plain_fat_sectors + WLFATFS.DUMMY_SECTORS_COUNT,
|
max_pos=self.plain_fat_sectors + WLFATFS.DUMMY_SECTORS_COUNT,
|
||||||
move_count=0,
|
move_count=0,
|
||||||
access_count=0,
|
access_count=0,
|
||||||
max_count=self._updaterate,
|
max_count=self._update_rate,
|
||||||
block_size=self.sector_size,
|
block_size=self.sector_size,
|
||||||
version=self._version,
|
version=self._version,
|
||||||
device_id=self._device_id or generate_4bytes_random(),
|
device_id=self._device_id or generate_4bytes_random(),
|
||||||
@ -187,12 +189,13 @@ class WLFATFS:
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
desc = 'Create a FAT filesystem with support for wear levelling and populate it with directory content'
|
desc = 'Create a FAT filesystem with support for wear levelling and populate it with directory content'
|
||||||
args = get_args_for_partition_generator(desc)
|
args = get_args_for_partition_generator(desc)
|
||||||
input_dir = args.input_directory
|
|
||||||
|
|
||||||
partition_size = int(str(args.partition_size), 0)
|
wl_fatfs = WLFATFS(sector_size=args.sector_size,
|
||||||
sector_size_bytes = int(str(args.sector_size), 0)
|
sectors_per_cluster=args.sectors_per_cluster,
|
||||||
|
size=args.partition_size,
|
||||||
|
root_entry_count=args.root_entry_count,
|
||||||
|
explicit_fat_type=args.fat_type)
|
||||||
|
|
||||||
wl_fatfs = WLFATFS(size=partition_size, sector_size=sector_size_bytes)
|
wl_fatfs.wl_generate(args.input_directory)
|
||||||
wl_fatfs.wl_generate(input_dir)
|
|
||||||
wl_fatfs.init_wl()
|
wl_fatfs.init_wl()
|
||||||
wl_fatfs.wl_write_filesystem(args.output_file)
|
wl_fatfs.wl_write_filesystem(args.output_file)
|
||||||
|
@ -95,7 +95,7 @@ The tool is used to create filesystem images on a host and populate it with cont
|
|||||||
|
|
||||||
The script is based on the partition generator (:component_file:`fatfsgen.py<fatfs/fatfsgen.py>`) and except for generating partition also initializes wear levelling.
|
The script is based on the partition generator (:component_file:`fatfsgen.py<fatfs/fatfsgen.py>`) and except for generating partition also initializes wear levelling.
|
||||||
|
|
||||||
Current implementation supports short file names and FAT12. Long file names, and FAT16 are subjects of the future work.
|
Current implementation supports short file names, FAT12 and FAT16. Long file names support is the subject of the future work.
|
||||||
|
|
||||||
|
|
||||||
Build system integration with FATFS partition generator
|
Build system integration with FATFS partition generator
|
||||||
|
Loading…
x
Reference in New Issue
Block a user