blob: 97fc9728b4a28e10aae0057904ba8fd57e656461 [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#
Patrick Georgi70517072020-05-10 18:47:05 +02009# SPDX-License-Identifier: BSD-3-Clause
10
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +053011#**/
12#
13#----------------------------------------------------------------------------
14#
15# EDIT HISTORY FOR FILE
16#
17# This section contains comments describing changes made to the module.
18# Notice that changes are listed in reverse chronological order.
19#
20# when who what, where, why
21# -------- --- ------------------------------------------------------
T Michael Turneybcd62f52019-08-07 14:26:32 -070022# 05/21/19 rissha Added --mbn_version to add MBN header accordingly
T Michael Turney101098c2018-05-01 15:59:37 -070023# 03/26/18 tv Added -e to enable extended MBNV5 support
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +053024# 09/04/15 et Added -x and -d to embed xbl_sec ELF
25# 02/11/15 ck Fixed missing elf type check in ZI OOB feature
26# 11/04/14 ck Updated calls to mbn_tools functions
T Michael Turneybcd62f52019-08-07 14:26:32 -070027# 10/22/14 ck Added -z option to remove out of bounds ZI segments when
28# converting from 64 to 32
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +053029# 10/10/14 ck Added -c option and logic to enable elf type swapping
30# 09/12/14 ck Added single file logic
31# 08/29/14 ck Added no_hash option
32# 08/29/14 ck Refactored to use proper python arguments and cleaned code
33# 06/16/14 niting xbl.mbn to xbl.elf
34# 05/28/14 niting Initial revision
35#
36#============================================================================
37from optparse import OptionParser
38import os
39import sys
40import shutil
41import mbn_tools
42
43PAGE_SIZE = 4096
44SEGMENT_ALIGN = 16
45ELF32_HDR_SIZE = 52
46ELF32_PHDR_SIZE = 32
47ELF64_HDR_SIZE = 64
48ELF64_PHDR_SIZE = 56
49
50
51##############################################################################
52# main
53##############################################################################
54def main():
55 parser = OptionParser(usage='usage: %prog [options] arguments')
56
57 parser.add_option("-f", "--first_filepath",
58 action="store", type="string", dest="elf_inp_file1",
59 help="First ELF file to merge.")
60
61 parser.add_option("-s", "--second_filepath",
62 action="store", type="string", dest="elf_inp_file2",
63 help="Second ELF file to merge.")
64
65 parser.add_option("-x", "--xbl_sec_filepath",
66 action="store", type="string", dest="elf_inp_xbl_sec",
67 help="Second ELF file to merge.")
68
69 parser.add_option("-o", "--output_filepath",
70 action="store", type="string", dest="binary_out",
71 help="Merged filename and path.")
72
73 parser.add_option("-a", "--first_elf_arch",
74 action="store", type="string", dest="elf_1_arch",
75 help="First (and output) ELF file architecture. '32' or '64'")
76
77 parser.add_option("-b", "--second_elf_arch",
78 action="store", type="string", dest="elf_2_arch",
79 help="Second ELF file architecture. '32' or '64'")
80
81 parser.add_option("-d", "--xbl_sec_elf_arch",
82 action="store", type="string", dest="elf_xbl_sec_arch",
83 help="xbl_sec file architecture. '32' or '64'")
84
85 parser.add_option("-c", "--output_elf_arch",
86 action="store", type="string", dest="elf_out_arch",
87 help="Output ELF file architecture. '32' or '64'" + \
88 " If not given defaults to first file arch.")
89
90 parser.add_option("-n", "--no_hash",
91 action="store_true", dest="hash_image",
92 help="Disables hashing of image after merging.")
93
94 parser.add_option("-z", "--zi_out_of_bounds",
95 action="store_true", dest="zi_oob",
96 help="Removes ZI segments that have addresses greater" + \
97 " than 32 bits when converting from a 64 to 32 bit ELF")
98
T Michael Turneybcd62f52019-08-07 14:26:32 -070099 parser.add_option("--mbn_version",
100 action="store", type="int", dest="mbn_version",
101 help="Add mbn header in elf image. '3', '5' or '6'")
102
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530103
104 (options, args) = parser.parse_args()
105 if not options.elf_inp_file1:
106 parser.error('First ELF filename not given')
107
108 if not options.binary_out:
109 parser.error('Output filename not given')
110
111 if not options.elf_1_arch:
112 parser.error('First ELF architecture not given')
113
114 if (not options.elf_1_arch == '64') and (not options.elf_1_arch == '32'):
115 parser.error('Invalid First ELF architecture given')
116
117 # Only evaluate elf_2_arch if two files are given for merging
118 if options.elf_inp_file2:
119 if (not options.elf_2_arch == '64') and (not options.elf_2_arch == '32'):
120 parser.error('Invalid Second ELF architecture given')
121
122 # Only evaluate elf_xbl_sec_arch if file is given
123 if options.elf_inp_xbl_sec:
124 if (not options.elf_xbl_sec_arch == '64') and (not options.elf_xbl_sec_arch == '32'):
125 parser.error('Invalid xbl_sec ELF architecture given')
126
127 # If output file architecture is given ensure it is either '32' or '64'
128 if options.elf_out_arch:
129 if (not options.elf_out_arch == '64') and (not options.elf_out_arch == '32'):
130 parser.error('Invalid Output ELF architecture given')
131
132
133 gen_dict = {}
134
135 elf_inp_file1 = options.elf_inp_file1
136
137 # It is valid for only one file to be "merged". This essentially just
138 # strips off the section names. If second file name is not given then
139 # set elf_inp_file2 to ""
140 if options.elf_inp_file2:
141 elf_inp_file2 = options.elf_inp_file2
142 else:
143 elf_inp_file2 = ""
144
145 # Do same for xbl_sec
146 elf_inp_xbl_sec = options.elf_inp_xbl_sec if options.elf_inp_xbl_sec else ""
147
148 binary_out = options.binary_out
149
150 if options.elf_1_arch == '64':
151 is_elf1_64_bit = True
152 else:
153 is_elf1_64_bit = False
154
155 # If second filename is not given then set is_elf2_64_bit to false so it
156 # can be passed even though it is not used.
157 if options.elf_inp_file2:
158 if options.elf_2_arch == '64':
159 is_elf2_64_bit = True
160 else:
161 is_elf2_64_bit = False
162 else:
163 is_elf2_64_bit = False
164
165 if options.elf_inp_xbl_sec:
166 if options.elf_xbl_sec_arch == '64':
167 is_elf_xbl_sec_64_bit = True
168 else:
169 is_elf_xbl_sec_64_bit = False
170 else:
171 is_elf_xbl_sec_64_bit = False
172
173 # If output ELF arch is given then set is_out_elf_64_bit accordingly.
174 # If not then default to be input1's setting
175 if options.elf_out_arch:
176 if options.elf_out_arch == '64':
177 is_out_elf_64_bit = True
178 else:
179 is_out_elf_64_bit = False
180 else:
181 is_out_elf_64_bit = is_elf1_64_bit
182
183
184 # Store ZI Out of Bounds value
185 if not options.zi_oob:
186 zi_oob_enabled = False
187 else:
188 zi_oob_enabled = True
189
T Michael Turneybcd62f52019-08-07 14:26:32 -0700190 header_version = 3
T Michael Turney101098c2018-05-01 15:59:37 -0700191
T Michael Turneybcd62f52019-08-07 14:26:32 -0700192 if options.elf_inp_xbl_sec:
193 header_version = 5
194
195 if options.mbn_version:
196 header_version = options.mbn_version
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530197
198 mbn_type = 'elf'
199 header_format = 'reg'
200 gen_dict['IMAGE_KEY_IMAGE_ID'] = mbn_tools.ImageType.APPSBL_IMG
201 #gen_dict['IMAGE_KEY_IMAGE_SOURCE'] = 0
202 #gen_dict['IMAGE_KEY_IMAGE_DEST'] = 0
203 gen_dict['IMAGE_KEY_MBN_TYPE'] = mbn_type
204 image_header_secflag = 'non_secure'
205
206 source_base = os.path.splitext(str(binary_out))[0]
207 target_base = os.path.splitext(str(binary_out))[0]
208 merged_elf = source_base + "_merged.elf"
209 source_elf = source_base + "_nohash.elf"
210 target_hash = target_base + ".hash"
211 target_hash_hd = target_base + "_hash.hd"
212 target_phdr_elf = target_base + "_phdr.pbn"
213 target_nonsec = target_base + "_combined_hash.mbn"
214
215
T Michael Turney540b8ec2020-01-24 08:42:47 -0800216 #print("Input file 1:", elf_inp_file1)
217 #print("Input file 2:", elf_inp_file2)
218 #print("Output file:", binary_out)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530219
220 merge_elfs([],
221 elf_inp_file1,
222 elf_inp_file2,
223 elf_inp_xbl_sec,
224 merged_elf,
225 is_elf1_64_bit,
226 is_elf2_64_bit,
227 is_elf_xbl_sec_64_bit,
228 is_out_elf_64_bit,
T Michael Turney101098c2018-05-01 15:59:37 -0700229 zi_oob_enabled,
T Michael Turneybcd62f52019-08-07 14:26:32 -0700230 header_version)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530231
232
233 # Hash the image if user did not explicitly say not to
234 if options.hash_image:
235 # Just copy the merged elf to the final output name
236 shutil.move(merged_elf, binary_out)
237 else:
238 shutil.copy(merged_elf, source_elf)
239
240 # Create hash table
241 rv = mbn_tools.pboot_gen_elf([],
242 source_elf,
243 target_hash,
244 elf_out_file_name = target_phdr_elf,
T Michael Turneybcd62f52019-08-07 14:26:32 -0700245 secure_type = image_header_secflag,
246 header_version = header_version )
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530247 if rv:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800248 raise RuntimeError("Failed to run pboot_gen_elf")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530249
250 # Create hash table header
251 rv = mbn_tools.image_header([],
252 gen_dict,
253 target_hash,
254 target_hash_hd,
255 image_header_secflag,
T Michael Turneybcd62f52019-08-07 14:26:32 -0700256 elf_file_name = source_elf,
257 header_version = header_version)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530258 if rv:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800259 raise RuntimeError("Failed to create image header for hash segment")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530260
261 files_to_cat_in_order = [target_hash_hd, target_hash]
262 mbn_tools.concat_files (target_nonsec, files_to_cat_in_order)
263
264 # Add the hash segment into the ELF
265 mbn_tools.pboot_add_hash([],
266 target_phdr_elf,
267 target_nonsec,
268 binary_out)
269
270 return
271
272
273##############################################################################
274# roundup
275##############################################################################
276def roundup(x, precision):
277 return x if x % precision == 0 else (x + precision - (x % precision))
278
279##############################################################################
280# merge_elfs
281##############################################################################
282def merge_elfs(env,
283 elf_in_file_name1,
284 elf_in_file_name2,
285 elf_in_file_xbl_sec,
286 elf_out_file_name,
287 is_elf1_64_bit,
288 is_elf2_64_bit,
289 is_elf_xbl_sec_64_bit,
290 is_out_elf_64_bit,
T Michael Turney101098c2018-05-01 15:59:37 -0700291 zi_oob_enabled,
T Michael Turneybcd62f52019-08-07 14:26:32 -0700292 header_version):
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530293
294 [elf_header1, phdr_table1] = \
295 mbn_tools.preprocess_elf_file(elf_in_file_name1)
296
297 # Check to make sure second file path exists before using
298 if elf_in_file_name2 != "":
299 [elf_header2, phdr_table2] = \
300 mbn_tools.preprocess_elf_file(elf_in_file_name2)
301
302 # Check to make sure xbl_sec file path exists before using
303 if elf_in_file_xbl_sec != "":
304 [elf_headerxblsec, phdr_tablexblsec] = \
305 mbn_tools.preprocess_elf_file(elf_in_file_xbl_sec)
306
307 # Open Files
308 elf_in_fp1 = mbn_tools.OPEN(elf_in_file_name1, "rb")
309 if elf_in_file_name2 != "":
310 elf_in_fp2 = mbn_tools.OPEN(elf_in_file_name2, "rb")
311 if elf_in_file_xbl_sec != "":
312 elf_in_fpxblsec = mbn_tools.OPEN(elf_in_file_xbl_sec, "rb")
313
314 if elf_out_file_name is not None:
315 elf_out_fp = mbn_tools.OPEN(elf_out_file_name, "wb+")
316
317
318 # Calculate the new program header size. This is dependant on the output
319 # ELF type and number of program headers going into output.
320 if is_out_elf_64_bit:
321 phdr_total_size = elf_header1.e_phnum * ELF64_PHDR_SIZE
322 phdr_total_count = elf_header1.e_phnum
323 else:
324 phdr_total_size = elf_header1.e_phnum * ELF32_PHDR_SIZE
325 phdr_total_count = elf_header1.e_phnum
326
327
328 # This logic only applies if two files are to be merged
329 if elf_in_file_name2 != "":
330 if is_out_elf_64_bit:
331 phdr_total_size += elf_header2.e_phnum * ELF64_PHDR_SIZE
332 phdr_total_count += elf_header2.e_phnum
333 else:
334 phdr_total_size += elf_header2.e_phnum * ELF32_PHDR_SIZE
335 phdr_total_count += elf_header2.e_phnum
336
337 # Account for xbl_sec header if included
338 if elf_in_file_xbl_sec != "":
339 phdr_total_count += 1
340 if is_out_elf_64_bit:
341 phdr_total_size += ELF64_PHDR_SIZE
342 else:
343 phdr_total_size += ELF32_PHDR_SIZE
344
345 # Create a new ELF header for the output file
346 if is_out_elf_64_bit:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800347 out_elf_header = mbn_tools.Elf64_Ehdr(b'\0' * ELF64_HDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530348 out_elf_header.e_phoff = ELF64_HDR_SIZE
349 out_elf_header.e_ehsize = ELF64_HDR_SIZE
350 out_elf_header.e_phentsize = ELF64_PHDR_SIZE
351 out_elf_header.e_machine = 183
352 out_elf_header.e_ident = str('\x7f' + 'E' + 'L' + 'F' + \
353 '\x02' + \
354 '\x01' + \
355 '\x01' + \
356 '\x00' + \
357 '\x00' + \
358 ('\x00' * 7))
359
360 out_elf_header.e_entry = elf_header1.e_entry
361 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800362 out_elf_header = mbn_tools.Elf32_Ehdr(b'\0' * ELF32_HDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530363 out_elf_header.e_phoff = ELF32_HDR_SIZE
364 out_elf_header.e_ehsize = ELF32_HDR_SIZE
365 out_elf_header.e_phentsize = ELF32_PHDR_SIZE
366 out_elf_header.e_machine = 40
367 out_elf_header.e_entry = elf_header1.e_entry
368 out_elf_header.e_ident = str('\x7f' + 'E' + 'L' + 'F' + \
369 '\x01' + \
370 '\x01' + \
371 '\x01' + \
372 '\x00' + \
373 '\x00' + \
374 ('\x00' * 7))
375
376 # Address needs to be verified that it is not greater than 32 bits
377 # as it is possible to go from a 64 bit elf to 32.
378 if (elf_header1.e_entry > 0xFFFFFFFF):
T Michael Turney540b8ec2020-01-24 08:42:47 -0800379 print("ERROR: File 1's entry point is too large to convert.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530380 exit()
381 out_elf_header.e_entry = elf_header1.e_entry
382
383 # Common header entries
384 out_elf_header.e_type = 2
385 out_elf_header.e_version = 1
386 out_elf_header.e_shoff = 0
387 out_elf_header.e_flags = 0
388 out_elf_header.e_shentsize = 0
389 out_elf_header.e_shnum = 0
390 out_elf_header.e_shstrndx = 0
391
392
393 # If ZI OOB is enabled then it is possible that a segment could be discarded
394 # Scan for that instance and handle before setting e_phnum and writing header
395 # Ensure ELF output is 32 bit
396 if zi_oob_enabled == True and is_out_elf_64_bit == False:
397 for i in range(len(phdr_table1)):
398 if (phdr_table1[i].p_vaddr > 0xFFFFFFFF) or \
399 (phdr_table1[i].p_paddr > 0xFFFFFFFF):
400 if phdr_table1[i].p_filesz == 0:
401 phdr_total_count = phdr_total_count - 1
402
403 if elf_in_file_name2 != "":
404 for i in range(len(phdr_table2)):
405 if (phdr_table2[i].p_vaddr > 0xFFFFFFFF) or \
406 (phdr_table2[i].p_paddr > 0xFFFFFFFF):
407 if phdr_table2[i].p_filesz == 0:
408 phdr_total_count = phdr_total_count - 1
409 # Do not include xbl_sec in above calculation
410 # xbl_sec is to be treated as a single blob
411
412
413 # Now it is ok to populate the ELF header and write it out
414 out_elf_header.e_phnum = phdr_total_count
415
416 # write elf header
417 if is_out_elf_64_bit == False:
418 elf_out_fp.write(mbn_tools.Elf32_Ehdr.getPackedData(out_elf_header))
419 else:
420 elf_out_fp.write(mbn_tools.Elf64_Ehdr.getPackedData(out_elf_header))
421
422 phdr_offset = out_elf_header.e_phoff # offset of where to put next phdr
423
424 # offset the start of the segments just after the program headers
425 segment_offset = roundup(out_elf_header.e_phoff + phdr_total_size, PAGE_SIZE)
426
427
428 # Output first elf data
429 for i in range(elf_header1.e_phnum):
430 curr_phdr = phdr_table1[i]
431
432 # Copy program header piece by piece to ensure possible conversion success
433 if is_out_elf_64_bit == True:
434 # Converting from 32 to 64 elf requires no data size validation
T Michael Turney540b8ec2020-01-24 08:42:47 -0800435 new_phdr = mbn_tools.Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530436 new_phdr.p_type = curr_phdr.p_type
437 new_phdr.p_offset = segment_offset
438 new_phdr.p_vaddr = curr_phdr.p_vaddr
439 new_phdr.p_paddr = curr_phdr.p_paddr
440 new_phdr.p_filesz = curr_phdr.p_filesz
441 new_phdr.p_memsz = curr_phdr.p_memsz
442 new_phdr.p_flags = curr_phdr.p_flags
443 new_phdr.p_align = curr_phdr.p_align
444 else:
445 # Converting from 64 to 32 elf requires data size validation
446 # Note that there is an option to discard a segment if it is only ZI
447 # and its address is greater than 32 bits
T Michael Turney540b8ec2020-01-24 08:42:47 -0800448 new_phdr = mbn_tools.Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530449 new_phdr.p_type = curr_phdr.p_type
450 new_phdr.p_offset = segment_offset
451
452 if curr_phdr.p_vaddr > 0xFFFFFFFF:
453 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
454 continue
455 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800456 print("ERROR: File 1 VAddr is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530457 exit()
458 new_phdr.p_vaddr = curr_phdr.p_vaddr
459
460 if curr_phdr.p_paddr > 0xFFFFFFFF:
461 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
462 continue
463 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800464 print("ERROR: File 1 PAddr is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530465 exit()
466 new_phdr.p_paddr = curr_phdr.p_paddr
467
468 if curr_phdr.p_filesz > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800469 print("ERROR: File 1 Filesz is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530470 exit()
471 new_phdr.p_filesz = curr_phdr.p_filesz
472
473 if curr_phdr.p_memsz > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800474 print("ERROR: File 1 Memsz is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530475 exit()
476 new_phdr.p_memsz = curr_phdr.p_memsz
477
478 if curr_phdr.p_flags > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800479 print("ERROR: File 1 Flags is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530480 exit()
481 new_phdr.p_flags = curr_phdr.p_flags
482
483 if curr_phdr.p_align > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800484 print("ERROR: File 1 Align is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530485 exit()
486 new_phdr.p_align = curr_phdr.p_align
487
488
T Michael Turney540b8ec2020-01-24 08:42:47 -0800489 #print("i=",i)
490 #print("phdr_offset=", phdr_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530491
492 # update output file location to next phdr location
493 elf_out_fp.seek(phdr_offset)
494 # increment phdr_offset to next location
495 phdr_offset += out_elf_header.e_phentsize
496
497 inp_data_offset = curr_phdr.p_offset # used to read data from input file
498
T Michael Turney540b8ec2020-01-24 08:42:47 -0800499# print("inp_data_offset=")
500# print(inp_data_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530501#
T Michael Turney540b8ec2020-01-24 08:42:47 -0800502# print("curr_phdr.p_offset=")
503# print(curr_phdr.p_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530504#
T Michael Turney540b8ec2020-01-24 08:42:47 -0800505# print("curr_phdr.p_filesz=")
506# print(curr_phdr.p_filesz)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530507
508 # output current phdr
509 if is_out_elf_64_bit == False:
510 elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr))
511 else:
512 elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr))
513
514 # Copy the ELF segment
515 bytes_written = mbn_tools.file_copy_offset(elf_in_fp1,
516 inp_data_offset,
517 elf_out_fp,
518 new_phdr.p_offset,
519 new_phdr.p_filesz)
520
521 # update data segment offset to be aligned after previous segment
522 segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN);
523 elf_in_fp1.close()
524
525 # Output second elf data if applicable
526 if elf_in_file_name2 != "":
527 for i in range(elf_header2.e_phnum):
528 curr_phdr = phdr_table2[i]
529
530 # Copy program header piece by piece to ensure possible conversion success
531 if is_out_elf_64_bit == True:
532 # Converting from 32 to 64 elf requires no data size validation
T Michael Turney540b8ec2020-01-24 08:42:47 -0800533 new_phdr = mbn_tools.Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530534 new_phdr.p_type = curr_phdr.p_type
535 new_phdr.p_offset = segment_offset
536 new_phdr.p_vaddr = curr_phdr.p_vaddr
537 new_phdr.p_paddr = curr_phdr.p_paddr
538 new_phdr.p_filesz = curr_phdr.p_filesz
539 new_phdr.p_memsz = curr_phdr.p_memsz
540 new_phdr.p_flags = curr_phdr.p_flags
541 new_phdr.p_align = curr_phdr.p_align
542 else:
543 # Converting from 64 to 32 elf requires data size validation
544 # Note that there is an option to discard a segment if it is only ZI
545 # and its address is greater than 32 bits
T Michael Turney540b8ec2020-01-24 08:42:47 -0800546 new_phdr = mbn_tools.Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530547 new_phdr.p_type = curr_phdr.p_type
548 new_phdr.p_offset = segment_offset
549
550 if curr_phdr.p_vaddr > 0xFFFFFFFF:
551 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
552 continue
553 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800554 print("ERROR: File 2 VAddr is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530555 exit()
556 new_phdr.p_vaddr = curr_phdr.p_vaddr
557
558 if curr_phdr.p_paddr > 0xFFFFFFFF:
559 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
560 continue
561 else:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800562 print("ERROR: File 2 PAddr is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530563 exit()
564 new_phdr.p_paddr = curr_phdr.p_paddr
565
566 if curr_phdr.p_filesz > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800567 print("ERROR: File 2 Filesz is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530568 exit()
569 new_phdr.p_filesz = curr_phdr.p_filesz
570
571 if curr_phdr.p_memsz > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800572 print("ERROR: File 2 Memsz is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530573 exit()
574 new_phdr.p_memsz = curr_phdr.p_memsz
575
576 if curr_phdr.p_flags > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800577 print("ERROR: File 2 Flags is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530578 exit()
579 new_phdr.p_flags = curr_phdr.p_flags
580
581 if curr_phdr.p_align > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800582 print("ERROR: File 2 Align is too large for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530583 exit()
584 new_phdr.p_align = curr_phdr.p_align
585
586
T Michael Turney540b8ec2020-01-24 08:42:47 -0800587# print("i=",i)
588# print("phdr_offset=", phdr_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530589
590 # update output file location to next phdr location
591 elf_out_fp.seek(phdr_offset)
592 # increment phdr_offset to next location
593 phdr_offset += out_elf_header.e_phentsize
594
595 inp_data_offset = curr_phdr.p_offset # used to read data from input file
596
T Michael Turney540b8ec2020-01-24 08:42:47 -0800597# print("inp_data_offset=")
598# print(inp_data_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530599#
T Michael Turney540b8ec2020-01-24 08:42:47 -0800600# print("curr_phdr.p_offset=")
601# print(curr_phdr.p_offset)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530602#
T Michael Turney540b8ec2020-01-24 08:42:47 -0800603# print("curr_phdr.p_filesz=")
604# print(curr_phdr.p_filesz)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530605
606 # output current phdr
607 if is_out_elf_64_bit == False:
608 elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr))
609 else:
610 elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr))
611
612 # Copy the ELF segment
613 bytes_written = mbn_tools.file_copy_offset(elf_in_fp2,
614 inp_data_offset,
615 elf_out_fp,
616 new_phdr.p_offset,
617 new_phdr.p_filesz)
618
619 # update data segment offset to be aligned after previous segment
620 segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN);
621 elf_in_fp2.close()
622
623 # Embed xbl_sec image if provided
624 if elf_in_file_xbl_sec != "":
625
626 # Scan pheaders in xbl_sec for segment that contains entry point address
627 entry_seg_offset = -1
628 entry_addr = elf_headerxblsec.e_entry
629 for i in range(elf_headerxblsec.e_phnum):
630 phdr = phdr_tablexblsec[i]
631 max_addr = phdr.p_vaddr + phdr.p_memsz
632 if phdr.p_vaddr <= entry_addr <= max_addr:
633 entry_seg_offset = phdr.p_offset
634 break
635 if entry_seg_offset == -1:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800636 print("Error: Failed to find entry point in any segment!")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530637 exit()
638 # magical equation for program header's phys and virt addr
639 phys_virt_addr = entry_addr - entry_seg_offset
640
641 if is_out_elf_64_bit:
642 # Converting from 32 to 64 elf requires no data size validation
T Michael Turney540b8ec2020-01-24 08:42:47 -0800643 new_phdr = mbn_tools.Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530644 new_phdr.p_type = 0x1
645 new_phdr.p_offset = segment_offset
646 new_phdr.p_vaddr = phys_virt_addr
647 new_phdr.p_paddr = phys_virt_addr
648 new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec)
649 new_phdr.p_memsz = new_phdr.p_filesz
T Michael Turneybcd62f52019-08-07 14:26:32 -0700650 if header_version >= 5:
651 new_phdr.p_flags = (0x5 |
652 (mbn_tools.MI_PBT_XBL_SEC_SEGMENT <<
653 mbn_tools.MI_PBT_FLAG_SEGMENT_TYPE_SHIFT));
T Michael Turney101098c2018-05-01 15:59:37 -0700654 else:
T Michael Turneybcd62f52019-08-07 14:26:32 -0700655 new_phdr.p_flags = 0x5
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530656 new_phdr.p_align = 0x1000
657 else:
658 # Converting from 64 to 32 elf requires data size validation
659 # Don't discard the segment containing xbl_sec, simply error out
660 # if the address is greater than 32 bits
T Michael Turney540b8ec2020-01-24 08:42:47 -0800661 new_phdr = mbn_tools.Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE)
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530662 new_phdr.p_type = 0x1 #
663 new_phdr.p_offset = segment_offset
T Michael Turneybcd62f52019-08-07 14:26:32 -0700664 if header_version >= 5:
665 new_phdr.p_flags = (0x5 |
666 (mbn_tools.MI_PBT_XBL_SEC_SEGMENT <<
667 mbn_tools.MI_PBT_FLAG_SEGMENT_TYPE_SHIFT));
T Michael Turney101098c2018-05-01 15:59:37 -0700668 else:
T Michael Turneybcd62f52019-08-07 14:26:32 -0700669 new_phdr.p_flags = 0x5
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530670 new_phdr.p_align = 0x1000
671
672 if phys_virt_addr > 0xFFFFFFFF:
673 if zi_oob_enabled == False or curr_phdr.p_filesz != 0:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800674 print("ERROR: File xbl_sec VAddr or PAddr is too big for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530675 exit()
676 new_phdr.p_vaddr = phys_virt_addr
677 new_phdr.p_paddr = phys_virt_addr
678
679 if os.path.getsize(elf_in_file_xbl_sec) > 0xFFFFFFFF:
T Michael Turney540b8ec2020-01-24 08:42:47 -0800680 print("ERROR: File xbl_sec Filesz is too big for conversion.")
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +0530681 exit()
682 new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec)
683 new_phdr.p_memsz = new_phdr.p_filesz
684
685
686 # update output file location to next phdr location
687 elf_out_fp.seek(phdr_offset)
688 # increment phdr_offset to next location
689 phdr_offset += out_elf_header.e_phentsize
690 # Copy entire xbl_sec file, so start from byte 0
691 inp_data_offset = 0
692
693 # Output xbl_sec's phdr
694 elf_in_file_xbl_sec
695 if is_out_elf_64_bit == False:
696 elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr))
697 else:
698 elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr))
699
700 # Copy the ENTIRE xbl_sec image
701 bytes_written = mbn_tools.file_copy_offset(elf_in_fpxblsec,
702 inp_data_offset,
703 elf_out_fp,
704 new_phdr.p_offset,
705 new_phdr.p_filesz)
706 # update data segment offset to be aligned after previous segment
707 # Not necessary, unless appending more pheaders after this point
708 segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN);
709
710 elf_in_fpxblsec.close()
711
712 elf_out_fp.close()
713
714 return 0
715
716
717main()