You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
7.3 KiB
Python
196 lines
7.3 KiB
Python
#!/usr/bin/env python
|
|
#############################################################
|
|
# ubi_reader/scripts/ubireader_display_blocks
|
|
# (c) 2019 Jason Pruitt (jrspruitt@gmail.com)
|
|
#
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#############################################################
|
|
|
|
#############################################################
|
|
# Search by block parameters and display information about
|
|
# matching blocks.
|
|
#############################################################
|
|
|
|
import os
|
|
import sys
|
|
import argparse
|
|
from ubireader.ubi import ubi_base
|
|
from ubireader.ubi_io import ubi_file
|
|
from ubireader import settings
|
|
from ubireader.ubi.defines import UBI_EC_HDR_MAGIC
|
|
from ubireader.ubifs.defines import UBIFS_NODE_MAGIC
|
|
from ubireader.utils import guess_filetype, guess_start_offset, guess_leb_size, guess_peb_size
|
|
|
|
|
|
def main():
|
|
description = 'Search for specified blocks and display information.'
|
|
usage = """
|
|
ubireader_display_blocks "{'block.attr': value,...}" path/to/image
|
|
Search for blocks by given parameters and display information about them.
|
|
This is block only, no volume or image information is created, which can
|
|
be used to debug file and image extraction.
|
|
Example:
|
|
"{'peb_num':[0, 1] + range(100, 102), 'ec_hdr.ec': 1, 'is_valid': True}"
|
|
This matches block.peb_num 0, 1, 100, 101, and 102
|
|
with a block.ec_hdr.ec (erase count) of 1, that are valid PEB blocks.
|
|
For a full list of parameters check ubireader.ubi.block.description.
|
|
"""
|
|
parser = argparse.ArgumentParser(usage=usage, description=description)
|
|
|
|
parser.add_argument('-l', '--log', action='store_true', dest='log',
|
|
help='Print extraction information to screen.')
|
|
|
|
parser.add_argument('-v', '--verbose-log', action='store_true', dest='verbose',
|
|
help='Prints nearly everything about anything to screen.')
|
|
|
|
parser.add_argument('-p', '--peb-size', type=int, dest='block_size',
|
|
help='Specify PEB size. (UBI Only)')
|
|
|
|
parser.add_argument('-e', '--leb-size', type=int, dest='block_size',
|
|
help='Specify LEB size. (UBIFS Only)')
|
|
|
|
parser.add_argument('-s', '--start-offset', type=int, dest='start_offset',
|
|
help='Specify offset of UBI/UBIFS data in file. (default: 0)')
|
|
|
|
parser.add_argument('-n', '--end-offset', type=int, dest='end_offset',
|
|
help='Specify end offset of UBI/UBIFS data in file.')
|
|
|
|
parser.add_argument('-g', '--guess-offset', type=int, dest='guess_offset',
|
|
help='Specify offset to start guessing where UBI data is in file. (default: 0)')
|
|
|
|
parser.add_argument('-w', '--warn-only-block-read-errors', action='store_true', dest='warn_only_block_read_errors',
|
|
help='Attempts to continue extracting files even with bad block reads. Some data will be missing or corrupted! (default: False)')
|
|
|
|
parser.add_argument('-i', '--ignore-block-header-errors', action='store_true', dest='ignore_block_header_errors',
|
|
help='Forces unused and error containing blocks to be included and also displayed with log/verbose. (default: False)')
|
|
|
|
parser.add_argument('-f', '--u-boot-fix', action='store_true', dest='uboot_fix',
|
|
help='Assume blocks with image_seq 0 are because of older U-boot implementations and include them. (default: False)')
|
|
|
|
parser.add_argument('block_search_params',
|
|
help="""
|
|
Double quoted Dict of ubi.block.description attributes, which is run through eval().
|
|
Ex. "{\'peb_num\':[0, 1], \'ec_hdr.ec\': 1, \'is_valid\': True}"
|
|
""")
|
|
|
|
parser.add_argument('filepath', help='File with blocks of interest.')
|
|
|
|
if len(sys.argv) == 1:
|
|
parser.print_help()
|
|
|
|
args = parser.parse_args()
|
|
|
|
settings.logging_on = args.log
|
|
|
|
settings.logging_on_verbose = args.verbose
|
|
|
|
settings.warn_only_block_read_errors = args.warn_only_block_read_errors
|
|
|
|
settings.ignore_block_header_errors = args.ignore_block_header_errors
|
|
|
|
settings.uboot_fix = args.uboot_fix
|
|
|
|
if args.filepath:
|
|
path = args.filepath
|
|
if not os.path.exists(path):
|
|
parser.error("File path doesn't exist.")
|
|
else:
|
|
parser.error('File path must be provided.')
|
|
sys.exit(1)
|
|
|
|
if args.start_offset:
|
|
start_offset = args.start_offset
|
|
elif args.guess_offset:
|
|
start_offset = guess_start_offset(path, args.guess_offset)
|
|
else:
|
|
start_offset = guess_start_offset(path)
|
|
|
|
if args.end_offset:
|
|
end_offset = args.end_offset
|
|
else:
|
|
end_offset = None
|
|
|
|
filetype = guess_filetype(path, start_offset)
|
|
if not filetype:
|
|
parser.error('Could not determine file type.')
|
|
|
|
if args.block_size:
|
|
block_size = args.block_size
|
|
else:
|
|
if filetype == UBI_EC_HDR_MAGIC:
|
|
block_size = guess_peb_size(path)
|
|
elif filetype == UBIFS_NODE_MAGIC:
|
|
block_size = guess_leb_size(path)
|
|
|
|
if not block_size:
|
|
parser.error('Block size could not be determined.')
|
|
|
|
if args.block_search_params:
|
|
try:
|
|
search_params = eval(args.block_search_params)
|
|
|
|
if not isinstance(search_params, dict):
|
|
parser.error('Search Param Error: Params must be a Dict of block PEB object items:value pairs.')
|
|
|
|
except NameError as e:
|
|
parser.error('Search Param Error: Dict key block attrs must be single quoted.')
|
|
|
|
except Exception as e:
|
|
parser.error('Search Param Error: %s' % e)
|
|
|
|
else:
|
|
parser.error('No search parameters given, -b arg is required.')
|
|
|
|
|
|
ufile_obj = ubi_file(path, block_size, start_offset, end_offset)
|
|
ubi_obj = ubi_base(ufile_obj)
|
|
blocks = []
|
|
|
|
for block in ubi_obj.blocks:
|
|
match = True
|
|
|
|
for key in search_params:
|
|
b = ubi_obj.blocks[block]
|
|
|
|
for attr in key.split('.'):
|
|
if hasattr(b, attr):
|
|
b = getattr(b, attr)
|
|
|
|
if isinstance(search_params[key], list):
|
|
if isinstance(b, list):
|
|
for value in b:
|
|
if value in search_params[key]:
|
|
break
|
|
else:
|
|
match = False
|
|
elif b not in search_params[key]:
|
|
match = False
|
|
|
|
elif b != search_params[key]:
|
|
match = False
|
|
break
|
|
|
|
if match:
|
|
blocks.append(ubi_obj.blocks[block])
|
|
|
|
ufile_obj.close()
|
|
|
|
print('\nBlock matches: %s' % len(blocks))
|
|
|
|
for block in blocks:
|
|
print(block.display())
|
|
|
|
if __name__=='__main__':
|
|
main()
|