fix(fatfs): Fixed fatfsparse.py parsing of FAT boot sector

The fatfsparse.py script was too strict in parsing the FAT boot sector, causing it to fail in
certain cases. This commit fixes the issue by making the parsing less strict and allowing for more
flexibility in the boot sector format.

This change improves the reliability and compatibility of the fatfsparse.py script, ensuring that it
can correctly parse a wider range of FAT boot sectors.

Docs updated
This commit is contained in:
radek.tandler 2023-11-02 11:33:47 +01:00
parent 0e69fcb8ac
commit a640626b76
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
from inspect import getmembers, isroutine
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 .fatfs_state import BootSectorState
@ -29,8 +29,7 @@ class BootSector:
BOOT_HEADER_SIZE = 512
BOOT_SECTOR_HEADER = Struct(
# this value reflects BS_jmpBoot used for ESP32 boot sector (any other accepted)
'BS_jmpBoot' / Const(b'\xeb\xfe\x90'),
'BS_jmpBoot' / Bytes(3),
'BS_OEMName' / PaddedString(MAX_OEM_NAME_SIZE, SHORT_NAMES_ENCODING),
'BPB_BytsPerSec' / Int16ul,
'BPB_SecPerClus' / Int8ul,
@ -45,12 +44,12 @@ class BootSector:
'BPB_HiddSec' / Int32ul,
'BPB_TotSec32' / Int32ul, # zero if the FAT type is 12/16, otherwise number of sectors
'BS_DrvNum' / Const(b'\x80'),
'BS_Reserved1' / Const(EMPTY_BYTE),
'BS_Reserved1' / Padding(1),
'BS_BootSig' / Const(b'\x29'),
'BS_VolID' / Int32ul,
'BS_VolLab' / PaddedString(MAX_VOL_LAB_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)
)
assert BOOT_SECTOR_HEADER.sizeof() == BOOT_HEADER_SIZE
@ -73,7 +72,8 @@ class BootSector:
* EMPTY_BYTE)
self.boot_sector_state.binary_image = (
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_SecPerClus=boot_sector_state.sectors_per_cluster,
BPB_RsvdSecCnt=boot_sector_state.reserved_sectors_cnt,
@ -91,8 +91,7 @@ class BootSector:
BS_VolLab=pad_string(boot_sector_state.volume_label,
size=BootSector.MAX_VOL_LAB_SIZE),
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
)

View File

@ -1,5 +1,5 @@
#!/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
import argparse
import os
@ -100,7 +100,7 @@ def remove_wear_levelling_if_exists(fs_: bytes) -> bytes:
boot_sector__.parse_boot_sector(fs_)
if boot_sector__.boot_sector_state.size == len(fs_):
return fs_
except construct.core.ConstError:
except UnicodeDecodeError:
pass
plain_fs: bytes = remove_wl(fs_)
return plain_fs
@ -124,6 +124,9 @@ if __name__ == '__main__':
default=None,
help="If detection doesn't work correctly, "
'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()
@ -157,6 +160,10 @@ if __name__ == '__main__':
boot_sector_ = BootSector()
boot_sector_.parse_boot_sector(fs)
if args.verbose:
print(str(boot_sector_))
fat = FAT(boot_sector_.boot_sector_state, init_=False)
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::
./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
------------------------

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 参考
------------------------