增加所有文件
This commit is contained in:
BIN
tools/sdtools/pactool/__pycache__/sfs_module.cpython-37.pyc
Normal file
BIN
tools/sdtools/pactool/__pycache__/sfs_module.cpython-37.pyc
Normal file
Binary file not shown.
1841
tools/sdtools/pactool/bpttool
Normal file
1841
tools/sdtools/pactool/bpttool
Normal file
File diff suppressed because it is too large
Load Diff
BIN
tools/sdtools/pactool/gen_pack_crc
Normal file
BIN
tools/sdtools/pactool/gen_pack_crc
Normal file
Binary file not shown.
247
tools/sdtools/pactool/gen_sfs_binary.py
Normal file
247
tools/sdtools/pactool/gen_sfs_binary.py
Normal file
@@ -0,0 +1,247 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.join(os.getcwd(), 'pactool'))
|
||||
import json
|
||||
import traceback
|
||||
import getopt
|
||||
import struct
|
||||
from ctypes import create_string_buffer
|
||||
from sfs_module import sfs_crc32
|
||||
|
||||
class GenSFS(object):
|
||||
|
||||
def __init__(self):
|
||||
self.tag = 0x53465301
|
||||
# self.init_act_data = struct.pack("60x")
|
||||
self.init_act_data = create_string_buffer(60)
|
||||
self.xfer_data = struct.pack("16x")
|
||||
self.ip_data = struct.pack("16x")
|
||||
self.freq = 0
|
||||
self.sw_reset_info = 0 # 1bytes
|
||||
self.training_pattern = struct.pack("8x")
|
||||
|
||||
def parse_value(self, arg):
|
||||
if sys.version_info[0] == 3 and isinstance(arg, str):
|
||||
return int(eval(str(arg)))
|
||||
elif sys.version_info[0] == 2 and (isinstance(arg, str) or isinstance(arg, unicode)):
|
||||
return int(eval(str(arg)))
|
||||
else:
|
||||
return int(arg)
|
||||
|
||||
def generate_sfs(self, jason_file, sfs_file, normal_img_addr, backup_img_addr, third_img_addr):
|
||||
try:
|
||||
self.load_json(jason_file)
|
||||
buffer = struct.pack('<I'
|
||||
'60s'
|
||||
'16s'
|
||||
'16s'
|
||||
'B'
|
||||
'6x' # change reserved[7] to reserved[6]
|
||||
'B' # sw_reset_info, change 'reseraved' to 'sw_reset_info'
|
||||
'8s'
|
||||
'I' # normal_img_addr
|
||||
'I' # backup_img_addr
|
||||
'I', # third_img_addr, change 'reseraved' to 'third_img_addr'
|
||||
self.tag,
|
||||
self.init_act_data.raw,
|
||||
self.xfer_data,
|
||||
self.ip_data,
|
||||
self.freq,
|
||||
self.sw_reset_info,
|
||||
self.training_pattern,
|
||||
normal_img_addr,
|
||||
backup_img_addr,
|
||||
third_img_addr
|
||||
)
|
||||
|
||||
crc32 = sfs_crc32(0, buffer, 124)
|
||||
# print(repr(buffer))
|
||||
# print("crc32=0x%X" % crc32)
|
||||
|
||||
data = struct.pack('<124sI',
|
||||
buffer,
|
||||
crc32)
|
||||
|
||||
image = open(sfs_file, 'wb')
|
||||
image.write(data)
|
||||
return True
|
||||
except ValueError as e:
|
||||
# error occurred.
|
||||
raise Exception("Failed to generate sfs file.")
|
||||
|
||||
def load_json(self, jason_file):
|
||||
try:
|
||||
load_f = open(jason_file, 'r')
|
||||
obj = json.loads(load_f.read())
|
||||
|
||||
# parse tag
|
||||
tag_obj = obj.get("tag")
|
||||
if tag_obj:
|
||||
self.tag = self.parse_value(tag_obj)
|
||||
|
||||
# parse init_act_t
|
||||
init_act_t = obj.get("init_act_t")
|
||||
if init_act_t:
|
||||
count = 0
|
||||
for item in init_act_t:
|
||||
struct.pack_into("BBHBB",
|
||||
self.init_act_data,
|
||||
count*6,
|
||||
self.parse_value(item["header"]),
|
||||
self.parse_value(item["command"]),
|
||||
self.parse_value(item["addr"]),
|
||||
self.parse_value(item["data0"]),
|
||||
self.parse_value(item["data1"]))
|
||||
count += 1
|
||||
# print(repr(self.init_act_data.raw ))
|
||||
|
||||
# parse xfer_attr_t
|
||||
xfer_obj = obj.get("xfer_attr_t")
|
||||
if xfer_obj:
|
||||
self.xfer_data = struct.pack("16B",
|
||||
self.parse_value(xfer_obj["cmd"]),
|
||||
self.parse_value(xfer_obj["cinst_type"]),
|
||||
self.parse_value(xfer_obj["caddr_type"]),
|
||||
self.parse_value(xfer_obj["cdata_type"]),
|
||||
self.parse_value(xfer_obj["caddr_size"]),
|
||||
self.parse_value(xfer_obj["cmode"]),
|
||||
self.parse_value(xfer_obj["cdummy_size"]),
|
||||
self.parse_value(xfer_obj["cflag"]),
|
||||
self.parse_value(xfer_obj["rsvd"][0]),
|
||||
self.parse_value(xfer_obj["rsvd"][1]),
|
||||
self.parse_value(xfer_obj["rsvd"][2]),
|
||||
self.parse_value(xfer_obj["rsvd"][3]),
|
||||
self.parse_value(xfer_obj["rsvd"][4]),
|
||||
self.parse_value(xfer_obj["rsvd"][5]),
|
||||
self.parse_value(xfer_obj["rsvd"][6]),
|
||||
self.parse_value(xfer_obj["rsvd"][7]),
|
||||
)
|
||||
# print(repr(self.xfer_data))
|
||||
|
||||
# parse ip_settings_t
|
||||
ip_setting_obj = obj.get("ip_settings_t")
|
||||
if ip_setting_obj:
|
||||
self.ip_data = struct.pack("H14B",
|
||||
self.parse_value(ip_setting_obj["flags"]),
|
||||
self.parse_value(ip_setting_obj["rx_delay"]),
|
||||
self.parse_value(ip_setting_obj["tx_delay"]),
|
||||
self.parse_value(ip_setting_obj["csda"]),
|
||||
self.parse_value(ip_setting_obj["csdada"]),
|
||||
self.parse_value(ip_setting_obj["cseot"]),
|
||||
self.parse_value(ip_setting_obj["cssot"]),
|
||||
self.parse_value(ip_setting_obj["min_rx_win"]),
|
||||
self.parse_value(ip_setting_obj["rx_training_step"]),
|
||||
self.parse_value(ip_setting_obj["ctrl_misc"]),
|
||||
self.parse_value(ip_setting_obj["rsvd"][0]),
|
||||
self.parse_value(ip_setting_obj["rsvd"][1]),
|
||||
self.parse_value(ip_setting_obj["rsvd"][2]),
|
||||
self.parse_value(ip_setting_obj["rsvd"][3]),
|
||||
self.parse_value(ip_setting_obj["rsvd"][4])
|
||||
)
|
||||
# print(repr(self.ip_data))
|
||||
|
||||
# parse freq
|
||||
freq_obj = obj.get("freq")
|
||||
if freq_obj:
|
||||
self.freq = self.parse_value(freq_obj)
|
||||
|
||||
# parse sw_reset_info
|
||||
freq_obj = obj.get("sw_reset_info")
|
||||
if freq_obj:
|
||||
self.sw_reset_info = self.parse_value(freq_obj)
|
||||
|
||||
# parse training_pattern
|
||||
training_obj = obj.get("training_pattern")
|
||||
if training_obj:
|
||||
self.training_pattern = struct.pack("8B",
|
||||
self.parse_value(training_obj[0]),
|
||||
self.parse_value(training_obj[1]),
|
||||
self.parse_value(training_obj[2]),
|
||||
self.parse_value(training_obj[3]),
|
||||
self.parse_value(training_obj[4]),
|
||||
self.parse_value(training_obj[5]),
|
||||
self.parse_value(training_obj[6]),
|
||||
self.parse_value(training_obj[7])
|
||||
)
|
||||
# print(repr(self.training_pattern))
|
||||
|
||||
except ValueError as e:
|
||||
# Unfortunately we can't easily get the line number where the
|
||||
# error occurred.
|
||||
raise Exception("Failed to Load jason file.")
|
||||
|
||||
|
||||
def show_usage():
|
||||
print("gen_sfs_binary version: 1.21.50.1")
|
||||
print("usage: gen_sfs_binary.py <--json file> <--out file> [--normal_img_off offset] [--backup_img_off offset] [--third_img_off offset] [-h]")
|
||||
print("options:")
|
||||
print("--json file Specify nor flash configuration")
|
||||
print("--out file Output specify sfs binary file")
|
||||
print("--normal_img_off Normal image address")
|
||||
print("--backup_img_off Backup image address")
|
||||
print("--third_img_off Third image address")
|
||||
print("-h Help")
|
||||
print("e.g.: gen_sfs_binary.py --json sfs.json --out ./sfs.img")
|
||||
|
||||
|
||||
def main(argv):
|
||||
"""
|
||||
主函数
|
||||
:param argv: <--out file> [-h]
|
||||
:return: 0:pass; other:fail
|
||||
"""
|
||||
exit_code = 1
|
||||
try:
|
||||
opts, args = getopt.getopt(argv, "-h", ["help", "json=", "out=", "normal_img_off=", "backup_img_off=", "third_img_off="])
|
||||
out_sfs_file = ""
|
||||
json_file = ""
|
||||
normal_img_addr = 0x7000
|
||||
backup_img_addr = 0x27000
|
||||
third_img_addr = 0x0
|
||||
for opt, arg in opts:
|
||||
if opt == '-h':
|
||||
show_usage()
|
||||
sys.exit(0)
|
||||
elif opt == "--out":
|
||||
out_sfs_file = arg
|
||||
elif opt == "--json":
|
||||
json_file = arg
|
||||
elif opt == "--normal_img_off":
|
||||
normal_img_addr = int(arg, 16)
|
||||
if len(arg) < 2 or not arg[:2].lower() == '0x':
|
||||
normal_img_addr = int(arg, 10)
|
||||
elif opt == "--backup_img_off":
|
||||
backup_img_addr = int(arg, 16)
|
||||
if len(arg) < 2 or not arg[:2].lower() == '0x':
|
||||
backup_img_addr = int(arg, 10)
|
||||
elif opt == "--third_img_off":
|
||||
third_img_addr = int(arg, 16)
|
||||
if len(arg) < 2 or not arg[:2].lower() == '0x':
|
||||
third_img_addr = int(arg, 10)
|
||||
print("normal image address = 0x%08X" % normal_img_addr)
|
||||
print("backup image address = 0x%08X" % backup_img_addr)
|
||||
print(" third image address = 0x%08X" % third_img_addr)
|
||||
if len(out_sfs_file) == 0:
|
||||
show_usage()
|
||||
raise Exception("Not specify output sfs binary file info is empty.")
|
||||
|
||||
if len(json_file) == 0:
|
||||
show_usage()
|
||||
raise Exception("Not input nor flash jason configuration file.")
|
||||
|
||||
obj = GenSFS()
|
||||
if not obj.generate_sfs(json_file, out_sfs_file, normal_img_addr, backup_img_addr, third_img_addr):
|
||||
raise Exception("[Error] Failed to sfs binary file.")
|
||||
|
||||
except Exception:
|
||||
print("[Error] %s" % traceback.format_exc())
|
||||
else:
|
||||
print("Successfully generated sfs binary file!")
|
||||
exit_code = 0
|
||||
|
||||
return exit_code
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv[1:])
|
||||
349
tools/sdtools/pactool/msfstool.py
Normal file
349
tools/sdtools/pactool/msfstool.py
Normal file
@@ -0,0 +1,349 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import sys
|
||||
import struct
|
||||
import traceback
|
||||
import argparse
|
||||
|
||||
|
||||
class MULTI_SFS_HEADER_T(object):
|
||||
MAGIC = 0x5346534D # which means "MSFS"
|
||||
VERSION = 0
|
||||
FORMAT_STRING = "<4I16x"
|
||||
|
||||
def __init__(self):
|
||||
self.magic = self.MAGIC # 0x5346534D
|
||||
self.version = self.VERSION # structure version
|
||||
self.fs_count = "" # flash sequence count
|
||||
self.fs_offset = struct.calcsize(self.FORMAT_STRING) # flash sequence offset, default is 32
|
||||
self.reserved = "" # reserved 16 bytes
|
||||
|
||||
|
||||
class FLASH_SEQ_INFO_T(object):
|
||||
VERSION = 0
|
||||
FORMAT_STRING = "<3IQ12x"
|
||||
|
||||
def __init__(self):
|
||||
self.version = self.VERSION # structure version
|
||||
self.offset = 0 # data offset
|
||||
self.size = 0 # data size
|
||||
self.flash_id = 0 # Memory Type (1 Byte) <<8 | Manufacturer ID (1 Byte),e.g. "gd25q32/16" -> 0x40C8
|
||||
self.reserved = "" # reserved 16 bytes
|
||||
# image data
|
||||
self.image_data = None
|
||||
|
||||
|
||||
class PackError(Exception):
|
||||
"""Application-specific errors.
|
||||
|
||||
These errors represent issues for which a stack-trace should not be
|
||||
presented.
|
||||
|
||||
Attributes:
|
||||
message: Error message.
|
||||
"""
|
||||
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
Exception.__init__(self, message)
|
||||
|
||||
|
||||
class SaveImage(object):
|
||||
def __init__(self, filename):
|
||||
self.file = None
|
||||
self.filename = filename
|
||||
self._initialize()
|
||||
|
||||
def _initialize(self):
|
||||
self.file = open(self.filename, 'wb+')
|
||||
|
||||
def write(self, data):
|
||||
if self.file:
|
||||
self.file.write(data)
|
||||
else:
|
||||
raise Exception("Failed to create binary file.")
|
||||
|
||||
def __del__(self):
|
||||
if self.file:
|
||||
self.file.flush()
|
||||
self.file.close()
|
||||
|
||||
|
||||
class ReadImage(object):
|
||||
|
||||
def __init__(self, image_filename):
|
||||
"""Initializes an image handler.
|
||||
|
||||
Arguments:
|
||||
image_filename: The name of the file to operate on.
|
||||
|
||||
Raises:
|
||||
ValueError: If data in the file is invalid.
|
||||
"""
|
||||
self.file = None
|
||||
self.image_size = 0
|
||||
self._file_pos = 0
|
||||
self.filename = image_filename
|
||||
self._initialize()
|
||||
|
||||
def _initialize(self):
|
||||
try:
|
||||
self._file_pos = 0
|
||||
self.file = open(self.filename, 'rb')
|
||||
self.file.seek(0, os.SEEK_END)
|
||||
self.image_size = self.file.tell()
|
||||
self.file.seek(0, os.SEEK_SET)
|
||||
except IOError as e:
|
||||
# print("Failed to open %s" % self.filename)
|
||||
self.file = None
|
||||
|
||||
def seek(self, offset):
|
||||
"""Sets the cursor position for reading from unsparsified file.
|
||||
|
||||
Arguments:
|
||||
offset: Offset to seek to from the beginning of the file.
|
||||
"""
|
||||
self._file_pos = offset
|
||||
|
||||
def read(self, size):
|
||||
"""Reads data from the unsparsified file.
|
||||
|
||||
This method may return fewer than |size| bytes of data if the end
|
||||
of the file was encountered.
|
||||
|
||||
The file cursor for reading is advanced by the number of bytes
|
||||
read.
|
||||
|
||||
Arguments:
|
||||
size: Number of bytes to read.
|
||||
|
||||
Returns:
|
||||
The data.
|
||||
|
||||
"""
|
||||
self.file.seek(self._file_pos)
|
||||
data = self.file.read(size)
|
||||
self._file_pos += len(data)
|
||||
return data
|
||||
|
||||
def tell(self):
|
||||
"""Returns the file cursor position for reading from unsparsified file.
|
||||
|
||||
Returns:
|
||||
The file cursor position for reading.
|
||||
"""
|
||||
return self._file_pos
|
||||
|
||||
|
||||
class Packet(object):
|
||||
"""Business logic for msfstool command-line tool."""
|
||||
|
||||
def make_msfs_image(self, output, images):
|
||||
"""Implementation of the 'make_msfs_image' command.
|
||||
|
||||
Arguments:
|
||||
output: Output file where disk image is to be written to.
|
||||
images: List of partition image paths to be combined (as specified by
|
||||
bpt). Each element is of the form.
|
||||
'FLASH_ID@/PATH/TO/SFS_IMAGE'
|
||||
|
||||
Raises:
|
||||
PackError: If application-specific error occurs.
|
||||
"""
|
||||
# Create mapping of partition name to partition image file.
|
||||
image_file_names = {}
|
||||
try:
|
||||
if images:
|
||||
for item in images:
|
||||
flash_id, path = item.split("@")
|
||||
flash_id = flash_id.lower()
|
||||
if 0 == flash_id.find("0x"):
|
||||
id = int(flash_id, 16)
|
||||
else:
|
||||
id = int(flash_id, 10)
|
||||
image_file_names[id] = path
|
||||
if not os.path.exists(path):
|
||||
raise PackError('image file do not exist: {}.'.format(item))
|
||||
except ValueError as e:
|
||||
raise PackError('Bad image argument {}.'.format(images))
|
||||
|
||||
_ids = []
|
||||
for k, v in image_file_names.items():
|
||||
print("Flash sequence info :0x%X : %s" % (k, v))
|
||||
_ids.append(k)
|
||||
_ids.sort(reverse=False)
|
||||
_fs_infos = []
|
||||
for k in _ids:
|
||||
_image = ReadImage(image_file_names[k])
|
||||
if _image.file is None:
|
||||
raise PackError('Failed to open sfs fie: {}.'.format(image_file_names[k]))
|
||||
_info = FLASH_SEQ_INFO_T()
|
||||
_info.version = FLASH_SEQ_INFO_T.VERSION
|
||||
_info.size = _image.image_size
|
||||
_info.flash_id = k
|
||||
_info.image_data = _image.read(_image.image_size)
|
||||
_fs_infos.append(_info)
|
||||
|
||||
# make image
|
||||
_header = MULTI_SFS_HEADER_T()
|
||||
_header.fs_count = len(_ids)
|
||||
_header.fs_offset = struct.calcsize(MULTI_SFS_HEADER_T.FORMAT_STRING)
|
||||
_header_data = struct.pack(MULTI_SFS_HEADER_T.FORMAT_STRING,
|
||||
_header.magic,
|
||||
_header.version,
|
||||
_header.fs_count,
|
||||
_header.fs_offset)
|
||||
|
||||
# create output image file
|
||||
_s_file = SaveImage(output)
|
||||
_s_file.write(_header_data)
|
||||
|
||||
# info
|
||||
offset = struct.calcsize(MULTI_SFS_HEADER_T.FORMAT_STRING) + \
|
||||
_header.fs_count*struct.calcsize(FLASH_SEQ_INFO_T.FORMAT_STRING)
|
||||
for item in _fs_infos:
|
||||
item.offset = offset
|
||||
_info_data = struct.pack(FLASH_SEQ_INFO_T.FORMAT_STRING,
|
||||
item.version,
|
||||
item.offset,
|
||||
item.size,
|
||||
item.flash_id)
|
||||
_s_file.write(_info_data)
|
||||
offset += item.size
|
||||
|
||||
for item in _fs_infos:
|
||||
_s_file.write(item.image_data)
|
||||
return True
|
||||
|
||||
def extract_msfs(self, output_path, image_file):
|
||||
output_path = output_path.replace('\\', '/')
|
||||
os.makedirs(output_path, exist_ok=True)
|
||||
_image = ReadImage(image_file)
|
||||
if _image.file is None:
|
||||
raise PackError('Failed to open msfs fie: {}.'.format(image_file))
|
||||
if _image.image_size < struct.calcsize(MULTI_SFS_HEADER_T.FORMAT_STRING):
|
||||
raise PackError('Invalid size of the msfs fie: {}.'.format(image_file))
|
||||
_header_bin = _image.read(struct.calcsize(MULTI_SFS_HEADER_T.FORMAT_STRING))
|
||||
_header = MULTI_SFS_HEADER_T()
|
||||
(_header.magic,
|
||||
_header.version,
|
||||
_header.fs_count,
|
||||
_header.fs_offset) = struct.unpack(MULTI_SFS_HEADER_T.FORMAT_STRING, _header_bin)
|
||||
if not _header.magic == MULTI_SFS_HEADER_T.MAGIC:
|
||||
raise PackError('Invalid msfs fie: {}.'.format(image_file))
|
||||
print("msfs summary information :")
|
||||
print(" magic: 0x%X" % _header.magic)
|
||||
print(" version: 0x%X" % _header.version)
|
||||
print(" fs count: 0x%X" % _header.fs_count)
|
||||
print(" fs offset: 0x%X" % _header.fs_offset)
|
||||
|
||||
_fs_infos = []
|
||||
for i in range(_header.fs_count):
|
||||
_info_bin = _image.read(struct.calcsize(FLASH_SEQ_INFO_T.FORMAT_STRING))
|
||||
_info = FLASH_SEQ_INFO_T()
|
||||
(_info.version,
|
||||
_info.offset,
|
||||
_info.size,
|
||||
_info.flash_id) = struct.unpack(FLASH_SEQ_INFO_T.FORMAT_STRING, _info_bin)
|
||||
_fs_infos.append(_info)
|
||||
|
||||
for item in _fs_infos:
|
||||
_sfs = "%s/FlashID_0x%X.img" % (output_path, item.flash_id)
|
||||
_file = SaveImage(_sfs)
|
||||
_image.seek(item.offset)
|
||||
_file.write(_image.read(item.size))
|
||||
|
||||
print("\nextracted sfs information : %s" % _sfs)
|
||||
print(" version: 0x%X" % item.version)
|
||||
print(" offset: 0x%X" % item.offset)
|
||||
print(" size: 0x%X" % item.size)
|
||||
print(" flash id: 0x%X" % item.flash_id)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class MsfsTool(object):
|
||||
"""Object for command-line tool."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initializer method."""
|
||||
self.packet = Packet()
|
||||
pass
|
||||
|
||||
def version(self, _):
|
||||
"""Implements the 'version' sub-command."""
|
||||
print('1.21.32.1')
|
||||
|
||||
def make_msfs(self, args):
|
||||
"""Implements the 'make_msfs' sub-command."""
|
||||
if 0 == len(args.output):
|
||||
print('Option --ouptut parameter is required.')
|
||||
return False
|
||||
result = False
|
||||
try:
|
||||
result = self.packet.make_msfs_image(args.output, args.image)
|
||||
except PackError as e:
|
||||
print('Error : {}'.format(e.message))
|
||||
finally:
|
||||
if result:
|
||||
print('Successfully generated msfs file.')
|
||||
else:
|
||||
os.remove(args.output)
|
||||
print('Failed to generate msfs file.')
|
||||
return result
|
||||
|
||||
def extract_msfs(self, args):
|
||||
"""Implements the 'extract_msfs' sub-command."""
|
||||
result = False
|
||||
try:
|
||||
result = self.packet.extract_msfs(args.output, args.image)
|
||||
except PackError as e:
|
||||
print('Error : {}'.format(e.message))
|
||||
finally:
|
||||
if result:
|
||||
print('Successfully extracted msfs file.')
|
||||
else:
|
||||
print('Failed to extract msfs file.')
|
||||
return result
|
||||
|
||||
def run(self, argv):
|
||||
parser = argparse.ArgumentParser()
|
||||
subparsers = parser.add_subparsers(title='subcommands')
|
||||
sub_parser = subparsers.add_parser('version', help='Prints version of MsfsTool.')
|
||||
sub_parser.set_defaults(func=self.version)
|
||||
|
||||
sub_parser = subparsers.add_parser('make_msfs', help='Create multi sfs image file.')
|
||||
sub_parser.add_argument('--output',
|
||||
help='Path to image output.',
|
||||
type=str,
|
||||
required=True)
|
||||
sub_parser.add_argument('--image',
|
||||
help='Flash ID and path to sfs/nfs image file.',
|
||||
metavar='FLASH_ID@SFS_FILE',
|
||||
action='append',
|
||||
required=True)
|
||||
sub_parser.set_defaults(func=self.make_msfs)
|
||||
|
||||
sub_parser = subparsers.add_parser('extract_msfs', help='Extract multi sfs image file.')
|
||||
sub_parser.add_argument('--output',
|
||||
help='Path to extract sfs.',
|
||||
type=str,
|
||||
required=True)
|
||||
sub_parser.add_argument('--image',
|
||||
help='Path to msfs file.',
|
||||
type=str,
|
||||
required=True)
|
||||
sub_parser.set_defaults(func=self.extract_msfs)
|
||||
|
||||
args = parser.parse_args(argv[1:])
|
||||
try:
|
||||
func = args.func
|
||||
except AttributeError:
|
||||
parser.error("invalid arguments")
|
||||
return func(args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
obj = MsfsTool()
|
||||
obj.run(sys.argv)
|
||||
1688
tools/sdtools/pactool/pactool
Normal file
1688
tools/sdtools/pactool/pactool
Normal file
File diff suppressed because it is too large
Load Diff
152
tools/sdtools/pactool/sfs_module.py
Normal file
152
tools/sdtools/pactool/sfs_module.py
Normal file
@@ -0,0 +1,152 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import os
|
||||
import struct
|
||||
|
||||
|
||||
# CRC table for the CRC-32. The poly isPoly : 0x04C11DB7
|
||||
SFS_CRC32_TABLE = [
|
||||
0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
|
||||
0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
|
||||
0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
|
||||
0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD,
|
||||
0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9,
|
||||
0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75,
|
||||
0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011,
|
||||
0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD,
|
||||
0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039,
|
||||
0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5,
|
||||
0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81,
|
||||
0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D,
|
||||
0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49,
|
||||
0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95,
|
||||
0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1,
|
||||
0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D,
|
||||
0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE,
|
||||
0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072,
|
||||
0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16,
|
||||
0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA,
|
||||
0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE,
|
||||
0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02,
|
||||
0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066,
|
||||
0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA,
|
||||
0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E,
|
||||
0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692,
|
||||
0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6,
|
||||
0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A,
|
||||
0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E,
|
||||
0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2,
|
||||
0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686,
|
||||
0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A,
|
||||
0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637,
|
||||
0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB,
|
||||
0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F,
|
||||
0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53,
|
||||
0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47,
|
||||
0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B,
|
||||
0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF,
|
||||
0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623,
|
||||
0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7,
|
||||
0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B,
|
||||
0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F,
|
||||
0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3,
|
||||
0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7,
|
||||
0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B,
|
||||
0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F,
|
||||
0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3,
|
||||
0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640,
|
||||
0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C,
|
||||
0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8,
|
||||
0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24,
|
||||
0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30,
|
||||
0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC,
|
||||
0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088,
|
||||
0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654,
|
||||
0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0,
|
||||
0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C,
|
||||
0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18,
|
||||
0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4,
|
||||
0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0,
|
||||
0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C,
|
||||
0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668,
|
||||
0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4
|
||||
]
|
||||
|
||||
|
||||
def sfs_crc32(crc, data, len):
|
||||
crc ^= 0xFFFFFFFF
|
||||
for i in range(len):
|
||||
if sys.version_info[0] == 3:
|
||||
crc = ((crc << 8) & 0xFFFFFF00) ^ SFS_CRC32_TABLE[((crc >> 24) & 0xFF) ^ data[i]]
|
||||
else:
|
||||
crc = ((crc << 8) & 0xFFFFFF00) ^ SFS_CRC32_TABLE[((crc >> 24) & 0xFF) ^ (struct.unpack('B', data[i])[0])]
|
||||
return crc ^ 0xFFFFFFFF
|
||||
|
||||
|
||||
class SFSImageHandler(object):
|
||||
# msfs define
|
||||
MSFS_MAGIC = 0x5346534D # "MSFS"
|
||||
MSFS_HEADER_FORMAT = '<4I16x'
|
||||
MSFS_ITEM_INFO_FORMAT = '<3I20s'
|
||||
MSFS_HEADE_SIZE = struct.calcsize(MSFS_HEADER_FORMAT)
|
||||
MSFS_ITEM_INFO_SIZE = struct.calcsize(MSFS_ITEM_INFO_FORMAT)
|
||||
|
||||
# sfs define
|
||||
SFS_MAGIC = 0x534653 # "SFS"
|
||||
SFS_FORMAT = '<I108s4I'
|
||||
SFS_STRUCTURE_SIZE = struct.calcsize(SFS_FORMAT)
|
||||
|
||||
def __init__(self, image_filename):
|
||||
self._file_name = image_filename
|
||||
self._normal_addr = 0
|
||||
self._backup_addr = 0
|
||||
self._third_addr = 0
|
||||
self._read_file()
|
||||
|
||||
def _read_file(self):
|
||||
self._image = open(self._file_name, 'r+b')
|
||||
self._image.seek(0, os.SEEK_END)
|
||||
self.image_size = self._image.tell()
|
||||
if self.image_size < 4:
|
||||
raise ValueError('Invalid msfs/sfs size.')
|
||||
# read magic
|
||||
self._image.seek(0, os.SEEK_SET)
|
||||
data = self._image.read(4)
|
||||
self._image.seek(0, os.SEEK_SET)
|
||||
magic, = struct.unpack('<I', data)
|
||||
if magic == self.MSFS_MAGIC:
|
||||
self._parser_msfs()
|
||||
elif (magic >> 8) == self.SFS_MAGIC:
|
||||
data = self._image.read(self.SFS_STRUCTURE_SIZE)
|
||||
self._parser_sfs(data)
|
||||
else:
|
||||
self._image.close()
|
||||
raise ValueError('Invalid msfs/sfs image.')
|
||||
self._image.close()
|
||||
|
||||
def _parser_sfs(self, data):
|
||||
(magic, _, self._normal_addr, self._backup_addr, self._third_addr, crc) = struct.unpack(self.SFS_FORMAT, data)
|
||||
if not ((magic >> 8) == self.SFS_MAGIC):
|
||||
raise ValueError('Invalid magic,sfs magic must be equal 0x534653 bytes.')
|
||||
|
||||
calc_crc32 = sfs_crc32(0, data, self.SFS_STRUCTURE_SIZE - 4)
|
||||
if not (calc_crc32 == crc):
|
||||
raise ValueError('Invalid crc,failed to check sfs crc.')
|
||||
|
||||
def _parser_msfs(self):
|
||||
self._image.seek(self.MSFS_HEADE_SIZE, os.SEEK_SET)
|
||||
# read first sfs info
|
||||
data = self._image.read(self.MSFS_ITEM_INFO_SIZE)
|
||||
(version, sfs_offset, sfs_size, _) = struct.unpack(self.MSFS_ITEM_INFO_FORMAT, data)
|
||||
|
||||
# read first sfs
|
||||
self._image.seek(sfs_offset, os.SEEK_SET)
|
||||
data = self._image.read(self.SFS_STRUCTURE_SIZE)
|
||||
self._parser_sfs(data)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sfs_file = sys.argv[1]
|
||||
obj = SFSImageHandler(sfs_file)
|
||||
# file = open("d:\\t.img", 'wb+')
|
||||
# file.write(obj.update_image_address(0x2000, 0x12000))
|
||||
Reference in New Issue
Block a user