blob: b01e628544fb67e5268a0741b0ecdbf962167e51 [file] [log] [blame]
Varadarajan Narayanan2dfbd932016-04-21 16:06:06 +05301#!/usr/bin/python
2#============================================================================
3#
4#/** @file createxbl.py
5#
6# GENERAL DESCRIPTION
7# Concatentates XBL segments into one ELF image
8#
9# Copyright (c) 2016, The Linux Foundation. All rights reserved.
10#
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# -------- --- ------------------------------------------------------
47# 09/04/15 et Added -x and -d to embed xbl_sec ELF
48# 02/11/15 ck Fixed missing elf type check in ZI OOB feature
49# 11/04/14 ck Updated calls to mbn_tools functions
50# 10/22/14 ck Added -z option to remove out of bounds ZI segments when converting from 64 to 32
51# 10/10/14 ck Added -c option and logic to enable elf type swapping
52# 09/12/14 ck Added single file logic
53# 08/29/14 ck Added no_hash option
54# 08/29/14 ck Refactored to use proper python arguments and cleaned code
55# 06/16/14 niting xbl.mbn to xbl.elf
56# 05/28/14 niting Initial revision
57#
58#============================================================================
59from optparse import OptionParser
60import os
61import sys
62import shutil
63import mbn_tools
64
65PAGE_SIZE = 4096
66SEGMENT_ALIGN = 16
67ELF32_HDR_SIZE = 52
68ELF32_PHDR_SIZE = 32
69ELF64_HDR_SIZE = 64
70ELF64_PHDR_SIZE = 56
71
72
73##############################################################################
74# main
75##############################################################################
76def main():
77 parser = OptionParser(usage='usage: %prog [options] arguments')
78
79 parser.add_option("-f", "--first_filepath",
80 action="store", type="string", dest="elf_inp_file1",
81 help="First ELF file to merge.")
82
83 parser.add_option("-s", "--second_filepath",
84 action="store", type="string", dest="elf_inp_file2",
85 help="Second ELF file to merge.")
86
87 parser.add_option("-x", "--xbl_sec_filepath",
88 action="store", type="string", dest="elf_inp_xbl_sec",
89 help="Second ELF file to merge.")
90
91 parser.add_option("-o", "--output_filepath",
92 action="store", type="string", dest="binary_out",
93 help="Merged filename and path.")
94
95 parser.add_option("-a", "--first_elf_arch",
96 action="store", type="string", dest="elf_1_arch",
97 help="First (and output) ELF file architecture. '32' or '64'")
98
99 parser.add_option("-b", "--second_elf_arch",
100 action="store", type="string", dest="elf_2_arch",
101 help="Second ELF file architecture. '32' or '64'")
102
103 parser.add_option("-d", "--xbl_sec_elf_arch",
104 action="store", type="string", dest="elf_xbl_sec_arch",
105 help="xbl_sec file architecture. '32' or '64'")
106
107 parser.add_option("-c", "--output_elf_arch",
108 action="store", type="string", dest="elf_out_arch",
109 help="Output ELF file architecture. '32' or '64'" + \
110 " If not given defaults to first file arch.")
111
112 parser.add_option("-n", "--no_hash",
113 action="store_true", dest="hash_image",
114 help="Disables hashing of image after merging.")
115
116 parser.add_option("-z", "--zi_out_of_bounds",
117 action="store_true", dest="zi_oob",
118 help="Removes ZI segments that have addresses greater" + \
119 " than 32 bits when converting from a 64 to 32 bit ELF")
120
121
122 (options, args) = parser.parse_args()
123 if not options.elf_inp_file1:
124 parser.error('First ELF filename not given')
125
126 if not options.binary_out:
127 parser.error('Output filename not given')
128
129 if not options.elf_1_arch:
130 parser.error('First ELF architecture not given')
131
132 if (not options.elf_1_arch == '64') and (not options.elf_1_arch == '32'):
133 parser.error('Invalid First ELF architecture given')
134
135 # Only evaluate elf_2_arch if two files are given for merging
136 if options.elf_inp_file2:
137 if (not options.elf_2_arch == '64') and (not options.elf_2_arch == '32'):
138 parser.error('Invalid Second ELF architecture given')
139
140 # Only evaluate elf_xbl_sec_arch if file is given
141 if options.elf_inp_xbl_sec:
142 if (not options.elf_xbl_sec_arch == '64') and (not options.elf_xbl_sec_arch == '32'):
143 parser.error('Invalid xbl_sec ELF architecture given')
144
145 # If output file architecture is given ensure it is either '32' or '64'
146 if options.elf_out_arch:
147 if (not options.elf_out_arch == '64') and (not options.elf_out_arch == '32'):
148 parser.error('Invalid Output ELF architecture given')
149
150
151 gen_dict = {}
152
153 elf_inp_file1 = options.elf_inp_file1
154
155 # It is valid for only one file to be "merged". This essentially just
156 # strips off the section names. If second file name is not given then
157 # set elf_inp_file2 to ""
158 if options.elf_inp_file2:
159 elf_inp_file2 = options.elf_inp_file2
160 else:
161 elf_inp_file2 = ""
162
163 # Do same for xbl_sec
164 elf_inp_xbl_sec = options.elf_inp_xbl_sec if options.elf_inp_xbl_sec else ""
165
166 binary_out = options.binary_out
167
168 if options.elf_1_arch == '64':
169 is_elf1_64_bit = True
170 else:
171 is_elf1_64_bit = False
172
173 # If second filename is not given then set is_elf2_64_bit to false so it
174 # can be passed even though it is not used.
175 if options.elf_inp_file2:
176 if options.elf_2_arch == '64':
177 is_elf2_64_bit = True
178 else:
179 is_elf2_64_bit = False
180 else:
181 is_elf2_64_bit = False
182
183 if options.elf_inp_xbl_sec:
184 if options.elf_xbl_sec_arch == '64':
185 is_elf_xbl_sec_64_bit = True
186 else:
187 is_elf_xbl_sec_64_bit = False
188 else:
189 is_elf_xbl_sec_64_bit = False
190
191 # If output ELF arch is given then set is_out_elf_64_bit accordingly.
192 # If not then default to be input1's setting
193 if options.elf_out_arch:
194 if options.elf_out_arch == '64':
195 is_out_elf_64_bit = True
196 else:
197 is_out_elf_64_bit = False
198 else:
199 is_out_elf_64_bit = is_elf1_64_bit
200
201
202 # Store ZI Out of Bounds value
203 if not options.zi_oob:
204 zi_oob_enabled = False
205 else:
206 zi_oob_enabled = True
207
208
209 mbn_type = 'elf'
210 header_format = 'reg'
211 gen_dict['IMAGE_KEY_IMAGE_ID'] = mbn_tools.ImageType.APPSBL_IMG
212 #gen_dict['IMAGE_KEY_IMAGE_SOURCE'] = 0
213 #gen_dict['IMAGE_KEY_IMAGE_DEST'] = 0
214 gen_dict['IMAGE_KEY_MBN_TYPE'] = mbn_type
215 image_header_secflag = 'non_secure'
216
217 source_base = os.path.splitext(str(binary_out))[0]
218 target_base = os.path.splitext(str(binary_out))[0]
219 merged_elf = source_base + "_merged.elf"
220 source_elf = source_base + "_nohash.elf"
221 target_hash = target_base + ".hash"
222 target_hash_hd = target_base + "_hash.hd"
223 target_phdr_elf = target_base + "_phdr.pbn"
224 target_nonsec = target_base + "_combined_hash.mbn"
225
226
227 #print "Input file 1:", elf_inp_file1
228 #print "Input file 2:", elf_inp_file2
229 #print "Output file:", binary_out
230
231 merge_elfs([],
232 elf_inp_file1,
233 elf_inp_file2,
234 elf_inp_xbl_sec,
235 merged_elf,
236 is_elf1_64_bit,
237 is_elf2_64_bit,
238 is_elf_xbl_sec_64_bit,
239 is_out_elf_64_bit,
240 zi_oob_enabled)
241
242
243 # Hash the image if user did not explicitly say not to
244 if options.hash_image:
245 # Just copy the merged elf to the final output name
246 shutil.move(merged_elf, binary_out)
247 else:
248 shutil.copy(merged_elf, source_elf)
249
250 # Create hash table
251 rv = mbn_tools.pboot_gen_elf([],
252 source_elf,
253 target_hash,
254 elf_out_file_name = target_phdr_elf,
255 secure_type = image_header_secflag)
256 if rv:
257 raise RuntimeError, "Failed to run pboot_gen_elf"
258
259 # Create hash table header
260 rv = mbn_tools.image_header([],
261 gen_dict,
262 target_hash,
263 target_hash_hd,
264 image_header_secflag,
265 elf_file_name = source_elf)
266 if rv:
267 raise RuntimeError, "Failed to create image header for hash segment"
268
269 files_to_cat_in_order = [target_hash_hd, target_hash]
270 mbn_tools.concat_files (target_nonsec, files_to_cat_in_order)
271
272 # Add the hash segment into the ELF
273 mbn_tools.pboot_add_hash([],
274 target_phdr_elf,
275 target_nonsec,
276 binary_out)
277
278 return
279
280
281##############################################################################
282# roundup
283##############################################################################
284def roundup(x, precision):
285 return x if x % precision == 0 else (x + precision - (x % precision))
286
287##############################################################################
288# merge_elfs
289##############################################################################
290def merge_elfs(env,
291 elf_in_file_name1,
292 elf_in_file_name2,
293 elf_in_file_xbl_sec,
294 elf_out_file_name,
295 is_elf1_64_bit,
296 is_elf2_64_bit,
297 is_elf_xbl_sec_64_bit,
298 is_out_elf_64_bit,
299 zi_oob_enabled):
300
301 [elf_header1, phdr_table1] = \
302 mbn_tools.preprocess_elf_file(elf_in_file_name1)
303
304 # Check to make sure second file path exists before using
305 if elf_in_file_name2 != "":
306 [elf_header2, phdr_table2] = \
307 mbn_tools.preprocess_elf_file(elf_in_file_name2)
308
309 # Check to make sure xbl_sec file path exists before using
310 if elf_in_file_xbl_sec != "":
311 [elf_headerxblsec, phdr_tablexblsec] = \
312 mbn_tools.preprocess_elf_file(elf_in_file_xbl_sec)
313
314 # Open Files
315 elf_in_fp1 = mbn_tools.OPEN(elf_in_file_name1, "rb")
316 if elf_in_file_name2 != "":
317 elf_in_fp2 = mbn_tools.OPEN(elf_in_file_name2, "rb")
318 if elf_in_file_xbl_sec != "":
319 elf_in_fpxblsec = mbn_tools.OPEN(elf_in_file_xbl_sec, "rb")
320
321 if elf_out_file_name is not None:
322 elf_out_fp = mbn_tools.OPEN(elf_out_file_name, "wb+")
323
324
325 # Calculate the new program header size. This is dependant on the output
326 # ELF type and number of program headers going into output.
327 if is_out_elf_64_bit:
328 phdr_total_size = elf_header1.e_phnum * ELF64_PHDR_SIZE
329 phdr_total_count = elf_header1.e_phnum
330 else:
331 phdr_total_size = elf_header1.e_phnum * ELF32_PHDR_SIZE
332 phdr_total_count = elf_header1.e_phnum
333
334
335 # This logic only applies if two files are to be merged
336 if elf_in_file_name2 != "":
337 if is_out_elf_64_bit:
338 phdr_total_size += elf_header2.e_phnum * ELF64_PHDR_SIZE
339 phdr_total_count += elf_header2.e_phnum
340 else:
341 phdr_total_size += elf_header2.e_phnum * ELF32_PHDR_SIZE
342 phdr_total_count += elf_header2.e_phnum
343
344 # Account for xbl_sec header if included
345 if elf_in_file_xbl_sec != "":
346 phdr_total_count += 1
347 if is_out_elf_64_bit:
348 phdr_total_size += ELF64_PHDR_SIZE
349 else:
350 phdr_total_size += ELF32_PHDR_SIZE
351
352 # Create a new ELF header for the output file
353 if is_out_elf_64_bit:
354 out_elf_header = mbn_tools.Elf64_Ehdr('\0' * ELF64_HDR_SIZE)
355 out_elf_header.e_phoff = ELF64_HDR_SIZE
356 out_elf_header.e_ehsize = ELF64_HDR_SIZE
357 out_elf_header.e_phentsize = ELF64_PHDR_SIZE
358 out_elf_header.e_machine = 183
359 out_elf_header.e_ident = str('\x7f' + 'E' + 'L' + 'F' + \
360 '\x02' + \
361 '\x01' + \
362 '\x01' + \
363 '\x00' + \
364 '\x00' + \
365 ('\x00' * 7))
366
367 out_elf_header.e_entry = elf_header1.e_entry
368 else:
369 out_elf_header = mbn_tools.Elf32_Ehdr('\0' * ELF32_HDR_SIZE)
370 out_elf_header.e_phoff = ELF32_HDR_SIZE
371 out_elf_header.e_ehsize = ELF32_HDR_SIZE
372 out_elf_header.e_phentsize = ELF32_PHDR_SIZE
373 out_elf_header.e_machine = 40
374 out_elf_header.e_entry = elf_header1.e_entry
375 out_elf_header.e_ident = str('\x7f' + 'E' + 'L' + 'F' + \
376 '\x01' + \
377 '\x01' + \
378 '\x01' + \
379 '\x00' + \
380 '\x00' + \
381 ('\x00' * 7))
382
383 # Address needs to be verified that it is not greater than 32 bits
384 # as it is possible to go from a 64 bit elf to 32.
385 if (elf_header1.e_entry > 0xFFFFFFFF):
386 print "ERROR: File 1's entry point is too large to convert."
387 exit()
388 out_elf_header.e_entry = elf_header1.e_entry
389
390 # Common header entries
391 out_elf_header.e_type = 2
392 out_elf_header.e_version = 1
393 out_elf_header.e_shoff = 0
394 out_elf_header.e_flags = 0
395 out_elf_header.e_shentsize = 0
396 out_elf_header.e_shnum = 0
397 out_elf_header.e_shstrndx = 0
398
399
400 # If ZI OOB is enabled then it is possible that a segment could be discarded
401 # Scan for that instance and handle before setting e_phnum and writing header
402 # Ensure ELF output is 32 bit
403 if zi_oob_enabled == True and is_out_elf_64_bit == False:
404 for i in range(len(phdr_table1)):
405 if (phdr_table1[i].p_vaddr > 0xFFFFFFFF) or \
406 (phdr_table1[i].p_paddr > 0xFFFFFFFF):
407 if phdr_table1[i].p_filesz == 0:
408 phdr_total_count = phdr_total_count - 1
409
410 if elf_in_file_name2 != "":
411 for i in range(len(phdr_table2)):
412 if (phdr_table2[i].p_vaddr > 0xFFFFFFFF) or \
413 (phdr_table2[i].p_paddr > 0xFFFFFFFF):
414 if phdr_table2[i].p_filesz == 0:
415 phdr_total_count = phdr_total_count - 1
416 # Do not include xbl_sec in above calculation
417 # xbl_sec is to be treated as a single blob
418
419
420 # Now it is ok to populate the ELF header and write it out
421 out_elf_header.e_phnum = phdr_total_count
422
423 # write elf header
424 if is_out_elf_64_bit == False:
425 elf_out_fp.write(mbn_tools.Elf32_Ehdr.getPackedData(out_elf_header))
426 else:
427 elf_out_fp.write(mbn_tools.Elf64_Ehdr.getPackedData(out_elf_header))
428
429 phdr_offset = out_elf_header.e_phoff # offset of where to put next phdr
430
431 # offset the start of the segments just after the program headers
432 segment_offset = roundup(out_elf_header.e_phoff + phdr_total_size, PAGE_SIZE)
433
434
435 # Output first elf data
436 for i in range(elf_header1.e_phnum):
437 curr_phdr = phdr_table1[i]
438
439 # Copy program header piece by piece to ensure possible conversion success
440 if is_out_elf_64_bit == True:
441 # Converting from 32 to 64 elf requires no data size validation
442 new_phdr = mbn_tools.Elf64_Phdr('\0' * ELF64_PHDR_SIZE)
443 new_phdr.p_type = curr_phdr.p_type
444 new_phdr.p_offset = segment_offset
445 new_phdr.p_vaddr = curr_phdr.p_vaddr
446 new_phdr.p_paddr = curr_phdr.p_paddr
447 new_phdr.p_filesz = curr_phdr.p_filesz
448 new_phdr.p_memsz = curr_phdr.p_memsz
449 new_phdr.p_flags = curr_phdr.p_flags
450 new_phdr.p_align = curr_phdr.p_align
451 else:
452 # Converting from 64 to 32 elf requires data size validation
453 # Note that there is an option to discard a segment if it is only ZI
454 # and its address is greater than 32 bits
455 new_phdr = mbn_tools.Elf32_Phdr('\0' * ELF32_PHDR_SIZE)
456 new_phdr.p_type = curr_phdr.p_type
457 new_phdr.p_offset = segment_offset
458
459 if curr_phdr.p_vaddr > 0xFFFFFFFF:
460 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
461 continue
462 else:
463 print "ERROR: File 1 VAddr is too large for conversion."
464 exit()
465 new_phdr.p_vaddr = curr_phdr.p_vaddr
466
467 if curr_phdr.p_paddr > 0xFFFFFFFF:
468 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
469 continue
470 else:
471 print "ERROR: File 1 PAddr is too large for conversion."
472 exit()
473 new_phdr.p_paddr = curr_phdr.p_paddr
474
475 if curr_phdr.p_filesz > 0xFFFFFFFF:
476 print "ERROR: File 1 Filesz is too large for conversion."
477 exit()
478 new_phdr.p_filesz = curr_phdr.p_filesz
479
480 if curr_phdr.p_memsz > 0xFFFFFFFF:
481 print "ERROR: File 1 Memsz is too large for conversion."
482 exit()
483 new_phdr.p_memsz = curr_phdr.p_memsz
484
485 if curr_phdr.p_flags > 0xFFFFFFFF:
486 print "ERROR: File 1 Flags is too large for conversion."
487 exit()
488 new_phdr.p_flags = curr_phdr.p_flags
489
490 if curr_phdr.p_align > 0xFFFFFFFF:
491 print "ERROR: File 1 Align is too large for conversion."
492 exit()
493 new_phdr.p_align = curr_phdr.p_align
494
495
496 #print "i=",i
497 #print "phdr_offset=", phdr_offset
498
499 # update output file location to next phdr location
500 elf_out_fp.seek(phdr_offset)
501 # increment phdr_offset to next location
502 phdr_offset += out_elf_header.e_phentsize
503
504 inp_data_offset = curr_phdr.p_offset # used to read data from input file
505
506# print "inp_data_offset="
507# print inp_data_offset
508#
509# print "curr_phdr.p_offset="
510# print curr_phdr.p_offset
511#
512# print "curr_phdr.p_filesz="
513# print curr_phdr.p_filesz
514
515 # output current phdr
516 if is_out_elf_64_bit == False:
517 elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr))
518 else:
519 elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr))
520
521 # Copy the ELF segment
522 bytes_written = mbn_tools.file_copy_offset(elf_in_fp1,
523 inp_data_offset,
524 elf_out_fp,
525 new_phdr.p_offset,
526 new_phdr.p_filesz)
527
528 # update data segment offset to be aligned after previous segment
529 segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN);
530 elf_in_fp1.close()
531
532 # Output second elf data if applicable
533 if elf_in_file_name2 != "":
534 for i in range(elf_header2.e_phnum):
535 curr_phdr = phdr_table2[i]
536
537 # Copy program header piece by piece to ensure possible conversion success
538 if is_out_elf_64_bit == True:
539 # Converting from 32 to 64 elf requires no data size validation
540 new_phdr = mbn_tools.Elf64_Phdr('\0' * ELF64_PHDR_SIZE)
541 new_phdr.p_type = curr_phdr.p_type
542 new_phdr.p_offset = segment_offset
543 new_phdr.p_vaddr = curr_phdr.p_vaddr
544 new_phdr.p_paddr = curr_phdr.p_paddr
545 new_phdr.p_filesz = curr_phdr.p_filesz
546 new_phdr.p_memsz = curr_phdr.p_memsz
547 new_phdr.p_flags = curr_phdr.p_flags
548 new_phdr.p_align = curr_phdr.p_align
549 else:
550 # Converting from 64 to 32 elf requires data size validation
551 # Note that there is an option to discard a segment if it is only ZI
552 # and its address is greater than 32 bits
553 new_phdr = mbn_tools.Elf32_Phdr('\0' * ELF32_PHDR_SIZE)
554 new_phdr.p_type = curr_phdr.p_type
555 new_phdr.p_offset = segment_offset
556
557 if curr_phdr.p_vaddr > 0xFFFFFFFF:
558 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
559 continue
560 else:
561 print "ERROR: File 2 VAddr is too large for conversion."
562 exit()
563 new_phdr.p_vaddr = curr_phdr.p_vaddr
564
565 if curr_phdr.p_paddr > 0xFFFFFFFF:
566 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
567 continue
568 else:
569 print "ERROR: File 2 PAddr is too large for conversion."
570 exit()
571 new_phdr.p_paddr = curr_phdr.p_paddr
572
573 if curr_phdr.p_filesz > 0xFFFFFFFF:
574 print "ERROR: File 2 Filesz is too large for conversion."
575 exit()
576 new_phdr.p_filesz = curr_phdr.p_filesz
577
578 if curr_phdr.p_memsz > 0xFFFFFFFF:
579 print "ERROR: File 2 Memsz is too large for conversion."
580 exit()
581 new_phdr.p_memsz = curr_phdr.p_memsz
582
583 if curr_phdr.p_flags > 0xFFFFFFFF:
584 print "ERROR: File 2 Flags is too large for conversion."
585 exit()
586 new_phdr.p_flags = curr_phdr.p_flags
587
588 if curr_phdr.p_align > 0xFFFFFFFF:
589 print "ERROR: File 2 Align is too large for conversion."
590 exit()
591 new_phdr.p_align = curr_phdr.p_align
592
593
594# print "i=",i
595# print "phdr_offset=", phdr_offset
596
597 # update output file location to next phdr location
598 elf_out_fp.seek(phdr_offset)
599 # increment phdr_offset to next location
600 phdr_offset += out_elf_header.e_phentsize
601
602 inp_data_offset = curr_phdr.p_offset # used to read data from input file
603
604# print "inp_data_offset="
605# print inp_data_offset
606#
607# print "curr_phdr.p_offset="
608# print curr_phdr.p_offset
609#
610# print "curr_phdr.p_filesz="
611# print curr_phdr.p_filesz
612
613 # output current phdr
614 if is_out_elf_64_bit == False:
615 elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr))
616 else:
617 elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr))
618
619 # Copy the ELF segment
620 bytes_written = mbn_tools.file_copy_offset(elf_in_fp2,
621 inp_data_offset,
622 elf_out_fp,
623 new_phdr.p_offset,
624 new_phdr.p_filesz)
625
626 # update data segment offset to be aligned after previous segment
627 segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN);
628 elf_in_fp2.close()
629
630 # Embed xbl_sec image if provided
631 if elf_in_file_xbl_sec != "":
632
633 # Scan pheaders in xbl_sec for segment that contains entry point address
634 entry_seg_offset = -1
635 entry_addr = elf_headerxblsec.e_entry
636 for i in range(elf_headerxblsec.e_phnum):
637 phdr = phdr_tablexblsec[i]
638 max_addr = phdr.p_vaddr + phdr.p_memsz
639 if phdr.p_vaddr <= entry_addr <= max_addr:
640 entry_seg_offset = phdr.p_offset
641 break
642 if entry_seg_offset == -1:
643 print "Error: Failed to find entry point in any segment!"
644 exit()
645 # magical equation for program header's phys and virt addr
646 phys_virt_addr = entry_addr - entry_seg_offset
647
648 if is_out_elf_64_bit:
649 # Converting from 32 to 64 elf requires no data size validation
650 new_phdr = mbn_tools.Elf64_Phdr('\0' * ELF64_PHDR_SIZE)
651 new_phdr.p_type = 0x1
652 new_phdr.p_offset = segment_offset
653 new_phdr.p_vaddr = phys_virt_addr
654 new_phdr.p_paddr = phys_virt_addr
655 new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec)
656 new_phdr.p_memsz = new_phdr.p_filesz
657 new_phdr.p_flags = 0x5
658 new_phdr.p_align = 0x1000
659 else:
660 # Converting from 64 to 32 elf requires data size validation
661 # Don't discard the segment containing xbl_sec, simply error out
662 # if the address is greater than 32 bits
663 new_phdr = mbn_tools.Elf32_Phdr('\0' * ELF32_PHDR_SIZE)
664 new_phdr.p_type = 0x1 #
665 new_phdr.p_offset = segment_offset
666 new_phdr.p_flags = 0x5
667 new_phdr.p_align = 0x1000
668
669 if phys_virt_addr > 0xFFFFFFFF:
670 if zi_oob_enabled == False or curr_phdr.p_filesz != 0:
671 print "ERROR: File xbl_sec VAddr or PAddr is too large for conversion."
672 exit()
673 new_phdr.p_vaddr = phys_virt_addr
674 new_phdr.p_paddr = phys_virt_addr
675
676 if os.path.getsize(elf_in_file_xbl_sec) > 0xFFFFFFFF:
677 print "ERROR: File xbl_sec Filesz is too large for conversion."
678 exit()
679 new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec)
680 new_phdr.p_memsz = new_phdr.p_filesz
681
682
683 # update output file location to next phdr location
684 elf_out_fp.seek(phdr_offset)
685 # increment phdr_offset to next location
686 phdr_offset += out_elf_header.e_phentsize
687 # Copy entire xbl_sec file, so start from byte 0
688 inp_data_offset = 0
689
690 # Output xbl_sec's phdr
691 elf_in_file_xbl_sec
692 if is_out_elf_64_bit == False:
693 elf_out_fp.write(mbn_tools.Elf32_Phdr.getPackedData(new_phdr))
694 else:
695 elf_out_fp.write(mbn_tools.Elf64_Phdr.getPackedData(new_phdr))
696
697 # Copy the ENTIRE xbl_sec image
698 bytes_written = mbn_tools.file_copy_offset(elf_in_fpxblsec,
699 inp_data_offset,
700 elf_out_fp,
701 new_phdr.p_offset,
702 new_phdr.p_filesz)
703 # update data segment offset to be aligned after previous segment
704 # Not necessary, unless appending more pheaders after this point
705 segment_offset += roundup(new_phdr.p_filesz, SEGMENT_ALIGN);
706
707 elf_in_fpxblsec.close()
708
709 elf_out_fp.close()
710
711 return 0
712
713
714main()