1#!/usr/bin/env python3 2#============================================================================ 3# 4#/** @file createxbl.py 5# 6# GENERAL DESCRIPTION 7# Concatentates XBL segments into one ELF image 8# 9# SPDX-License-Identifier: BSD-3-Clause 10 11#**/ 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# -------- --- ------------------------------------------------------ 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 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 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'") 102 103 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 190 header_version = 3 191 192 if options.elf_inp_xbl_sec: 193 header_version = 5 194 195 if options.mbn_version: 196 header_version = options.mbn_version 197 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 216 #print("Input file 1:", elf_inp_file1) 217 #print("Input file 2:", elf_inp_file2) 218 #print("Output file:", binary_out) 219 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) 231 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, 245 secure_type = image_header_secflag, 246 header_version = header_version ) 247 if rv: 248 raise RuntimeError("Failed to run pboot_gen_elf") 249 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") 260 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, 291 zi_oob_enabled, 292 header_version): 293 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: 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)) 359 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)) 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): 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 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 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 451 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 459 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 467 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 472 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 477 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 482 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 487 488 489 #print("i=",i) 490 #print("phdr_offset=", phdr_offset) 491 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 499# print("inp_data_offset=") 500# print(inp_data_offset) 501# 502# print("curr_phdr.p_offset=") 503# print(curr_phdr.p_offset) 504# 505# print("curr_phdr.p_filesz=") 506# print(curr_phdr.p_filesz) 507 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 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 549 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 557 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 565 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 570 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 575 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 580 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 585 586 587# print("i=",i) 588# print("phdr_offset=", phdr_offset) 589 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 597# print("inp_data_offset=") 598# print(inp_data_offset) 599# 600# print("curr_phdr.p_offset=") 601# print(curr_phdr.p_offset) 602# 603# print("curr_phdr.p_filesz=") 604# print(curr_phdr.p_filesz) 605 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: 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 640 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 671 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 678 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 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() 718