diff options
author | T Michael Turney <mturney@codeaurora.org> | 2018-05-01 15:59:37 -0700 |
---|---|---|
committer | Julius Werner <jwerner@chromium.org> | 2019-05-03 21:59:05 +0000 |
commit | 101098c41a047184e3eceabca2c1baa11141f36e (patch) | |
tree | b6fcf8f46131e4e8fc28554e0c79eda984bb7fca /util/ipqheader | |
parent | 61309e39b3c4545f47c9107a0e0ddaedef854505 (diff) |
sdm845: Combine BB with QC-Sec for ROM boot
TEST=build & run
Change-Id: I222a56f1c9b74856a1e1ff8132bab5e041672c5d
Signed-off-by: T Michael Turney <mturney@codeaurora.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/25207
Reviewed-by: Julius Werner <jwerner@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'util/ipqheader')
-rwxr-xr-x | util/ipqheader/createxbl.py | 714 | ||||
-rwxr-xr-x | util/ipqheader/ipqheader.py | 129 | ||||
-rwxr-xr-x | util/ipqheader/mbn_tools.py | 2315 | ||||
-rwxr-xr-x | util/ipqheader/mbncat.py | 200 |
4 files changed, 0 insertions, 3358 deletions
diff --git a/util/ipqheader/createxbl.py b/util/ipqheader/createxbl.py deleted file mode 100755 index 1efd8bac0c..0000000000 --- a/util/ipqheader/createxbl.py +++ /dev/null @@ -1,714 +0,0 @@ -#!/usr/bin/env python2 -#============================================================================ -# -#/** @file createxbl.py -# -# GENERAL DESCRIPTION -# Concatentates XBL segments into one ELF image -# -# Copyright (c) 2016, 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. -# -#**/ -# -#---------------------------------------------------------------------------- -# -# EDIT HISTORY FOR FILE -# -# This section contains comments describing changes made to the module. -# Notice that changes are listed in reverse chronological order. -# -# when who what, where, why -# -------- --- ------------------------------------------------------ -# 09/04/15 et Added -x and -d to embed xbl_sec ELF -# 02/11/15 ck Fixed missing elf type check in ZI OOB feature -# 11/04/14 ck Updated calls to mbn_tools functions -# 10/22/14 ck Added -z option to remove out of bounds ZI segments when converting from 64 to 32 -# 10/10/14 ck Added -c option and logic to enable elf type swapping -# 09/12/14 ck Added single file logic -# 08/29/14 ck Added no_hash option -# 08/29/14 ck Refactored to use proper python arguments and cleaned code -# 06/16/14 niting xbl.mbn to xbl.elf -# 05/28/14 niting Initial revision -# -#============================================================================ -from optparse import OptionParser -import os -import sys -import shutil -import mbn_tools - -PAGE_SIZE = 4096 -SEGMENT_ALIGN = 16 -ELF32_HDR_SIZE = 52 -ELF32_PHDR_SIZE = 32 -ELF64_HDR_SIZE = 64 -ELF64_PHDR_SIZE = 56 - - -############################################################################## -# main -############################################################################## -def main(): - parser = OptionParser(usage='usage: %prog [options] arguments') - - parser.add_option("-f", "--first_filepath", - action="store", type="string", dest="elf_inp_file1", - help="First ELF file to merge.") - - parser.add_option("-s", "--second_filepath", - action="store", type="string", dest="elf_inp_file2", - help="Second ELF file to merge.") - - parser.add_option("-x", "--xbl_sec_filepath", - action="store", type="string", dest="elf_inp_xbl_sec", - help="Second ELF file to merge.") - - parser.add_option("-o", "--output_filepath", - action="store", type="string", dest="binary_out", - help="Merged filename and path.") - - parser.add_option("-a", "--first_elf_arch", - action="store", type="string", dest="elf_1_arch", - help="First (and output) ELF file architecture. '32' or '64'") - - parser.add_option("-b", "--second_elf_arch", - action="store", type="string", dest="elf_2_arch", - help="Second ELF file architecture. '32' or '64'") - - parser.add_option("-d", "--xbl_sec_elf_arch", - action="store", type="string", dest="elf_xbl_sec_arch", - help="xbl_sec file architecture. '32' or '64'") - - parser.add_option("-c", "--output_elf_arch", - action="store", type="string", dest="elf_out_arch", - help="Output ELF file architecture. '32' or '64'" + \ - " If not given defaults to first file arch.") - - parser.add_option("-n", "--no_hash", - action="store_true", dest="hash_image", - help="Disables hashing of image after merging.") - - parser.add_option("-z", "--zi_out_of_bounds", - action="store_true", dest="zi_oob", - help="Removes ZI segments that have addresses greater" + \ - " than 32 bits when converting from a 64 to 32 bit ELF") - - - (options, args) = parser.parse_args() - if not options.elf_inp_file1: - parser.error('First ELF filename not given') - - if not options.binary_out: - parser.error('Output filename not given') - - if not options.elf_1_arch: - parser.error('First ELF architecture not given') - - if (not options.elf_1_arch == '64') and (not options.elf_1_arch == '32'): - parser.error('Invalid First ELF architecture given') - - # Only evaluate elf_2_arch if two files are given for merging - if options.elf_inp_file2: - if (not options.elf_2_arch == '64') and (not options.elf_2_arch == '32'): - parser.error('Invalid Second ELF architecture given') - - # Only evaluate elf_xbl_sec_arch if file is given - if options.elf_inp_xbl_sec: - if (not options.elf_xbl_sec_arch == '64') and (not options.elf_xbl_sec_arch == '32'): - parser.error('Invalid xbl_sec ELF architecture given') - - # If output file architecture is given ensure it is either '32' or '64' - if options.elf_out_arch: - if (not options.elf_out_arch == '64') and (not options.elf_out_arch == '32'): - parser.error('Invalid Output ELF architecture given') - - - gen_dict = {} - - elf_inp_file1 = options.elf_inp_file1 - - # It is valid for only one file to be "merged". This essentially just - # strips off the section names. If second file name is not given then - # set elf_inp_file2 to "" - if options.elf_inp_file2: - elf_inp_file2 = options.elf_inp_file2 - else: - elf_inp_file2 = "" - - # Do same for xbl_sec - elf_inp_xbl_sec = options.elf_inp_xbl_sec if options.elf_inp_xbl_sec else "" - - binary_out = options.binary_out - - if options.elf_1_arch == '64': - is_elf1_64_bit = True - else: - is_elf1_64_bit = False - - # If second filename is not given then set is_elf2_64_bit to false so it - # can be passed even though it is not used. - if options.elf_inp_file2: - if options.elf_2_arch == '64': - is_elf2_64_bit = True - else: - is_elf2_64_bit = False - else: - is_elf2_64_bit = False - - if options.elf_inp_xbl_sec: - if options.elf_xbl_sec_arch == '64': - is_elf_xbl_sec_64_bit = True - else: - is_elf_xbl_sec_64_bit = False - else: - is_elf_xbl_sec_64_bit = False - - # If output ELF arch is given then set is_out_elf_64_bit accordingly. - # If not then default to be input1's setting - if options.elf_out_arch: - if options.elf_out_arch == '64': - is_out_elf_64_bit = True - else: - is_out_elf_64_bit = False - else: - is_out_elf_64_bit = is_elf1_64_bit - - - # Store ZI Out of Bounds value - if not options.zi_oob: - zi_oob_enabled = False - else: - zi_oob_enabled = True - - - mbn_type = 'elf' - header_format = 'reg' - gen_dict['IMAGE_KEY_IMAGE_ID'] = mbn_tools.ImageType.APPSBL_IMG - #gen_dict['IMAGE_KEY_IMAGE_SOURCE'] = 0 - #gen_dict['IMAGE_KEY_IMAGE_DEST'] = 0 - gen_dict['IMAGE_KEY_MBN_TYPE'] = mbn_type - image_header_secflag = 'non_secure' - - source_base = os.path.splitext(str(binary_out))[0] - target_base = os.path.splitext(str(binary_out))[0] - merged_elf = source_base + "_merged.elf" - source_elf = source_base + "_nohash.elf" - target_hash = target_base + ".hash" - target_hash_hd = target_base + "_hash.hd" - target_phdr_elf = target_base + "_phdr.pbn" - target_nonsec = target_base + "_combined_hash.mbn" - - - #print "Input file 1:", elf_inp_file1 - #print "Input file 2:", elf_inp_file2 - #print "Output file:", binary_out - - merge_elfs([], - elf_inp_file1, - elf_inp_file2, - elf_inp_xbl_sec, - merged_elf, - is_elf1_64_bit, - is_elf2_64_bit, - is_elf_xbl_sec_64_bit, - is_out_elf_64_bit, - zi_oob_enabled) - - - # Hash the image if user did not explicitly say not to - if options.hash_image: - # Just copy the merged elf to the final output name - shutil.move(merged_elf, binary_out) - else: - shutil.copy(merged_elf, source_elf) - - # Create hash table - rv = mbn_tools.pboot_gen_elf([], - source_elf, - target_hash, - elf_out_file_name = target_phdr_elf, - secure_type = image_header_secflag) - if rv: - raise RuntimeError, "Failed to run pboot_gen_elf" - - # Create hash table header - rv = mbn_tools.image_header([], - gen_dict, - target_hash, - target_hash_hd, - image_header_secflag, - elf_file_name = source_elf) - if rv: - raise RuntimeError, "Failed to create image header for hash segment" - - files_to_cat_in_order = [target_hash_hd, target_hash] - mbn_tools.concat_files (target_nonsec, files_to_cat_in_order) - - # Add the hash segment into the ELF - mbn_tools.pboot_add_hash([], - target_phdr_elf, - target_nonsec, - binary_out) - - return - - -############################################################################## -# roundup -############################################################################## -def roundup(x, precision): - return x if x % precision == 0 else (x + precision - (x % precision)) - -############################################################################## -# merge_elfs -############################################################################## -def merge_elfs(env, - elf_in_file_name1, - elf_in_file_name2, - elf_in_file_xbl_sec, - elf_out_file_name, - is_elf1_64_bit, - is_elf2_64_bit, - is_elf_xbl_sec_64_bit, - is_out_elf_64_bit, - zi_oob_enabled): - - [elf_header1, phdr_table1] = \ - mbn_tools.preprocess_elf_file(elf_in_file_name1) - - # Check to make sure second file path exists before using - if elf_in_file_name2 != "": - [elf_header2, phdr_table2] = \ - mbn_tools.preprocess_elf_file(elf_in_file_name2) - - # Check to make sure xbl_sec file path exists before using - if elf_in_file_xbl_sec != "": - [elf_headerxblsec, phdr_tablexblsec] = \ - mbn_tools.preprocess_elf_file(elf_in_file_xbl_sec) - - # Open Files - elf_in_fp1 = mbn_tools.OPEN(elf_in_file_name1, "rb") - if elf_in_file_name2 != "": - elf_in_fp2 = mbn_tools.OPEN(elf_in_file_name2, "rb") - if elf_in_file_xbl_sec != "": - elf_in_fpxblsec = mbn_tools.OPEN(elf_in_file_xbl_sec, "rb") - - if elf_out_file_name is not None: - elf_out_fp = mbn_tools.OPEN(elf_out_file_name, "wb+") - - - # Calculate the new program header size. This is dependant on the output - # ELF type and number of program headers going into output. - if is_out_elf_64_bit: - phdr_total_size = elf_header1.e_phnum * ELF64_PHDR_SIZE - phdr_total_count = elf_header1.e_phnum - else: - phdr_total_size = elf_header1.e_phnum * ELF32_PHDR_SIZE - phdr_total_count = elf_header1.e_phnum - - - # This logic only applies if two files are to be merged - if elf_in_file_name2 != "": - if is_out_elf_64_bit: - phdr_total_size += elf_header2.e_phnum * ELF64_PHDR_SIZE - phdr_total_count += elf_header2.e_phnum - else: - phdr_total_size += elf_header2.e_phnum * ELF32_PHDR_SIZE - phdr_total_count += elf_header2.e_phnum - - # Account for xbl_sec header if included - if elf_in_file_xbl_sec != "": - phdr_total_count += 1 - if is_out_elf_64_bit: - phdr_total_size += ELF64_PHDR_SIZE - else: - phdr_total_size += ELF32_PHDR_SIZE - - # Create a new ELF header for the output file - if is_out_elf_64_bit: - out_elf_header = mbn_tools.Elf64_Ehdr('\0' * ELF64_HDR_SIZE) - out_elf_header.e_phoff = ELF64_HDR_SIZE - out_elf_header.e_ehsize = ELF64_HDR_SIZE - out_elf_header.e_phentsize = ELF64_PHDR_SIZE - out_elf_header.e_machine = 183 - out_elf_header.e_ident = str('\x7f' + 'E' + 'L' + 'F' + \ - '\x02' + \ - '\x01' + \ - '\x01' + \ - '\x00' + \ - '\x00' + \ - ('\x00' * 7)) - - out_elf_header.e_entry = elf_header1.e_entry - else: - out_elf_header = mbn_tools.Elf32_Ehdr('\0' * ELF32_HDR_SIZE) - out_elf_header.e_phoff = ELF32_HDR_SIZE - out_elf_header.e_ehsize = ELF32_HDR_SIZE - out_elf_header.e_phentsize = ELF32_PHDR_SIZE - out_elf_header.e_machine = 40 - out_elf_header.e_entry = elf_header1.e_entry - out_elf_header.e_ident = str('\x7f' + 'E' + 'L' + 'F' + \ - '\x01' + \ - '\x01' + \ - '\x01' + \ - '\x00' + \ - '\x00' + \ - ('\x00' * 7)) - - # Address needs to be verified that it is not greater than 32 bits - # as it is possible to go from a 64 bit elf to 32. - if (elf_header1.e_entry > 0xFFFFFFFF): - print "ERROR: File 1's entry point is too large to convert." - exit() - out_elf_header.e_entry = elf_header1.e_entry - - # Common header entries - out_elf_header.e_type = 2 - out_elf_header.e_version = 1 - out_elf_header.e_shoff = 0 - out_elf_header.e_flags = 0 - out_elf_header.e_shentsize = 0 - out_elf_header.e_shnum = 0 - out_elf_header.e_shstrndx = 0 - - - # If ZI OOB is enabled then it is possible that a segment could be discarded - # Scan for that instance and handle before setting e_phnum and writing header - # Ensure ELF output is 32 bit - if zi_oob_enabled == True and is_out_elf_64_bit == False: - for i in range(len(phdr_table1)): - if (phdr_table1[i].p_vaddr > 0xFFFFFFFF) or \ - (phdr_table1[i].p_paddr > 0xFFFFFFFF): - if phdr_table1[i].p_filesz == 0: - phdr_total_count = phdr_total_count - 1 - - if elf_in_file_name2 != "": - for i in range(len(phdr_table2)): - if (phdr_table2[i].p_vaddr > 0xFFFFFFFF) or \ - (phdr_table2[i].p_paddr > 0xFFFFFFFF): - if phdr_table2[i].p_filesz == 0: - phdr_total_count = phdr_total_count - 1 - # Do not include xbl_sec in above calculation - # xbl_sec is to be treated as a single blob - - - # Now it is ok to populate the ELF header and write it out - out_elf_header.e_phnum = phdr_total_count - - # write elf header - if is_out_elf_64_bit == False: - elf_out_fp.write(mbn_tools.Elf32_Ehdr.getPackedData(out_elf_header)) - else: - elf_out_fp.write(mbn_tools.Elf64_Ehdr.getPackedData(out_elf_header)) - - phdr_offset = out_elf_header.e_phoff # offset of where to put next phdr - - # offset the start of the segments just after the program headers - segment_offset = roundup(out_elf_header.e_phoff + phdr_total_size, PAGE_SIZE) - - - # Output first elf data - for i in range(elf_header1.e_phnum): - curr_phdr = phdr_table1[i] - - # Copy program header piece by piece to ensure possible conversion success - if is_out_elf_64_bit == True: - # Converting from 32 to 64 elf requires no data size validation - new_phdr = mbn_tools.Elf64_Phdr('\0' * ELF64_PHDR_SIZE) - new_phdr.p_type = curr_phdr.p_type - new_phdr.p_offset = segment_offset - new_phdr.p_vaddr = curr_phdr.p_vaddr - new_phdr.p_paddr = curr_phdr.p_paddr - new_phdr.p_filesz = curr_phdr.p_filesz - new_phdr.p_memsz = curr_phdr.p_memsz - new_phdr.p_flags = curr_phdr.p_flags - new_phdr.p_align = curr_phdr.p_align - else: - # Converting from 64 to 32 elf requires data size validation - # Note that there is an option to discard a segment if it is only ZI - # and its address is greater than 32 bits - new_phdr = mbn_tools.Elf32_Phdr('\0' * ELF32_PHDR_SIZE) - new_phdr.p_type = curr_phdr.p_type - new_phdr.p_offset = segment_offset - - if curr_phdr.p_vaddr > 0xFFFFFFFF: - if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0): - continue - else: - print "ERROR: File 1 VAddr is too large for conversion." - exit() - new_phdr.p_vaddr = curr_phdr.p_vaddr - - if curr_phdr.p_paddr > 0xFFFFFFFF: - if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0): - continue - else: - print "ERROR: File 1 PAddr is too large for conversion." - exit() - new_phdr.p_paddr = curr_phdr.p_paddr - - if curr_phdr.p_filesz > 0xFFFFFFFF: - print "ERROR: File 1 Filesz is too large for conversion." - exit() - new_phdr.p_filesz = curr_phdr.p_filesz - - if curr_phdr.p_memsz > 0xFFFFFFFF: - print "ERROR: File 1 Memsz is too large for conversion." - exit() - new_phdr.p_memsz = curr_phdr.p_memsz - - if curr_phdr.p_flags > 0xFFFFFFFF: - print "ERROR: File 1 Flags is too large for conversion." - exit() - new_phdr.p_flags = curr_phdr.p_flags - - if curr_phdr.p_align > 0xFFFFFFFF: - print "ERROR: File 1 Align is too large for conversion." - exit() - new_phdr.p_align = curr_phdr.p_align - - - #print "i=",i - #print "phdr_offset=", phdr_offset - - # update output file location to next phdr location - elf_out_fp.seek(phdr_offset) - # increment phdr_offset to next location - phdr_offset += out_elf_header.e_phentsize - - inp_data_offset = curr_phdr.p_offset # used to read data from input file - -# print "inp_data_offset=" -# print inp_data_offset -# -# print "curr_phdr.p_offset=" -# print curr_phdr.p_offset -# -# print "curr_phdr.p_filesz=" -# print curr_phdr.p_filesz - - # output current phdr - if is_out_elf_64_bit == False: - elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr)) - else: - elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr)) - - # Copy the ELF segment - bytes_written = mbn_tools.file_copy_offset(elf_in_fp1, - inp_data_offset, - elf_out_fp, - new_phdr.p_offset, - new_phdr.p_filesz) - - # update data segment offset to be aligned after previous segment - segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN); - elf_in_fp1.close() - - # Output second elf data if applicable - if elf_in_file_name2 != "": - for i in range(elf_header2.e_phnum): - curr_phdr = phdr_table2[i] - - # Copy program header piece by piece to ensure possible conversion success - if is_out_elf_64_bit == True: - # Converting from 32 to 64 elf requires no data size validation - new_phdr = mbn_tools.Elf64_Phdr('\0' * ELF64_PHDR_SIZE) - new_phdr.p_type = curr_phdr.p_type - new_phdr.p_offset = segment_offset - new_phdr.p_vaddr = curr_phdr.p_vaddr - new_phdr.p_paddr = curr_phdr.p_paddr - new_phdr.p_filesz = curr_phdr.p_filesz - new_phdr.p_memsz = curr_phdr.p_memsz - new_phdr.p_flags = curr_phdr.p_flags - new_phdr.p_align = curr_phdr.p_align - else: - # Converting from 64 to 32 elf requires data size validation - # Note that there is an option to discard a segment if it is only ZI - # and its address is greater than 32 bits - new_phdr = mbn_tools.Elf32_Phdr('\0' * ELF32_PHDR_SIZE) - new_phdr.p_type = curr_phdr.p_type - new_phdr.p_offset = segment_offset - - if curr_phdr.p_vaddr > 0xFFFFFFFF: - if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0): - continue - else: - print "ERROR: File 2 VAddr is too large for conversion." - exit() - new_phdr.p_vaddr = curr_phdr.p_vaddr - - if curr_phdr.p_paddr > 0xFFFFFFFF: - if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0): - continue - else: - print "ERROR: File 2 PAddr is too large for conversion." - exit() - new_phdr.p_paddr = curr_phdr.p_paddr - - if curr_phdr.p_filesz > 0xFFFFFFFF: - print "ERROR: File 2 Filesz is too large for conversion." - exit() - new_phdr.p_filesz = curr_phdr.p_filesz - - if curr_phdr.p_memsz > 0xFFFFFFFF: - print "ERROR: File 2 Memsz is too large for conversion." - exit() - new_phdr.p_memsz = curr_phdr.p_memsz - - if curr_phdr.p_flags > 0xFFFFFFFF: - print "ERROR: File 2 Flags is too large for conversion." - exit() - new_phdr.p_flags = curr_phdr.p_flags - - if curr_phdr.p_align > 0xFFFFFFFF: - print "ERROR: File 2 Align is too large for conversion." - exit() - new_phdr.p_align = curr_phdr.p_align - - -# print "i=",i -# print "phdr_offset=", phdr_offset - - # update output file location to next phdr location - elf_out_fp.seek(phdr_offset) - # increment phdr_offset to next location - phdr_offset += out_elf_header.e_phentsize - - inp_data_offset = curr_phdr.p_offset # used to read data from input file - -# print "inp_data_offset=" -# print inp_data_offset -# -# print "curr_phdr.p_offset=" -# print curr_phdr.p_offset -# -# print "curr_phdr.p_filesz=" -# print curr_phdr.p_filesz - - # output current phdr - if is_out_elf_64_bit == False: - elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr)) - else: - elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr)) - - # Copy the ELF segment - bytes_written = mbn_tools.file_copy_offset(elf_in_fp2, - inp_data_offset, - elf_out_fp, - new_phdr.p_offset, - new_phdr.p_filesz) - - # update data segment offset to be aligned after previous segment - segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN); - elf_in_fp2.close() - - # Embed xbl_sec image if provided - if elf_in_file_xbl_sec != "": - - # Scan pheaders in xbl_sec for segment that contains entry point address - entry_seg_offset = -1 - entry_addr = elf_headerxblsec.e_entry - for i in range(elf_headerxblsec.e_phnum): - phdr = phdr_tablexblsec[i] - max_addr = phdr.p_vaddr + phdr.p_memsz - if phdr.p_vaddr <= entry_addr <= max_addr: - entry_seg_offset = phdr.p_offset - break - if entry_seg_offset == -1: - print "Error: Failed to find entry point in any segment!" - exit() - # magical equation for program header's phys and virt addr - phys_virt_addr = entry_addr - entry_seg_offset - - if is_out_elf_64_bit: - # Converting from 32 to 64 elf requires no data size validation - new_phdr = mbn_tools.Elf64_Phdr('\0' * ELF64_PHDR_SIZE) - new_phdr.p_type = 0x1 - new_phdr.p_offset = segment_offset - new_phdr.p_vaddr = phys_virt_addr - new_phdr.p_paddr = phys_virt_addr - new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec) - new_phdr.p_memsz = new_phdr.p_filesz - new_phdr.p_flags = 0x5 - new_phdr.p_align = 0x1000 - else: - # Converting from 64 to 32 elf requires data size validation - # Don't discard the segment containing xbl_sec, simply error out - # if the address is greater than 32 bits - new_phdr = mbn_tools.Elf32_Phdr('\0' * ELF32_PHDR_SIZE) - new_phdr.p_type = 0x1 # - new_phdr.p_offset = segment_offset - new_phdr.p_flags = 0x5 - new_phdr.p_align = 0x1000 - - if phys_virt_addr > 0xFFFFFFFF: - if zi_oob_enabled == False or curr_phdr.p_filesz != 0: - print "ERROR: File xbl_sec VAddr or PAddr is too large for conversion." - exit() - new_phdr.p_vaddr = phys_virt_addr - new_phdr.p_paddr = phys_virt_addr - - if os.path.getsize(elf_in_file_xbl_sec) > 0xFFFFFFFF: - print "ERROR: File xbl_sec Filesz is too large for conversion." - exit() - new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec) - new_phdr.p_memsz = new_phdr.p_filesz - - - # update output file location to next phdr location - elf_out_fp.seek(phdr_offset) - # increment phdr_offset to next location - phdr_offset += out_elf_header.e_phentsize - # Copy entire xbl_sec file, so start from byte 0 - inp_data_offset = 0 - - # Output xbl_sec's phdr - elf_in_file_xbl_sec - if is_out_elf_64_bit == False: - elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr)) - else: - elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr)) - - # Copy the ENTIRE xbl_sec image - bytes_written = mbn_tools.file_copy_offset(elf_in_fpxblsec, - inp_data_offset, - elf_out_fp, - new_phdr.p_offset, - new_phdr.p_filesz) - # update data segment offset to be aligned after previous segment - # Not necessary, unless appending more pheaders after this point - segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN); - - elf_in_fpxblsec.close() - - elf_out_fp.close() - - return 0 - - -main() diff --git a/util/ipqheader/ipqheader.py b/util/ipqheader/ipqheader.py deleted file mode 100755 index 7615146499..0000000000 --- a/util/ipqheader/ipqheader.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python2 -# -# Copyright (c) 2013 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: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# 2. 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. -# -# 3. Neither the name of the copyright holder 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 HOLDER 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 struct -import sys - -PROG_NAME = os.path.basename(sys.argv[0]) - -def create_header(base, size): - """Returns a packed MBN header image with the specified base and size. - - @arg base: integer, specifies the image load address in RAM - @arg size: integer, specifies the size of the image - @returns: string, the MBN header - """ - - # SBLs require size to be 4 bytes aligned. - size = (size + 3) & 0xfffffffc - - # We currently do not support appending certificates. Signing GPL - # code might violate the GPL. So U-Boot will never be signed. So - # this is not required for U-Boot. - - header = [ - 0x5, # Type: APPSBL - 0x3, # Version: 3 - 0x0, # Image source pointer - base, # Image destination pointer - size, # Code Size + Cert Size + Signature Size - size, # Code Size - base + size, # Destination + Code Size - 0x0, # Signature Size - base + size, # Destination + Code Size + Signature Size - 0x0, # Cert Size - ] - - header_packed = struct.pack('<10I', *header) - return header_packed - -def mkheader(base_addr, infname, outfname): - """Prepends the image with the MBN header. - - @arg base_addr: integer, specifies the image load address in RAM - @arg infname: string, image filename - @arg outfname: string, output image with header prepended - @raises IOError: if reading/writing input/output file fails - """ - with open(infname, "rb") as infp: - image = infp.read() - insize = len(image) - - if base_addr > 0xFFFFFFFF: - raise ValueError("invalid base address") - - if base_addr + insize > 0xFFFFFFFF: - raise ValueError("invalid destination range") - - header = create_header(base_addr, insize) - with open(outfname, "wb") as outfp: - outfp.write(header) - outfp.write(image) - -def usage(msg=None): - """Print command usage. - - @arg msg: string, error message if any (default: None) - """ - if msg != None: - sys.stderr.write("%s: %s\n" % (PROG_NAME, msg)) - - print "Usage: %s <base-addr> <input-file> <output-file>" % PROG_NAME - - if msg != None: - exit(1) - -def main(): - """Main entry function""" - - if len(sys.argv) != 4: - usage("incorrect number of arguments") - - try: - base_addr = int(sys.argv[1], 0) - infname = sys.argv[2] - outfname = sys.argv[3] - except ValueError as e: - sys.stderr.write("mkheader: invalid base address '%s'\n" % sys.argv[1]) - exit(1) - - try: - mkheader(base_addr, infname, outfname) - except IOError as e: - sys.stderr.write("%s: %s\n" % (PROG_NAME, e)) - exit(1) - except ValueError as e: - sys.stderr.write("%s: %s\n" % (PROG_NAME, e)) - exit(1) - -if __name__ == "__main__": - main() diff --git a/util/ipqheader/mbn_tools.py b/util/ipqheader/mbn_tools.py deleted file mode 100755 index c66afda7b5..0000000000 --- a/util/ipqheader/mbn_tools.py +++ /dev/null @@ -1,2315 +0,0 @@ -#!/usr/bin/env python2 -#=============================================================================== -# -# MBN TOOLS -# -# GENERAL DESCRIPTION -# Contains all MBN Utilities for image generation -# -# Copyright (c) 2016, 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. -# -#------------------------------------------------------------------------------- -# EDIT HISTORY FOR FILE -# -# This section contains comments describing changes made to the module. -# Notice that changes are listed in reverse chronological order. -# -# when who what, where, why -# -------- --- --------------------------------------------------------- -# 06/06/13 yliong CR 497042: Signed and encrypted image is corrupted. MRC features. -# 03/18/13 dhaval Add support for hashing elf segments with SHA256 and -# sync up to mpss, adsp mbn-tools -# 01/14/13 kedara Remove dependency on .builds, cust<bid>.h, targ<bid>.h files -# 08/30/12 kedara Add virtual block suppport -# 02/24/12 dh Add ssd side effect file names -# 07/08/11 aus Added support for image_id in SBL image header as required by PBL -# Sahara mode -# 10/20/11 dxiang Clean up -#=============================================================================== - -import stat -import csv -import itertools -import struct -import os -import shutil -import hashlib - -#---------------------------------------------------------------------------- -# GLOBAL VARIABLES BEGIN -#---------------------------------------------------------------------------- -PAD_BYTE_1 = 255 # Padding byte 1s -PAD_BYTE_0 = 0 # Padding byte 0s -SHA256_SIGNATURE_SIZE = 256 # Support SHA256 -MAX_NUM_ROOT_CERTS = 4 # Maximum number of OEM root certificates -MI_BOOT_IMG_HDR_SIZE = 40 # sizeof(mi_boot_image_header_type) -MI_BOOT_SBL_HDR_SIZE = 80 # sizeof(sbl_header) -BOOT_HEADER_LENGTH = 20 # Boot Header Number of Elements -SBL_HEADER_LENGTH = 20 # SBL Header Number of Elements -FLASH_PARTI_VERSION = 3 # Flash Partition Version Number -MAX_PHDR_COUNT = 100 # Maximum allowable program headers -CERT_CHAIN_ONEROOT_MAXSIZE = 6*1024 # Default Cert Chain Max Size for one root -VIRTUAL_BLOCK_SIZE = 131072 # Virtual block size for MCs insertion in SBL1 if ENABLE_VIRTUAL_BLK ON -MAGIC_COOKIE_LENGTH = 12 # Length of magic Cookie inserted per VIRTUAL_BLOCK_SIZE -MIN_IMAGE_SIZE_WITH_PAD = 256*1024 # Minimum image size for sbl1 Nand based OTA feature - -SBL_AARCH64 = 0xF # Indicate that SBL is a Aarch64 image -SBL_AARCH32 = 0x0 # Indicate that SBL is a Aarch32 image - -# Magic numbers filled in for boot headers -FLASH_CODE_WORD = 0x844BDCD1 -UNIFIED_BOOT_COOKIE_MAGIC_NUMBER = 0x33836685 -MAGIC_NUM = 0x73D71034 -AUTODETECT_PAGE_SIZE_MAGIC_NUM = 0x7D0B435A -AUTODETECT_PAGE_SIZE_MAGIC_NUM64 = 0x7D0B5436 -AUTODETECT_PAGE_SIZE_MAGIC_NUM128 = 0x7D0B6577 -SBL_VIRTUAL_BLOCK_MAGIC_NUM = 0xD48B54C6 - -# ELF Definitions -ELF_HDR_COMMON_SIZE = 24 -ELF32_HDR_SIZE = 52 -ELF32_PHDR_SIZE = 32 -ELF64_HDR_SIZE = 64 -ELF64_PHDR_SIZE = 56 -ELFINFO_MAG0_INDEX = 0 -ELFINFO_MAG1_INDEX = 1 -ELFINFO_MAG2_INDEX = 2 -ELFINFO_MAG3_INDEX = 3 -ELFINFO_MAG0 = '\x7f' -ELFINFO_MAG1 = 'E' -ELFINFO_MAG2 = 'L' -ELFINFO_MAG3 = 'F' -ELFINFO_CLASS_INDEX = 4 -ELFINFO_CLASS_32 = '\x01' -ELFINFO_CLASS_64 = '\x02' -ELFINFO_VERSION_INDEX = 6 -ELFINFO_VERSION_CURRENT = '\x01' -ELF_BLOCK_ALIGN = 0x1000 -ALIGNVALUE_1MB = 0x100000 -ALIGNVALUE_4MB = 0x400000 -ELFINFO_DATA2LSB = '\x01' -ELFINFO_EXEC_ETYPE = '\x02\x00' -ELFINFO_ARM_MACHINETYPE = '\x28\x00' -ELFINFO_VERSION_EV_CURRENT = '\x01\x00\x00\x00' -ELFINFO_SHOFF = 0x00 -ELFINFO_PHNUM = '\x01\x00' -ELFINFO_RESERVED = 0x00 - -# ELF Program Header Types -NULL_TYPE = 0x0 -LOAD_TYPE = 0x1 -DYNAMIC_TYPE = 0x2 -INTERP_TYPE = 0x3 -NOTE_TYPE = 0x4 -SHLIB_TYPE = 0x5 -PHDR_TYPE = 0x6 -TLS_TYPE = 0x7 - -""" -The eight bits between 20 and 27 in the p_flags field in ELF program headers -is not used by the standard ELF format. We use this byte to hold OS and processor -specific fields as recommended by ARM. - -The bits in this byte are defined as follows: - - Pool Indx Segment type Access type Page/non page - bits in p_flags /-----27-----/----26-24-------/---- 23-21----/------20-------/ - -After parsing segment description strings in the SCL file, the appropriate segment -flag values are chosen from the follow definitions. The mask defined below is then -used to update the existing p_flags field in the program headers with the updated -values. -""" -# Mask for bits 20-27 to parse program header p_flags -MI_PBT_FLAGS_MASK = 0x0FF00000 - -# Helper defines to help parse ELF program headers -MI_PROG_BOOT_DIGEST_SIZE = 20 -MI_PBT_FLAG_SEGMENT_TYPE_MASK = 0x07000000 -MI_PBT_FLAG_SEGMENT_TYPE_SHIFT = 0x18 -MI_PBT_FLAG_PAGE_MODE_MASK = 0x00100000 -MI_PBT_FLAG_PAGE_MODE_SHIFT = 0x14 -MI_PBT_FLAG_ACCESS_TYPE_MASK = 0x00E00000 -MI_PBT_FLAG_ACCESS_TYPE_SHIFT = 0x15 -MI_PBT_FLAG_POOL_INDEX_MASK = 0x08000000 -MI_PBT_FLAG_POOL_INDEX_SHIFT = 0x1B - -# Segment Type -MI_PBT_L4_SEGMENT = 0x0 -MI_PBT_AMSS_SEGMENT = 0x1 -MI_PBT_HASH_SEGMENT = 0x2 -MI_PBT_BOOT_SEGMENT = 0x3 -MI_PBT_L4BSP_SEGMENT = 0x4 -MI_PBT_SWAPPED_SEGMENT = 0x5 -MI_PBT_SWAP_POOL_SEGMENT = 0x6 -MI_PBT_PHDR_SEGMENT = 0x7 - -# Page/Non-Page Type -MI_PBT_NON_PAGED_SEGMENT = 0x0 -MI_PBT_PAGED_SEGMENT = 0x1 - -# Access Type -MI_PBT_RW_SEGMENT = 0x0 -MI_PBT_RO_SEGMENT = 0x1 -MI_PBT_ZI_SEGMENT = 0x2 -MI_PBT_NOTUSED_SEGMENT = 0x3 -MI_PBT_SHARED_SEGMENT = 0x4 -MI_PBT_RWE_SEGMENT = 0x7 - -# ELF Segment Flag Definitions -MI_PBT_ELF_AMSS_NON_PAGED_RO_SEGMENT = 0x01200000 -MI_PBT_ELF_AMSS_PAGED_RO_SEGMENT = 0x01300000 -MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX0 = 0x06400000 -MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX0 = 0x05300000 -MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX1 = 0x0E400000 -MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX1 = 0x0D300000 -MI_PBT_ELF_AMSS_NON_PAGED_ZI_SEGMENT = 0x01400000 -MI_PBT_ELF_AMSS_PAGED_ZI_SEGMENT = 0x01500000 -MI_PBT_ELF_AMSS_NON_PAGED_RW_SEGMENT = 0x01000000 -MI_PBT_ELF_AMSS_PAGED_RW_SEGMENT = 0x01100000 -MI_PBT_ELF_AMSS_NON_PAGED_NOTUSED_SEGMENT = 0x01600000 -MI_PBT_ELF_AMSS_PAGED_NOTUSED_SEGMENT = 0x01700000 -MI_PBT_ELF_AMSS_NON_PAGED_SHARED_SEGMENT = 0x01800000 -MI_PBT_ELF_AMSS_PAGED_SHARED_SEGMENT = 0x01900000 -MI_PBT_ELF_HASH_SEGMENT = 0x02200000 -MI_PBT_ELF_BOOT_SEGMENT = 0x03200000 -MI_PBT_ELF_PHDR_SEGMENT = 0x07000000 -MI_PBT_ELF_NON_PAGED_L4BSP_SEGMENT = 0x04000000 -MI_PBT_ELF_PAGED_L4BSP_SEGMENT = 0x04100000 -MI_PBT_ELF_AMSS_RELOCATABLE_IMAGE = 0x8000000 - -# New definitions for EOS demap paging requirement -# Bit 20 (0b) Bit 24-26(000): Non Paged = 0x0000_0000 -# Bit 20 (1b) Bit 24-26(000): Locked Paged = 0x0010_0000 -# Bit 20 (1b) Bit 24-26(001): Unlocked Paged = 0x0110_0000 -# Bit 20 (0b) Bit 24-26(011): non secure = 0x0310_0000 -MI_PBT_ELF_RESIDENT_SEGMENT = 0x00000000 -MI_PBT_ELF_PAGED_LOCKED_SEGMENT = 0x00100000 -MI_PBT_ELF_PAGED_UNLOCKED_SEGMENT = 0x01100000 -MI_PBT_ELF_UNSECURE_SEGMENT = 0x03100000 -#---------------------------------------------------------------------------- -# GLOBAL VARIABLES END -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# CLASS DEFINITIONS BEGIN -#---------------------------------------------------------------------------- -#---------------------------------------------------------------------------- -# OS Type ID Class -#---------------------------------------------------------------------------- -class OSType: - BMP_BOOT_OS = 0 - WM_BOOT_OS = 1 - ANDROID_BOOT_OS = 2 - CHROME_BOOT_OS = 3 - SYMBIAN_BOOT_OS = 4 - LINUX_BOOT_OS = 5 - -#---------------------------------------------------------------------------- -# Image Type ID Class - These values must be kept consistent with mibib.h -#---------------------------------------------------------------------------- -class ImageType: - NONE_IMG = 0 - OEM_SBL_IMG = 1 - AMSS_IMG = 2 - QCSBL_IMG = 3 - HASH_IMG = 4 - APPSBL_IMG = 5 - APPS_IMG = 6 - HOSTDL_IMG = 7 - DSP1_IMG = 8 - FSBL_IMG = 9 - DBL_IMG = 10 - OSBL_IMG = 11 - DSP2_IMG = 12 - EHOSTDL_IMG = 13 - NANDPRG_IMG = 14 - NORPRG_IMG = 15 - RAMFS1_IMG = 16 - RAMFS2_IMG = 17 - ADSP_Q5_IMG = 18 - APPS_KERNEL_IMG = 19 - BACKUP_RAMFS_IMG = 20 - SBL1_IMG = 21 - SBL2_IMG = 22 - RPM_IMG = 23 - SBL3_IMG = 24 - TZ_IMG = 25 - PSI_IMG = 32 - -#---------------------------------------------------------------------------- -# Global Image Type Table -# Format of the look-up table: -# KEY - IMAGE_TYPE string as passed into mbn_builder.py -# VALUE - [Specific ImageType ID enum, Template key string, MBN Type] -#---------------------------------------------------------------------------- -image_id_table = { - 'appsbl': [ImageType.APPSBL_IMG, 'APPSBL_IMG', 'bin'], - 'dbl': [ImageType.DBL_IMG, 'DBL_IMG', 'bin'], - 'osbl': [ImageType.OSBL_IMG, 'OSBL_IMG', 'bin'], - 'amss': [ImageType.AMSS_IMG, 'AMSS_IMG', 'elf'], - 'amss_mbn': [ImageType.HASH_IMG, 'HASH_IMG', 'elf'], - 'apps': [ImageType.APPS_IMG, 'APPS_IMG', 'bin'], - 'hostdl': [ImageType.HOSTDL_IMG, 'HOSTDL_IMG', 'bin'], - 'ehostdl': [ImageType.EHOSTDL_IMG, 'EHOSTDL_IMG', 'bin'], - 'emmcbld': [ImageType.EHOSTDL_IMG, 'EMMCBLD_IMG', 'bin'], - 'qdsp6fw': [ImageType.DSP1_IMG, 'DSP1_IMG', 'elf'], - 'qdsp6sw': [ImageType.DSP2_IMG, 'DSP2_IMG', 'elf'], - 'qdsp5': [ImageType.ADSP_Q5_IMG, 'ADSP_Q5_IMG', 'bin'], - 'tz': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], - 'tz_rumi': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], - 'tz_virtio': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], - 'tzbsp_no_xpu': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], - 'tzbsp_with_test': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], - 'rpm': [ImageType.RPM_IMG, 'RPM_IMG', 'elf'], - 'sbl1': [ImageType.SBL1_IMG, 'SBL1_IMG', 'bin'], - 'sbl2': [ImageType.SBL2_IMG, 'SBL2_IMG', 'bin'], - 'sbl3': [ImageType.SBL3_IMG, 'SBL3_IMG', 'bin'], - 'efs1': [ImageType.RAMFS1_IMG, 'RAMFS1_IMG', 'bin'], - 'efs2': [ImageType.RAMFS2_IMG, 'RAMFS2_IMG', 'bin'], - 'pmic': [ImageType.PSI_IMG, 'PSI_IMG', 'elf'], - # DO NOT add any additional image information -} - -#---------------------------------------------------------------------------- -# Header Class Notes: -# In order to properly read and write the header structures as binary data, -# the Python Struct library is used to align and package up the header objects -# All Struct objects are initialized by a special string with the following -# notation. These structure objects are then used to decode binary data in order -# to fill out the appropriate class in Python, or they are used to package up -# the Python class so that we may write the binary data out. -#---------------------------------------------------------------------------- -""" - Format | C Type | Python Type | Standard Size - ----------------------------------------------------- - 1) 'X's | char * | string | 'X' bytes - 2) H | unsigned short | integer | 2 bytes - 3) I | unsigned int | integer | 4 bytes - -""" - -#---------------------------------------------------------------------------- -# ELF Header Class -#---------------------------------------------------------------------------- -class Elf_Ehdr_common: - # Structure object to align and package the ELF Header - s = struct.Struct('16sHHI') - - def __init__(self, data): - unpacked_data = (Elf_Ehdr_common.s).unpack(data) - self.unpacked_data = unpacked_data - self.e_ident = unpacked_data[0] - self.e_type = unpacked_data[1] - self.e_machine = unpacked_data[2] - self.e_version = unpacked_data[3] - - def printValues(self): - print "ATTRIBUTE / VALUE" - for attr, value in self.__dict__.iteritems(): - print attr, value - - - -#---------------------------------------------------------------------------- -# ELF Header Class -#---------------------------------------------------------------------------- -class Elf32_Ehdr: - # Structure object to align and package the ELF Header - s = struct.Struct('16sHHIIIIIHHHHHH') - - def __init__(self, data): - unpacked_data = (Elf32_Ehdr.s).unpack(data) - self.unpacked_data = unpacked_data - self.e_ident = unpacked_data[0] - self.e_type = unpacked_data[1] - self.e_machine = unpacked_data[2] - self.e_version = unpacked_data[3] - self.e_entry = unpacked_data[4] - self.e_phoff = unpacked_data[5] - self.e_shoff = unpacked_data[6] - self.e_flags = unpacked_data[7] - self.e_ehsize = unpacked_data[8] - self.e_phentsize = unpacked_data[9] - self.e_phnum = unpacked_data[10] - self.e_shentsize = unpacked_data[11] - self.e_shnum = unpacked_data[12] - self.e_shstrndx = unpacked_data[13] - - def printValues(self): - print "ATTRIBUTE / VALUE" - for attr, value in self.__dict__.iteritems(): - print attr, value - - def getPackedData(self): - values = [self.e_ident, - self.e_type, - self.e_machine, - self.e_version, - self.e_entry, - self.e_phoff, - self.e_shoff, - self.e_flags, - self.e_ehsize, - self.e_phentsize, - self.e_phnum, - self.e_shentsize, - self.e_shnum, - self.e_shstrndx - ] - - return (Elf32_Ehdr.s).pack(*values) - -#---------------------------------------------------------------------------- -# ELF Program Header Class -#---------------------------------------------------------------------------- -class Elf32_Phdr: - - # Structure object to align and package the ELF Program Header - s = struct.Struct('I' * 8) - - def __init__(self, data): - unpacked_data = (Elf32_Phdr.s).unpack(data) - self.unpacked_data = unpacked_data - self.p_type = unpacked_data[0] - self.p_offset = unpacked_data[1] - self.p_vaddr = unpacked_data[2] - self.p_paddr = unpacked_data[3] - self.p_filesz = unpacked_data[4] - self.p_memsz = unpacked_data[5] - self.p_flags = unpacked_data[6] - self.p_align = unpacked_data[7] - - def printValues(self): - print "ATTRIBUTE / VALUE" - for attr, value in self.__dict__.iteritems(): - print attr, value - - def getPackedData(self): - values = [self.p_type, - self.p_offset, - self.p_vaddr, - self.p_paddr, - self.p_filesz, - self.p_memsz, - self.p_flags, - self.p_align - ] - - return (Elf32_Phdr.s).pack(*values) - -#---------------------------------------------------------------------------- -# ELF Header Class -#---------------------------------------------------------------------------- -class Elf64_Ehdr: - # Structure object to align and package the ELF Header - s = struct.Struct('16sHHIQQQIHHHHHH') - - def __init__(self, data): - unpacked_data = (Elf64_Ehdr.s).unpack(data) - self.unpacked_data = unpacked_data - self.e_ident = unpacked_data[0] - self.e_type = unpacked_data[1] - self.e_machine = unpacked_data[2] - self.e_version = unpacked_data[3] - self.e_entry = unpacked_data[4] - self.e_phoff = unpacked_data[5] - self.e_shoff = unpacked_data[6] - self.e_flags = unpacked_data[7] - self.e_ehsize = unpacked_data[8] - self.e_phentsize = unpacked_data[9] - self.e_phnum = unpacked_data[10] - self.e_shentsize = unpacked_data[11] - self.e_shnum = unpacked_data[12] - self.e_shstrndx = unpacked_data[13] - - def printValues(self): - print "ATTRIBUTE / VALUE" - for attr, value in self.__dict__.iteritems(): - print attr, value - - def getPackedData(self): - values = [self.e_ident, - self.e_type, - self.e_machine, - self.e_version, - self.e_entry, - self.e_phoff, - self.e_shoff, - self.e_flags, - self.e_ehsize, - self.e_phentsize, - self.e_phnum, - self.e_shentsize, - self.e_shnum, - self.e_shstrndx - ] - - return (Elf64_Ehdr.s).pack(*values) - -#---------------------------------------------------------------------------- -# ELF Program Header Class -#---------------------------------------------------------------------------- -class Elf64_Phdr: - - # Structure object to align and package the ELF Program Header - s = struct.Struct('IIQQQQQQ') - - def __init__(self, data): - unpacked_data = (Elf64_Phdr.s).unpack(data) - self.unpacked_data = unpacked_data - self.p_type = unpacked_data[0] - self.p_flags = unpacked_data[1] - self.p_offset = unpacked_data[2] - self.p_vaddr = unpacked_data[3] - self.p_paddr = unpacked_data[4] - self.p_filesz = unpacked_data[5] - self.p_memsz = unpacked_data[6] - self.p_align = unpacked_data[7] - - def printValues(self): - print "ATTRIBUTE / VALUE" - for attr, value in self.__dict__.iteritems(): - print attr, value - - def getPackedData(self): - values = [self.p_type, - self.p_flags, - self.p_offset, - self.p_vaddr, - self.p_paddr, - self.p_filesz, - self.p_memsz, - self.p_align - ] - - return (Elf64_Phdr.s).pack(*values) - - -#---------------------------------------------------------------------------- -# ELF Segment Information Class -#---------------------------------------------------------------------------- -class SegmentInfo: - def __init__(self): - self.flag = 0 - def printValues(self): - print 'Flag: ' + str(self.flag) - -#---------------------------------------------------------------------------- -# Regular Boot Header Class -#---------------------------------------------------------------------------- -class Boot_Hdr: - def __init__(self, init_val): - self.image_id = ImageType.NONE_IMG - self.flash_parti_ver = FLASH_PARTI_VERSION - self.image_src = init_val - self.image_dest_ptr = init_val - self.image_size = init_val - self.code_size = init_val - self.sig_ptr = init_val - self.sig_size = init_val - self.cert_chain_ptr = init_val - self.cert_chain_size = init_val - self.magic_number1 = init_val - self.version = init_val - self.OS_type = init_val - self.boot_apps_parti_entry = init_val - self.boot_apps_size_entry = init_val - self.boot_apps_ram_loc = init_val - self.reserved_ptr = init_val - self.reserved_1 = init_val - self.reserved_2 = init_val - self.reserved_3 = init_val - - def getLength(self): - return BOOT_HEADER_LENGTH - - def writePackedData(self, target, write_full_hdr): - values = [self.image_id, - self.flash_parti_ver, - self.image_src, - self.image_dest_ptr, - self.image_size, - self.code_size , - self.sig_ptr, - self.sig_size, - self.cert_chain_ptr, - self.cert_chain_size, - self.magic_number1, - self.version, - self.OS_type, - self.boot_apps_parti_entry, - self.boot_apps_size_entry, - self.boot_apps_ram_loc, - self.reserved_ptr, - self.reserved_1, - self.reserved_2, - self.reserved_3 ] - - if self.image_dest_ptr >= 0x100000000: - values[3] = 0xFFFFFFFF - - if self.cert_chain_ptr >= 0x100000000: - values[6] = 0xFFFFFFFF - - if self.sig_ptr >= 0x100000000: - values[8] = 0xFFFFFFFF - - # Write 10 entries(40B) or 20 entries(80B) of boot header - if write_full_hdr is False: - s = struct.Struct('I'* 10) - values = values[:10] - else: - s = struct.Struct('I' * self.getLength()) - - packed_data = s.pack(*values) - - fp = OPEN(target,'wb') - fp.write(packed_data) - fp.close() - - return s.size - -#---------------------------------------------------------------------------- -# SBL Boot Header Class -#---------------------------------------------------------------------------- -class Sbl_Hdr: - def __init__(self, init_val): - self.codeword = init_val - self.magic = init_val - self.image_id = init_val - self.reserved_1 = init_val - self.reserved_2 = init_val - self.image_src = init_val - self.image_dest_ptr = init_val - self.image_size = init_val - self.code_size = init_val - self.sig_ptr = init_val - self.sig_size = init_val - self.cert_chain_ptr = init_val - self.cert_chain_size = init_val - self.oem_root_cert_sel = init_val - self.oem_num_root_certs = init_val - self.booting_image_config = init_val - self.reserved_6 = init_val - self.reserved_7 = init_val - self.reserved_8 = init_val - self.reserved_9 = init_val - - def getLength(self): - return SBL_HEADER_LENGTH - - def writePackedData(self, target): - values = [self.codeword, - self.magic, - self.image_id, - self.reserved_1, - self.reserved_2, - self.image_src, - self.image_dest_ptr, - self.image_size, - self.code_size, - self.sig_ptr, - self.sig_size, - self.cert_chain_ptr, - self.cert_chain_size, - self.oem_root_cert_sel, - self.oem_num_root_certs, - self.booting_image_config, - self.reserved_6, - self.reserved_7, - self.reserved_8, - self.reserved_9 ] - - s = struct.Struct('I' * self.getLength()) - packed_data = s.pack(*values) - - fp = OPEN(target,'wb') - fp.write(packed_data) - fp.close() - - return s.size - -#---------------------------------------------------------------------------- -# CLASS DEFINITIONS END -#---------------------------------------------------------------------------- - -#------------------------------------------------------------------------------ -# Hooks for Scons -#------------------------------------------------------------------------------ -def exists(env): - return env.Detect('mbn_tools') - -def generate(env): - - #---------------------------------------------------------------------------- - # Generate Global Dictionary - #---------------------------------------------------------------------------- - generate_global_dict(env) - - #---------------------------------------------------------------------------- - # Assign Build Configurable Values - #---------------------------------------------------------------------------- - init_build_vars(env) - - #---------------------------------------------------------------------------- - # Add Methods to Environment - #---------------------------------------------------------------------------- - env.AddMethod(filter_dictionary, "FilterDictionary") - env.AddMethod(image_auth, "ImageAuth") - env.AddMethod(image_header, "ImageHeader") - env.AddMethod(pboot_gen_elf, "PBootGenElf") - env.AddMethod(pboot_add_hash, "PBootAddHash") - env.AddMethod(modify_elf_flags, "ModifyElfFlags") - env.AddMethod(generate_code_hash, "GenerateCodeHash") - env.AddMethod(insert_SBL1_magicCookie, "InsertSBLMagicCookie") - env.AddMethod(modify_relocatable_flags, "ModifyRelocatableFlags") - - #---------------------------------------------------------------------------- - # Load Encryption Tools and Methods if required - #---------------------------------------------------------------------------- - if 'USES_ENCRYPT_MBN' in env: - # Add Encryption Tools to environment - env.Tool('pil_encrypt', toolpath = ['${BUILD_ROOT}/core/securemsm/ssd/tools/pil_encrypt']) - env.AddMethod(get_ssd_se_fname, "GetSSDSideEffectFileName") - env.AddMethod(encrypt_elf_segments, "EncryptElfSegments") - env.AddMethod(generate_meta_data, "GenerateMetaData") - env.AddMethod(encrypt_mbn, "EncryptMBN") - return None - -#---------------------------------------------------------------------------- -# BOOT TOOLS BEGIN -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# generate_meta_data -#---------------------------------------------------------------------------- -def generate_meta_data(env, meta_out_file_name, add_magic_num = False): - - ''' - Make call to SSD API to return buffer filled with XML header information. - The XML header which we write contains information regarding the algorithms - being used along with specific key values which are to be used for encrpytion. - ''' - xml_header = env.SSDGetMetaData(add_magic_num) - - # Initialize - xml_target_file = open(meta_out_file_name,'wb') - xml_header_size = len(xml_header) - - # Write XML buffer into target file - xml_target_file.write(xml_header) - - # Pad if necessary to the maximum size - if xml_header_size <= XML_HEADER_MAXSIZE: - bytes_to_pad = XML_HEADER_MAXSIZE - xml_header_size - pad_file(xml_target_file, bytes_to_pad, PAD_BYTE_1) - xml_target_file.close() - else: - xml_target_file.close() - raise RuntimeError, "XML Size too large: " + str(xml_header_size) - -#---------------------------------------------------------------------------- -# encrypt_mbn -#---------------------------------------------------------------------------- -def encrypt_mbn(env, mbn_in_file_name, mbn_out_file_name): - # Open Files - mbn_in_fp = OPEN(mbn_in_file_name, "rb") - mbn_out_fp = OPEN(mbn_out_file_name, "wb+") - - # encrypt the input file content and write to output file - mbn_file_size = os.path.getsize(mbn_in_file_name) - file_buff = mbn_in_fp.read(mbn_file_size) - encrypted_buf = env.SSDEncryptSegment(0, file_buff, mbn_file_size) - mbn_out_fp.write(encrypted_buf) - - # Close Files - mbn_in_fp.close() - mbn_out_fp.close() - - # Clean up encryption files - env.SSDDeInit() - -#---------------------------------------------------------------------------- -# get_ssd_se_fname -#---------------------------------------------------------------------------- -def get_ssd_se_fname(env): - return env.SSDGetSideEffectFileName() - -#---------------------------------------------------------------------------- -# encrypt_elf_segments -#---------------------------------------------------------------------------- -def encrypt_elf_segments(env, elf_in_file_name, - elf_out_file_name): - - # Open Files - elf_in_fp = OPEN(elf_in_file_name, "rb") - elf_out_fp = OPEN(elf_out_file_name, "wb+") - - # Initialize - [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) - encrypted_seg_counter = 0 - - # Copy input file to output file - shutil.copyfileobj(elf_in_fp, elf_out_fp, os.path.getsize(elf_in_file_name)) - - # Begin ELF segment encryption - for i in range(elf_header.e_phnum): - curr_phdr = phdr_table[i] - - # Only encrypt segments of LOAD_TYPE. Do not encrypt the hash segment. - if curr_phdr.p_type == LOAD_TYPE and \ - MI_PBT_SEGMENT_TYPE_VALUE(curr_phdr.p_flags) != MI_PBT_HASH_SEGMENT: - - # Read full segment into buffer - elf_in_fp.seek(curr_phdr.p_offset) - data_len = curr_phdr.p_filesz - file_buff = elf_in_fp.read(data_len) - - # Call encryption routine on buffer - encrypted_buf = env.SSDEncryptSegment(encrypted_seg_counter, file_buff, data_len) - encrypted_seg_counter += 1 - - # Write encrypted segment into output file in same location - elf_out_fp.seek(curr_phdr.p_offset) - elf_out_fp.write(encrypted_buf) - - # Close Files - elf_in_fp.close() - elf_out_fp.close() - - # Clean up encryption files - env.SSDDeInit() - -#---------------------------------------------------------------------------- -# Converts integer to bytes. If length after conversion -# is smaller than given length of byte string, returned value is right-filled -# with 0x00 bytes. Use Little-endian byte order. -#---------------------------------------------------------------------------- -def convert_int_to_byte_string(n, l): - return b''.join([chr((n >> ((l - i - 1) * 8)) % 256) for i in xrange(l)][::-1]) - -#---------------------------------------------------------------------------- -# Create default elf header -#---------------------------------------------------------------------------- -def create_elf_header( output_file_name, - image_dest, - image_size, - is_elf_64_bit = False): - - if (output_file_name is None): - raise RuntimeError, "Requires a ELF header file" - - # Create a elf header and program header - # Write the headers to the output file - elf_fp = file(output_file_name, "wb") - - if (is_elf_64_bit is True): - # ELf header - elf_fp.write(ELFINFO_MAG0) - elf_fp.write(ELFINFO_MAG1) - elf_fp.write(ELFINFO_MAG2) - elf_fp.write(ELFINFO_MAG3) - elf_fp.write(ELFINFO_CLASS_64) - elf_fp.write(ELFINFO_DATA2LSB) - elf_fp.write(ELFINFO_VERSION_CURRENT) - elf_fp.write(''.rjust(9, chr(ELFINFO_RESERVED))) - elf_fp.write(ELFINFO_EXEC_ETYPE) - elf_fp.write(ELFINFO_ARM_MACHINETYPE) - elf_fp.write(ELFINFO_VERSION_EV_CURRENT) - elf_fp.write(convert_int_to_byte_string(image_dest, 8)) - elf_fp.write(convert_int_to_byte_string(ELF64_HDR_SIZE, 8)) - elf_fp.write(convert_int_to_byte_string(ELFINFO_SHOFF, 8)) - elf_fp.write(''.rjust(4, chr(ELFINFO_RESERVED))) - elf_fp.write(convert_int_to_byte_string(ELF64_HDR_SIZE, 2)) - elf_fp.write(convert_int_to_byte_string(ELF64_PHDR_SIZE, 2)) - elf_fp.write(ELFINFO_PHNUM) - elf_fp.write(''.rjust(6, chr(ELFINFO_RESERVED))) - - # Program Header - elf_fp.write(convert_int_to_byte_string(LOAD_TYPE, 4)) - elf_fp.write(convert_int_to_byte_string(MI_PBT_RWE_SEGMENT, 4)) - elf_fp.write(convert_int_to_byte_string(ELF64_HDR_SIZE+ELF64_PHDR_SIZE, 8)) - elf_fp.write(convert_int_to_byte_string(image_dest, 8)) - elf_fp.write(convert_int_to_byte_string(image_dest, 8)) - elf_fp.write(convert_int_to_byte_string(image_size, 8)) - elf_fp.write(convert_int_to_byte_string(image_size, 8)) - elf_fp.write(convert_int_to_byte_string(ELF_BLOCK_ALIGN, 8)) - else: - # ELf header - elf_fp.write(ELFINFO_MAG0) - elf_fp.write(ELFINFO_MAG1) - elf_fp.write(ELFINFO_MAG2) - elf_fp.write(ELFINFO_MAG3) - elf_fp.write(ELFINFO_CLASS_32) - elf_fp.write(ELFINFO_DATA2LSB) - elf_fp.write(ELFINFO_VERSION_CURRENT) - elf_fp.write(''.rjust(9, chr(ELFINFO_RESERVED))) - elf_fp.write(ELFINFO_EXEC_ETYPE) - elf_fp.write(ELFINFO_ARM_MACHINETYPE) - elf_fp.write(ELFINFO_VERSION_EV_CURRENT) - elf_fp.write(convert_int_to_byte_string(image_dest, 4)) - elf_fp.write(convert_int_to_byte_string(ELF32_HDR_SIZE, 4)) - elf_fp.write(convert_int_to_byte_string(ELFINFO_SHOFF, 4)) - elf_fp.write(''.rjust(4, chr(ELFINFO_RESERVED))) - elf_fp.write(convert_int_to_byte_string(ELF32_HDR_SIZE, 2)) - elf_fp.write(convert_int_to_byte_string(ELF32_PHDR_SIZE, 2)) - elf_fp.write(ELFINFO_PHNUM) - elf_fp.write(''.rjust(6, chr(ELFINFO_RESERVED))) - - # Program Header - elf_fp.write(convert_int_to_byte_string(LOAD_TYPE, 4)) - elf_fp.write(convert_int_to_byte_string(ELF32_HDR_SIZE+ELF32_PHDR_SIZE, 4)) - elf_fp.write(convert_int_to_byte_string(image_dest, 4)) - elf_fp.write(convert_int_to_byte_string(image_dest, 4)) - elf_fp.write(convert_int_to_byte_string(image_size, 4)) - elf_fp.write(convert_int_to_byte_string(image_size, 4)) - elf_fp.write(convert_int_to_byte_string(MI_PBT_RWE_SEGMENT, 4)) - elf_fp.write(convert_int_to_byte_string(ELF_BLOCK_ALIGN, 4)) - - elf_fp.close() - return 0 - -#---------------------------------------------------------------------------- -# image_header -#---------------------------------------------------------------------------- -def image_header(env, gen_dict, - code_file_name, - output_file_name, - secure_type, - header_format = 'reg', - requires_preamble = False, - preamble_file_name = None, - elf_file_name = None, - write_full_hdr = False, - in_code_size = None, - cert_chain_size_in = CERT_CHAIN_ONEROOT_MAXSIZE, - num_of_pages = None): - - # Preliminary checks - if (requires_preamble is True) and (preamble_file_name is None): - raise RuntimeError, "Image Header requires a preamble file" - - if (gen_dict['IMAGE_KEY_MBN_TYPE'] == 'elf') and (elf_file_name is None): - raise RuntimeError, "ELF Image Headers require an elf file" - - if (in_code_size is None) and (os.path.exists(code_file_name) is False): - raise RuntimeError, "Code size unavailable, and input file does not exist" - - # Initialize - if in_code_size is not None: - code_size = in_code_size - else: - code_size = os.path.getsize(code_file_name) - - image_dest = 0 - image_source = 0 - - # If secure build, set signature and cert chain sizes - if secure_type == 'secure': - signature_size = SHA256_SIGNATURE_SIZE - cert_chain_size = cert_chain_size_in - image_size = code_size + cert_chain_size + signature_size - if (image_size % 4) != 0: - image_size += (4 - (image_size % 4)) - else: - signature_size = 0 - cert_chain_size = 0 - image_size = code_size - - # For ELF or hashed images, image destination will be determined from an ELF input file - if gen_dict['IMAGE_KEY_MBN_TYPE'] == 'elf': - image_dest = get_hash_address(elf_file_name) + MI_BOOT_IMG_HDR_SIZE - elif gen_dict['IMAGE_KEY_MBN_TYPE'] == 'bin': - image_dest = gen_dict['IMAGE_KEY_IMAGE_DEST'] - image_source = gen_dict['IMAGE_KEY_IMAGE_SOURCE'] - - # Build the header based on format specified - if header_format == 'sbl': - boot_sbl_header = Sbl_Hdr(init_val = int('0xFFFFFFFF',16)) - boot_sbl_header.codeword = FLASH_CODE_WORD - boot_sbl_header.magic = MAGIC_NUM - boot_sbl_header.image_id = gen_dict['IMAGE_KEY_IMAGE_ID'] - boot_sbl_header.image_src = MI_BOOT_SBL_HDR_SIZE - boot_sbl_header.image_dest_ptr = image_dest - boot_sbl_header.image_size = image_size - boot_sbl_header.code_size = code_size - boot_sbl_header.sig_ptr = image_dest + code_size - boot_sbl_header.sig_size = signature_size - boot_sbl_header.cert_chain_ptr = image_dest + code_size + signature_size - boot_sbl_header.cert_chain_size = cert_chain_size - boot_sbl_header.oem_root_cert_sel = gen_dict['IMAGE_KEY_OEM_ROOT_CERT_SEL'] - boot_sbl_header.oem_num_root_certs = gen_dict['IMAGE_KEY_OEM_NUM_ROOT_CERTS'] - if 'USES_SBL_FOR_AARCH64' in env: - boot_sbl_header.booting_image_config = SBL_AARCH64 - elif 'USES_SBL_FOR_AARCH632' in env: - boot_sbl_header.booting_image_config = SBL_AARCH32 - - # If preamble is required, output the preamble file and update the boot_sbl_header - if requires_preamble is True: - boot_sbl_header = image_preamble(gen_dict, preamble_file_name, boot_sbl_header, num_of_pages) - - # Package up the header and write to output file - boot_sbl_header.writePackedData(target = output_file_name) - - elif header_format == 'reg': - boot_header = Boot_Hdr(init_val = int('0x0',16)) - boot_header.image_id = gen_dict['IMAGE_KEY_IMAGE_ID'] - boot_header.image_src = image_source - boot_header.image_dest_ptr = image_dest - boot_header.image_size = image_size - boot_header.code_size = code_size - boot_header.sig_ptr = image_dest + code_size - boot_header.sig_size = signature_size - boot_header.cert_chain_ptr = image_dest + code_size + signature_size - boot_header.cert_chain_size = cert_chain_size - - # If preamble is required, output the preamble file and update the boot_header - if requires_preamble is True: - boot_header = image_preamble(gen_dict, preamble_file_name, boot_header, num_of_pages) - - # Package up the header and write to output file - boot_header.writePackedData(target = output_file_name, write_full_hdr = write_full_hdr) - - else: - raise RuntimeError, "Header format not supported: " + str(header_format) - return 0 - - -#---------------------------------------------------------------------------- -# pboot_gen_elf -#---------------------------------------------------------------------------- -def pboot_gen_elf(env, elf_in_file_name, - hash_out_file_name, - elf_out_file_name, - secure_type = 'non_secure', - hash_seg_max_size = None, - last_phys_addr = None, - append_xml_hdr = False, - is_sha256_algo = True, - cert_chain_size_in = CERT_CHAIN_ONEROOT_MAXSIZE): - global MI_PROG_BOOT_DIGEST_SIZE - if (is_sha256_algo is True): - MI_PROG_BOOT_DIGEST_SIZE = 32 - else: - MI_PROG_BOOT_DIGEST_SIZE = 20 - - # Open Files - elf_in_fp = OPEN(elf_in_file_name, "rb") - hash_out_fp = OPEN(hash_out_file_name, "wb+") - - if elf_out_file_name is not None: - elf_out_fp = OPEN(elf_out_file_name, "wb+") - - # Initialize - [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) - num_phdrs = elf_header.e_phnum - phdr_total_size = num_phdrs * elf_header.e_phentsize - phdr_size = elf_header.e_phentsize - hashtable_size = 0 - hashtable_shift = 0 - - if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: - new_phdr = Elf64_Phdr('\0' * ELF64_PHDR_SIZE) - elf_header_size = ELF64_HDR_SIZE - is_elf64 = True - else: - new_phdr = Elf32_Phdr('\0' * ELF32_PHDR_SIZE) - elf_header_size = ELF32_HDR_SIZE - is_elf64 = False - - hash = '\0' * MI_PROG_BOOT_DIGEST_SIZE - phdr_start = 0 - bytes_to_pad = 0 - hash_seg_end = 0 - - # Process program headers if an output elf is specified - if elf_out_file_name is not None: - # Assert limit on number of program headers in input ELF - if num_phdrs > MAX_PHDR_COUNT: - raise RuntimeError, "Input ELF has exceeded maximum number of program headers" - - # Create new program header for the ELF Header + Program Headers - new_phdr.p_type = NULL_TYPE - new_phdr.p_flags = MI_PBT_ELF_PHDR_SEGMENT - - # If hash table program header is not found, make sure to include it - elf_header.e_phnum += 2 - - # Create an empty hash entry for PHDR_TYPE - hash_out_fp.write('\0' * MI_PROG_BOOT_DIGEST_SIZE) - hashtable_size += MI_PROG_BOOT_DIGEST_SIZE - - # Create an empty hash entry for the hash segment itself - hash_out_fp.write('\0' * MI_PROG_BOOT_DIGEST_SIZE) - hashtable_size += MI_PROG_BOOT_DIGEST_SIZE - - # Begin hash table generation - for i in range(num_phdrs): - curr_phdr = phdr_table[i] - - if (MI_PBT_PAGE_MODE_VALUE(curr_phdr.p_flags) == MI_PBT_PAGED_SEGMENT): - seg_offset = curr_phdr.p_offset - seg_size = curr_phdr.p_filesz - hash_size = 0 - - # Check if the vaddr is page aligned - off = curr_phdr.p_vaddr & (ELF_BLOCK_ALIGN - 1) - if int(off) is not 0: - seg_size -= (ELF_BLOCK_ALIGN - off) - seg_offset += (ELF_BLOCK_ALIGN - off) - - # Seg_size should be page aligned - if (seg_size & (ELF_BLOCK_ALIGN - 1)) > 0: - raise RuntimeError, "seg_size: " + hex(seg_size) + " is not ELF page aligned!" - - off = seg_offset + seg_size - - while seg_offset < off: - - if seg_offset < ELF_BLOCK_ALIGN: - hash_size = seg_offset - else: - hash_size = ELF_BLOCK_ALIGN - - elf_in_fp.seek(seg_offset) - fbuf = elf_in_fp.read(hash_size) - - if MI_PBT_CHECK_FLAG_TYPE(curr_phdr.p_flags) is True: - hash = generate_hash(fbuf, is_sha256_algo) - else: - hash = '\0' * MI_PROG_BOOT_DIGEST_SIZE - - # Write hash to file - hash_out_fp.write(hash) - - hashtable_size += MI_PROG_BOOT_DIGEST_SIZE - seg_offset += ELF_BLOCK_ALIGN - - # Copy the hash entry for all that are PAGED segments and those that are not the PHDR type. This is for - # backward tool compatibility where some images are generated using older exe tools. - elif((MI_PBT_PAGE_MODE_VALUE(curr_phdr.p_flags) == MI_PBT_NON_PAGED_SEGMENT) and (curr_phdr.p_type is not PHDR_TYPE)): - # Read full hash entry into buffer - elf_in_fp.seek(curr_phdr.p_offset) - data_len = curr_phdr.p_filesz - file_buff = elf_in_fp.read(data_len) - - if (MI_PBT_CHECK_FLAG_TYPE(curr_phdr.p_flags) is True) and (data_len > 0): - hash = generate_hash(file_buff, is_sha256_algo) - else: - hash = '\0' * MI_PROG_BOOT_DIGEST_SIZE - - # Write hash to file - hash_out_fp.write(hash) - - hashtable_size += MI_PROG_BOOT_DIGEST_SIZE - # End hash table generation - - # Generate the rest of the ELF output file if specified - if elf_out_file_name is not None: - - # Preempt hash table size if necessary - if secure_type == 'secure': - hashtable_size += (SHA256_SIGNATURE_SIZE + cert_chain_size_in) - - if append_xml_hdr is True: - hashtable_size += XML_HEADER_MAXSIZE - - # Initialize the hash table program header - [hash_Phdr, pad_hash_segment, hash_tbl_end_addr, hash_tbl_offset] = \ - initialize_hash_phdr(elf_in_file_name, hashtable_size, MI_BOOT_IMG_HDR_SIZE, ELF_BLOCK_ALIGN, is_elf64) - - # Check if hash segment max size parameter was passed - if (hash_seg_max_size is not None): - # Error checking for hash segment size validity - if hashtable_size > hash_seg_max_size: - raise RuntimeError, "Hash table exceeds maximum hash segment size: " + hex(hash_seg_max_size) - if (hash_seg_max_size & (ELF_BLOCK_ALIGN-1)) is not 0: - raise RuntimeError, "Hash segment size passed is not ELF Block Aligned: " + hex(hash_seg_max_size) - - # Check if hash physical address parameter was passed - if last_phys_addr is not None: - hash_Phdr.p_vaddr = last_phys_addr - hash_Phdr.p_paddr = last_phys_addr - - # Check if hash segment max size was passed - if hash_seg_max_size is not None: - hash_Phdr.p_memsz = hash_seg_max_size - - # Determine the end of the hash segment, make sure it's block aligned - bytes_to_pad = ELF_BLOCK_ALIGN - pad_hash_segment - hash_seg_end = hash_tbl_end_addr + bytes_to_pad - - # Check if a shifting is required to accommodate for the hash segment. - # Get the minimum offset by going through the program headers. - # Note that the program headers in the input file do not contain - # the dummy program header for ELF + Program header, and the - # program header for the hashtable. - min_offset = phdr_table[0].p_offset - for i in range(num_phdrs): - curr_phdr = phdr_table[i] - if curr_phdr.p_offset < min_offset: - min_offset = curr_phdr.p_offset - - if min_offset < hash_seg_end: - hashtable_shift = hash_seg_end - min_offset - - # Move program headers to after ELF header - phdr_start = elf_header_size - - # We copy over no section headers so assign these values to 0 in ELF Header - elf_header.e_shnum = 0 - elf_header.e_shstrndx = 0 - elf_header.e_shoff = 0 - - # Output remaining ELF segments - for i in range(num_phdrs): - - # Increment the file offset before writing to the destination file - curr_phdr = phdr_table[i] - - # We do not copy over program headers of PHDR type, decrement the program - # header count and continue the loop - if curr_phdr.p_type is PHDR_TYPE: - elf_header.e_phnum -= 1 - continue - - src_offset = curr_phdr.p_offset - - # Copy the ELF segment - file_copy_offset(elf_in_fp, src_offset, elf_out_fp, curr_phdr.p_offset + hashtable_shift, curr_phdr.p_filesz) - - # Output remaining program headers and ELF segments - elf_header.e_phoff = phdr_start - - # Output new program headers which we have generated - elf_out_fp.seek(phdr_start) - new_phdr.p_filesz = elf_header_size + (elf_header.e_phnum * phdr_size) - elf_out_fp.write(new_phdr.getPackedData()) - elf_out_fp.write(hash_Phdr.getPackedData()) - phdr_start += (2 * phdr_size) - - # Increment the file offset before writing to the destination file - for i in range(num_phdrs): - curr_phdr = phdr_table[i] - - if curr_phdr.p_type is PHDR_TYPE: - continue - - curr_phdr.p_offset += hashtable_shift - - # Copy the program header - elf_out_fp.seek(phdr_start) - elf_out_fp.write(curr_phdr.getPackedData()) - - # Update phdr_start - phdr_start += phdr_size - - # Finally, copy the new ELF header to the destination file - elf_out_fp.seek(0) - elf_out_fp.write(elf_header.getPackedData()) - - # Recalculate hash of ELF + program headers and output to hash output file - elf_out_fp.seek(0) - # Read the elf header - elfhdr_buff = elf_out_fp.read(elf_header_size) - # Seek to the program header offset listed in elf header. - elf_out_fp.seek(elf_header.e_phoff) - # Read the program header and compute hash - proghdr_buff = elf_out_fp.read(elf_header.e_phnum * phdr_size) - - hash = generate_hash(elfhdr_buff + proghdr_buff, is_sha256_algo) - - # Write hash to file as first hash table entry - hash_out_fp.seek(0) - hash_out_fp.write(hash) - - # Close files - elf_in_fp.close() - hash_out_fp.close() - - if elf_out_file_name is not None: - elf_out_fp.close() - - return 0 - - -#---------------------------------------------------------------------------- -# pboot_add_hash -#---------------------------------------------------------------------------- -def pboot_add_hash(env, elf_in_file_name, - hash_tbl_file_name, - elf_out_file_name): - - # Open files - elf_in_fp = OPEN(elf_in_file_name, "rb") - hash_tbl_fp = OPEN(hash_tbl_file_name, "rb") - elf_out_fp = OPEN(elf_out_file_name, "wb+") - - # Initialize - [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) - - hash_size = os.path.getsize(hash_tbl_file_name) - hash_segment_found = False - - # Attempt to find the location of the hash program header - for i in range(elf_header.e_phnum): - curr_phdr = phdr_table[i] - if curr_phdr.p_flags == MI_PBT_ELF_HASH_SEGMENT: - hash_segment_found = True - break - - if hash_segment_found is True: - # Copy input file to output file - shutil.copyfileobj(elf_in_fp, elf_out_fp, os.path.getsize(elf_in_file_name)) - - # Update ELF to insert hash table at corresponding file offset - hash_hdr_offset = curr_phdr.p_offset - file_copy_offset(hash_tbl_fp, 0, elf_out_fp, hash_hdr_offset, hash_size) - - else: - raise RuntimeError, "Hash segment program header not found in file " + elf_in_file_name - - # Close files - elf_in_fp.close() - hash_tbl_fp.close() - elf_out_fp.close() - - return 0 - -#---------------------------------------------------------------------------- -# image_auth -#---------------------------------------------------------------------------- -def image_auth(env, *args): - - if len(args) < 7 or len(args) > 8: - raise RuntimeError, "Usage Invalid" - - # Initialize File Names - binary_in = args[0] - signature = args[1] - attestation_cert = args[2] - attestation_ca_cert = args[3] - root_cert = args[4] - cert_chain_out = args[5] - signed_image_out = args[6] - if len(args) == 8: - cert_size_max_in = args[7] - else: - cert_size_max_in = CERT_CHAIN_ONEROOT_MAXSIZE - - # Creating list of certificates to support creation of certificate chains - # of lenth 1, 2, or 3 certificates - cert_list = [] - num_certs = 0 - if (os.path.exists(attestation_cert)): - cert_list.append(attestation_cert) - num_certs = num_certs + 1 - if (os.path.exists(attestation_ca_cert)): - cert_list.append(attestation_ca_cert) - num_certs = num_certs + 1 - if (os.path.exists(root_cert)): - cert_list.append(root_cert) - num_certs = num_certs + 1 - - if (num_certs == 0): - raise RuntimeError, "Missing file(s) required for signing.\n" - - # Create the Certificate Chain - concat_files (cert_chain_out, cert_list) - - # Pad to ensure Certificate Chain Size is CERT_CHAIN_MAX_SIZE - cert_size = os.path.getsize(cert_chain_out) - - if cert_size <= cert_size_max_in: - bytes_to_pad = cert_size_max_in - cert_size - cert_fp = OPEN(cert_chain_out,'ab') - pad_file(cert_fp, bytes_to_pad, PAD_BYTE_1) - cert_fp.close() - else: - raise RuntimeError, "Certificate Size too large: " + str(cert_size) - - # Create the Final Signed Image File - concat_files (signed_image_out, [binary_in, signature, cert_chain_out]) - - return 0 - -#---------------------------------------------------------------------------- -# modify_relocatable_flags -#---------------------------------------------------------------------------- -def modify_relocatable_flags(env, output_elf ): - - # Offset into program header where the p_flags field is stored - phdr_align_flag_offset = 28 - phdr_reloc_flag_offset = 24 - - # Initialize - [elf_header, phdr_table] = preprocess_elf_file(output_elf) - - if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: - curr_phdr = Elf64_Phdr('\0' * ELF64_PHDR_SIZE) - elf_header_size = ELF64_HDR_SIZE - is_elf64 = True - else: - curr_phdr = Elf32_Phdr('\0' * ELF32_PHDR_SIZE) - elf_header_size = ELF32_HDR_SIZE - is_elf64 = False - - # Open files - elf_in_fp = OPEN(output_elf, "r+") - - # Go to the start of the p_flag entry in the first program header - file_offset_align_flag = elf_header.e_phoff + phdr_align_flag_offset - - # Change the align field in the program header in the ELF file - elf_in_fp.seek(file_offset_align_flag) - curr_phdr = phdr_table[0] - - #default alignment value is 1MB unless otherwise specified - if 'USES_RELOC_ALIGN_VALUE_4MB' in env: - alignment_value = ALIGNVALUE_4MB - else: - alignment_value = ALIGNVALUE_1MB - - - - #create new alignment value - new_align = (curr_phdr.p_align & 0) | alignment_value - - # Create structure to package new flag field - s = struct.Struct('I') - new_flag_bytes = s.pack(new_align) - - # Write the new flag value and incr ement offset - elf_in_fp.write(new_flag_bytes) - - # Go to the start of the p_flag entry in the first program header - file_offset_reloc_flag = elf_header.e_phoff + phdr_reloc_flag_offset - - # Change each program header flag in the ELF file with relocatable flag - for i in range(elf_header.e_phnum): - # Seek to correct location and create new p_flag value - elf_in_fp.seek(file_offset_reloc_flag) - curr_phdr = phdr_table[i] - new_flag = (curr_phdr.p_flags & ~MI_PBT_FLAGS_MASK) | (MI_PBT_ELF_AMSS_RELOCATABLE_IMAGE) - - # Create structure to package new flag field - s = struct.Struct('I') - new_flag_bytes = s.pack(new_flag) - - # Write the new flag value and increment offset - elf_in_fp.write(new_flag_bytes) - file_offset_reloc_flag += elf_header.e_phentsize - - # Close files - elf_in_fp.close() - - - return 0 - - -#---------------------------------------------------------------------------- -# modify_elf_flags -#---------------------------------------------------------------------------- -def modify_elf_flags(env, elf_in_file_name, - scl_file_name): - - # Initialize - [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) - segment_list = readSCL(scl_file_name, env['GLOBAL_DICT']) - - if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: - curr_phdr = Elf64_Phdr('\0' * ELF64_PHDR_SIZE) - # Offset into program header where the p_flags field is stored - phdr_flag_off = 4 - else: - curr_phdr = Elf32_Phdr('\0' * ELF32_PHDR_SIZE) - # Offset into program header where the p_flags field is stored - phdr_flag_off = 24 - - # Open files - elf_in_fp = OPEN(elf_in_file_name, "r+") - - # Check for corresponding number of segments - if len(segment_list) is not elf_header.e_phnum: - raise RuntimeError, 'SCL file and ELF file have different number of segments!' - - # Go to the start of the p_flag entry in the first program header - file_offset = elf_header.e_phoff + phdr_flag_off - - # Change each program header flag in the ELF file based off the SCL file - for i in range(elf_header.e_phnum): - # Seek to correct location and create new p_flag value - elf_in_fp.seek(file_offset) - curr_phdr = phdr_table[i] - new_flag = (curr_phdr.p_flags & ~MI_PBT_FLAGS_MASK) | (segment_list[i].flag) - - # Create structure to package new flag field - s = struct.Struct('I') - new_flag_bytes = s.pack(new_flag) - - # Write the new flag value and increment offset - elf_in_fp.write(new_flag_bytes) - file_offset += elf_header.e_phentsize - - # Close files - elf_in_fp.close() - - return 0 - -#---------------------------------------------------------------------------- -# generate_code_hash -#---------------------------------------------------------------------------- -def generate_code_hash(env, elf_in_file_name): - - # Initialize - [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) - - if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: - curr_phdr = Elf64_Phdr('\0' * ELF64_PHDR_SIZE) - # Offset into program header where the p_flags field is stored - phdr_flag_off = 4 - else: - curr_phdr = Elf32_Phdr('\0' * ELF32_PHDR_SIZE) - # Offset into program header where the p_flags field is stored - phdr_flag_off = 24 - - # Open files - elf_in_fp = OPEN(elf_in_file_name, "rb+") - - # Go to the start of the p_flag entry in the first program header - file_offset = elf_header.e_phoff + phdr_flag_off - - # XXX Get these from env? - DP_CODE_ALIGN = 0x100 - DP_PAGE_SIZE = 4096 - DP_HASH_SIZE = 32 # SHA-256 - DP_HASH_MAGIC = 0xC0DEDEC0 - PH_PERM_RW = 0x06 - PH_PERM_RX = 0x05 - PH_PERM_RO = 0x04 - PH_PERM_MASK = 0x07 - - page_size = DP_PAGE_SIZE - hash_size = DP_HASH_SIZE - - # First identify the hash segment. It is the first RW section. - # Its Align should be 8, and its size a multiple of DP_HASH_SIZE; - - hash_seg_idx = -1 - for i in range(elf_header.e_phnum): - curr_phdr = phdr_table[i] - - if (curr_phdr.p_align == 8 and - (curr_phdr.p_flags & PH_PERM_MASK) == PH_PERM_RW and - curr_phdr.p_filesz != 0 and (curr_phdr.p_filesz % DP_HASH_SIZE) == 0): - hash_seg_idx = i - # Validate the contents of the hash segment. It should be - # filled with DP_HASH_MAGIC - elf_in_fp.seek(curr_phdr.p_offset) - hash_data = ""; - while (len(hash_data) < curr_phdr.p_filesz): - hash_data = hash_data + elf_in_fp.read(curr_phdr.p_filesz - len(hash_data)) - - hash_data = struct.unpack("I" * (curr_phdr.p_filesz / 4), hash_data) - - for v in hash_data[:]: - if (v != DP_HASH_MAGIC): - hash_seg_idx = -1 - break; - - if (hash_seg_idx != -1): - break - - if (hash_seg_idx == -1): - # return if there is no hash segment. - return 0 - - hash_phdr = phdr_table[hash_seg_idx] - - # Now find the code segment for the hashes. Look for matching number of pages - code_seg_idx = -1 - code_seg_pages = hash_phdr.p_filesz / DP_HASH_SIZE - - for i in range(elf_header.e_phnum): - curr_phdr = phdr_table[i] - curr_pages = (curr_phdr.p_filesz + DP_PAGE_SIZE - 1) / DP_PAGE_SIZE - - if (curr_phdr.p_align == DP_CODE_ALIGN and - (curr_phdr.p_flags & PH_PERM_MASK) == PH_PERM_RX and - curr_pages == code_seg_pages): - if (code_seg_idx != -1): - raise RuntimeError, 'Multiple code segments match for: ' + code_seg_pages + ' pages' - code_seg_idx = i - - if (code_seg_idx == -1): - raise RuntimeError, 'No matching code segment found' - - code_phdr = phdr_table[code_seg_idx] - - # Now hash the pages in the code segment - hashes = [] - elf_in_fp.seek(code_phdr.p_offset) - bytes_left = code_phdr.p_filesz; - while (bytes_left > 0): - bytes_in_page = min(bytes_left, DP_PAGE_SIZE) - page = ""; - while (len(page) < bytes_in_page): - page = page + elf_in_fp.read(bytes_in_page - len(page)) - if (len(page) < DP_PAGE_SIZE): - page = page + (struct.pack('b', 0) * (DP_PAGE_SIZE - len(page))) - hashes = hashes + [generate_hash(page, True)] - bytes_left -= bytes_in_page - - # And write them to the hash segment - elf_in_fp.seek(hash_phdr.p_offset) - - for h in hashes[:]: - elf_in_fp.write(h) - - # Close files - elf_in_fp.close() - - return 0 - -#---------------------------------------------------------------------------- -# BOOT TOOLS END -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# HELPER FUNCTIONS BEGIN -#---------------------------------------------------------------------------- - -#---------------------------------------------------------------------------- -# Create a list to hold all segment information from an input SCL file -#---------------------------------------------------------------------------- -def readSCL(filename, global_dict): - - scl_fp = OPEN(filename,'r') - - # Initialize - file_data = scl_fp.readlines() - num_lines = len(file_data) - current_line = '' - previous_line = '' - strip_chars = '(){}[]' - i = 0 - bracket_counter = 0 - seg_list = [] - - # Parse through all lines - while i < num_lines: - - # Save the last line read - previous_line = current_line - current_line = file_data[i] - - # Look for the symbol '{' for the line to read. - # Use bracket counter to skip nested '{ }' - if ('{' in current_line): - if bracket_counter is 0: - # Create a new SegmentInfo class and set up tokens - new_scl_entry = SegmentInfo() - previous_line = previous_line.strip() - tokens = previous_line.split(' ') - - # Check that at least two tokens were parsed - # Token 1: Segment Name - # Token 2: Start Address -- not used in MBN tools - if len(tokens) < 2: - raise RuntimeError, 'SCL Segment Syntax malformed: ' + previous_line - - # Get the segment flags corresponding to the segment name description - new_scl_entry.flag = getSegmentFlag(tokens[0].strip(strip_chars)) - seg_list.append(new_scl_entry) - - bracket_counter += 1 - elif '}' in current_line: - bracket_counter -= 1 - - i+=1 - - scl_fp.close() - return seg_list - -#---------------------------------------------------------------------------- -# Given a string parsed from a SCL file, returns the ELF segment flags -#---------------------------------------------------------------------------- -def getSegmentFlag(seg_info): - - ret_val = None - - # Define string values for various types of segments - RO = "RO" - RW = "RW" - ZI = "ZI" - PAGEABLE = "PAGED" - NOTPAGEABLE = "NOTPAGED" - SWAPABLE = "SWAPPED" - SWAP_POOL = "SWAP_POOL" - RESERVED = "RESERVED" - HASHTBL = "HASH" - SHARED = "SHARED" - NOTUSED = "NOTUSED" - BOOT_SEGMENT = "BOOT_SEGMENT" - CODE = "CODE" - L4BSP = "L4BSP" - POOL_INDEX_0 = "INDEX_0" - POOL_INDEX_1 = "INDEX_1" - - # New definitions for EOS demand paging - NONPAGE = "NONPAGE" - PAGEUNLOCKED = "PAGEUNLOCKED" - PAGELOCKED = "PAGELOCKED" - UNSECURE = "UNSECURE" - - if seg_info is None or len(seg_info) is 0: - raise RuntimeError, 'Invalid segment information passed: ' + seg_info - - # Conditional checks and assignments of the corresponding segment flag values - if NOTPAGEABLE in seg_info: - if RO in seg_info: - ret_val = MI_PBT_ELF_AMSS_NON_PAGED_RO_SEGMENT - elif CODE in seg_info: - ret_val = MI_PBT_ELF_AMSS_NON_PAGED_RO_SEGMENT - elif ZI in seg_info: - if SWAP_POOL in seg_info: - if POOL_INDEX_0 in seg_info: - ret_val = MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX0 - else: - ret_val = MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX1 - else: - ret_val = MI_PBT_ELF_AMSS_NON_PAGED_ZI_SEGMENT - - elif NOTUSED in seg_info: - ret_val = MI_PBT_ELF_AMSS_NON_PAGED_NOTUSED_SEGMENT - - elif SHARED in seg_info: - ret_val = MI_PBT_ELF_AMSS_NON_PAGED_SHARED_SEGMENT - elif HASHTBL in seg_info: - ret_val = MI_PBT_ELF_HASH_SEGMENT - elif BOOT_SEGMENT in seg_info: - ret_val = MI_PBT_ELF_BOOT_SEGMENT - elif L4BSP in seg_info: - ret_val = MI_PBT_ELF_NON_PAGED_L4BSP_SEGMENT - else: - ret_val = MI_PBT_ELF_AMSS_NON_PAGED_RW_SEGMENT - - elif PAGEABLE in seg_info: - if RO in seg_info or CODE in seg_info: - if SWAPABLE in seg_info: - if POOL_INDEX_0 in seg_info: - ret_val = MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX0 - else: - ret_val = MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX1 - else: - ret_val = MI_PBT_ELF_AMSS_PAGED_RO_SEGMENT - elif ZI in seg_info: - ret_val = MI_PBT_ELF_AMSS_PAGED_ZI_SEGMENT - - elif NOTUSED in seg_info: - ret_val = MI_PBT_ELF_AMSS_PAGED_NOTUSED_SEGMENT - elif SHARED in seg_info: - ret_val = MI_PBT_ELF_AMSS_PAGED_SHARED_SEGMENT - elif L4BSP in seg_info: - ret_val = MI_PBT_ELF_PAGED_L4BSP_SEGMENT - else: - ret_val = MI_PBT_ELF_AMSS_PAGED_RW_SEGMENT - - elif PAGELOCKED in seg_info: - ret_val = MI_PBT_ELF_PAGED_LOCKED_SEGMENT - elif PAGEUNLOCKED in seg_info: - ret_val = MI_PBT_ELF_PAGED_UNLOCKED_SEGMENT - elif NONPAGE in seg_info: - ret_val = MI_PBT_ELF_RESIDENT_SEGMENT - elif UNSECURE in seg_info: - ret_val = MI_PBT_ELF_UNSECURE_SEGMENT - - else: - raise RuntimeError, 'The segment name is wrongly defined in the SCL file: ' + seg_info - - return ret_val - -#---------------------------------------------------------------------------- -# Pad a file with specific number of bytes -# Note: Assumes the fp is seeked to the correct location of padding -#---------------------------------------------------------------------------- -def pad_file(fp, num_bytes, value): - - if num_bytes < 0: - raise RuntimeError, "Number of bytes to pad must be greater than zero" - - while num_bytes > 0: - fp.write('%c' % value) - num_bytes -= 1 - - return - -#---------------------------------------------------------------------------- -# Concatenates the files listed in 'sources' in order and writes to 'target' -#---------------------------------------------------------------------------- -def concat_files (target, sources): - if type(sources) is not list: - sources = [sources] - - target_file = OPEN(target,'wb') - - for fname in sources: - file = OPEN(fname,'rb') - while True: - bin_data = file.read(65536) - if not bin_data: - break - target_file.write(bin_data) - file.close() - target_file.close() - -#---------------------------------------------------------------------------- -# Parse build configurable values and assign to global variables for tools -#---------------------------------------------------------------------------- -def init_build_vars(env): - - # Maximum size of Certificate Chain used in Secure Boot - global CERT_CHAIN_ONEROOT_MAXSIZE - CERT_CHAIN_ONEROOT_MAXSIZE = get_dict_value(env['GLOBAL_DICT'], 'CERT_CHAIN_MAXSIZE', (6*1024)) - - # Maximum size of the XML Header used in encrypted ELF images - global XML_HEADER_MAXSIZE - XML_HEADER_MAXSIZE = get_dict_value(env['GLOBAL_DICT'], 'XML_HEADER_MAXSIZE', (2*1024)) - -#---------------------------------------------------------------------------- -# Generates the global dictionary and add to the environment -#---------------------------------------------------------------------------- -def generate_global_dict(env): - - # Get file names for 'cust' and 'targ' auto-generated files inside 'build/ms' - cust_h = env.subst('CUST${BUILD_ID}.H').lower() - targ_h = env.subst('TARG${BUILD_ID}.H').lower() - cust_file_name = str(env.FindFile(cust_h, "${INC_ROOT}/build/ms")) - targ_file_name = str(env.FindFile(targ_h, "${INC_ROOT}/build/ms")) - - # Check that files are present - if (os.path.exists(cust_file_name) is True) and \ - (os.path.exists(targ_file_name) is True): - - # Populate the dictionary from the auto-generated files - global_dict = populate_dictionary(targ_file_name, cust_file_name) - else: - global_dict = {} - - # Add the dictionary to the environment - env.Replace(GLOBAL_DICT = global_dict) - -#---------------------------------------------------------------------------- -# Populate the dictionary from a list of input files -#---------------------------------------------------------------------------- -def populate_dictionary(*args): - - if len(args) < 1: - raise RuntimeError, "At least 1 file must be specified as an input" - - global_dict = {} - Fields = ["Define", "Key", "Value"] - - # For each input file - for i in range(len(args)): - - template_file_path = args[i] - instream = OPEN(template_file_path, 'r') - # Tokenize each line with a white space - values = csv.DictReader(instream, Fields, delimiter=" ") - - for values in itertools.izip(values): - new_entry = values[0] - # Verify the parsed tokens - if (new_entry['Define'] == '#define') and \ - (new_entry['Key'] != None) and \ - (new_entry['Value'] != None): - - new_key = new_entry['Key'].strip() - new_value = new_entry['Value'].strip() - - # If value pair is empty string, assume feature definition is true - if new_value == '': - new_value = 'yes' - - # Check for and handle text replacements as we parse - if global_dict is not None and len(global_dict.keys()) > 0: - for key in global_dict: - new_value = new_value.replace(key, str(global_dict.get(key))) - - # Attempt to evaluate value - try: - new_value = eval(new_value) - # Catch exceptions and do not evaluate - except: - pass - - # Add to global dictionary - global_dict[new_key] = new_value - instream.close() - - return global_dict - -#---------------------------------------------------------------------------- -# Filter out a generic dictionary from the global dictionary -#---------------------------------------------------------------------------- -def filter_dictionary(env, global_dict, **kwargs): - - # Check for Image Type - # If IMAGE_TYPE parameter is not provided, raise error - if not kwargs.has_key('IMAGE_TYPE'): - raise RuntimeError, "IMAGE_TYPE must be defined to use FilterDictionary." - else: - image_type = kwargs.get('IMAGE_TYPE') - if type(image_type) is not str: - raise RuntimeError, "IMAGE_TYPE must be of string type." - - # Check for Flash Type - # If FLASH_TYPE parameter is not provided, default to 'nand' - if not kwargs.has_key('FLASH_TYPE'): - flash_type = 'nand' - else: - flash_type = kwargs.get('FLASH_TYPE') - if type(flash_type) is not str: - raise RuntimeError, "FLASH_TYPE must be of string type. " - - # Check for MBN Type - # If MBN_TYPE parameter is not provided, default to 'elf' - if not kwargs.has_key('MBN_TYPE'): - mbn_type = 'elf' - else: - mbn_type = kwargs.get('MBN_TYPE') - if mbn_type != 'elf' and mbn_type != 'bin': - raise RuntimeError, "MBN_TYPE currently not supported: " + mbn_type - - # Check for Image ID - # If IMAGE_ID parameter is not provided, default to ID 0 - if not kwargs.has_key('IMAGE_ID'): - image_id = ImageType.NONE_IMG - else: - image_id = kwargs.get('IMAGE_ID') - if type(image_id) is not int: - raise RuntimeError, "IMAGE_ID must be of integer type." - - # Initialize - gen_dict = {} - image_dest = 0 - image_source = 0 - - # Check for image_type - if image_type not in image_id_table: - id = image_id - id_match_str = image_type.upper() + "_IMG" - id_mbn_type = mbn_type - else: - id = image_id_table[image_type][0] - id_match_str = image_id_table[image_type][1] - id_mbn_type = image_id_table[image_type][2] - - # Handle MBN Type and assign image destination address - if id_mbn_type is 'elf': - pass - elif id_mbn_type is 'bin': - template_key_match = 'IMAGE_KEY_' + id_match_str + "_DEST_ADDR" - if template_key_match in global_dict: - image_dest = global_dict[template_key_match] - else: - raise RuntimeError, "Builds file does not have IMAGE_KEY pair for: " + image_type - else: - raise RuntimeError, "MBN_TYPE currently not supported: " + mbn_type - - # Assign generic dictionary key/value pairs - gen_dict['IMAGE_KEY_IMAGE_ID'] = id - gen_dict['IMAGE_KEY_IMAGE_DEST'] = image_dest - gen_dict['IMAGE_KEY_IMAGE_SOURCE'] = image_source - gen_dict['IMAGE_KEY_FLASH_TYPE'] = flash_type - gen_dict['IMAGE_KEY_MBN_TYPE'] = id_mbn_type - gen_dict['IMAGE_KEY_ID_MATCH_STR'] = id_match_str - gen_dict['IMAGE_KEY_FLASH_AUTO_DETECT_MAX_PAGE'] = \ - get_dict_value(global_dict,'FLASH_AUTO_DETECT_MAX_PAGE', 8192) - gen_dict['IMAGE_KEY_FLASH_AUTO_DETECT_MIN_PAGE'] = \ - get_dict_value(global_dict,'FLASH_AUTO_DETECT_MIN_PAGE', 2048) - gen_dict['IMAGE_KEY_MAX_SIZE_OF_VERIFY_BUFFER'] = \ - get_dict_value(global_dict,'MAX_SIZE_OF_VERIFY_BUFFER', 8192) - gen_dict['IMAGE_KEY_BOOT_SMALL_PREAMBLE'] = \ - get_dict_value(global_dict,'BOOT_SMALL_PREAMBLE', 1) - - # Get OEM root certificate select and number - oem_root_cert_sel = get_dict_value(global_dict,'OEM_ROOT_CERT_SEL', 1) - oem_num_root_certs = get_dict_value(global_dict,'OEM_NUM_ROOT_CERTS', 1) - - # Error checking for OEM configurable values - if oem_root_cert_sel in range(1, MAX_NUM_ROOT_CERTS + 1) and \ - oem_num_root_certs in range(1, MAX_NUM_ROOT_CERTS + 1) and \ - oem_root_cert_sel <= oem_num_root_certs: - - gen_dict['IMAGE_KEY_OEM_ROOT_CERT_SEL'] = oem_root_cert_sel - gen_dict['IMAGE_KEY_OEM_NUM_ROOT_CERTS'] = oem_num_root_certs - - else: - raise RuntimeError, "Invalid OEM root certificate configuration values" - - # Assign additional dictionary key/values pair as needed by tools. - - return gen_dict - - -#---------------------------------------------------------------------------- -# Get index value from dictionary if exists, otherwise return default -#---------------------------------------------------------------------------- -def get_dict_value(dict, key_string, default): - - key = 'IMAGE_KEY_' + key_string - - if key in dict: - return dict[key] - else: - return default - -#---------------------------------------------------------------------------- -# Preprocess an ELF file and return the ELF Header Object and an -# array of ELF Program Header Objects -#---------------------------------------------------------------------------- -def preprocess_elf_file(elf_file_name): - - # Initialize - elf_fp = OPEN(elf_file_name, 'rb') - elf_header = Elf_Ehdr_common(elf_fp.read(ELF_HDR_COMMON_SIZE)) - - if verify_elf_header(elf_header) is False: - raise RuntimeError, "ELF file failed verification: " + elf_file_name - - elf_fp.seek(0) - - if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: - elf_header = Elf64_Ehdr(elf_fp.read(ELF64_HDR_SIZE)) - else: - elf_header = Elf32_Ehdr(elf_fp.read(ELF32_HDR_SIZE)) - - phdr_table = [] - - # Verify ELF header information - if verify_elf_header(elf_header) is False: - raise RuntimeError, "ELF file failed verification: " + elf_file_name - - # Get program header size - phdr_size = elf_header.e_phentsize - - # Find the program header offset - file_offset = elf_header.e_phoff - elf_fp.seek(file_offset) - - # Read in the program headers - for i in range(elf_header.e_phnum): - if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: - phdr_table.append(Elf64_Phdr(elf_fp.read(phdr_size))) - else: - phdr_table.append(Elf32_Phdr(elf_fp.read(phdr_size))) - - elf_fp.close() - return [elf_header, phdr_table] - -#---------------------------------------------------------------------------- -# Get the hash table address from an input ELF file -#---------------------------------------------------------------------------- -def get_hash_address(elf_file_name): - - [elf_header, phdr_table] = preprocess_elf_file(elf_file_name) - - last_paddr = 0 - last_paddr_segment = 0 - - # Find the segment with the largest physical address. - # Hash segment's physical address will be immediately after this segment. - for i in range(elf_header.e_phnum): - curr_phdr = phdr_table[i] - if curr_phdr.p_paddr > last_paddr: - # Skip the demand paging segment as it would be outside the physical RAM location - if MI_PBT_SEGMENT_TYPE_VALUE(curr_phdr.p_flags) != MI_PBT_SWAPPED_SEGMENT: - last_paddr = curr_phdr.p_paddr; - last_paddr_segment = i; - - max_phdr = phdr_table[last_paddr_segment] - - ret_val = (((max_phdr.p_paddr + max_phdr.p_memsz - 1) & \ - ~(ELF_BLOCK_ALIGN-1)) + ELF_BLOCK_ALIGN) - - return ret_val - -#---------------------------------------------------------------------------- -# Verify ELF header contents from an input ELF file -#---------------------------------------------------------------------------- -def verify_elf_header(elf_header): - if (elf_header.e_ident[ELFINFO_MAG0_INDEX] != ELFINFO_MAG0) or \ - (elf_header.e_ident[ELFINFO_MAG1_INDEX] != ELFINFO_MAG1) or \ - (elf_header.e_ident[ELFINFO_MAG2_INDEX] != ELFINFO_MAG2) or \ - (elf_header.e_ident[ELFINFO_MAG3_INDEX] != ELFINFO_MAG3) or \ - ((elf_header.e_ident[ELFINFO_CLASS_INDEX] != ELFINFO_CLASS_64) and \ - (elf_header.e_ident[ELFINFO_CLASS_INDEX] != ELFINFO_CLASS_32)) or \ - (elf_header.e_ident[ELFINFO_VERSION_INDEX] != ELFINFO_VERSION_CURRENT): - - return False - else: - return True - -#---------------------------------------------------------------------------- -# Perform file copy given offsets and the number of bytes to copy -#---------------------------------------------------------------------------- -def file_copy_offset(in_fp, in_off, out_fp, out_off, num_bytes): - in_fp.seek(in_off) - read_in = in_fp.read(num_bytes) - out_fp.seek(out_off) - out_fp.write(read_in) - - return num_bytes - -#---------------------------------------------------------------------------- -# sha1/sha256 hash routine wrapper -#---------------------------------------------------------------------------- -def generate_hash(in_buf, is_sha256_algo): - # Initialize a SHA1 object from the Python hash library - if (is_sha256_algo is True): - m = hashlib.sha256() - else: - m = hashlib.sha1() - - # Set the input buffer and return the output digest - m.update(in_buf) - return m.digest() - -#---------------------------------------------------------------------------- -# Initialize the hash program header. -#---------------------------------------------------------------------------- -def initialize_hash_phdr(elf_in_file_name, hash_tbl_size, hdr_size, hdr_offset, is_elf64): - # Set hash header offset to page size boundary. Hash table will be - # located at first segment of elf image. - hash_hdr_size = hdr_size - hash_hdr_offset = hdr_offset - hash_tbl_offset = hash_hdr_offset + hash_hdr_size - hash_tbl_end_addr = hash_tbl_offset + hash_tbl_size; - pad_hash_segment = (hash_tbl_end_addr) & (ELF_BLOCK_ALIGN-1) - - # Update the hash table program header - if is_elf64 is True: - hash_Phdr = Elf64_Phdr('\0'*ELF64_PHDR_SIZE) - else: - hash_Phdr = Elf32_Phdr('\0'*ELF32_PHDR_SIZE) - hash_Phdr.p_flags = MI_PBT_ELF_HASH_SEGMENT - hash_Phdr.p_align = ELF_BLOCK_ALIGN - hash_Phdr.p_offset = hash_hdr_offset - hash_Phdr.p_memsz = hash_hdr_size + hash_tbl_size + (ELF_BLOCK_ALIGN - pad_hash_segment) - hash_Phdr.p_filesz = hash_hdr_size + hash_tbl_size - hash_Phdr.p_type = NULL_TYPE - hash_Phdr.p_vaddr = get_hash_address(elf_in_file_name) - hash_Phdr.p_paddr = hash_Phdr.p_vaddr - - return [hash_Phdr, pad_hash_segment, hash_tbl_end_addr, hash_tbl_offset] - -#---------------------------------------------------------------------------- -# image_preamble -#---------------------------------------------------------------------------- -def image_preamble(gen_dict, preamble_file_name, boot_sbl_header, num_of_pages=None): - # Generate the preamble file - preamble_fp = OPEN(preamble_file_name, 'wb') - - # Initialize - max_size_verify = gen_dict['IMAGE_KEY_MAX_SIZE_OF_VERIFY_BUFFER'] - flash_max_page = gen_dict['IMAGE_KEY_FLASH_AUTO_DETECT_MAX_PAGE'] - flash_min_page = gen_dict['IMAGE_KEY_FLASH_AUTO_DETECT_MIN_PAGE'] - autodetectpage = [int('0xFFFFFFFF',16)] * max_size_verify - - # The first three entries in the preamble must include the following values - autodetectpage[0] = FLASH_CODE_WORD - autodetectpage[1] = MAGIC_NUM - if (num_of_pages == 64): - autodetectpage[2] = AUTODETECT_PAGE_SIZE_MAGIC_NUM64 - elif (num_of_pages == 128): - autodetectpage[2] = AUTODETECT_PAGE_SIZE_MAGIC_NUM128 - else: - autodetectpage[2] = AUTODETECT_PAGE_SIZE_MAGIC_NUM - - # Package the list into binary data to be written to the preamble - s = struct.Struct('I' * max_size_verify) - packed_data = s.pack(*autodetectpage) - - # Output preamble pages based on maximum/minimum page size support - for i in range(flash_max_page/flash_min_page): - preamble_fp.write(packed_data[:flash_min_page]) - - # Determine appropriate amount of padding for the preamble and - # update the boot_sbl_header accordingly - if gen_dict['IMAGE_KEY_BOOT_SMALL_PREAMBLE'] == 1: - boot_sbl_header.image_src += (flash_max_page + flash_min_page) - amount_to_write = flash_min_page - else: - boot_sbl_header.image_src += flash_max_page * 2 - amount_to_write = flash_max_page - - pad_file(preamble_fp, amount_to_write, PAD_BYTE_1) - preamble_fp.close() - - return boot_sbl_header - -#---------------------------------------------------------------------------- -# Helper functions to parse ELF program headers -#---------------------------------------------------------------------------- -def MI_PBT_SEGMENT_TYPE_VALUE(x): - return ( ((x) & MI_PBT_FLAG_SEGMENT_TYPE_MASK) >> MI_PBT_FLAG_SEGMENT_TYPE_SHIFT ) - -def MI_PBT_PAGE_MODE_VALUE(x): - return ( ((x) & MI_PBT_FLAG_PAGE_MODE_MASK) >> MI_PBT_FLAG_PAGE_MODE_SHIFT ) - -def MI_PBT_ACCESS_TYPE_VALUE(x): - return ( ((x) & MI_PBT_FLAG_ACCESS_TYPE_MASK) >> MI_PBT_FLAG_ACCESS_TYPE_SHIFT ) - -def MI_PBT_CHECK_FLAG_TYPE(x): - return (MI_PBT_SEGMENT_TYPE_VALUE(x) != MI_PBT_HASH_SEGMENT) and \ - (MI_PBT_ACCESS_TYPE_VALUE(x) != MI_PBT_NOTUSED_SEGMENT) and \ - (MI_PBT_ACCESS_TYPE_VALUE(x) != MI_PBT_SHARED_SEGMENT) - - -#---------------------------------------------------------------------------- -# Helper functions to open a file and return a valid file object -#---------------------------------------------------------------------------- -def OPEN(file_name, mode): - try: - fp = open(file_name, mode) - except IOError: - raise RuntimeError, "The file could not be opened: " + file_name - - # File open has succeeded with the given mode, return the file object - return fp - -#---------------------------------------------------------------------------- -# Helper functions to insert MCs in SBL1(Badger) if ENABLE_VIRTUAL_BLK is ON -#---------------------------------------------------------------------------- -def insert_SBL1_magicCookie (env, target): - file = open(target, "rb") - #read the file contents - filedata = file.read() - length = len(filedata) - file.close() - - if (length <= VIRTUAL_BLOCK_SIZE): - return None - else: - #remove the previous file - os.remove(target) - #generate new file for appending target data + required MCs - file = open(target, "ab") - - while length > VIRTUAL_BLOCK_SIZE: - filedata_till_128kb = filedata[0:VIRTUAL_BLOCK_SIZE] - filedata_after_128kb = filedata[VIRTUAL_BLOCK_SIZE:length] - - a = str(hex(FLASH_CODE_WORD)) - mc1 = chr(int(a[8:10],16)) + chr(int(a[6:8],16)) + chr(int(a[4:6],16)) + chr(int(a[2:4],16)) - - b = str(hex(MAGIC_NUM)) - mc2 = chr(int(b[8:10],16)) + chr(int(b[6:8],16)) + chr(int(b[4:6],16)) + chr(int(b[2:4],16)) - - c = str(hex(SBL_VIRTUAL_BLOCK_MAGIC_NUM)) - mc3 = chr(int(c[8:10],16)) + chr(int(c[6:8],16)) + chr(int(c[4:6],16)) + chr(int(c[2:4],16)) - - MC_inserted_data = filedata_till_128kb + mc1 + mc2 + mc3 - file.write(MC_inserted_data) - - filedata = filedata_after_128kb - length = len(filedata) - - #copy the leftover data (<128KB) in output file - if length > 0: - file.write(filedata) - - #close the final output file - file.close() - # MC_insertion code end - -#---------------------------------------------------------------------------- -# Helper functions to remove MCs in SBL1(Badger) -#---------------------------------------------------------------------------- -def remove_SBL1_magicCookie (env, target, dest): - file = open(target, "rb") - #read the file contents - filedata = file.read() - length = len(filedata) - file.close() - - #generate new file for appending target data + required MCs - file = open(dest, "ab") - - while length > VIRTUAL_BLOCK_SIZE: - filedata_till_128kb = filedata[0:VIRTUAL_BLOCK_SIZE] - # skipped 12 byte of Virtual Block Magic Cookie Header - filedata_after_128kb = filedata[VIRTUAL_BLOCK_SIZE+MAGIC_COOKIE_LENGTH:length] - - file.write(filedata_till_128kb) - - filedata = filedata_after_128kb - length = len(filedata) - - #copy the leftover data (<128KB) in output file - if length > 0: - file.write(filedata) - - #close the final output file - file.close() - - # MC_removal code end - -#---------------------------------------------------------------------------- -# Helper functions to pad SBL1 image -# min_size defaults to 256k -# If page_size or num_of_pages is set to 0, the variable is unset -#---------------------------------------------------------------------------- -def pad_SBL1_image (env, target, min_size_with_pad=MIN_IMAGE_SIZE_WITH_PAD, page_size=0, num_of_pages=0): - file = open(target, "rb") - #read the file contents - filedata = file.read() - length = len(filedata) - file.close() - - multiple = 1 - alignment = page_size * num_of_pages - - if (length > alignment and alignment > 0): - import math - multiple = math.ceil(length/float(alignment)) - - final_image_size = max(min_size_with_pad, multiple * alignment) - - if length < final_image_size: - sbl1_fp = open(target, 'ab') - pad_file (sbl1_fp, (final_image_size-length), PAD_BYTE_0) - sbl1_fp.close() - - # SBL1 pad code end -#---------------------------------------------------------------------------- -# HELPER FUNCTIONS END -#---------------------------------------------------------------------------- diff --git a/util/ipqheader/mbncat.py b/util/ipqheader/mbncat.py deleted file mode 100755 index c4da265f80..0000000000 --- a/util/ipqheader/mbncat.py +++ /dev/null @@ -1,200 +0,0 @@ -#!/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() |