Python 3 is the default Python interpreter on most modern systems. Python 2 scripts must specify they should be run with Python 2 in their shebang. Solves issue raised in CB:28953. Change-Id: I9ace4afd668539c05e7ace30e255af50c7a069c2 Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/29666 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Patrick Georgi <pgeorgi@google.com>
		
			
				
	
	
		
			715 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			715 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/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()
 |