aboutsummaryrefslogtreecommitdiff
path: root/util/qualcomm/createxbl.py
diff options
context:
space:
mode:
Diffstat (limited to 'util/qualcomm/createxbl.py')
-rwxr-xr-xutil/qualcomm/createxbl.py733
1 files changed, 733 insertions, 0 deletions
diff --git a/util/qualcomm/createxbl.py b/util/qualcomm/createxbl.py
new file mode 100755
index 0000000000..4a218544c0
--- /dev/null
+++ b/util/qualcomm/createxbl.py
@@ -0,0 +1,733 @@
+#!/usr/bin/env python2
+#============================================================================
+#
+#/** @file createxbl.py
+#
+# GENERAL DESCRIPTION
+# Concatentates XBL segments into one ELF image
+#
+# Copyright (c) 2016, 2018, 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
+# -------- --- ------------------------------------------------------
+# 03/26/18 tv Added -e to enable extended MBNV5 support
+# 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
+
+ if options.elf_inp_xbl_sec:
+ is_ext_mbn_v5 = True
+ else:
+ is_ext_mbn_v5 = False
+
+
+ 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,
+ is_ext_mbn_v5)
+
+
+ # 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,
+ is_ext_mbn_v5,
+ 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,
+ is_ext_mbn_v5):
+
+ [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
+ if is_ext_mbn_v5 == True:
+ new_phdr.p_flags = (0x5 |
+ (mbn_tools.MI_PBT_XBL_SEC_SEGMENT <<
+ mbn_tools.MI_PBT_FLAG_SEGMENT_TYPE_SHIFT));
+ else:
+ 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
+ if is_ext_mbn_v5 == True:
+ new_phdr.p_flags = (0x5 |
+ (mbn_tools.MI_PBT_XBL_SEC_SEGMENT <<
+ mbn_tools.MI_PBT_FLAG_SEGMENT_TYPE_SHIFT));
+ else:
+ 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 big 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 big 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()