diff options
Diffstat (limited to 'util/qualcomm/mbncat.py')
-rwxr-xr-x | util/qualcomm/mbncat.py | 200 |
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() |