mainboard/dell: Add new mainboard XPS 8300 (Sandy Bridge)
[coreboot.git] / util / qualcomm / createxbl.py
blob97fc9728b4a28e10aae0057904ba8fd57e656461
1 #!/usr/bin/env python3
2 #============================================================================
4 #/** @file createxbl.py
6 # GENERAL DESCRIPTION
7 # Concatentates XBL segments into one ELF image
9 # SPDX-License-Identifier: BSD-3-Clause
11 #**/
13 #----------------------------------------------------------------------------
15 # EDIT HISTORY FOR FILE
17 # This section contains comments describing changes made to the module.
18 # Notice that changes are listed in reverse chronological order.
20 # when who what, where, why
21 # -------- --- ------------------------------------------------------
22 # 05/21/19 rissha Added --mbn_version to add MBN header accordingly
23 # 03/26/18 tv Added -e to enable extended MBNV5 support
24 # 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
27 # 10/22/14 ck Added -z option to remove out of bounds ZI segments when
28 # converting from 64 to 32
29 # 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
36 #============================================================================
37 from optparse import OptionParser
38 import os
39 import sys
40 import shutil
41 import mbn_tools
43 PAGE_SIZE = 4096
44 SEGMENT_ALIGN = 16
45 ELF32_HDR_SIZE = 52
46 ELF32_PHDR_SIZE = 32
47 ELF64_HDR_SIZE = 64
48 ELF64_PHDR_SIZE = 56
51 ##############################################################################
52 # main
53 ##############################################################################
54 def main():
55 parser = OptionParser(usage='usage: %prog [options] arguments')
57 parser.add_option("-f", "--first_filepath",
58 action="store", type="string", dest="elf_inp_file1",
59 help="First ELF file to merge.")
61 parser.add_option("-s", "--second_filepath",
62 action="store", type="string", dest="elf_inp_file2",
63 help="Second ELF file to merge.")
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.")
69 parser.add_option("-o", "--output_filepath",
70 action="store", type="string", dest="binary_out",
71 help="Merged filename and path.")
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'")
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'")
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'")
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.")
90 parser.add_option("-n", "--no_hash",
91 action="store_true", dest="hash_image",
92 help="Disables hashing of image after merging.")
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")
99 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'")
104 (options, args) = parser.parse_args()
105 if not options.elf_inp_file1:
106 parser.error('First ELF filename not given')
108 if not options.binary_out:
109 parser.error('Output filename not given')
111 if not options.elf_1_arch:
112 parser.error('First ELF architecture not given')
114 if (not options.elf_1_arch == '64') and (not options.elf_1_arch == '32'):
115 parser.error('Invalid First ELF architecture given')
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')
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')
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')
133 gen_dict = {}
135 elf_inp_file1 = options.elf_inp_file1
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 = ""
145 # Do same for xbl_sec
146 elf_inp_xbl_sec = options.elf_inp_xbl_sec if options.elf_inp_xbl_sec else ""
148 binary_out = options.binary_out
150 if options.elf_1_arch == '64':
151 is_elf1_64_bit = True
152 else:
153 is_elf1_64_bit = False
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
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
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
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
190 header_version = 3
192 if options.elf_inp_xbl_sec:
193 header_version = 5
195 if options.mbn_version:
196 header_version = options.mbn_version
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'
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"
216 #print("Input file 1:", elf_inp_file1)
217 #print("Input file 2:", elf_inp_file2)
218 #print("Output file:", binary_out)
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,
229 zi_oob_enabled,
230 header_version)
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)
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,
245 secure_type = image_header_secflag,
246 header_version = header_version )
247 if rv:
248 raise RuntimeError("Failed to run pboot_gen_elf")
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,
256 elf_file_name = source_elf,
257 header_version = header_version)
258 if rv:
259 raise RuntimeError("Failed to create image header for hash segment")
261 files_to_cat_in_order = [target_hash_hd, target_hash]
262 mbn_tools.concat_files (target_nonsec, files_to_cat_in_order)
264 # Add the hash segment into the ELF
265 mbn_tools.pboot_add_hash([],
266 target_phdr_elf,
267 target_nonsec,
268 binary_out)
270 return
273 ##############################################################################
274 # roundup
275 ##############################################################################
276 def roundup(x, precision):
277 return x if x % precision == 0 else (x + precision - (x % precision))
279 ##############################################################################
280 # merge_elfs
281 ##############################################################################
282 def 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,
291 zi_oob_enabled,
292 header_version):
294 [elf_header1, phdr_table1] = \
295 mbn_tools.preprocess_elf_file(elf_in_file_name1)
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)
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)
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")
314 if elf_out_file_name is not None:
315 elf_out_fp = mbn_tools.OPEN(elf_out_file_name, "wb+")
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
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
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
345 # Create a new ELF header for the output file
346 if is_out_elf_64_bit:
347 out_elf_header = mbn_tools.Elf64_Ehdr(b'\0' * ELF64_HDR_SIZE)
348 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))
360 out_elf_header.e_entry = elf_header1.e_entry
361 else:
362 out_elf_header = mbn_tools.Elf32_Ehdr(b'\0' * ELF32_HDR_SIZE)
363 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))
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):
379 print("ERROR: File 1's entry point is too large to convert.")
380 exit()
381 out_elf_header.e_entry = elf_header1.e_entry
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
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
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
413 # Now it is ok to populate the ELF header and write it out
414 out_elf_header.e_phnum = phdr_total_count
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))
422 phdr_offset = out_elf_header.e_phoff # offset of where to put next phdr
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)
428 # Output first elf data
429 for i in range(elf_header1.e_phnum):
430 curr_phdr = phdr_table1[i]
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
435 new_phdr = mbn_tools.Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE)
436 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
448 new_phdr = mbn_tools.Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE)
449 new_phdr.p_type = curr_phdr.p_type
450 new_phdr.p_offset = segment_offset
452 if curr_phdr.p_vaddr > 0xFFFFFFFF:
453 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
454 continue
455 else:
456 print("ERROR: File 1 VAddr is too large for conversion.")
457 exit()
458 new_phdr.p_vaddr = curr_phdr.p_vaddr
460 if curr_phdr.p_paddr > 0xFFFFFFFF:
461 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
462 continue
463 else:
464 print("ERROR: File 1 PAddr is too large for conversion.")
465 exit()
466 new_phdr.p_paddr = curr_phdr.p_paddr
468 if curr_phdr.p_filesz > 0xFFFFFFFF:
469 print("ERROR: File 1 Filesz is too large for conversion.")
470 exit()
471 new_phdr.p_filesz = curr_phdr.p_filesz
473 if curr_phdr.p_memsz > 0xFFFFFFFF:
474 print("ERROR: File 1 Memsz is too large for conversion.")
475 exit()
476 new_phdr.p_memsz = curr_phdr.p_memsz
478 if curr_phdr.p_flags > 0xFFFFFFFF:
479 print("ERROR: File 1 Flags is too large for conversion.")
480 exit()
481 new_phdr.p_flags = curr_phdr.p_flags
483 if curr_phdr.p_align > 0xFFFFFFFF:
484 print("ERROR: File 1 Align is too large for conversion.")
485 exit()
486 new_phdr.p_align = curr_phdr.p_align
489 #print("i=",i)
490 #print("phdr_offset=", phdr_offset)
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
497 inp_data_offset = curr_phdr.p_offset # used to read data from input file
499 # print("inp_data_offset=")
500 # print(inp_data_offset)
502 # print("curr_phdr.p_offset=")
503 # print(curr_phdr.p_offset)
505 # print("curr_phdr.p_filesz=")
506 # print(curr_phdr.p_filesz)
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))
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)
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()
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]
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
533 new_phdr = mbn_tools.Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE)
534 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
546 new_phdr = mbn_tools.Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE)
547 new_phdr.p_type = curr_phdr.p_type
548 new_phdr.p_offset = segment_offset
550 if curr_phdr.p_vaddr > 0xFFFFFFFF:
551 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
552 continue
553 else:
554 print("ERROR: File 2 VAddr is too large for conversion.")
555 exit()
556 new_phdr.p_vaddr = curr_phdr.p_vaddr
558 if curr_phdr.p_paddr > 0xFFFFFFFF:
559 if (zi_oob_enabled == True) and (curr_phdr.p_filesz == 0):
560 continue
561 else:
562 print("ERROR: File 2 PAddr is too large for conversion.")
563 exit()
564 new_phdr.p_paddr = curr_phdr.p_paddr
566 if curr_phdr.p_filesz > 0xFFFFFFFF:
567 print("ERROR: File 2 Filesz is too large for conversion.")
568 exit()
569 new_phdr.p_filesz = curr_phdr.p_filesz
571 if curr_phdr.p_memsz > 0xFFFFFFFF:
572 print("ERROR: File 2 Memsz is too large for conversion.")
573 exit()
574 new_phdr.p_memsz = curr_phdr.p_memsz
576 if curr_phdr.p_flags > 0xFFFFFFFF:
577 print("ERROR: File 2 Flags is too large for conversion.")
578 exit()
579 new_phdr.p_flags = curr_phdr.p_flags
581 if curr_phdr.p_align > 0xFFFFFFFF:
582 print("ERROR: File 2 Align is too large for conversion.")
583 exit()
584 new_phdr.p_align = curr_phdr.p_align
587 # print("i=",i)
588 # print("phdr_offset=", phdr_offset)
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
595 inp_data_offset = curr_phdr.p_offset # used to read data from input file
597 # print("inp_data_offset=")
598 # print(inp_data_offset)
600 # print("curr_phdr.p_offset=")
601 # print(curr_phdr.p_offset)
603 # print("curr_phdr.p_filesz=")
604 # print(curr_phdr.p_filesz)
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))
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)
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()
623 # Embed xbl_sec image if provided
624 if elf_in_file_xbl_sec != "":
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:
636 print("Error: Failed to find entry point in any segment!")
637 exit()
638 # magical equation for program header's phys and virt addr
639 phys_virt_addr = entry_addr - entry_seg_offset
641 if is_out_elf_64_bit:
642 # Converting from 32 to 64 elf requires no data size validation
643 new_phdr = mbn_tools.Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE)
644 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
650 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));
654 else:
655 new_phdr.p_flags = 0x5
656 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
661 new_phdr = mbn_tools.Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE)
662 new_phdr.p_type = 0x1 #
663 new_phdr.p_offset = segment_offset
664 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));
668 else:
669 new_phdr.p_flags = 0x5
670 new_phdr.p_align = 0x1000
672 if phys_virt_addr > 0xFFFFFFFF:
673 if zi_oob_enabled == False or curr_phdr.p_filesz != 0:
674 print("ERROR: File xbl_sec VAddr or PAddr is too big for conversion.")
675 exit()
676 new_phdr.p_vaddr = phys_virt_addr
677 new_phdr.p_paddr = phys_virt_addr
679 if os.path.getsize(elf_in_file_xbl_sec) > 0xFFFFFFFF:
680 print("ERROR: File xbl_sec Filesz is too big for conversion.")
681 exit()
682 new_phdr.p_filesz = os.path.getsize(elf_in_file_xbl_sec)
683 new_phdr.p_memsz = new_phdr.p_filesz
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
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))
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);
710 elf_in_fpxblsec.close()
712 elf_out_fp.close()
714 return 0
717 main()