blob: 65d8eb9460b02fb6d3456272f6db6dab3047444d [file] [log] [blame]
T Michael Turney540b8ec2020-01-24 08:42:47 -08001#!/usr/bin/env python3
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +05302#============================================================================
3#
4#/** @file createxbl.py
5#
6# GENERAL DESCRIPTION
7# Concatentates XBL segments into one ELF image
8#
T Michael Turney101098c2018-05-01 15:59:37 -07009# Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved.
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +053010#
11# Redistribution and use in source and binary forms, with or without
12# modification, are permitted provided that the following conditions are
13# met:
14# * Redistributions of source code must retain the above copyright
15# notice, this list of conditions and the following disclaimer.
16# * Redistributions in binary form must reproduce the above
17# copyright notice, this list of conditions and the following
18# disclaimer in the documentation and/or other materials provided
19# with the distribution.
20# * Neither the name of The Linux Foundation nor the names of its
21# contributors may be used to endorse or promote products derived
22# from this software without specific prior written permission.
23#
24# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
25# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
27# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
28# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35#
36#**/
37#
38#----------------------------------------------------------------------------
39#
40# EDIT HISTORY FOR FILE
41#
42# This section contains comments describing changes made to the module.
43# Notice that changes are listed in reverse chronological order.
44#
45# when who what, where, why
46# -------- --- ------------------------------------------------------
T Michael Turneybcd62f52019-08-07 14:26:32 -070047# 05/21/19 rissha Added --mbn_version to add MBN header accordingly
T Michael Turney101098c2018-05-01 15:59:37 -070048# 03/26/18 tv Added -e to enable extended MBNV5 support
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +053049# 09/04/15 et Added -x and -d to embed xbl_sec ELF
50# 02/11/15 ck Fixed missing elf type check in ZI OOB feature
51# 11/04/14 ck Updated calls to mbn_tools functions
T Michael Turneybcd62f52019-08-07 14:26:32 -070052# 10/22/14 ck Added -z option to remove out of bounds ZI segments when
53# converting from 64 to 32
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +053054# 10/10/14 ck Added -c option and logic to enable elf type swapping
55# 09/12/14 ck Added single file logic
56# 08/29/14 ck Added no_hash option
57# 08/29/14 ck Refactored to use proper python arguments and cleaned code
58# 06/16/14 niting xbl.mbn to xbl.elf
59# 05/28/14 niting Initial revision
60#
61#============================================================================
62from optparse import OptionParser
63import os
64import sys
65import shutil
66import mbn_tools
67
68PAGE_SIZE = 4096
69SEGMENT_ALIGN = 16
70ELF32_HDR_SIZE = 52
71ELF32_PHDR_SIZE = 32
72ELF64_HDR_SIZE = 64
73ELF64_PHDR_SIZE = 56
74
75
76##############################################################################
77# main
78##############################################################################
79def main():
80 parser = OptionParser(usage='usage: %prog [options] arguments')
81
82 parser.add_option("-f", "--first_filepath",
83 action="store", type="string", dest="elf_inp_file1",
84 help="First ELF file to merge.")
85
86 parser.add_option("-s", "--second_filepath",
87 action="store", type="string", dest="elf_inp_file2",
88 help="Second ELF file to merge.")
89
90 parser.add_option("-x", "--xbl_sec_filepath",
91 action="store", type="string", dest="elf_inp_xbl_sec",
92 help="Second ELF file to merge.")
93
94 parser.add_option("-o", "--output_filepath",
95 action="store", type="string", dest="binary_out",
96 help="Merged filename and path.")
97
98 parser.add_option("-a", "--first_elf_arch",
99 action="store", type="string", dest="elf_1_arch",
100 help="First (and output) ELF file architecture. '32' or '64'")
101
102 parser.add_option("-b", "--second_elf_arch",
103 action="store", type="string", dest="elf_2_arch",
104 help="Second ELF file architecture. '32' or '64'")
105
106 parser.add_option("-d", "--xbl_sec_elf_arch",
107 action="store", type="string", dest="elf_xbl_sec_arch",
108 help="xbl_sec file architecture. '32' or '64'")
109
110 parser.add_option("-c", "--output_elf_arch",
111 action="store", type="string", dest="elf_out_arch",
112 help="Output ELF file architecture. '32' or '64'" + \
113 " If not given defaults to first file arch.")
114
115 parser.add_option("-n", "--no_hash",
116 action="store_true", dest="hash_image",
117 help="Disables hashing of image after merging.")
118
119 parser.add_option("-z", "--zi_out_of_bounds",
120 action="store_true", dest="zi_oob",
121 help="Removes ZI segments that have addresses greater" + \
122 " than 32 bits when converting from a 64 to 32 bit ELF")
123
T Michael Turneybcd62f52019-08-07 14:26:32 -0700124 parser.add_option("--mbn_version",
125 action="store", type="int", dest="mbn_version",
126 help="Add mbn header in elf image. '3', '5' or '6'")
127
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530128
129 (options, args) = parser.parse_args()
130 if not options.elf_inp_file1:
131 parser.error('First ELF filename not given')
132
133 if not options.binary_out:
134 parser.error('Output filename not given')
135
136 if not options.elf_1_arch:
137 parser.error('First ELF architecture not given')
138
139 if (not options.elf_1_arch == '64') and (not options.elf_1_arch == '32'):
140 parser.error('Invalid First ELF architecture given')
141
142 # Only evaluate elf_2_arch if two files are given for merging
143 if options.elf_inp_file2:
144 if (not options.elf_2_arch == '64') and (not options.elf_2_arch == '32'):
145 parser.error('Invalid Second ELF architecture given')
146
147 # Only evaluate elf_xbl_sec_arch if file is given
148 if options.elf_inp_xbl_sec:
149 if (not options.elf_xbl_sec_arch == '64') and (not options.elf_xbl_sec_arch == '32'):
150 parser.error('Invalid xbl_sec ELF architecture given')
151
152 # If output file architecture is given ensure it is either '32' or '64'
153 if options.elf_out_arch:
154 if (not options.elf_out_arch == '64') and (not options.elf_out_arch == '32'):
155 parser.error('Invalid Output ELF architecture given')
156
157
158 gen_dict = {}
159
160 elf_inp_file1 = options.elf_inp_file1
161
162 # It is valid for only one file to be "merged". This essentially just
163 # strips off the section names. If second file name is not given then
164 # set elf_inp_file2 to ""
165 if options.elf_inp_file2:
166 elf_inp_file2 = options.elf_inp_file2
167 else:
168 elf_inp_file2 = ""
169
170 # Do same for xbl_sec
171 elf_inp_xbl_sec = options.elf_inp_xbl_sec if options.elf_inp_xbl_sec else ""
172
173 binary_out = options.binary_out
174
175 if options.elf_1_arch == '64':
176 is_elf1_64_bit = True
177 else:
178 is_elf1_64_bit = False
179
180 # If second filename is not given then set is_elf2_64_bit to false so it
181 # can be passed even though it is not used.
182 if options.elf_inp_file2:
183 if options.elf_2_arch == '64':
184 is_elf2_64_bit = True
185 else:
186 is_elf2_64_bit = False
187 else:
188 is_elf2_64_bit = False
189
190 if options.elf_inp_xbl_sec:
191 if options.elf_xbl_sec_arch == '64':
192 is_elf_xbl_sec_64_bit = True
193 else:
194 is_elf_xbl_sec_64_bit = False
195 else:
196 is_elf_xbl_sec_64_bit = False
197
198 # If output ELF arch is given then set is_out_elf_64_bit accordingly.
199 # If not then default to be input1's setting
200 if options.elf_out_arch:
201 if options.elf_out_arch == '64':
202 is_out_elf_64_bit = True
203 else:
204 is_out_elf_64_bit = False
205 else:
206 is_out_elf_64_bit = is_elf1_64_bit
207
208
209 # Store ZI Out of Bounds value
210 if not options.zi_oob:
211 zi_oob_enabled = False
212 else:
213 zi_oob_enabled = True
214
T Michael Turneybcd62f52019-08-07 14:26:32 -0700215 header_version = 3
T Michael Turney101098c2018-05-01 15:59:37 -0700216
T Michael Turneybcd62f52019-08-07 14:26:32 -0700217 if options.elf_inp_xbl_sec:
218 header_version = 5
219
220 if options.mbn_version:
221 header_version = options.mbn_version
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530222
223 mbn_type = 'elf'
224 header_format = 'reg'
225 gen_dict['IMAGE_KEY_IMAGE_ID'] = mbn_tools.ImageType.APPSBL_IMG
226 #gen_dict['IMAGE_KEY_IMAGE_SOURCE'] = 0
227 #gen_dict['IMAGE_KEY_IMAGE_DEST'] = 0
228 gen_dict['IMAGE_KEY_MBN_TYPE'] = mbn_type
229 image_header_secflag = 'non_secure'
230
231 source_base = os.path.splitext(str(binary_out))[0]
232 target_base = os.path.splitext(str(binary_out))[0]
233 merged_elf = source_base + "_merged.elf"
234 source_elf = source_base + "_nohash.elf"
235 target_hash = target_base + ".hash"
236 target_hash_hd = target_base + "_hash.hd"
237 target_phdr_elf = target_base + "_phdr.pbn"
238 target_nonsec = target_base + "_combined_hash.mbn"
239
240
T Michael Turney540b8ec2020-01-24 08:42:47 -0800241 #print("Input file 1:", elf_inp_file1)
242 #print("Input file 2:", elf_inp_file2)
243 #print("Output file:", binary_out)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530244
245 merge_elfs([],
246 elf_inp_file1,
247 elf_inp_file2,
248 elf_inp_xbl_sec,
249 merged_elf,
250 is_elf1_64_bit,
251 is_elf2_64_bit,
252 is_elf_xbl_sec_64_bit,
253 is_out_elf_64_bit,
T Michael Turney101098c2018-05-01 15:59:37 -0700254 zi_oob_enabled,
T Michael Turneybcd62f52019-08-07 14:26:32 -0700255 header_version)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530256
257
258 # Hash the image if user did not explicitly say not to
259 if options.hash_image:
260 # Just copy the merged elf to the final output name
261 shutil.move(merged_elf, binary_out)
262 else:
263 shutil.copy(merged_elf, source_elf)
264
265 # Create hash table
266 rv = mbn_tools.pboot_gen_elf([],
267 source_elf,
268 target_hash,
269 elf_out_file_name = target_phdr_elf,
T Michael Turneybcd62f52019-08-07 14:26:32 -0700270 secure_type = image_header_secflag,
271 header_version = header_version )
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530272 if rv:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800273 raise RuntimeError("Failed to run pboot_gen_elf")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530274
275 # Create hash table header
276 rv = mbn_tools.image_header([],
277 gen_dict,
278 target_hash,
279 target_hash_hd,
280 image_header_secflag,
T Michael Turneybcd62f52019-08-07 14:26:32 -0700281 elf_file_name = source_elf,
282 header_version = header_version)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530283 if rv:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800284 raise RuntimeError("Failed to create image header for hash segment")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530285
286 files_to_cat_in_order = [target_hash_hd, target_hash]
287 mbn_tools.concat_files (target_nonsec, files_to_cat_in_order)
288
289 # Add the hash segment into the ELF
290 mbn_tools.pboot_add_hash([],
291 target_phdr_elf,
292 target_nonsec,
293 binary_out)
294
295 return
296
297
298##############################################################################
299# roundup
300##############################################################################
301def roundup(x, precision):
302 return x if x % precision == 0 else (x + precision - (x % precision))
303
304##############################################################################
305# merge_elfs
306##############################################################################
307def merge_elfs(env,
308 elf_in_file_name1,
309 elf_in_file_name2,
310 elf_in_file_xbl_sec,
311 elf_out_file_name,
312 is_elf1_64_bit,
313 is_elf2_64_bit,
314 is_elf_xbl_sec_64_bit,
315 is_out_elf_64_bit,
T Michael Turney101098c2018-05-01 15:59:37 -0700316 zi_oob_enabled,
T Michael Turneybcd62f52019-08-07 14:26:32 -0700317 header_version):
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530318
319 [elf_header1, phdr_table1] = \
320 mbn_tools.preprocess_elf_file(elf_in_file_name1)
321
322 # Check to make sure second file path exists before using
323 if elf_in_file_name2 != "":
324 [elf_header2, phdr_table2] = \
325 mbn_tools.preprocess_elf_file(elf_in_file_name2)
326
327 # Check to make sure xbl_sec file path exists before using
328 if elf_in_file_xbl_sec != "":
329 [elf_headerxblsec, phdr_tablexblsec] = \
330 mbn_tools.preprocess_elf_file(elf_in_file_xbl_sec)
331
332 # Open Files
333 elf_in_fp1 = mbn_tools.OPEN(elf_in_file_name1, "rb")
334 if elf_in_file_name2 != "":
335 elf_in_fp2 = mbn_tools.OPEN(elf_in_file_name2, "rb")
336 if elf_in_file_xbl_sec != "":
337 elf_in_fpxblsec = mbn_tools.OPEN(elf_in_file_xbl_sec, "rb")
338
339 if elf_out_file_name is not None:
340 elf_out_fp = mbn_tools.OPEN(elf_out_file_name, "wb+")
341
342
343 # Calculate the new program header size. This is dependant on the output
344 # ELF type and number of program headers going into output.
345 if is_out_elf_64_bit:
346 phdr_total_size = elf_header1.e_phnum * ELF64_PHDR_SIZE
347 phdr_total_count = elf_header1.e_phnum
348 else:
349 phdr_total_size = elf_header1.e_phnum * ELF32_PHDR_SIZE
350 phdr_total_count = elf_header1.e_phnum
351
352
353 # This logic only applies if two files are to be merged
354 if elf_in_file_name2 != "":
355 if is_out_elf_64_bit:
356 phdr_total_size += elf_header2.e_phnum * ELF64_PHDR_SIZE
357 phdr_total_count += elf_header2.e_phnum
358 else:
359 phdr_total_size += elf_header2.e_phnum * ELF32_PHDR_SIZE
360 phdr_total_count += elf_header2.e_phnum
361
362 # Account for xbl_sec header if included
363 if elf_in_file_xbl_sec != "":
364 phdr_total_count += 1
365 if is_out_elf_64_bit:
366 phdr_total_size += ELF64_PHDR_SIZE
367 else:
368 phdr_total_size += ELF32_PHDR_SIZE
369
370 # Create a new ELF header for the output file
371 if is_out_elf_64_bit:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800372 out_elf_header = mbn_tools.Elf64_Ehdr(b'\0' * ELF64_HDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530373 out_elf_header.e_phoff = ELF64_HDR_SIZE
374 out_elf_header.e_ehsize = ELF64_HDR_SIZE
375 out_elf_header.e_phentsize = ELF64_PHDR_SIZE
376 out_elf_header.e_machine = 183
377 out_elf_header.e_ident = str('\x7f' + 'E' + 'L' + 'F' + \
378 '\x02' + \
379 '\x01' + \
380 '\x01' + \
381 '\x00' + \
382 '\x00' + \
383 ('\x00' * 7))
384
385 out_elf_header.e_entry = elf_header1.e_entry
386 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800387 out_elf_header = mbn_tools.Elf32_Ehdr(b'\0' * ELF32_HDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530388 out_elf_header.e_phoff = ELF32_HDR_SIZE
389 out_elf_header.e_ehsize = ELF32_HDR_SIZE
390 out_elf_header.e_phentsize = ELF32_PHDR_SIZE
391 out_elf_header.e_machine = 40
392 out_elf_header.e_entry = elf_header1.e_entry
393 out_elf_header.e_ident = str('\x7f' + 'E' + 'L' + 'F' + \
394 '\x01' + \
395 '\x01' + \
396 '\x01' + \
397 '\x00' + \
398 '\x00' + \
399 ('\x00' * 7))
400
401 # Address needs to be verified that it is not greater than 32 bits
402 # as it is possible to go from a 64 bit elf to 32.
403 if (elf_header1.e_entry > 0xFFFFFFFF):
T Michael Turney540b8ec2020-01-24 08:42:47 -0800404 print("ERROR: File 1's entry point is too large to convert.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530405 exit()
406 out_elf_header.e_entry = elf_header1.e_entry
407
408 # Common header entries
409 out_elf_header.e_type = 2
410 out_elf_header.e_version = 1
411 out_elf_header.e_shoff = 0
412 out_elf_header.e_flags = 0
413 out_elf_header.e_shentsize = 0
414 out_elf_header.e_shnum = 0
415 out_elf_header.e_shstrndx = 0
416
417
418 # If ZI OOB is enabled then it is possible that a segment could be discarded
419 # Scan for that instance and handle before setting e_phnum and writing header
420 # Ensure ELF output is 32 bit
421 if zi_oob_enabled == True and is_out_elf_64_bit == False:
422 for i in range(len(phdr_table1)):
423 if (phdr_table1[i].p_vaddr > 0xFFFFFFFF) or \
424 (phdr_table1[i].p_paddr > 0xFFFFFFFF):
425 if phdr_table1[i].p_filesz == 0:
426 phdr_total_count = phdr_total_count - 1
427
428 if elf_in_file_name2 != "":
429 for i in range(len(phdr_table2)):
430 if (phdr_table2[i].p_vaddr > 0xFFFFFFFF) or \
431 (phdr_table2[i].p_paddr > 0xFFFFFFFF):
432 if phdr_table2[i].p_filesz == 0:
433 phdr_total_count = phdr_total_count - 1
434 # Do not include xbl_sec in above calculation
435 # xbl_sec is to be treated as a single blob
436
437
438 # Now it is ok to populate the ELF header and write it out
439 out_elf_header.e_phnum = phdr_total_count
440
441 # write elf header
442 if is_out_elf_64_bit == False:
443 elf_out_fp.write(mbn_tools.Elf32_Ehdr.getPackedData(out_elf_header))
444 else:
445 elf_out_fp.write(mbn_tools.Elf64_Ehdr.getPackedData(out_elf_header))
446
447 phdr_offset = out_elf_header.e_phoff # offset of where to put next phdr
448
449 # offset the start of the segments just after the program headers
450 segment_offset = roundup(out_elf_header.e_phoff + phdr_total_size, PAGE_SIZE)
451
452
453 # Output first elf data
454 for i in range(elf_header1.e_phnum):
455 curr_phdr = phdr_table1[i]
456
457 # Copy program header piece by piece to ensure possible conversion success
458 if is_out_elf_64_bit == True:
459 # Converting from 32 to 64 elf requires no data size validation
T Michael Turney540b8ec2020-01-24 08:42:47 -0800460 new_phdr = mbn_tools.Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530461 new_phdr.p_type = curr_phdr.p_type
462 new_phdr.p_offset = segment_offset
463 new_phdr.p_vaddr = curr_phdr.p_vaddr
464 new_phdr.p_paddr = curr_phdr.p_paddr
465 new_phdr.p_filesz = curr_phdr.p_filesz
466 new_phdr.p_memsz = curr_phdr.p_memsz
467 new_phdr.p_flags = curr_phdr.p_flags
468 new_phdr.p_align = curr_phdr.p_align
469 else:
470 # Converting from 64 to 32 elf requires data size validation
471 # Note that there is an option to discard a segment if it is only ZI
472 # and its address is greater than 32 bits
T Michael Turney540b8ec2020-01-24 08:42:47 -0800473 new_phdr = mbn_tools.Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530474 new_phdr.p_type = curr_phdr.p_type
475 new_phdr.p_offset = segment_offset
476
477 if curr_phdr.p_vaddr > 0xFFFFFFFF:
478 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
479 continue
480 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800481 print("ERROR: File 1 VAddr is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530482 exit()
483 new_phdr.p_vaddr = curr_phdr.p_vaddr
484
485 if curr_phdr.p_paddr > 0xFFFFFFFF:
486 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
487 continue
488 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800489 print("ERROR: File 1 PAddr is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530490 exit()
491 new_phdr.p_paddr = curr_phdr.p_paddr
492
493 if curr_phdr.p_filesz > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800494 print("ERROR: File 1 Filesz is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530495 exit()
496 new_phdr.p_filesz = curr_phdr.p_filesz
497
498 if curr_phdr.p_memsz > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800499 print("ERROR: File 1 Memsz is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530500 exit()
501 new_phdr.p_memsz = curr_phdr.p_memsz
502
503 if curr_phdr.p_flags > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800504 print("ERROR: File 1 Flags is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530505 exit()
506 new_phdr.p_flags = curr_phdr.p_flags
507
508 if curr_phdr.p_align > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800509 print("ERROR: File 1 Align is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530510 exit()
511 new_phdr.p_align = curr_phdr.p_align
512
513
T Michael Turney540b8ec2020-01-24 08:42:47 -0800514 #print("i=",i)
515 #print("phdr_offset=", phdr_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530516
517 # update output file location to next phdr location
518 elf_out_fp.seek(phdr_offset)
519 # increment phdr_offset to next location
520 phdr_offset += out_elf_header.e_phentsize
521
522 inp_data_offset = curr_phdr.p_offset # used to read data from input file
523
T Michael Turney540b8ec2020-01-24 08:42:47 -0800524# print("inp_data_offset=")
525# print(inp_data_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530526#
T Michael Turney540b8ec2020-01-24 08:42:47 -0800527# print("curr_phdr.p_offset=")
528# print(curr_phdr.p_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530529#
T Michael Turney540b8ec2020-01-24 08:42:47 -0800530# print("curr_phdr.p_filesz=")
531# print(curr_phdr.p_filesz)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530532
533 # output current phdr
534 if is_out_elf_64_bit == False:
535 elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr))
536 else:
537 elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr))
538
539 # Copy the ELF segment
540 bytes_written = mbn_tools.file_copy_offset(elf_in_fp1,
541 inp_data_offset,
542 elf_out_fp,
543 new_phdr.p_offset,
544 new_phdr.p_filesz)
545
546 # update data segment offset to be aligned after previous segment
547 segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN);
548 elf_in_fp1.close()
549
550 # Output second elf data if applicable
551 if elf_in_file_name2 != "":
552 for i in range(elf_header2.e_phnum):
553 curr_phdr = phdr_table2[i]
554
555 # Copy program header piece by piece to ensure possible conversion success
556 if is_out_elf_64_bit == True:
557 # Converting from 32 to 64 elf requires no data size validation
T Michael Turney540b8ec2020-01-24 08:42:47 -0800558 new_phdr = mbn_tools.Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530559 new_phdr.p_type = curr_phdr.p_type
560 new_phdr.p_offset = segment_offset
561 new_phdr.p_vaddr = curr_phdr.p_vaddr
562 new_phdr.p_paddr = curr_phdr.p_paddr
563 new_phdr.p_filesz = curr_phdr.p_filesz
564 new_phdr.p_memsz = curr_phdr.p_memsz
565 new_phdr.p_flags = curr_phdr.p_flags
566 new_phdr.p_align = curr_phdr.p_align
567 else:
568 # Converting from 64 to 32 elf requires data size validation
569 # Note that there is an option to discard a segment if it is only ZI
570 # and its address is greater than 32 bits
T Michael Turney540b8ec2020-01-24 08:42:47 -0800571 new_phdr = mbn_tools.Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530572 new_phdr.p_type = curr_phdr.p_type
573 new_phdr.p_offset = segment_offset
574
575 if curr_phdr.p_vaddr > 0xFFFFFFFF:
576 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
577 continue
578 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800579 print("ERROR: File 2 VAddr is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530580 exit()
581 new_phdr.p_vaddr = curr_phdr.p_vaddr
582
583 if curr_phdr.p_paddr > 0xFFFFFFFF:
584 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
585 continue
586 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800587 print("ERROR: File 2 PAddr is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530588 exit()
589 new_phdr.p_paddr = curr_phdr.p_paddr
590
591 if curr_phdr.p_filesz > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800592 print("ERROR: File 2 Filesz is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530593 exit()
594 new_phdr.p_filesz = curr_phdr.p_filesz
595
596 if curr_phdr.p_memsz > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800597 print("ERROR: File 2 Memsz is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530598 exit()
599 new_phdr.p_memsz = curr_phdr.p_memsz
600
601 if curr_phdr.p_flags > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800602 print("ERROR: File 2 Flags is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530603 exit()
604 new_phdr.p_flags = curr_phdr.p_flags
605
606 if curr_phdr.p_align > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800607 print("ERROR: File 2 Align is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530608 exit()
609 new_phdr.p_align = curr_phdr.p_align
610
611
T Michael Turney540b8ec2020-01-24 08:42:47 -0800612# print("i=",i)
613# print("phdr_offset=", phdr_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530614
615 # update output file location to next phdr location
616 elf_out_fp.seek(phdr_offset)
617 # increment phdr_offset to next location
618 phdr_offset += out_elf_header.e_phentsize
619
620 inp_data_offset = curr_phdr.p_offset # used to read data from input file
621
T Michael Turney540b8ec2020-01-24 08:42:47 -0800622# print("inp_data_offset=")
623# print(inp_data_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530624#
T Michael Turney540b8ec2020-01-24 08:42:47 -0800625# print("curr_phdr.p_offset=")
626# print(curr_phdr.p_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530627#
T Michael Turney540b8ec2020-01-24 08:42:47 -0800628# print("curr_phdr.p_filesz=")
629# print(curr_phdr.p_filesz)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530630
631 # output current phdr
632 if is_out_elf_64_bit == False:
633 elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr))
634 else:
635 elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr))
636
637 # Copy the ELF segment
638 bytes_written = mbn_tools.file_copy_offset(elf_in_fp2,
639 inp_data_offset,
640 elf_out_fp,
641 new_phdr.p_offset,
642 new_phdr.p_filesz)
643
644 # update data segment offset to be aligned after previous segment
645 segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN);
646 elf_in_fp2.close()
647
648 # Embed xbl_sec image if provided
649 if elf_in_file_xbl_sec != "":
650
651 # Scan pheaders in xbl_sec for segment that contains entry point address
652 entry_seg_offset = -1
653 entry_addr = elf_headerxblsec.e_entry
654 for i in range(elf_headerxblsec.e_phnum):
655 phdr = phdr_tablexblsec[i]
656 max_addr = phdr.p_vaddr + phdr.p_memsz
657 if phdr.p_vaddr <= entry_addr <= max_addr:
658 entry_seg_offset = phdr.p_offset
659 break
660 if entry_seg_offset == -1:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800661 print("Error: Failed to find entry point in any segment!")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530662 exit()
663 # magical equation for program header's phys and virt addr
664 phys_virt_addr = entry_addr - entry_seg_offset
665
666 if is_out_elf_64_bit:
667 # Converting from 32 to 64 elf requires no data size validation
T Michael Turney540b8ec2020-01-24 08:42:47 -0800668 new_phdr = mbn_tools.Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530669 new_phdr.p_type = 0x1
670 new_phdr.p_offset = segment_offset
671 new_phdr.p_vaddr = phys_virt_addr
672 new_phdr.p_paddr = phys_virt_addr
673 new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec)
674 new_phdr.p_memsz = new_phdr.p_filesz
T Michael Turneybcd62f52019-08-07 14:26:32 -0700675 if header_version >= 5:
676 new_phdr.p_flags = (0x5 |
677 (mbn_tools.MI_PBT_XBL_SEC_SEGMENT <<
678 mbn_tools.MI_PBT_FLAG_SEGMENT_TYPE_SHIFT));
T Michael Turney101098c2018-05-01 15:59:37 -0700679 else:
T Michael Turneybcd62f52019-08-07 14:26:32 -0700680 new_phdr.p_flags = 0x5
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530681 new_phdr.p_align = 0x1000
682 else:
683 # Converting from 64 to 32 elf requires data size validation
684 # Don't discard the segment containing xbl_sec, simply error out
685 # if the address is greater than 32 bits
T Michael Turney540b8ec2020-01-24 08:42:47 -0800686 new_phdr = mbn_tools.Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530687 new_phdr.p_type = 0x1 #
688 new_phdr.p_offset = segment_offset
T Michael Turneybcd62f52019-08-07 14:26:32 -0700689 if header_version >= 5:
690 new_phdr.p_flags = (0x5 |
691 (mbn_tools.MI_PBT_XBL_SEC_SEGMENT <<
692 mbn_tools.MI_PBT_FLAG_SEGMENT_TYPE_SHIFT));
T Michael Turney101098c2018-05-01 15:59:37 -0700693 else:
T Michael Turneybcd62f52019-08-07 14:26:32 -0700694 new_phdr.p_flags = 0x5
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530695 new_phdr.p_align = 0x1000
696
697 if phys_virt_addr > 0xFFFFFFFF:
698 if zi_oob_enabled == False or curr_phdr.p_filesz != 0:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800699 print("ERROR: File xbl_sec VAddr or PAddr is too big for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530700 exit()
701 new_phdr.p_vaddr = phys_virt_addr
702 new_phdr.p_paddr = phys_virt_addr
703
704 if os.path.getsize(elf_in_file_xbl_sec) > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800705 print("ERROR: File xbl_sec Filesz is too big for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530706 exit()
707 new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec)
708 new_phdr.p_memsz = new_phdr.p_filesz
709
710
711 # update output file location to next phdr location
712 elf_out_fp.seek(phdr_offset)
713 # increment phdr_offset to next location
714 phdr_offset += out_elf_header.e_phentsize
715 # Copy entire xbl_sec file, so start from byte 0
716 inp_data_offset = 0
717
718 # Output xbl_sec's phdr
719 elf_in_file_xbl_sec
720 if is_out_elf_64_bit == False:
721 elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr))
722 else:
723 elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr))
724
725 # Copy the ENTIRE xbl_sec image
726 bytes_written = mbn_tools.file_copy_offset(elf_in_fpxblsec,
727 inp_data_offset,
728 elf_out_fp,
729 new_phdr.p_offset,
730 new_phdr.p_filesz)
731 # update data segment offset to be aligned after previous segment
732 # Not necessary, unless appending more pheaders after this point
733 segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN);
734
735 elf_in_fpxblsec.close()
736
737 elf_out_fp.close()
738
739 return 0
740
741
742main()