aboutsummaryrefslogtreecommitdiff
path: root/util/ipqheader/createxbl.py
diff options
context:
space:
mode:
authorVaradarajan Narayanan <varada@codeaurora.org>2016-04-21 16:06:06 +0530
committerPatrick Georgi <pgeorgi@google.com>2016-05-09 09:36:27 +0200
commit2dfbd93ed6bf830a9655e70d0dd1e26b008cd482 (patch)
tree033996e573c5bed8bf78a01b7a8aaf141ace4801 /util/ipqheader/createxbl.py
parentc1ae7e9183356ad1aaf5050fff82fc899896cc5c (diff)
util: ipq40xx: Scripts to combine SBL and Coreboot ELFs
The IPQ40xx Primary Boot Loader (PBL, i.e. Boot-ROM) expects an ELF in the boot medium to load and boot. These scripts combine the Secondary Boot Loader (SBL) and Coreboot ELF to an image as expected by the PBL. BUG=chrome-os-partner:49249 TEST=Able to boot and reach depthcharge BRANCH=none Change-Id: I5d02b7f1f58bb23d81a3e19fb9b78f3a999b89f3 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Original-Commit-Id: 819c7f2a810ca2880718ba14f2451f06eef4d98b Original-Change-Id: I017207b2d4108de150853f421aa7bcfd0e12e9a4 Original-Signed-off-by: Varadarajan Narayanan <varada@codeaurora.org> Original-Reviewed-on: https://chromium-review.googlesource.com/340181 Original-Commit-Ready: Nicolas Boichat <drinkcat@chromium.org> Original-Reviewed-by: David Hendricks <dhendrix@chromium.org> Reviewed-on: https://review.coreboot.org/14680 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Diffstat (limited to 'util/ipqheader/createxbl.py')
-rwxr-xr-xutil/ipqheader/createxbl.py714
1 files changed, 714 insertions, 0 deletions
diff --git a/util/ipqheader/createxbl.py b/util/ipqheader/createxbl.py
new file mode 100755
index 0000000000..b01e628544
--- /dev/null
+++ b/util/ipqheader/createxbl.py
@@ -0,0 +1,714 @@
+#!/usr/bin/python
+#============================================================================
+#
+#/** @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()