summaryrefslogtreecommitdiff
path: root/cxmanage_api/simg.py
diff options
context:
space:
mode:
Diffstat (limited to 'cxmanage_api/simg.py')
-rw-r--r--cxmanage_api/simg.py239
1 files changed, 239 insertions, 0 deletions
diff --git a/cxmanage_api/simg.py b/cxmanage_api/simg.py
new file mode 100644
index 0000000..6ae8bf8
--- /dev/null
+++ b/cxmanage_api/simg.py
@@ -0,0 +1,239 @@
+# 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
+
+
+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)
+
+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
+
+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')
+
+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
+
+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])
+
+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
+