summaryrefslogtreecommitdiff
path: root/util/qualcomm/mbncat.py
diff options
context:
space:
mode:
Diffstat (limited to 'util/qualcomm/mbncat.py')
-rwxr-xr-xutil/qualcomm/mbncat.py200
1 files changed, 200 insertions, 0 deletions
diff --git a/util/qualcomm/mbncat.py b/util/qualcomm/mbncat.py
new file mode 100755
index 0000000000..c4da265f80
--- /dev/null
+++ b/util/qualcomm/mbncat.py
@@ -0,0 +1,200 @@
+#!/usr/bin/env python2
+# Copyright (c) 2014, The Linux Foundation. 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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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
+import sys
+import os
+
+"""A utility to generate ipq8064 uber SBL..
+
+The very first blob (aka 'uber SBL') read out of NOR SPI flash by the IPQ8064
+maskrom is supposed to be a concatenation of up to three binaries: one to run
+on the RPM, another one to run on the AP, and the third one - the actual
+coreboot bootblock.
+
+The uber SBL starts with the combined header descriptor of 80 bytes, with the
+first two 4 byte words set to certain values, and the total size of the
+payload saved at offsets 28 and 32.
+
+To generate the uber SBL this utility expects two or three input file names in
+the command line, the first file including the described header, and the
+following one(s) - in QCA MBN format. This allows to create the uber SBL in
+one or two invocations.
+
+The input files are concatenated together aligned at 256 byte boundary offset
+from the combined header. See Usage() below for more details.
+
+The resulting uber SBL file is prepended by the same combined header adjusted
+to reflect the new total file size.
+"""
+
+DEFAULT_OUTPUT_FILE_NAME = 'sbl-ro.mbn'
+
+class NorSbl:
+ """Object representing the uber SBL."""
+
+ NOR_SBL1_HEADER = '<II72s'
+ NOR_SBL1_HEADER_SZ = struct.calcsize(NOR_SBL1_HEADER)
+ ALIGNMENT = 256 # Make sure this == UBER_SBL_PAD_SIZE
+ NOR_CODE_WORD = 0x844bdcd1
+ MAGIC_NUM = 0x73d71034
+
+ def __init__(self, sbl1, verbose):
+ """Initialize the object and verify the first file in the sequence.
+
+ Args:
+ sbl1: string, the name of the first out of the three input blobs,
+ must be prepended by the combined header.
+ verbose: boolean, if True - print debug information on the console.
+ """
+ self.verbose = verbose
+ self.mbn_file_names = []
+ if self.verbose:
+ print 'Reading ' + sbl1
+
+ try:
+ self.sbl1 = open(sbl1, 'rb').read()
+ except IOError as e:
+ print 'I/O error({0}): {1}'.format(e.errno, e.strerror)
+ raise
+
+ (codeword, magic, _) = struct.unpack_from(
+ self.NOR_SBL1_HEADER, self.sbl1)
+
+ if codeword != self.NOR_CODE_WORD:
+ print '\n\nError: Unexpected Codeword!'
+ print 'Codeword : ' + ('0x%x' % self.NOR_CODE_WORD) + \
+ ' != ' + ('0x%x' % codeword)
+ sys.exit(-1)
+
+ if magic != self.MAGIC_NUM:
+ print '\n\nError: Unexpected Magic!'
+ print 'Magic : ' + ('0x%x' % self.MAGIC_NUM) + \
+ ' != ' + ('0x%x' % magic)
+ sys.exit(-1)
+
+ def Append(self, src):
+ """Add a file to the list of files to be concatenated"""
+ self.mbn_file_names.append(src)
+
+ def PadOutput(self, outfile, size):
+ """Pad output file to the required alignment.
+
+ Adds 0xff to the passed in file to get its size to the ALIGNMENT
+ boundary.
+
+ Args:
+ outfile: file handle of the file to be padded
+ size: int, current size of the file
+
+ Returns number of bytes in the added padding.
+ """
+
+ # Is padding needed?
+ overflow = size % self.ALIGNMENT
+ if overflow:
+ pad_size = self.ALIGNMENT - overflow
+ pad = '\377' * pad_size
+ outfile.write(pad)
+ if self.verbose:
+ print 'Added %d byte padding' % pad_size
+ return pad_size
+ return 0
+
+ def Create(self, out_file_name):
+ """Create the uber SBL.
+
+ Concatenate input files with the appropriate padding and update the
+ combined header to reflect the new blob size.
+
+ Args:
+ out_file_name: string, name of the file to save the generated uber
+ SBL in.
+ """
+ outfile = open(out_file_name, 'wb')
+ total_size = len(self.sbl1) - self.NOR_SBL1_HEADER_SZ
+ outfile.write(self.sbl1)
+
+ for mbn_file_name in self.mbn_file_names:
+ total_size += self.PadOutput(outfile, total_size)
+ mbn_file_data = open(mbn_file_name, 'r').read()
+ outfile.write(mbn_file_data)
+ if self.verbose:
+ print 'Added %s (%d bytes)' % (mbn_file_name,
+ len(mbn_file_data))
+ total_size += len(mbn_file_data)
+
+ outfile.seek(28)
+ outfile.write(struct.pack('<I', total_size))
+ outfile.write(struct.pack('<I', total_size))
+
+
+def Usage(v):
+ print '%s: [-v] [-h] [-o Output MBN] sbl1 sbl2 [bootblock]' % (
+ os.path.basename(sys.argv[0]))
+ print
+ print 'Concatenates up to three mbn files: two SBLs and a coreboot bootblock'
+ print ' -h This message'
+ print ' -v verbose'
+ print ' -o Output file name, (default: %s)\n' % DEFAULT_OUTPUT_FILE_NAME
+ sys.exit(v)
+
+def main():
+ verbose = 0
+ mbn_output = DEFAULT_OUTPUT_FILE_NAME
+ i = 0
+
+ while i < (len(sys.argv) - 1):
+ i += 1
+ if (sys.argv[i] == '-h'):
+ Usage(0) # doesn't return
+
+ if (sys.argv[i] == '-o'):
+ mbn_output = sys.argv[i + 1]
+ i += 1
+ continue
+
+ if (sys.argv[i] == '-v'):
+ verbose = 1
+ continue
+
+ break
+
+ argv = sys.argv[i:]
+ if len(argv) < 2 or len(argv) > 3:
+ Usage(-1)
+
+ nsbl = NorSbl(argv[0], verbose)
+
+ for mbnf in argv[1:]:
+ nsbl.Append(mbnf)
+
+ nsbl.Create(mbn_output)
+
+if __name__ == '__main__':
+ main()