diff options
Diffstat (limited to 'cxmanage_api/image.py')
-rw-r--r-- | cxmanage_api/image.py | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/cxmanage_api/image.py b/cxmanage_api/image.py new file mode 100644 index 0000000..23642c4 --- /dev/null +++ b/cxmanage_api/image.py @@ -0,0 +1,178 @@ +# Copyright (c) 2012, Calxeda Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of Calxeda Inc. nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR +# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. + + +import os +import subprocess + +from cxmanage_api import temp_file +from cxmanage_api.simg import create_simg, has_simg +from cxmanage_api.simg import valid_simg, get_simg_contents +from cxmanage_api.cx_exceptions import InvalidImageError + + +class Image: + """An Image consists of: an image type, a filename, and SIMG header info. + + >>> from cxmanage_api.image import Image + >>> img = Image(filename='spi_highbank.bin', image_type='PACAKGE') + + :param filename: Path to the image. + :type filename: string + :param image_type: Type of image. [CDB, BOOT_LOG, SOC_ELF] + :type image_type: string + :param simg: Path to the simg file. + :type simg: string + :param daddr: The daddr field in the SIMG Header. + :type daddr: integer + :param skip_crc32: Flag to skip (or not) CRC32 checking. + :type skip_crc32: boolean + :param version: Image version. + :type version: string + + :raises ValueError: If the image file does not exist. + :raises InvalidImageError: If the file is NOT a valid image. + + """ + + def __init__(self, filename, image_type, simg=None, daddr=None, + skip_crc32=False, version=None): + """Default constructor for the Image class.""" + self.filename = filename + self.type = image_type + self.daddr = daddr + self.skip_crc32 = skip_crc32 + self.version = version + + if (not os.path.exists(filename)): + raise ValueError("File %s does not exist" % filename) + + if (simg == None): + contents = open(filename).read() + self.simg = has_simg(contents) + else: + self.simg = simg + + if (not self.verify()): + raise InvalidImageError("%s is not a valid %s image" % + (filename, image_type)) + + def render_to_simg(self, priority, daddr): + """Creates a SIMG file. + + >>> img.render_to_simg(priority=1, daddr=0) + >>> 'spi_highbank.bin' + + :param priority: SIMG header priority value. + :type priority: integer + :param daddr: SIMG daddr field value. + :type daddr: integer + + :returns: The file name of the image. + :rtype: string + + :raises InvalidImageError: If the SIMG image is not valid. + + """ + filename = self.filename + # Create new image if necessary + if (not self.simg): + contents = open(filename).read() + # Figure out daddr + if (self.daddr != None): + daddr = self.daddr + # Create simg + align = (self.type in ["CDB", "BOOT_LOG"]) + simg = create_simg(contents, priority=priority, daddr=daddr, + skip_crc32=self.skip_crc32, align=align, + version=self.version) + filename = temp_file() + with open(filename, "w") as f: + f.write(simg) + + # Make sure the simg was built correctly + if (not valid_simg(open(filename).read())): + raise InvalidImageError("%s is not a valid SIMG" % + os.path.basename(self.filename)) + + return filename + + def size(self): + """Return the full size of this image (as an SIMG) + + >>> img.size() + 2174976 + + :returns: The size of the image file in bytes. + :rtype: integer + + """ + if (self.simg): + return os.path.getsize(self.filename) + else: + contents = open(self.filename).read() + align = (self.type in ["CDB", "BOOT_LOG"]) + simg = create_simg(contents, skip_crc32=True, align=align) + return len(simg) + + def verify(self): + """Returns true if the image is valid, false otherwise. + + >>> img.verify() + True + + :returns: Whether or not the image file is valid. + :rtype: boolean + + """ + if (self.type == "SOC_ELF"): + try: + file_process = subprocess.Popen(["file", self.filename], + stdout=subprocess.PIPE) + file_type = file_process.communicate()[0].split()[1] + + if (file_type != "ELF"): + return False + except OSError: + # "file" tool wasn't found, just continue without it + # typically located: /usr/bin/file + pass + + if (self.type in ["CDB", "BOOT_LOG"]): + # Look for "CDBH" + contents = open(self.filename).read() + if (self.simg): + contents = get_simg_contents(contents) + if (contents[:4] != "CDBH"): + return False + return True + + +# End of file: ./image.py |