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.
150 lines
5.0 KiB
Python
150 lines
5.0 KiB
Python
#!/usr/bin/env python
|
|
#############################################################
|
|
# ubi_reader/ubifs
|
|
# (c) 2013 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/>.
|
|
#############################################################
|
|
|
|
from ubireader.debug import error, log, verbose_display
|
|
from ubireader.ubifs.defines import *
|
|
from ubireader.ubifs import nodes, display
|
|
|
|
class ubifs():
|
|
"""UBIFS object
|
|
|
|
Arguments:
|
|
Str:path -- File path to UBIFS image.
|
|
|
|
Attributes:
|
|
Obj:file -- File object
|
|
Int:leb_size -- Size of Logical Erase Blocks.
|
|
Int:min_io -- Size of min I/O from vid_hdr_offset.
|
|
Obj:sb_node -- Superblock node of UBIFS image LEB0
|
|
Obj:mst_node -- Master Node of UBIFS image LEB1
|
|
Obj:mst_node2 -- Master Node 2 of UBIFS image LEB2
|
|
"""
|
|
def __init__(self, ubifs_file):
|
|
self.__name__ = 'UBIFS'
|
|
self._file = ubifs_file
|
|
try:
|
|
self.file.reset()
|
|
sb_chdr = nodes.common_hdr(self.file.read(UBIFS_COMMON_HDR_SZ))
|
|
log(self , '%s file addr: %s' % (sb_chdr, self.file.last_read_addr()))
|
|
verbose_display(sb_chdr)
|
|
|
|
if sb_chdr.node_type == UBIFS_SB_NODE:
|
|
self.file.seek(UBIFS_COMMON_HDR_SZ)
|
|
buf = self.file.read(UBIFS_SB_NODE_SZ)
|
|
self._sb_node = nodes.sb_node(buf, self.file.last_read_addr())
|
|
self._min_io_size = self._sb_node.min_io_size
|
|
self._leb_size = self._sb_node.leb_size
|
|
log(self , '%s file addr: %s' % (self._sb_node, self.file.last_read_addr()))
|
|
verbose_display(self._sb_node)
|
|
else:
|
|
raise Exception('Wrong node type.')
|
|
except Exception as e:
|
|
error(self, 'Fatal', 'Super block error: %s' % e)
|
|
|
|
self._mst_nodes = [None, None]
|
|
for i in range(0, 2):
|
|
try:
|
|
mst_offset = self.leb_size * (UBIFS_MST_LNUM + i)
|
|
self.file.seek(mst_offset)
|
|
mst_chdr = nodes.common_hdr(self.file.read(UBIFS_COMMON_HDR_SZ))
|
|
log(self , '%s file addr: %s' % (mst_chdr, self.file.last_read_addr()))
|
|
verbose_display(mst_chdr)
|
|
|
|
if mst_chdr.node_type == UBIFS_MST_NODE:
|
|
self.file.seek(mst_offset + UBIFS_COMMON_HDR_SZ)
|
|
buf = self.file.read(UBIFS_MST_NODE_SZ)
|
|
self._mst_nodes[i] = nodes.mst_node(buf, self.file.last_read_addr())
|
|
log(self , '%s%s file addr: %s' % (self._mst_nodes[i], i, self.file.last_read_addr()))
|
|
verbose_display(self._mst_nodes[i])
|
|
else:
|
|
raise Exception('Wrong node type.')
|
|
except Exception as e:
|
|
error(self, 'Warn', 'Master block %s error: %s' % (i, e))
|
|
|
|
if self._mst_nodes[0] is None and self._mst_nodes[1] is None:
|
|
error(self, 'Fatal', 'No valid Master Node found.')
|
|
|
|
elif self._mst_nodes[0] is None and self._mst_nodes[1] is not None:
|
|
self._mst_nodes[0] = self._mst_nodes[1]
|
|
self._mst_nodes[1] = None
|
|
log(self , 'Swapping Master Nodes due to bad first node.')
|
|
|
|
|
|
def _get_file(self):
|
|
return self._file
|
|
file = property(_get_file)
|
|
|
|
|
|
def _get_superblock(self):
|
|
""" Superblock Node Object
|
|
|
|
Returns:
|
|
Obj:Superblock Node
|
|
"""
|
|
return self._sb_node
|
|
superblock_node = property(_get_superblock)
|
|
|
|
|
|
def _get_master_node(self):
|
|
"""Master Node Object
|
|
|
|
Returns:
|
|
Obj:Master Node
|
|
"""
|
|
return self._mst_nodes[0]
|
|
master_node = property(_get_master_node)
|
|
|
|
|
|
def _get_master_node2(self):
|
|
"""Master Node Object 2
|
|
|
|
Returns:
|
|
Obj:Master Node
|
|
"""
|
|
return self._mst_nodes[1]
|
|
master_node2 = property(_get_master_node2)
|
|
|
|
|
|
def _get_leb_size(self):
|
|
"""LEB size of UBI blocks in file.
|
|
|
|
Returns:
|
|
Int -- LEB Size.
|
|
"""
|
|
return self._leb_size
|
|
leb_size = property(_get_leb_size)
|
|
|
|
|
|
def _get_min_io_size(self):
|
|
"""Min I/O Size
|
|
|
|
Returns:
|
|
Int -- Min I/O Size.
|
|
"""
|
|
return self._min_io_size
|
|
min_io_size = property(_get_min_io_size)
|
|
|
|
def display(self, tab=''):
|
|
"""Print information about this object.
|
|
|
|
Argument:
|
|
Str:tab -- '\t' for spacing this object.
|
|
"""
|
|
return display.ubifs(self, tab)
|