Source code for cxmanage_api.simg

# 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 struct

from cxmanage_api.crc32 import get_crc32


HEADER_LENGTH = 60
MIN_HEADER_LENGTH = 28


[docs]class SIMGHeader: """Container for an SIMG header. >>> from cxmanage_api.simg import SIMGHeader >>> simg = SIMGHeader() :param header_string: SIMG Header value. :type header_string: string """ def __init__(self, header_string=None): """Default constructor for the SIMGHeader class.""" if (header_string == None): self.magic_string = 'SIMG' self.hdrfmt = 2 self.priority = 0 self.imgoff = HEADER_LENGTH self.imglen = 0 self.daddr = 0 self.flags = 0 self.crc32 = 0 self.version = '' else: header_string = header_string.ljust(HEADER_LENGTH, chr(0)) tup = struct.unpack('<4sHHIIIII32s', header_string) self.magic_string = tup[0] self.hdrfmt = tup[1] self.priority = tup[2] self.imgoff = tup[3] self.imglen = tup[4] self.daddr = tup[5] self.flags = tup[6] self.crc32 = tup[7] if (self.hdrfmt >= 2): self.version = tup[8] else: self.version = '' def __str__(self): return struct.pack('<4sHHIIIII32s', self.magic_string, self.hdrfmt, self.priority, self.imgoff, self.imglen, self.daddr, self.flags, self.crc32, self.version)
[docs]def create_simg(contents, priority=0, daddr=0, skip_crc32=False, align=False, version=None): """Create an SIMG version of a file. >>> from cxmanage_api.simg import create_simg >>> simg = create_simg(contents='foobarbaz') >>> simg 'SIMG\\x02\\x00\\x00\\x00<\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\xff\\xff\\xff\\xffK\\xf3\\xea\\x0c\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00 \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00foobarbaz' :param contents: Contents of the SIMG file. :type contents: string :param priority: SIMG Header priority value. :type priority: integer :param daddr: SIMG Header daddr value. :type daddr: integer :param skip_crc32: Flag to skip crc32 calculating. :type skip_crc32: boolean :param align: Flag used to turn on/off image offset of 4096. :type align: boolean :param version: Version string. :type version: string :returns: String representation of the SIMG file. :rtype: string """ if (version == None): version = '' header = SIMGHeader() header.priority = priority header.imglen = len(contents) header.daddr = daddr header.version = version if (align): header.imgoff = 4096 # Calculate crc value if (skip_crc32): crc32 = 0 else: crc32 = get_crc32(contents, get_crc32(str(header)[:MIN_HEADER_LENGTH])) # Get SIMG header header.flags = 0xFFFFFFFF header.crc32 = crc32 return str(header).ljust(header.imgoff, chr(0)) + contents
[docs]def has_simg(simg): """Returns true if this string has an SIMG header. >>> from cxmanage_api.simg import create_simg >>> simg=create_simg(contents='foobarbaz') >>> from cxmanage_api.simg import has_simg >>> has_simg(simg=simg) True :param simg: SIMG string (representation of a SIMG file). :type simg: string :returns: Whether or not the string has a SIMG header. :rtype: boolean """ if (len(simg) < MIN_HEADER_LENGTH): return False header = SIMGHeader(simg[:HEADER_LENGTH]) # Check for magic word return (header.magic_string == 'SIMG')
[docs]def valid_simg(simg): """Return true if this is a valid SIMG. >>> from cxmanage_api.simg import create_simg >>> simg=create_simg(contents='foobarbaz') >>> from cxmanage_api.simg import valid_simg >>> valid_simg(simg=simg) True :param simg: SIMG string (representation of a SIMG file). :type simg: string :returns: Whether or not the SIMG is valid. :rtype: boolean """ if (not has_simg(simg)): return False header = SIMGHeader(simg[:HEADER_LENGTH]) # Check offset if (header.imgoff < MIN_HEADER_LENGTH): return False # Check length start = header.imgoff end = start + header.imglen contents = simg[start:end] if (len(contents) < header.imglen): return False # Check crc32 crc32 = header.crc32 if (crc32 != 0): header.flags = 0 header.crc32 = 0 if (crc32 != get_crc32(contents, get_crc32(str(header)[:MIN_HEADER_LENGTH]))): return False return True
[docs]def get_simg_header(simg): """Returns the header of this SIMG. >>> from cxmanage_api.simg import get_simg_header >>> get_simg_header(x) <cxmanage_api.simg.SIMGHeader instance at 0x7f4d1ce9aef0> :param simg: Path to SIMG file. :type simg: string :returns: The SIMG header. :rtype: string :raises ValueError: If the SIMG cannot be read. """ if (not valid_simg(simg)): raise ValueError("Failed to read invalid SIMG") return SIMGHeader(simg[:HEADER_LENGTH])
[docs]def get_simg_contents(simg): """Returns the contents of this SIMG. >>> from cxmanage_api.simg import get_simg_contents >>> get_simg_contents(simg=simg) 'foobarbaz' :param simg: Path to SIMG file. :type simg: string :returns: Contents of this SIMG. :rtype: string """ header = get_simg_header(simg) start = header.imgoff end = start + header.imglen return simg[start:end] # End of file: ./simg.py