Merge branch 'bugfix/fatfs_fatfsparse_relaxed' into 'master'

bugfix(fatfs): Fixed fatfsparse.py parses FAT boot sector too strictly

See merge request espressif/esp-idf!26888
This commit is contained in:
Radek Tandler
2023-12-08 23:48:25 +08:00
4 changed files with 21 additions and 13 deletions

View File

@@ -1,9 +1,9 @@
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
from inspect import getmembers, isroutine from inspect import getmembers, isroutine
from typing import Optional 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 .exceptions import InconsistentFATAttributes, NotInitialized
from .fatfs_state import BootSectorState from .fatfs_state import BootSectorState
@@ -29,8 +29,7 @@ class BootSector:
BOOT_HEADER_SIZE = 512 BOOT_HEADER_SIZE = 512
BOOT_SECTOR_HEADER = Struct( BOOT_SECTOR_HEADER = Struct(
# this value reflects BS_jmpBoot used for ESP32 boot sector (any other accepted) 'BS_jmpBoot' / Bytes(3),
'BS_jmpBoot' / Const(b'\xeb\xfe\x90'),
'BS_OEMName' / PaddedString(MAX_OEM_NAME_SIZE, SHORT_NAMES_ENCODING), 'BS_OEMName' / PaddedString(MAX_OEM_NAME_SIZE, SHORT_NAMES_ENCODING),
'BPB_BytsPerSec' / Int16ul, 'BPB_BytsPerSec' / Int16ul,
'BPB_SecPerClus' / Int8ul, 'BPB_SecPerClus' / Int8ul,
@@ -45,12 +44,12 @@ class BootSector:
'BPB_HiddSec' / Int32ul, 'BPB_HiddSec' / Int32ul,
'BPB_TotSec32' / Int32ul, # zero if the FAT type is 12/16, otherwise number of sectors 'BPB_TotSec32' / Int32ul, # zero if the FAT type is 12/16, otherwise number of sectors
'BS_DrvNum' / Const(b'\x80'), 'BS_DrvNum' / Const(b'\x80'),
'BS_Reserved1' / Const(EMPTY_BYTE), 'BS_Reserved1' / Padding(1),
'BS_BootSig' / Const(b'\x29'), 'BS_BootSig' / Const(b'\x29'),
'BS_VolID' / Int32ul, 'BS_VolID' / Int32ul,
'BS_VolLab' / PaddedString(MAX_VOL_LAB_SIZE, SHORT_NAMES_ENCODING), 'BS_VolLab' / PaddedString(MAX_VOL_LAB_SIZE, SHORT_NAMES_ENCODING),
'BS_FilSysType' / PaddedString(MAX_FS_TYPE_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) 'Signature_word' / Const(FATDefaults.SIGNATURE_WORD)
) )
assert BOOT_SECTOR_HEADER.sizeof() == BOOT_HEADER_SIZE assert BOOT_SECTOR_HEADER.sizeof() == BOOT_HEADER_SIZE
@@ -73,7 +72,8 @@ class BootSector:
* EMPTY_BYTE) * EMPTY_BYTE)
self.boot_sector_state.binary_image = ( self.boot_sector_state.binary_image = (
BootSector.BOOT_SECTOR_HEADER.build( 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_BytsPerSec=boot_sector_state.sector_size,
BPB_SecPerClus=boot_sector_state.sectors_per_cluster, BPB_SecPerClus=boot_sector_state.sectors_per_cluster,
BPB_RsvdSecCnt=boot_sector_state.reserved_sectors_cnt, BPB_RsvdSecCnt=boot_sector_state.reserved_sectors_cnt,
@@ -91,8 +91,7 @@ class BootSector:
BS_VolLab=pad_string(boot_sector_state.volume_label, BS_VolLab=pad_string(boot_sector_state.volume_label,
size=BootSector.MAX_VOL_LAB_SIZE), size=BootSector.MAX_VOL_LAB_SIZE),
BS_FilSysType=pad_string(boot_sector_state.file_sys_type, 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 ) + pad_header + fat_tables_content + root_dir_content + data_content
) )

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
import argparse import argparse
import os import os
@@ -100,7 +100,7 @@ def remove_wear_levelling_if_exists(fs_: bytes) -> bytes:
boot_sector__.parse_boot_sector(fs_) boot_sector__.parse_boot_sector(fs_)
if boot_sector__.boot_sector_state.size == len(fs_): if boot_sector__.boot_sector_state.size == len(fs_):
return fs_ return fs_
except construct.core.ConstError: except UnicodeDecodeError:
pass pass
plain_fs: bytes = remove_wl(fs_) plain_fs: bytes = remove_wl(fs_)
return plain_fs return plain_fs
@@ -124,6 +124,9 @@ if __name__ == '__main__':
default=None, default=None,
help="If detection doesn't work correctly, " help="If detection doesn't work correctly, "
'you can force analyzer to or not to assume WL.') 'you can force analyzer to or not to assume WL.')
argument_parser.add_argument('--verbose',
action='store_true',
help='Prints details about FAT image.')
args = argument_parser.parse_args() args = argument_parser.parse_args()
@@ -157,6 +160,10 @@ if __name__ == '__main__':
boot_sector_ = BootSector() boot_sector_ = BootSector()
boot_sector_.parse_boot_sector(fs) boot_sector_.parse_boot_sector(fs)
if args.verbose:
print(str(boot_sector_))
fat = FAT(boot_sector_.boot_sector_state, init_=False) fat = FAT(boot_sector_.boot_sector_state, init_=False)
boot_dir_start_ = boot_sector_.boot_sector_state.root_directory_start boot_dir_start_ = boot_sector_.boot_sector_state.root_directory_start

View File

@@ -136,8 +136,9 @@ It is a reverse tool of (:component_file:`fatfsgen.py <fatfs/fatfsgen.py>`), i.e
Usage:: Usage::
./fatfsparse.py [-h] [--wl-layer {detect,enabled,disabled}] fatfs_image.img ./fatfsparse.py [-h] [--wl-layer {detect,enabled,disabled}] [--verbose] fatfs_image.img
Parameter --verbose prints detailed information from boot sector of the FatFs image to the terminal before folder structure is generated.
High-level API Reference High-level API Reference
------------------------ ------------------------

View File

@@ -136,8 +136,9 @@ FatFs 分区分析器
可以使用:: 可以使用::
./fatfsparse.py [-h] [--wl-layer {detect,enabled,disabled}] fatfs_image.img ./fatfsparse.py [-h] [--wl-layer {detect,enabled,disabled}] [--verbose] fatfs_image.img
生成文件夹结构之前,参数 --verbose 将根据 FatFs 镜像的引导扇区在终端打印详细信息。
高级 API 参考 高级 API 参考
------------------------ ------------------------