1#!/usr/bin/env python3 2#=============================================================================== 3# 4# MBN TOOLS 5# 6# GENERAL DESCRIPTION 7# Contains all MBN Utilities for image generation 8# 9# SPDX-License-Identifier: BSD-3-Clause 10 11#------------------------------------------------------------------------------- 12# EDIT HISTORY FOR FILE 13# 14# This section contains comments describing changes made to the module. 15# Notice that changes are listed in reverse chronological order. 16# 17# when who what, where, why 18# -------- --- --------------------------------------------------------- 19# 05/21/18 rissha Added support for extended MBNV6 and Add support for hashing elf segments with SHA384 20# 03/22/18 thiru Added support for extended MBNV5. 21# 06/06/13 yliong CR 497042: Signed and encrypted image is corrupted. MRC features. 22# 03/18/13 dhaval Add support for hashing elf segments with SHA256 and 23# sync up to mpss, adsp mbn-tools 24# 01/14/13 kedara Remove dependency on .builds, cust<bid>.h, targ<bid>.h files 25# 08/30/12 kedara Add virtual block suppport 26# 02/24/12 dh Add ssd side effect file names 27# 07/08/11 aus Added support for image_id in SBL image header as required by PBL 28# Sahara mode 29# 10/20/11 dxiang Clean up 30#=============================================================================== 31 32import stat 33import csv 34import itertools 35import struct 36import os 37import shutil 38import hashlib 39 40#---------------------------------------------------------------------------- 41# GLOBAL VARIABLES BEGIN 42#---------------------------------------------------------------------------- 43PAD_BYTE_1 = 255 # Padding byte 1s 44PAD_BYTE_0 = 0 # Padding byte 0s 45SHA256_SIGNATURE_SIZE = 256 # Support SHA256 46MAX_NUM_ROOT_CERTS = 4 # Maximum number of OEM root certificates 47MI_BOOT_SBL_HDR_SIZE = 80 # sizeof(sbl_header) 48BOOT_HEADER_LENGTH = 20 # Boot Header Number of Elements 49SBL_HEADER_LENGTH = 20 # SBL Header Number of Elements 50MAX_PHDR_COUNT = 100 # Maximum allowable program headers 51CERT_CHAIN_ONEROOT_MAXSIZE = 6*1024 # Default Cert Chain Max Size for one root 52VIRTUAL_BLOCK_SIZE = 131072 # Virtual block size for MCs insertion in SBL1 if ENABLE_VIRTUAL_BLK ON 53MAGIC_COOKIE_LENGTH = 12 # Length of magic Cookie inserted per VIRTUAL_BLOCK_SIZE 54MIN_IMAGE_SIZE_WITH_PAD = 256*1024 # Minimum image size for sbl1 Nand based OTA feature 55 56SBL_AARCH64 = 0xF # Indicate that SBL is a Aarch64 image 57SBL_AARCH32 = 0x0 # Indicate that SBL is a Aarch32 image 58 59# Magic numbers filled in for boot headers 60FLASH_CODE_WORD = 0x844BDCD1 61UNIFIED_BOOT_COOKIE_MAGIC_NUMBER = 0x33836685 62MAGIC_NUM = 0x73D71034 63AUTODETECT_PAGE_SIZE_MAGIC_NUM = 0x7D0B435A 64AUTODETECT_PAGE_SIZE_MAGIC_NUM64 = 0x7D0B5436 65AUTODETECT_PAGE_SIZE_MAGIC_NUM128 = 0x7D0B6577 66SBL_VIRTUAL_BLOCK_MAGIC_NUM = 0xD48B54C6 67 68# ELF Definitions 69ELF_HDR_COMMON_SIZE = 24 70ELF32_HDR_SIZE = 52 71ELF32_PHDR_SIZE = 32 72ELF64_HDR_SIZE = 64 73ELF64_PHDR_SIZE = 56 74ELFINFO_MAG0_INDEX = 0 75ELFINFO_MAG1_INDEX = 1 76ELFINFO_MAG2_INDEX = 2 77ELFINFO_MAG3_INDEX = 3 78ELFINFO_MAG0 = 127 # 0x7F 79ELFINFO_MAG1 = 69 # E 80ELFINFO_MAG2 = 76 # L 81ELFINFO_MAG3 = 70 # F 82ELFINFO_CLASS_INDEX = 4 83ELFINFO_CLASS_32 = 1 84ELFINFO_CLASS_64 = 2 85ELFINFO_VERSION_INDEX = 6 86ELFINFO_VERSION_CURRENT = 1 87ELF_BLOCK_ALIGN = 0x1000 88ALIGNVALUE_1MB = 0x100000 89ALIGNVALUE_4MB = 0x400000 90ELFINFO_DATA2LSB = b'\x01' 91ELFINFO_EXEC_ETYPE = b'\x02\x00' 92ELFINFO_ARM_MACHINETYPE = b'\x28\x00' 93ELFINFO_VERSION_EV_CURRENT = b'\x01\x00\x00\x00' 94ELFINFO_SHOFF = 0x00 95ELFINFO_PHNUM = b'\x01\x00' 96ELFINFO_RESERVED = 0x00 97 98# ELF Program Header Types 99NULL_TYPE = 0x0 100LOAD_TYPE = 0x1 101DYNAMIC_TYPE = 0x2 102INTERP_TYPE = 0x3 103NOTE_TYPE = 0x4 104SHLIB_TYPE = 0x5 105PHDR_TYPE = 0x6 106TLS_TYPE = 0x7 107 108""" 109The eight bits between 20 and 27 in the p_flags field in ELF program headers 110is not used by the standard ELF format. We use this byte to hold OS and processor 111specific fields as recommended by ARM. 112 113The bits in this byte are defined as follows: 114 115 Pool Indx Segment type Access type Page/non page 116 bits in p_flags /-----27-----/----26-24-------/---- 23-21----/------20-------/ 117 118After parsing segment description strings in the SCL file, the appropriate segment 119flag values are chosen from the follow definitions. The mask defined below is then 120used to update the existing p_flags field in the program headers with the updated 121values. 122""" 123# Mask for bits 20-27 to parse program header p_flags 124MI_PBT_FLAGS_MASK = 0x0FF00000 125 126# Helper defines to help parse ELF program headers 127MI_PBT_FLAG_SEGMENT_TYPE_MASK = 0x07000000 128MI_PBT_FLAG_SEGMENT_TYPE_SHIFT = 0x18 129MI_PBT_FLAG_PAGE_MODE_MASK = 0x00100000 130MI_PBT_FLAG_PAGE_MODE_SHIFT = 0x14 131MI_PBT_FLAG_ACCESS_TYPE_MASK = 0x00E00000 132MI_PBT_FLAG_ACCESS_TYPE_SHIFT = 0x15 133MI_PBT_FLAG_POOL_INDEX_MASK = 0x08000000 134MI_PBT_FLAG_POOL_INDEX_SHIFT = 0x1B 135 136# Segment Type 137MI_PBT_L4_SEGMENT = 0x0 138MI_PBT_AMSS_SEGMENT = 0x1 139MI_PBT_HASH_SEGMENT = 0x2 140MI_PBT_BOOT_SEGMENT = 0x3 141MI_PBT_L4BSP_SEGMENT = 0x4 142MI_PBT_SWAPPED_SEGMENT = 0x5 143MI_PBT_XBL_SEC_SEGMENT = 0x5 144MI_PBT_SWAP_POOL_SEGMENT = 0x6 145MI_PBT_PHDR_SEGMENT = 0x7 146 147# Page/Non-Page Type 148MI_PBT_NON_PAGED_SEGMENT = 0x0 149MI_PBT_PAGED_SEGMENT = 0x1 150 151# Access Type 152MI_PBT_RW_SEGMENT = 0x0 153MI_PBT_RO_SEGMENT = 0x1 154MI_PBT_ZI_SEGMENT = 0x2 155MI_PBT_NOTUSED_SEGMENT = 0x3 156MI_PBT_SHARED_SEGMENT = 0x4 157MI_PBT_RWE_SEGMENT = 0x7 158 159# ELF Segment Flag Definitions 160MI_PBT_ELF_AMSS_NON_PAGED_RO_SEGMENT = 0x01200000 161MI_PBT_ELF_AMSS_PAGED_RO_SEGMENT = 0x01300000 162MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX0 = 0x06400000 163MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX0 = 0x05300000 164MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX1 = 0x0E400000 165MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX1 = 0x0D300000 166MI_PBT_ELF_AMSS_NON_PAGED_ZI_SEGMENT = 0x01400000 167MI_PBT_ELF_AMSS_PAGED_ZI_SEGMENT = 0x01500000 168MI_PBT_ELF_AMSS_NON_PAGED_RW_SEGMENT = 0x01000000 169MI_PBT_ELF_AMSS_PAGED_RW_SEGMENT = 0x01100000 170MI_PBT_ELF_AMSS_NON_PAGED_NOTUSED_SEGMENT = 0x01600000 171MI_PBT_ELF_AMSS_PAGED_NOTUSED_SEGMENT = 0x01700000 172MI_PBT_ELF_AMSS_NON_PAGED_SHARED_SEGMENT = 0x01800000 173MI_PBT_ELF_AMSS_PAGED_SHARED_SEGMENT = 0x01900000 174MI_PBT_ELF_HASH_SEGMENT = 0x02200000 175MI_PBT_ELF_BOOT_SEGMENT = 0x03200000 176MI_PBT_ELF_PHDR_SEGMENT = 0x07000000 177MI_PBT_ELF_NON_PAGED_L4BSP_SEGMENT = 0x04000000 178MI_PBT_ELF_PAGED_L4BSP_SEGMENT = 0x04100000 179MI_PBT_ELF_AMSS_RELOCATABLE_IMAGE = 0x8000000 180 181# New definitions for EOS demap paging requirement 182# Bit 20 (0b) Bit 24-26(000): Non Paged = 0x0000_0000 183# Bit 20 (1b) Bit 24-26(000): Locked Paged = 0x0010_0000 184# Bit 20 (1b) Bit 24-26(001): Unlocked Paged = 0x0110_0000 185# Bit 20 (0b) Bit 24-26(011): non secure = 0x0310_0000 186MI_PBT_ELF_RESIDENT_SEGMENT = 0x00000000 187MI_PBT_ELF_PAGED_LOCKED_SEGMENT = 0x00100000 188MI_PBT_ELF_PAGED_UNLOCKED_SEGMENT = 0x01100000 189MI_PBT_ELF_UNSECURE_SEGMENT = 0x03100000 190#---------------------------------------------------------------------------- 191# GLOBAL VARIABLES END 192#---------------------------------------------------------------------------- 193 194#---------------------------------------------------------------------------- 195# CLASS DEFINITIONS BEGIN 196#---------------------------------------------------------------------------- 197#---------------------------------------------------------------------------- 198# OS Type ID Class 199#---------------------------------------------------------------------------- 200class OSType: 201 BMP_BOOT_OS = 0 202 WM_BOOT_OS = 1 203 ANDROID_BOOT_OS = 2 204 CHROME_BOOT_OS = 3 205 SYMBIAN_BOOT_OS = 4 206 LINUX_BOOT_OS = 5 207 208#---------------------------------------------------------------------------- 209# Image Type ID Class - These values must be kept consistent with mibib.h 210#---------------------------------------------------------------------------- 211class ImageType: 212 NONE_IMG = 0 213 OEM_SBL_IMG = 1 214 AMSS_IMG = 2 215 QCSBL_IMG = 3 216 HASH_IMG = 4 217 APPSBL_IMG = 5 218 APPS_IMG = 6 219 HOSTDL_IMG = 7 220 DSP1_IMG = 8 221 FSBL_IMG = 9 222 DBL_IMG = 10 223 OSBL_IMG = 11 224 DSP2_IMG = 12 225 EHOSTDL_IMG = 13 226 NANDPRG_IMG = 14 227 NORPRG_IMG = 15 228 RAMFS1_IMG = 16 229 RAMFS2_IMG = 17 230 ADSP_Q5_IMG = 18 231 APPS_KERNEL_IMG = 19 232 BACKUP_RAMFS_IMG = 20 233 SBL1_IMG = 21 234 SBL2_IMG = 22 235 RPM_IMG = 23 236 SBL3_IMG = 24 237 TZ_IMG = 25 238 PSI_IMG = 32 239 240#---------------------------------------------------------------------------- 241# Global Image Type Table 242# Format of the look-up table: 243# KEY - IMAGE_TYPE string as passed into mbn_builder.py 244# VALUE - [Specific ImageType ID enum, Template key string, MBN Type] 245#---------------------------------------------------------------------------- 246image_id_table = { 247 'appsbl': [ImageType.APPSBL_IMG, 'APPSBL_IMG', 'bin'], 248 'dbl': [ImageType.DBL_IMG, 'DBL_IMG', 'bin'], 249 'osbl': [ImageType.OSBL_IMG, 'OSBL_IMG', 'bin'], 250 'amss': [ImageType.AMSS_IMG, 'AMSS_IMG', 'elf'], 251 'amss_mbn': [ImageType.HASH_IMG, 'HASH_IMG', 'elf'], 252 'apps': [ImageType.APPS_IMG, 'APPS_IMG', 'bin'], 253 'hostdl': [ImageType.HOSTDL_IMG, 'HOSTDL_IMG', 'bin'], 254 'ehostdl': [ImageType.EHOSTDL_IMG, 'EHOSTDL_IMG', 'bin'], 255 'emmcbld': [ImageType.EHOSTDL_IMG, 'EMMCBLD_IMG', 'bin'], 256 'qdsp6fw': [ImageType.DSP1_IMG, 'DSP1_IMG', 'elf'], 257 'qdsp6sw': [ImageType.DSP2_IMG, 'DSP2_IMG', 'elf'], 258 'qdsp5': [ImageType.ADSP_Q5_IMG, 'ADSP_Q5_IMG', 'bin'], 259 'tz': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], 260 'tz_rumi': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], 261 'tz_virtio': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], 262 'tzbsp_no_xpu': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], 263 'tzbsp_with_test': [ImageType.TZ_IMG, 'TZ_IMG', 'elf'], 264 'rpm': [ImageType.RPM_IMG, 'RPM_IMG', 'elf'], 265 'sbl1': [ImageType.SBL1_IMG, 'SBL1_IMG', 'bin'], 266 'sbl2': [ImageType.SBL2_IMG, 'SBL2_IMG', 'bin'], 267 'sbl3': [ImageType.SBL3_IMG, 'SBL3_IMG', 'bin'], 268 'efs1': [ImageType.RAMFS1_IMG, 'RAMFS1_IMG', 'bin'], 269 'efs2': [ImageType.RAMFS2_IMG, 'RAMFS2_IMG', 'bin'], 270 'pmic': [ImageType.PSI_IMG, 'PSI_IMG', 'elf'], 271 # DO NOT add any additional image information 272} 273 274#---------------------------------------------------------------------------- 275# Header Class Notes: 276# In order to properly read and write the header structures as binary data, 277# the Python Struct library is used to align and package up the header objects 278# All Struct objects are initialized by a special string with the following 279# notation. These structure objects are then used to decode binary data in order 280# to fill out the appropriate class in Python, or they are used to package up 281# the Python class so that we may write the binary data out. 282#---------------------------------------------------------------------------- 283""" 284 Format | C Type | Python Type | Standard Size 285 ----------------------------------------------------- 286 1) 'X's | char * | string | 'X' bytes 287 2) H | unsigned short | integer | 2 bytes 288 3) I | unsigned int | integer | 4 bytes 289 290""" 291 292#---------------------------------------------------------------------------- 293# ELF Header Class 294#---------------------------------------------------------------------------- 295class Elf_Ehdr_common: 296 # Structure object to align and package the ELF Header 297 s = struct.Struct('16sHHI') 298 299 def __init__(self, data): 300 unpacked_data = (Elf_Ehdr_common.s).unpack(data) 301 self.unpacked_data = unpacked_data 302 self.e_ident = unpacked_data[0] 303 self.e_type = unpacked_data[1] 304 self.e_machine = unpacked_data[2] 305 self.e_version = unpacked_data[3] 306 307 def printValues(self): 308 print("ATTRIBUTE / VALUE") 309 for attr, value in self.__dict__.items(): 310 print(attr, value) 311 312 313 314#---------------------------------------------------------------------------- 315# ELF Header Class 316#---------------------------------------------------------------------------- 317class Elf32_Ehdr: 318 # Structure object to align and package the ELF Header 319 s = struct.Struct('16sHHIIIIIHHHHHH') 320 321 def __init__(self, data): 322 unpacked_data = (Elf32_Ehdr.s).unpack(data) 323 self.unpacked_data = unpacked_data 324 self.e_ident = unpacked_data[0] 325 self.e_type = unpacked_data[1] 326 self.e_machine = unpacked_data[2] 327 self.e_version = unpacked_data[3] 328 self.e_entry = unpacked_data[4] 329 self.e_phoff = unpacked_data[5] 330 self.e_shoff = unpacked_data[6] 331 self.e_flags = unpacked_data[7] 332 self.e_ehsize = unpacked_data[8] 333 self.e_phentsize = unpacked_data[9] 334 self.e_phnum = unpacked_data[10] 335 self.e_shentsize = unpacked_data[11] 336 self.e_shnum = unpacked_data[12] 337 self.e_shstrndx = unpacked_data[13] 338 339 def printValues(self): 340 print("ATTRIBUTE / VALUE") 341 for attr, value in self.__dict__.items(): 342 print(attr, value) 343 344 def getPackedData(self): 345 if type(self.e_ident) == str: 346 packvalue = bytes(self.e_ident, 'utf-8') 347 else: 348 packvalue = self.e_ident 349 values = [packvalue, 350 self.e_type, 351 self.e_machine, 352 self.e_version, 353 self.e_entry, 354 self.e_phoff, 355 self.e_shoff, 356 self.e_flags, 357 self.e_ehsize, 358 self.e_phentsize, 359 self.e_phnum, 360 self.e_shentsize, 361 self.e_shnum, 362 self.e_shstrndx 363 ] 364 365 return (Elf32_Ehdr.s).pack(*values) 366 367#---------------------------------------------------------------------------- 368# ELF Program Header Class 369#---------------------------------------------------------------------------- 370class Elf32_Phdr: 371 372 # Structure object to align and package the ELF Program Header 373 s = struct.Struct('I' * 8) 374 375 def __init__(self, data): 376 unpacked_data = (Elf32_Phdr.s).unpack(data) 377 self.unpacked_data = unpacked_data 378 self.p_type = unpacked_data[0] 379 self.p_offset = unpacked_data[1] 380 self.p_vaddr = unpacked_data[2] 381 self.p_paddr = unpacked_data[3] 382 self.p_filesz = unpacked_data[4] 383 self.p_memsz = unpacked_data[5] 384 self.p_flags = unpacked_data[6] 385 self.p_align = unpacked_data[7] 386 387 def printValues(self): 388 print("ATTRIBUTE / VALUE") 389 for attr, value in self.__dict__.items(): 390 print(attr, value) 391 392 def getPackedData(self): 393 values = [self.p_type, 394 self.p_offset, 395 self.p_vaddr, 396 self.p_paddr, 397 self.p_filesz, 398 self.p_memsz, 399 self.p_flags, 400 self.p_align 401 ] 402 403 return (Elf32_Phdr.s).pack(*values) 404 405#---------------------------------------------------------------------------- 406# ELF Header Class 407#---------------------------------------------------------------------------- 408class Elf64_Ehdr: 409 # Structure object to align and package the ELF Header 410 s = struct.Struct('16sHHIQQQIHHHHHH') 411 412 def __init__(self, data): 413 unpacked_data = (Elf64_Ehdr.s).unpack(data) 414 self.unpacked_data = unpacked_data 415 self.e_ident = unpacked_data[0] 416 self.e_type = unpacked_data[1] 417 self.e_machine = unpacked_data[2] 418 self.e_version = unpacked_data[3] 419 self.e_entry = unpacked_data[4] 420 self.e_phoff = unpacked_data[5] 421 self.e_shoff = unpacked_data[6] 422 self.e_flags = unpacked_data[7] 423 self.e_ehsize = unpacked_data[8] 424 self.e_phentsize = unpacked_data[9] 425 self.e_phnum = unpacked_data[10] 426 self.e_shentsize = unpacked_data[11] 427 self.e_shnum = unpacked_data[12] 428 self.e_shstrndx = unpacked_data[13] 429 430 def printValues(self): 431 print("ATTRIBUTE / VALUE") 432 for attr, value in self.__dict__.items(): 433 print(attr, value) 434 435 def getPackedData(self): 436 if type(self.e_ident) == str: 437 packvalue = bytes(self.e_ident, 'utf-8') 438 else: 439 packvalue = self.e_ident 440 values = [packvalue, 441 self.e_type, 442 self.e_machine, 443 self.e_version, 444 self.e_entry, 445 self.e_phoff, 446 self.e_shoff, 447 self.e_flags, 448 self.e_ehsize, 449 self.e_phentsize, 450 self.e_phnum, 451 self.e_shentsize, 452 self.e_shnum, 453 self.e_shstrndx 454 ] 455 456 return (Elf64_Ehdr.s).pack(*values) 457 458#---------------------------------------------------------------------------- 459# ELF Program Header Class 460#---------------------------------------------------------------------------- 461class Elf64_Phdr: 462 463 # Structure object to align and package the ELF Program Header 464 s = struct.Struct('IIQQQQQQ') 465 466 def __init__(self, data): 467 unpacked_data = (Elf64_Phdr.s).unpack(data) 468 self.unpacked_data = unpacked_data 469 self.p_type = unpacked_data[0] 470 self.p_flags = unpacked_data[1] 471 self.p_offset = unpacked_data[2] 472 self.p_vaddr = unpacked_data[3] 473 self.p_paddr = unpacked_data[4] 474 self.p_filesz = unpacked_data[5] 475 self.p_memsz = unpacked_data[6] 476 self.p_align = unpacked_data[7] 477 478 def printValues(self): 479 print("ATTRIBUTE / VALUE") 480 for attr, value in self.__dict__.items(): 481 print(attr, value) 482 483 def getPackedData(self): 484 values = [self.p_type, 485 self.p_flags, 486 self.p_offset, 487 self.p_vaddr, 488 self.p_paddr, 489 self.p_filesz, 490 self.p_memsz, 491 self.p_align 492 ] 493 494 return (Elf64_Phdr.s).pack(*values) 495 496 497#---------------------------------------------------------------------------- 498# ELF Segment Information Class 499#---------------------------------------------------------------------------- 500class SegmentInfo: 501 def __init__(self): 502 self.flag = 0 503 def printValues(self): 504 print('Flag: ' + str(self.flag)) 505 506#---------------------------------------------------------------------------- 507# Regular Boot Header Class 508#---------------------------------------------------------------------------- 509class Boot_Hdr: 510 def __init__(self, init_val): 511 self.image_id = ImageType.NONE_IMG 512 self.flash_parti_ver = 3 513 self.image_src = init_val 514 self.image_dest_ptr = init_val 515 self.image_size = init_val 516 self.code_size = init_val 517 self.sig_ptr = init_val 518 self.sig_size = init_val 519 self.cert_chain_ptr = init_val 520 self.cert_chain_size = init_val 521 self.magic_number1 = init_val 522 self.version = init_val 523 self.OS_type = init_val 524 self.boot_apps_parti_entry = init_val 525 self.boot_apps_size_entry = init_val 526 self.boot_apps_ram_loc = init_val 527 self.reserved_ptr = init_val 528 self.reserved_1 = init_val 529 self.reserved_2 = init_val 530 self.reserved_3 = init_val 531 532 def getLength(self): 533 return BOOT_HEADER_LENGTH 534 535 def writePackedData(self, target, write_full_hdr): 536 values = [self.image_id, 537 self.flash_parti_ver, 538 self.image_src, 539 self.image_dest_ptr, 540 self.image_size, 541 self.code_size , 542 self.sig_ptr, 543 self.sig_size, 544 self.cert_chain_ptr, 545 self.cert_chain_size, 546 self.magic_number1, 547 self.version, 548 self.OS_type, 549 self.boot_apps_parti_entry, 550 self.boot_apps_size_entry, 551 self.boot_apps_ram_loc, 552 self.reserved_ptr, 553 self.reserved_1, 554 self.reserved_2, 555 self.reserved_3 ] 556 557 if self.flash_parti_ver >= 6: 558 values.insert(10, self.metadata_size_qti) 559 values.insert(11, self.metadata_size) 560 561 if self.image_dest_ptr >= 0x100000000: 562 values[3] = 0xFFFFFFFF 563 564 if self.cert_chain_ptr >= 0x100000000: 565 values[6] = 0xFFFFFFFF 566 567 if self.sig_ptr >= 0x100000000: 568 values[8] = 0xFFFFFFFF 569 570 # Write 10 entries(40B) or 20 entries(80B) of boot header 571 if write_full_hdr is False: 572 if self.flash_parti_ver >= 6: 573 s = struct.Struct('I'* 12) 574 values = values[:12] 575 else: 576 s = struct.Struct('I'* 10) 577 values = values[:10] 578 else: 579 s = struct.Struct('I' * self.getLength()) 580 581 packed_data = s.pack(*values) 582 583 fp = OPEN(target,'wb') 584 fp.write(packed_data) 585 fp.close() 586 587 return s.size 588 589#---------------------------------------------------------------------------- 590# SBL Boot Header Class 591#---------------------------------------------------------------------------- 592class Sbl_Hdr: 593 def __init__(self, init_val): 594 self.codeword = init_val 595 self.magic = init_val 596 self.image_id = init_val 597 self.reserved_1 = init_val 598 self.reserved_2 = init_val 599 self.image_src = init_val 600 self.image_dest_ptr = init_val 601 self.image_size = init_val 602 self.code_size = init_val 603 self.sig_ptr = init_val 604 self.sig_size = init_val 605 self.cert_chain_ptr = init_val 606 self.cert_chain_size = init_val 607 self.oem_root_cert_sel = init_val 608 self.oem_num_root_certs = init_val 609 self.booting_image_config = init_val 610 self.reserved_6 = init_val 611 self.reserved_7 = init_val 612 self.reserved_8 = init_val 613 self.reserved_9 = init_val 614 615 def getLength(self): 616 return SBL_HEADER_LENGTH 617 618 def writePackedData(self, target): 619 values = [self.codeword, 620 self.magic, 621 self.image_id, 622 self.reserved_1, 623 self.reserved_2, 624 self.image_src, 625 self.image_dest_ptr, 626 self.image_size, 627 self.code_size, 628 self.sig_ptr, 629 self.sig_size, 630 self.cert_chain_ptr, 631 self.cert_chain_size, 632 self.oem_root_cert_sel, 633 self.oem_num_root_certs, 634 self.booting_image_config, 635 self.reserved_6, 636 self.reserved_7, 637 self.reserved_8, 638 self.reserved_9 ] 639 640 s = struct.Struct('I' * self.getLength()) 641 packed_data = s.pack(*values) 642 643 fp = OPEN(target,'wb') 644 fp.write(packed_data) 645 fp.close() 646 647 return s.size 648 649#---------------------------------------------------------------------------- 650# CLASS DEFINITIONS END 651#---------------------------------------------------------------------------- 652 653#------------------------------------------------------------------------------ 654# Hooks for Scons 655#------------------------------------------------------------------------------ 656def exists(env): 657 return env.Detect('mbn_tools') 658 659def generate(env): 660 661 #---------------------------------------------------------------------------- 662 # Generate Global Dictionary 663 #---------------------------------------------------------------------------- 664 generate_global_dict(env) 665 666 #---------------------------------------------------------------------------- 667 # Assign Build Configurable Values 668 #---------------------------------------------------------------------------- 669 init_build_vars(env) 670 671 #---------------------------------------------------------------------------- 672 # Add Methods to Environment 673 #---------------------------------------------------------------------------- 674 env.AddMethod(filter_dictionary, "FilterDictionary") 675 env.AddMethod(image_auth, "ImageAuth") 676 env.AddMethod(image_header, "ImageHeader") 677 env.AddMethod(pboot_gen_elf, "PBootGenElf") 678 env.AddMethod(pboot_add_hash, "PBootAddHash") 679 env.AddMethod(modify_elf_flags, "ModifyElfFlags") 680 env.AddMethod(generate_code_hash, "GenerateCodeHash") 681 env.AddMethod(insert_SBL1_magicCookie, "InsertSBLMagicCookie") 682 env.AddMethod(modify_relocatable_flags, "ModifyRelocatableFlags") 683 684 #---------------------------------------------------------------------------- 685 # Load Encryption Tools and Methods if required 686 #---------------------------------------------------------------------------- 687 if 'USES_ENCRYPT_MBN' in env: 688 # Add Encryption Tools to environment 689 env.Tool('pil_encrypt', toolpath = ['${BUILD_ROOT}/core/securemsm/ssd/tools/pil_encrypt']) 690 env.AddMethod(get_ssd_se_fname, "GetSSDSideEffectFileName") 691 env.AddMethod(encrypt_elf_segments, "EncryptElfSegments") 692 env.AddMethod(generate_meta_data, "GenerateMetaData") 693 env.AddMethod(encrypt_mbn, "EncryptMBN") 694 return None 695 696#---------------------------------------------------------------------------- 697# BOOT TOOLS BEGIN 698#---------------------------------------------------------------------------- 699 700#---------------------------------------------------------------------------- 701# generate_meta_data 702#---------------------------------------------------------------------------- 703def generate_meta_data(env, meta_out_file_name, add_magic_num = False): 704 705 ''' 706 Make call to SSD API to return buffer filled with XML header information. 707 The XML header which we write contains information regarding the algorithms 708 being used along with specific key values which are to be used for encrpytion. 709 ''' 710 xml_header = env.SSDGetMetaData(add_magic_num) 711 712 # Initialize 713 xml_target_file = open(meta_out_file_name,'wb') 714 xml_header_size = len(xml_header) 715 716 # Write XML buffer into target file 717 xml_target_file.write(xml_header) 718 719 # Pad if necessary to the maximum size 720 if xml_header_size <= XML_HEADER_MAXSIZE: 721 bytes_to_pad = XML_HEADER_MAXSIZE - xml_header_size 722 pad_file(xml_target_file, bytes_to_pad, PAD_BYTE_1) 723 xml_target_file.close() 724 else: 725 xml_target_file.close() 726 raise RuntimeError("XML Size too large: " + str(xml_header_size)) 727 728#---------------------------------------------------------------------------- 729# encrypt_mbn 730#---------------------------------------------------------------------------- 731def encrypt_mbn(env, mbn_in_file_name, mbn_out_file_name): 732 # Open Files 733 mbn_in_fp = OPEN(mbn_in_file_name, "rb") 734 mbn_out_fp = OPEN(mbn_out_file_name, "wb+") 735 736 # encrypt the input file content and write to output file 737 mbn_file_size = os.path.getsize(mbn_in_file_name) 738 file_buff = mbn_in_fp.read(mbn_file_size) 739 encrypted_buf = env.SSDEncryptSegment(0, file_buff, mbn_file_size) 740 mbn_out_fp.write(encrypted_buf) 741 742 # Close Files 743 mbn_in_fp.close() 744 mbn_out_fp.close() 745 746 # Clean up encryption files 747 env.SSDDeInit() 748 749#---------------------------------------------------------------------------- 750# get_ssd_se_fname 751#---------------------------------------------------------------------------- 752def get_ssd_se_fname(env): 753 return env.SSDGetSideEffectFileName() 754 755#---------------------------------------------------------------------------- 756# encrypt_elf_segments 757#---------------------------------------------------------------------------- 758def encrypt_elf_segments(env, elf_in_file_name, 759 elf_out_file_name): 760 761 # Open Files 762 elf_in_fp = OPEN(elf_in_file_name, "rb") 763 elf_out_fp = OPEN(elf_out_file_name, "wb+") 764 765 # Initialize 766 [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) 767 encrypted_seg_counter = 0 768 769 # Copy input file to output file 770 shutil.copyfileobj(elf_in_fp, elf_out_fp, os.path.getsize(elf_in_file_name)) 771 772 # Begin ELF segment encryption 773 for i in range(elf_header.e_phnum): 774 curr_phdr = phdr_table[i] 775 776 # Only encrypt segments of LOAD_TYPE. Do not encrypt the hash segment. 777 if curr_phdr.p_type == LOAD_TYPE and \ 778 MI_PBT_SEGMENT_TYPE_VALUE(curr_phdr.p_flags) != MI_PBT_HASH_SEGMENT: 779 780 # Read full segment into buffer 781 elf_in_fp.seek(curr_phdr.p_offset) 782 data_len = curr_phdr.p_filesz 783 file_buff = elf_in_fp.read(data_len) 784 785 # Call encryption routine on buffer 786 encrypted_buf = env.SSDEncryptSegment(encrypted_seg_counter, file_buff, data_len) 787 encrypted_seg_counter += 1 788 789 # Write encrypted segment into output file in same location 790 elf_out_fp.seek(curr_phdr.p_offset) 791 elf_out_fp.write(encrypted_buf) 792 793 # Close Files 794 elf_in_fp.close() 795 elf_out_fp.close() 796 797 # Clean up encryption files 798 env.SSDDeInit() 799 800#---------------------------------------------------------------------------- 801# Converts integer to bytes. If length after conversion 802# is smaller than given length of byte string, returned value is right-filled 803# with 0x00 bytes. Use Little-endian byte order. 804#---------------------------------------------------------------------------- 805def convert_int_to_byte_string(n, l): 806 return b''.join([chr((n >> ((l - i - 1) * 8)) % 256) for i in xrange(l)][::-1]) 807 808#---------------------------------------------------------------------------- 809# Create default elf header 810#---------------------------------------------------------------------------- 811def create_elf_header( output_file_name, 812 image_dest, 813 image_size, 814 is_elf_64_bit = False): 815 816 if (output_file_name is None): 817 raise RuntimeError("Requires a ELF header file") 818 819 # Create a elf header and program header 820 # Write the headers to the output file 821 elf_fp = file(output_file_name, "wb") 822 823 if (is_elf_64_bit is True): 824 # ELf header 825 elf_fp.write(ELFINFO_MAG0) 826 elf_fp.write(ELFINFO_MAG1) 827 elf_fp.write(ELFINFO_MAG2) 828 elf_fp.write(ELFINFO_MAG3) 829 elf_fp.write(ELFINFO_CLASS_64) 830 elf_fp.write(ELFINFO_DATA2LSB) 831 elf_fp.write(ELFINFO_VERSION_CURRENT) 832 elf_fp.write(''.rjust(9, chr(ELFINFO_RESERVED))) 833 elf_fp.write(ELFINFO_EXEC_ETYPE) 834 elf_fp.write(ELFINFO_ARM_MACHINETYPE) 835 elf_fp.write(ELFINFO_VERSION_EV_CURRENT) 836 elf_fp.write(convert_int_to_byte_string(image_dest, 8)) 837 elf_fp.write(convert_int_to_byte_string(ELF64_HDR_SIZE, 8)) 838 elf_fp.write(convert_int_to_byte_string(ELFINFO_SHOFF, 8)) 839 elf_fp.write(''.rjust(4, chr(ELFINFO_RESERVED))) 840 elf_fp.write(convert_int_to_byte_string(ELF64_HDR_SIZE, 2)) 841 elf_fp.write(convert_int_to_byte_string(ELF64_PHDR_SIZE, 2)) 842 elf_fp.write(ELFINFO_PHNUM) 843 elf_fp.write(''.rjust(6, chr(ELFINFO_RESERVED))) 844 845 # Program Header 846 elf_fp.write(convert_int_to_byte_string(LOAD_TYPE, 4)) 847 elf_fp.write(convert_int_to_byte_string(MI_PBT_RWE_SEGMENT, 4)) 848 elf_fp.write(convert_int_to_byte_string(ELF64_HDR_SIZE+ELF64_PHDR_SIZE, 8)) 849 elf_fp.write(convert_int_to_byte_string(image_dest, 8)) 850 elf_fp.write(convert_int_to_byte_string(image_dest, 8)) 851 elf_fp.write(convert_int_to_byte_string(image_size, 8)) 852 elf_fp.write(convert_int_to_byte_string(image_size, 8)) 853 elf_fp.write(convert_int_to_byte_string(ELF_BLOCK_ALIGN, 8)) 854 else: 855 # ELf header 856 elf_fp.write(ELFINFO_MAG0) 857 elf_fp.write(ELFINFO_MAG1) 858 elf_fp.write(ELFINFO_MAG2) 859 elf_fp.write(ELFINFO_MAG3) 860 elf_fp.write(ELFINFO_CLASS_32) 861 elf_fp.write(ELFINFO_DATA2LSB) 862 elf_fp.write(ELFINFO_VERSION_CURRENT) 863 elf_fp.write(''.rjust(9, chr(ELFINFO_RESERVED))) 864 elf_fp.write(ELFINFO_EXEC_ETYPE) 865 elf_fp.write(ELFINFO_ARM_MACHINETYPE) 866 elf_fp.write(ELFINFO_VERSION_EV_CURRENT) 867 elf_fp.write(convert_int_to_byte_string(image_dest, 4)) 868 elf_fp.write(convert_int_to_byte_string(ELF32_HDR_SIZE, 4)) 869 elf_fp.write(convert_int_to_byte_string(ELFINFO_SHOFF, 4)) 870 elf_fp.write(''.rjust(4, chr(ELFINFO_RESERVED))) 871 elf_fp.write(convert_int_to_byte_string(ELF32_HDR_SIZE, 2)) 872 elf_fp.write(convert_int_to_byte_string(ELF32_PHDR_SIZE, 2)) 873 elf_fp.write(ELFINFO_PHNUM) 874 elf_fp.write(''.rjust(6, chr(ELFINFO_RESERVED))) 875 876 # Program Header 877 elf_fp.write(convert_int_to_byte_string(LOAD_TYPE, 4)) 878 elf_fp.write(convert_int_to_byte_string(ELF32_HDR_SIZE+ELF32_PHDR_SIZE, 4)) 879 elf_fp.write(convert_int_to_byte_string(image_dest, 4)) 880 elf_fp.write(convert_int_to_byte_string(image_dest, 4)) 881 elf_fp.write(convert_int_to_byte_string(image_size, 4)) 882 elf_fp.write(convert_int_to_byte_string(image_size, 4)) 883 elf_fp.write(convert_int_to_byte_string(MI_PBT_RWE_SEGMENT, 4)) 884 elf_fp.write(convert_int_to_byte_string(ELF_BLOCK_ALIGN, 4)) 885 886 elf_fp.close() 887 return 0 888 889#---------------------------------------------------------------------------- 890# image_header 891#---------------------------------------------------------------------------- 892def image_header(env, gen_dict, 893 code_file_name, 894 output_file_name, 895 secure_type, 896 header_format = 'reg', 897 requires_preamble = False, 898 preamble_file_name = None, 899 elf_file_name = None, 900 write_full_hdr = False, 901 in_code_size = None, 902 cert_chain_size_in = CERT_CHAIN_ONEROOT_MAXSIZE, 903 num_of_pages = None, 904 header_version = None): 905 906 # Preliminary checks 907 if (requires_preamble is True) and (preamble_file_name is None): 908 raise RuntimeError("Image Header requires a preamble file") 909 910 if (gen_dict['IMAGE_KEY_MBN_TYPE'] == 'elf') and (elf_file_name is None): 911 raise RuntimeError("ELF Image Headers require an elf file") 912 913 if (in_code_size is None) and (os.path.exists(code_file_name) is False): 914 raise RuntimeError("Code size unavailable, and input file does not exist") 915 916 # Initialize 917 if in_code_size is not None: 918 code_size = in_code_size 919 else: 920 code_size = os.path.getsize(code_file_name) 921 922 image_dest = 0 923 image_source = 0 924 925 # If secure build, set signature and cert chain sizes 926 if secure_type == 'secure': 927 signature_size = SHA256_SIGNATURE_SIZE 928 cert_chain_size = cert_chain_size_in 929 image_size = code_size + cert_chain_size + signature_size 930 if (image_size % 4) != 0: 931 image_size += (4 - (image_size % 4)) 932 else: 933 signature_size = 0 934 cert_chain_size = 0 935 image_size = code_size 936 937 if header_version: 938 assert header_version in [3, 5, 6], 'Not a valid MBN header version' 939 940 # For ELF or hashed images, image destination will be determined from an ELF input file 941 if gen_dict['IMAGE_KEY_MBN_TYPE'] == 'elf': 942 image_dest = get_hash_address(elf_file_name) + (header_size(header_version)) 943 elif gen_dict['IMAGE_KEY_MBN_TYPE'] == 'bin': 944 image_dest = gen_dict['IMAGE_KEY_IMAGE_DEST'] 945 image_source = gen_dict['IMAGE_KEY_IMAGE_SOURCE'] 946 947 # Build the header based on format specified 948 if header_format == 'sbl': 949 boot_sbl_header = Sbl_Hdr(init_val = int('0xFFFFFFFF',16)) 950 boot_sbl_header.codeword = FLASH_CODE_WORD 951 boot_sbl_header.magic = MAGIC_NUM 952 boot_sbl_header.image_id = gen_dict['IMAGE_KEY_IMAGE_ID'] 953 boot_sbl_header.image_src = MI_BOOT_SBL_HDR_SIZE 954 boot_sbl_header.image_dest_ptr = image_dest 955 boot_sbl_header.image_size = image_size 956 boot_sbl_header.code_size = code_size 957 boot_sbl_header.sig_ptr = image_dest + code_size 958 boot_sbl_header.sig_size = signature_size 959 boot_sbl_header.cert_chain_ptr = image_dest + code_size + signature_size 960 boot_sbl_header.cert_chain_size = cert_chain_size 961 boot_sbl_header.oem_root_cert_sel = gen_dict['IMAGE_KEY_OEM_ROOT_CERT_SEL'] 962 boot_sbl_header.oem_num_root_certs = gen_dict['IMAGE_KEY_OEM_NUM_ROOT_CERTS'] 963 if 'USES_SBL_FOR_AARCH64' in env: 964 boot_sbl_header.booting_image_config = SBL_AARCH64 965 elif 'USES_SBL_FOR_AARCH632' in env: 966 boot_sbl_header.booting_image_config = SBL_AARCH32 967 968 # If preamble is required, output the preamble file and update the boot_sbl_header 969 if requires_preamble is True: 970 boot_sbl_header = image_preamble(gen_dict, preamble_file_name, boot_sbl_header, num_of_pages) 971 972 # Package up the header and write to output file 973 boot_sbl_header.writePackedData(target = output_file_name) 974 975 elif header_format == 'reg': 976 boot_header = Boot_Hdr(init_val = int('0x0',16)) 977 boot_header.image_id = gen_dict['IMAGE_KEY_IMAGE_ID'] 978 boot_header.image_src = image_source 979 boot_header.image_dest_ptr = image_dest 980 boot_header.image_size = image_size 981 boot_header.code_size = code_size 982 boot_header.sig_ptr = image_dest + code_size 983 boot_header.sig_size = signature_size 984 boot_header.cert_chain_ptr = image_dest + code_size + signature_size 985 boot_header.cert_chain_size = cert_chain_size 986 boot_header.flash_parti_ver = header_version # version 987 988 if header_version >= 5: 989 boot_header.image_src = 0 # sig_size_qc 990 boot_header.image_dest_ptr = 0 # cert_chain_size_qc 991 992 if header_version >= 6: 993 boot_header.metadata_size_qti = 0 # qti_metadata size 994 boot_header.metadata_size = 0 # oem_metadata size 995 996 # If preamble is required, output the preamble file and update the boot_header 997 if requires_preamble is True: 998 boot_header = image_preamble(gen_dict, preamble_file_name, boot_header, num_of_pages) 999 1000 # Package up the header and write to output file 1001 boot_header.writePackedData(target = output_file_name, write_full_hdr = write_full_hdr) 1002 1003 else: 1004 raise RuntimeError("Header format not supported: " + str(header_format)) 1005 return 0 1006 1007 1008#---------------------------------------------------------------------------- 1009# pboot_gen_elf 1010#---------------------------------------------------------------------------- 1011def pboot_gen_elf(env, elf_in_file_name, 1012 hash_out_file_name, 1013 elf_out_file_name, 1014 secure_type = 'non_secure', 1015 hash_seg_max_size = None, 1016 last_phys_addr = None, 1017 append_xml_hdr = False, 1018 is_sha256_algo = True, 1019 cert_chain_size_in = CERT_CHAIN_ONEROOT_MAXSIZE, 1020 header_version = None): 1021 sha_algo = 'SHA1' 1022 if is_sha256_algo: 1023 sha_algo = 'SHA256' 1024 1025 if header_version >= 6: 1026 sha_algo = 'SHA384' 1027 image_header_size = header_size(header_version) 1028 1029 if (sha_algo == 'SHA384'): 1030 mi_prog_boot_digest_size = 48 1031 elif sha_algo == 'SHA256': 1032 mi_prog_boot_digest_size = 32 1033 else: 1034 mi_prog_boot_digest_size = 20 1035 1036 # Open Files 1037 elf_in_fp = OPEN(elf_in_file_name, "rb") 1038 hash_out_fp = OPEN(hash_out_file_name, "wb+") 1039 1040 if elf_out_file_name is not None: 1041 elf_out_fp = OPEN(elf_out_file_name, "wb+") 1042 1043 # Initialize 1044 [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) 1045 num_phdrs = elf_header.e_phnum 1046 phdr_total_size = num_phdrs * elf_header.e_phentsize 1047 phdr_size = elf_header.e_phentsize 1048 hashtable_size = 0 1049 hashtable_shift = 0 1050 1051 if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: 1052 new_phdr = Elf64_Phdr(b'\0' * ELF64_PHDR_SIZE) 1053 elf_header_size = ELF64_HDR_SIZE 1054 is_elf64 = True 1055 else: 1056 new_phdr = Elf32_Phdr(b'\0' * ELF32_PHDR_SIZE) 1057 elf_header_size = ELF32_HDR_SIZE 1058 is_elf64 = False 1059 1060 hash = b'\0' * mi_prog_boot_digest_size 1061 phdr_start = 0 1062 bytes_to_pad = 0 1063 hash_seg_end = 0 1064 1065 # Process program headers if an output elf is specified 1066 if elf_out_file_name is not None: 1067 # Assert limit on number of program headers in input ELF 1068 if num_phdrs > MAX_PHDR_COUNT: 1069 raise RuntimeError("Input ELF has exceeded maximum number of program headers") 1070 1071 # Create new program header for the ELF Header + Program Headers 1072 new_phdr.p_type = NULL_TYPE 1073 new_phdr.p_flags = MI_PBT_ELF_PHDR_SEGMENT 1074 1075 # If hash table program header is not found, make sure to include it 1076 elf_header.e_phnum += 2 1077 1078 # Create an empty hash entry for PHDR_TYPE 1079 hash_out_fp.write(b'\0' * mi_prog_boot_digest_size) 1080 hashtable_size += mi_prog_boot_digest_size 1081 1082 # Create an empty hash entry for the hash segment itself 1083 hash_out_fp.write(b'\0' * mi_prog_boot_digest_size) 1084 hashtable_size += mi_prog_boot_digest_size 1085 1086 # Begin hash table generation 1087 for i in range(num_phdrs): 1088 curr_phdr = phdr_table[i] 1089 1090 if (MI_PBT_PAGE_MODE_VALUE(curr_phdr.p_flags) == MI_PBT_PAGED_SEGMENT): 1091 seg_offset = curr_phdr.p_offset 1092 seg_size = curr_phdr.p_filesz 1093 hash_size = 0 1094 1095 # Check if the vaddr is page aligned 1096 off = curr_phdr.p_vaddr & (ELF_BLOCK_ALIGN - 1) 1097 if int(off) != 0: 1098 seg_size -= (ELF_BLOCK_ALIGN - off) 1099 seg_offset += (ELF_BLOCK_ALIGN - off) 1100 1101 # Seg_size should be page aligned 1102 if (seg_size & (ELF_BLOCK_ALIGN - 1)) > 0: 1103 raise RuntimeError("seg_size: " + hex(seg_size) + " is not ELF page aligned!") 1104 1105 off = seg_offset + seg_size 1106 1107 while seg_offset < off: 1108 1109 if seg_offset < ELF_BLOCK_ALIGN: 1110 hash_size = seg_offset 1111 else: 1112 hash_size = ELF_BLOCK_ALIGN 1113 1114 elf_in_fp.seek(seg_offset) 1115 fbuf = elf_in_fp.read(hash_size) 1116 1117 if MI_PBT_CHECK_FLAG_TYPE(curr_phdr.p_flags) is True: 1118 hash = generate_hash(fbuf, sha_algo) 1119 else: 1120 hash = b'\0' * mi_prog_boot_digest_size 1121 1122 # Write hash to file 1123 hash_out_fp.write(hash) 1124 1125 hashtable_size += mi_prog_boot_digest_size 1126 seg_offset += ELF_BLOCK_ALIGN 1127 1128 # Copy the hash entry for all that are PAGED segments and those that are not the PHDR type. This is for 1129 # backward tool compatibility where some images are generated using older exe tools. 1130 elif((MI_PBT_PAGE_MODE_VALUE(curr_phdr.p_flags) == MI_PBT_NON_PAGED_SEGMENT) and (curr_phdr.p_type is not PHDR_TYPE)): 1131 # Read full hash entry into buffer 1132 elf_in_fp.seek(curr_phdr.p_offset) 1133 data_len = curr_phdr.p_filesz 1134 file_buff = elf_in_fp.read(data_len) 1135 1136 if (MI_PBT_CHECK_FLAG_TYPE(curr_phdr.p_flags) is True) and (data_len > 0): 1137 hash = generate_hash(file_buff, sha_algo) 1138 else: 1139 hash = b'\0' * mi_prog_boot_digest_size 1140 1141 # Write hash to file 1142 hash_out_fp.write(hash) 1143 1144 hashtable_size += mi_prog_boot_digest_size 1145 # End hash table generation 1146 1147 # Generate the rest of the ELF output file if specified 1148 if elf_out_file_name is not None: 1149 1150 # Preempt hash table size if necessary 1151 if secure_type == 'secure': 1152 hashtable_size += (SHA256_SIGNATURE_SIZE + cert_chain_size_in) 1153 1154 if append_xml_hdr is True: 1155 hashtable_size += XML_HEADER_MAXSIZE 1156 1157 # Initialize the hash table program header 1158 [hash_Phdr, pad_hash_segment, hash_tbl_end_addr, hash_tbl_offset] = \ 1159 initialize_hash_phdr(elf_in_file_name, hashtable_size, image_header_size, ELF_BLOCK_ALIGN, is_elf64) 1160 1161 # Check if hash segment max size parameter was passed 1162 if (hash_seg_max_size is not None): 1163 # Error checking for hash segment size validity 1164 if hashtable_size > hash_seg_max_size: 1165 raise RuntimeError("Hash table exceeds maximum hash segment size: " + hex(hash_seg_max_size)) 1166 if (hash_seg_max_size & (ELF_BLOCK_ALIGN-1)) != 0: 1167 raise RuntimeError("Hash segment size passed is not ELF Block Aligned: " + hex(hash_seg_max_size)) 1168 1169 # Check if hash physical address parameter was passed 1170 if last_phys_addr is not None: 1171 hash_Phdr.p_vaddr = last_phys_addr 1172 hash_Phdr.p_paddr = last_phys_addr 1173 1174 # Check if hash segment max size was passed 1175 if hash_seg_max_size is not None: 1176 hash_Phdr.p_memsz = hash_seg_max_size 1177 1178 # Determine the end of the hash segment, make sure it's block aligned 1179 bytes_to_pad = ELF_BLOCK_ALIGN - pad_hash_segment 1180 hash_seg_end = hash_tbl_end_addr + bytes_to_pad 1181 1182 # Check if a shifting is required to accommodate for the hash segment. 1183 # Get the minimum offset by going through the program headers. 1184 # Note that the program headers in the input file do not contain 1185 # the dummy program header for ELF + Program header, and the 1186 # program header for the hashtable. 1187 min_offset = phdr_table[0].p_offset 1188 for i in range(num_phdrs): 1189 curr_phdr = phdr_table[i] 1190 if curr_phdr.p_offset < min_offset: 1191 min_offset = curr_phdr.p_offset 1192 1193 if min_offset < hash_seg_end: 1194 hashtable_shift = hash_seg_end - min_offset 1195 1196 # Move program headers to after ELF header 1197 phdr_start = elf_header_size 1198 1199 # We copy over no section headers so assign these values to 0 in ELF Header 1200 elf_header.e_shnum = 0 1201 elf_header.e_shstrndx = 0 1202 elf_header.e_shoff = 0 1203 1204 # Output remaining ELF segments 1205 for i in range(num_phdrs): 1206 1207 # Increment the file offset before writing to the destination file 1208 curr_phdr = phdr_table[i] 1209 1210 # We do not copy over program headers of PHDR type, decrement the program 1211 # header count and continue the loop 1212 if curr_phdr.p_type is PHDR_TYPE: 1213 elf_header.e_phnum -= 1 1214 continue 1215 1216 src_offset = curr_phdr.p_offset 1217 1218 # Copy the ELF segment 1219 file_copy_offset(elf_in_fp, src_offset, elf_out_fp, curr_phdr.p_offset + hashtable_shift, curr_phdr.p_filesz) 1220 1221 # Output remaining program headers and ELF segments 1222 elf_header.e_phoff = phdr_start 1223 1224 # Output new program headers which we have generated 1225 elf_out_fp.seek(phdr_start) 1226 new_phdr.p_filesz = elf_header_size + (elf_header.e_phnum * phdr_size) 1227 elf_out_fp.write(new_phdr.getPackedData()) 1228 elf_out_fp.write(hash_Phdr.getPackedData()) 1229 phdr_start += (2 * phdr_size) 1230 1231 # Increment the file offset before writing to the destination file 1232 for i in range(num_phdrs): 1233 curr_phdr = phdr_table[i] 1234 1235 if curr_phdr.p_type is PHDR_TYPE: 1236 continue 1237 1238 curr_phdr.p_offset += hashtable_shift 1239 1240 # Copy the program header 1241 elf_out_fp.seek(phdr_start) 1242 elf_out_fp.write(curr_phdr.getPackedData()) 1243 1244 # Update phdr_start 1245 phdr_start += phdr_size 1246 1247 # Finally, copy the new ELF header to the destination file 1248 elf_out_fp.seek(0) 1249 elf_out_fp.write(elf_header.getPackedData()) 1250 1251 # Recalculate hash of ELF + program headers and output to hash output file 1252 elf_out_fp.seek(0) 1253 # Read the elf header 1254 elfhdr_buff = elf_out_fp.read(elf_header_size) 1255 # Seek to the program header offset listed in elf header. 1256 elf_out_fp.seek(elf_header.e_phoff) 1257 # Read the program header and compute hash 1258 proghdr_buff = elf_out_fp.read(elf_header.e_phnum * phdr_size) 1259 1260 hash = generate_hash(elfhdr_buff + proghdr_buff, sha_algo) 1261 1262 # Write hash to file as first hash table entry 1263 hash_out_fp.seek(0) 1264 hash_out_fp.write(hash) 1265 1266 # Close files 1267 elf_in_fp.close() 1268 hash_out_fp.close() 1269 1270 if elf_out_file_name is not None: 1271 elf_out_fp.close() 1272 1273 return 0 1274 1275 1276#---------------------------------------------------------------------------- 1277# pboot_add_hash 1278#---------------------------------------------------------------------------- 1279def pboot_add_hash(env, elf_in_file_name, 1280 hash_tbl_file_name, 1281 elf_out_file_name): 1282 1283 # Open files 1284 elf_in_fp = OPEN(elf_in_file_name, "rb") 1285 hash_tbl_fp = OPEN(hash_tbl_file_name, "rb") 1286 elf_out_fp = OPEN(elf_out_file_name, "wb+") 1287 1288 # Initialize 1289 [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) 1290 1291 hash_size = os.path.getsize(hash_tbl_file_name) 1292 hash_segment_found = False 1293 1294 # Attempt to find the location of the hash program header 1295 for i in range(elf_header.e_phnum): 1296 curr_phdr = phdr_table[i] 1297 if curr_phdr.p_flags == MI_PBT_ELF_HASH_SEGMENT: 1298 hash_segment_found = True 1299 break 1300 1301 if hash_segment_found is True: 1302 # Copy input file to output file 1303 shutil.copyfileobj(elf_in_fp, elf_out_fp, os.path.getsize(elf_in_file_name)) 1304 1305 # Update ELF to insert hash table at corresponding file offset 1306 hash_hdr_offset = curr_phdr.p_offset 1307 file_copy_offset(hash_tbl_fp, 0, elf_out_fp, hash_hdr_offset, hash_size) 1308 1309 else: 1310 raise RuntimeError("Hash segment program header not found in file " + elf_in_file_name) 1311 1312 # Close files 1313 elf_in_fp.close() 1314 hash_tbl_fp.close() 1315 elf_out_fp.close() 1316 1317 return 0 1318 1319#---------------------------------------------------------------------------- 1320# image_auth 1321#---------------------------------------------------------------------------- 1322def image_auth(env, *args): 1323 1324 if len(args) < 7 or len(args) > 8: 1325 raise RuntimeError("Usage Invalid") 1326 1327 # Initialize File Names 1328 binary_in = args[0] 1329 signature = args[1] 1330 attestation_cert = args[2] 1331 attestation_ca_cert = args[3] 1332 root_cert = args[4] 1333 cert_chain_out = args[5] 1334 signed_image_out = args[6] 1335 if len(args) == 8: 1336 cert_size_max_in = args[7] 1337 else: 1338 cert_size_max_in = CERT_CHAIN_ONEROOT_MAXSIZE 1339 1340 # Creating list of certificates to support creation of certificate chains 1341 # of lenth 1, 2, or 3 certificates 1342 cert_list = [] 1343 num_certs = 0 1344 if (os.path.exists(attestation_cert)): 1345 cert_list.append(attestation_cert) 1346 num_certs = num_certs + 1 1347 if (os.path.exists(attestation_ca_cert)): 1348 cert_list.append(attestation_ca_cert) 1349 num_certs = num_certs + 1 1350 if (os.path.exists(root_cert)): 1351 cert_list.append(root_cert) 1352 num_certs = num_certs + 1 1353 1354 if (num_certs == 0): 1355 raise RuntimeError("Missing file(s) required for signing.\n") 1356 1357 # Create the Certificate Chain 1358 concat_files (cert_chain_out, cert_list) 1359 1360 # Pad to ensure Certificate Chain Size is CERT_CHAIN_MAX_SIZE 1361 cert_size = os.path.getsize(cert_chain_out) 1362 1363 if cert_size <= cert_size_max_in: 1364 bytes_to_pad = cert_size_max_in - cert_size 1365 cert_fp = OPEN(cert_chain_out,'ab') 1366 pad_file(cert_fp, bytes_to_pad, PAD_BYTE_1) 1367 cert_fp.close() 1368 else: 1369 raise RuntimeError("Certificate Size too large: " + str(cert_size)) 1370 1371 # Create the Final Signed Image File 1372 concat_files (signed_image_out, [binary_in, signature, cert_chain_out]) 1373 1374 return 0 1375 1376#---------------------------------------------------------------------------- 1377# modify_relocatable_flags 1378#---------------------------------------------------------------------------- 1379def modify_relocatable_flags(env, output_elf ): 1380 1381 # Offset into program header where the p_flags field is stored 1382 phdr_align_flag_offset = 28 1383 phdr_reloc_flag_offset = 24 1384 1385 # Initialize 1386 [elf_header, phdr_table] = preprocess_elf_file(output_elf) 1387 1388 if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: 1389 curr_phdr = Elf64_Phdr('\0' * ELF64_PHDR_SIZE) 1390 elf_header_size = ELF64_HDR_SIZE 1391 is_elf64 = True 1392 else: 1393 curr_phdr = Elf32_Phdr('\0' * ELF32_PHDR_SIZE) 1394 elf_header_size = ELF32_HDR_SIZE 1395 is_elf64 = False 1396 1397 # Open files 1398 elf_in_fp = OPEN(output_elf, "r+") 1399 1400 # Go to the start of the p_flag entry in the first program header 1401 file_offset_align_flag = elf_header.e_phoff + phdr_align_flag_offset 1402 1403 # Change the align field in the program header in the ELF file 1404 elf_in_fp.seek(file_offset_align_flag) 1405 curr_phdr = phdr_table[0] 1406 1407 #default alignment value is 1MB unless otherwise specified 1408 if 'USES_RELOC_ALIGN_VALUE_4MB' in env: 1409 alignment_value = ALIGNVALUE_4MB 1410 else: 1411 alignment_value = ALIGNVALUE_1MB 1412 1413 1414 1415 #create new alignment value 1416 new_align = (curr_phdr.p_align & 0) | alignment_value 1417 1418 # Create structure to package new flag field 1419 s = struct.Struct('I') 1420 new_flag_bytes = s.pack(new_align) 1421 1422 # Write the new flag value and incr ement offset 1423 elf_in_fp.write(new_flag_bytes) 1424 1425 # Go to the start of the p_flag entry in the first program header 1426 file_offset_reloc_flag = elf_header.e_phoff + phdr_reloc_flag_offset 1427 1428 # Change each program header flag in the ELF file with relocatable flag 1429 for i in range(elf_header.e_phnum): 1430 # Seek to correct location and create new p_flag value 1431 elf_in_fp.seek(file_offset_reloc_flag) 1432 curr_phdr = phdr_table[i] 1433 new_flag = (curr_phdr.p_flags & ~MI_PBT_FLAGS_MASK) | (MI_PBT_ELF_AMSS_RELOCATABLE_IMAGE) 1434 1435 # Create structure to package new flag field 1436 s = struct.Struct('I') 1437 new_flag_bytes = s.pack(new_flag) 1438 1439 # Write the new flag value and increment offset 1440 elf_in_fp.write(new_flag_bytes) 1441 file_offset_reloc_flag += elf_header.e_phentsize 1442 1443 # Close files 1444 elf_in_fp.close() 1445 1446 1447 return 0 1448 1449 1450#---------------------------------------------------------------------------- 1451# modify_elf_flags 1452#---------------------------------------------------------------------------- 1453def modify_elf_flags(env, elf_in_file_name, 1454 scl_file_name): 1455 1456 # Initialize 1457 [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) 1458 segment_list = readSCL(scl_file_name, env['GLOBAL_DICT']) 1459 1460 if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: 1461 curr_phdr = Elf64_Phdr('\0' * ELF64_PHDR_SIZE) 1462 # Offset into program header where the p_flags field is stored 1463 phdr_flag_off = 4 1464 else: 1465 curr_phdr = Elf32_Phdr('\0' * ELF32_PHDR_SIZE) 1466 # Offset into program header where the p_flags field is stored 1467 phdr_flag_off = 24 1468 1469 # Open files 1470 elf_in_fp = OPEN(elf_in_file_name, "r+") 1471 1472 # Check for corresponding number of segments 1473 if len(segment_list) is not elf_header.e_phnum: 1474 raise RuntimeError('SCL file and ELF file have different number of segments!') 1475 1476 # Go to the start of the p_flag entry in the first program header 1477 file_offset = elf_header.e_phoff + phdr_flag_off 1478 1479 # Change each program header flag in the ELF file based off the SCL file 1480 for i in range(elf_header.e_phnum): 1481 # Seek to correct location and create new p_flag value 1482 elf_in_fp.seek(file_offset) 1483 curr_phdr = phdr_table[i] 1484 new_flag = (curr_phdr.p_flags & ~MI_PBT_FLAGS_MASK) | (segment_list[i].flag) 1485 1486 # Create structure to package new flag field 1487 s = struct.Struct('I') 1488 new_flag_bytes = s.pack(new_flag) 1489 1490 # Write the new flag value and increment offset 1491 elf_in_fp.write(new_flag_bytes) 1492 file_offset += elf_header.e_phentsize 1493 1494 # Close files 1495 elf_in_fp.close() 1496 1497 return 0 1498 1499#---------------------------------------------------------------------------- 1500# generate_code_hash 1501#---------------------------------------------------------------------------- 1502def generate_code_hash(env, elf_in_file_name): 1503 1504 # Initialize 1505 [elf_header, phdr_table] = preprocess_elf_file(elf_in_file_name) 1506 1507 if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: 1508 curr_phdr = Elf64_Phdr('\0' * ELF64_PHDR_SIZE) 1509 # Offset into program header where the p_flags field is stored 1510 phdr_flag_off = 4 1511 else: 1512 curr_phdr = Elf32_Phdr('\0' * ELF32_PHDR_SIZE) 1513 # Offset into program header where the p_flags field is stored 1514 phdr_flag_off = 24 1515 1516 # Open files 1517 elf_in_fp = OPEN(elf_in_file_name, "rb+") 1518 1519 # Go to the start of the p_flag entry in the first program header 1520 file_offset = elf_header.e_phoff + phdr_flag_off 1521 1522 # XXX Get these from env? 1523 DP_CODE_ALIGN = 0x100 1524 DP_PAGE_SIZE = 4096 1525 DP_HASH_SIZE = 32 # SHA-256 1526 DP_HASH_MAGIC = 0xC0DEDEC0 1527 PH_PERM_RW = 0x06 1528 PH_PERM_RX = 0x05 1529 PH_PERM_RO = 0x04 1530 PH_PERM_MASK = 0x07 1531 1532 page_size = DP_PAGE_SIZE 1533 hash_size = DP_HASH_SIZE 1534 1535 # First identify the hash segment. It is the first RW section. 1536 # Its Align should be 8, and its size a multiple of DP_HASH_SIZE; 1537 1538 hash_seg_idx = -1 1539 for i in range(elf_header.e_phnum): 1540 curr_phdr = phdr_table[i] 1541 1542 if (curr_phdr.p_align == 8 and 1543 (curr_phdr.p_flags & PH_PERM_MASK) == PH_PERM_RW and 1544 curr_phdr.p_filesz != 0 and (curr_phdr.p_filesz % DP_HASH_SIZE) == 0): 1545 hash_seg_idx = i 1546 # Validate the contents of the hash segment. It should be 1547 # filled with DP_HASH_MAGIC 1548 elf_in_fp.seek(curr_phdr.p_offset) 1549 hash_data = ""; 1550 while (len(hash_data) < curr_phdr.p_filesz): 1551 hash_data = hash_data + elf_in_fp.read(curr_phdr.p_filesz - len(hash_data)) 1552 1553 hash_data = struct.unpack("I" * (curr_phdr.p_filesz / 4), hash_data) 1554 1555 for v in hash_data[:]: 1556 if (v != DP_HASH_MAGIC): 1557 hash_seg_idx = -1 1558 break; 1559 1560 if (hash_seg_idx != -1): 1561 break 1562 1563 if (hash_seg_idx == -1): 1564 # return if there is no hash segment. 1565 return 0 1566 1567 hash_phdr = phdr_table[hash_seg_idx] 1568 1569 # Now find the code segment for the hashes. Look for matching number of pages 1570 code_seg_idx = -1 1571 code_seg_pages = hash_phdr.p_filesz / DP_HASH_SIZE 1572 1573 for i in range(elf_header.e_phnum): 1574 curr_phdr = phdr_table[i] 1575 curr_pages = (curr_phdr.p_filesz + DP_PAGE_SIZE - 1) / DP_PAGE_SIZE 1576 1577 if (curr_phdr.p_align == DP_CODE_ALIGN and 1578 (curr_phdr.p_flags & PH_PERM_MASK) == PH_PERM_RX and 1579 curr_pages == code_seg_pages): 1580 if (code_seg_idx != -1): 1581 raise RuntimeError('Multiple code segments match for: ' + code_seg_pages + ' pages') 1582 code_seg_idx = i 1583 1584 if (code_seg_idx == -1): 1585 raise RuntimeError('No matching code segment found') 1586 1587 code_phdr = phdr_table[code_seg_idx] 1588 1589 # Now hash the pages in the code segment 1590 hashes = [] 1591 elf_in_fp.seek(code_phdr.p_offset) 1592 bytes_left = code_phdr.p_filesz; 1593 while (bytes_left > 0): 1594 bytes_in_page = min(bytes_left, DP_PAGE_SIZE) 1595 page = ""; 1596 while (len(page) < bytes_in_page): 1597 page = page + elf_in_fp.read(bytes_in_page - len(page)) 1598 if (len(page) < DP_PAGE_SIZE): 1599 page = page + (struct.pack('b', 0) * (DP_PAGE_SIZE - len(page))) 1600 hashes = hashes + [generate_hash(page, 'SHA256')] 1601 bytes_left -= bytes_in_page 1602 1603 # And write them to the hash segment 1604 elf_in_fp.seek(hash_phdr.p_offset) 1605 1606 for h in hashes[:]: 1607 elf_in_fp.write(h) 1608 1609 # Close files 1610 elf_in_fp.close() 1611 1612 return 0 1613 1614#---------------------------------------------------------------------------- 1615# BOOT TOOLS END 1616#---------------------------------------------------------------------------- 1617 1618#---------------------------------------------------------------------------- 1619# HELPER FUNCTIONS BEGIN 1620#---------------------------------------------------------------------------- 1621 1622#---------------------------------------------------------------------------- 1623# Create a list to hold all segment information from an input SCL file 1624#---------------------------------------------------------------------------- 1625def readSCL(filename, global_dict): 1626 1627 scl_fp = OPEN(filename,'r') 1628 1629 # Initialize 1630 file_data = scl_fp.readlines() 1631 num_lines = len(file_data) 1632 current_line = '' 1633 previous_line = '' 1634 strip_chars = '(){}[]' 1635 i = 0 1636 bracket_counter = 0 1637 seg_list = [] 1638 1639 # Parse through all lines 1640 while i < num_lines: 1641 1642 # Save the last line read 1643 previous_line = current_line 1644 current_line = file_data[i] 1645 1646 # Look for the symbol '{' for the line to read. 1647 # Use bracket counter to skip nested '{ }' 1648 if ('{' in current_line): 1649 if bracket_counter == 0: 1650 # Create a new SegmentInfo class and set up tokens 1651 new_scl_entry = SegmentInfo() 1652 previous_line = previous_line.strip() 1653 tokens = previous_line.split(' ') 1654 1655 # Check that at least two tokens were parsed 1656 # Token 1: Segment Name 1657 # Token 2: Start Address -- not used in MBN tools 1658 if len(tokens) < 2: 1659 raise RuntimeError('SCL Segment Syntax malformed: ' + previous_line) 1660 1661 # Get the segment flags corresponding to the segment name description 1662 new_scl_entry.flag = getSegmentFlag(tokens[0].strip(strip_chars)) 1663 seg_list.append(new_scl_entry) 1664 1665 bracket_counter += 1 1666 elif '}' in current_line: 1667 bracket_counter -= 1 1668 1669 i+=1 1670 1671 scl_fp.close() 1672 return seg_list 1673 1674#---------------------------------------------------------------------------- 1675# Given a string parsed from a SCL file, returns the ELF segment flags 1676#---------------------------------------------------------------------------- 1677def getSegmentFlag(seg_info): 1678 1679 ret_val = None 1680 1681 # Define string values for various types of segments 1682 RO = "RO" 1683 RW = "RW" 1684 ZI = "ZI" 1685 PAGEABLE = "PAGED" 1686 NOTPAGEABLE = "NOTPAGED" 1687 SWAPABLE = "SWAPPED" 1688 SWAP_POOL = "SWAP_POOL" 1689 RESERVED = "RESERVED" 1690 HASHTBL = "HASH" 1691 SHARED = "SHARED" 1692 NOTUSED = "NOTUSED" 1693 BOOT_SEGMENT = "BOOT_SEGMENT" 1694 CODE = "CODE" 1695 L4BSP = "L4BSP" 1696 POOL_INDEX_0 = "INDEX_0" 1697 POOL_INDEX_1 = "INDEX_1" 1698 1699 # New definitions for EOS demand paging 1700 NONPAGE = "NONPAGE" 1701 PAGEUNLOCKED = "PAGEUNLOCKED" 1702 PAGELOCKED = "PAGELOCKED" 1703 UNSECURE = "UNSECURE" 1704 1705 if seg_info is None or len(seg_info) == 0: 1706 raise RuntimeError('Invalid segment information passed: ' + seg_info) 1707 1708 # Conditional checks and assignments of the corresponding segment flag values 1709 if NOTPAGEABLE in seg_info: 1710 if RO in seg_info: 1711 ret_val = MI_PBT_ELF_AMSS_NON_PAGED_RO_SEGMENT 1712 elif CODE in seg_info: 1713 ret_val = MI_PBT_ELF_AMSS_NON_PAGED_RO_SEGMENT 1714 elif ZI in seg_info: 1715 if SWAP_POOL in seg_info: 1716 if POOL_INDEX_0 in seg_info: 1717 ret_val = MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX0 1718 else: 1719 ret_val = MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX1 1720 else: 1721 ret_val = MI_PBT_ELF_AMSS_NON_PAGED_ZI_SEGMENT 1722 1723 elif NOTUSED in seg_info: 1724 ret_val = MI_PBT_ELF_AMSS_NON_PAGED_NOTUSED_SEGMENT 1725 1726 elif SHARED in seg_info: 1727 ret_val = MI_PBT_ELF_AMSS_NON_PAGED_SHARED_SEGMENT 1728 elif HASHTBL in seg_info: 1729 ret_val = MI_PBT_ELF_HASH_SEGMENT 1730 elif BOOT_SEGMENT in seg_info: 1731 ret_val = MI_PBT_ELF_BOOT_SEGMENT 1732 elif L4BSP in seg_info: 1733 ret_val = MI_PBT_ELF_NON_PAGED_L4BSP_SEGMENT 1734 else: 1735 ret_val = MI_PBT_ELF_AMSS_NON_PAGED_RW_SEGMENT 1736 1737 elif PAGEABLE in seg_info: 1738 if RO in seg_info or CODE in seg_info: 1739 if SWAPABLE in seg_info: 1740 if POOL_INDEX_0 in seg_info: 1741 ret_val = MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX0 1742 else: 1743 ret_val = MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX1 1744 else: 1745 ret_val = MI_PBT_ELF_AMSS_PAGED_RO_SEGMENT 1746 elif ZI in seg_info: 1747 ret_val = MI_PBT_ELF_AMSS_PAGED_ZI_SEGMENT 1748 1749 elif NOTUSED in seg_info: 1750 ret_val = MI_PBT_ELF_AMSS_PAGED_NOTUSED_SEGMENT 1751 elif SHARED in seg_info: 1752 ret_val = MI_PBT_ELF_AMSS_PAGED_SHARED_SEGMENT 1753 elif L4BSP in seg_info: 1754 ret_val = MI_PBT_ELF_PAGED_L4BSP_SEGMENT 1755 else: 1756 ret_val = MI_PBT_ELF_AMSS_PAGED_RW_SEGMENT 1757 1758 elif PAGELOCKED in seg_info: 1759 ret_val = MI_PBT_ELF_PAGED_LOCKED_SEGMENT 1760 elif PAGEUNLOCKED in seg_info: 1761 ret_val = MI_PBT_ELF_PAGED_UNLOCKED_SEGMENT 1762 elif NONPAGE in seg_info: 1763 ret_val = MI_PBT_ELF_RESIDENT_SEGMENT 1764 elif UNSECURE in seg_info: 1765 ret_val = MI_PBT_ELF_UNSECURE_SEGMENT 1766 1767 else: 1768 raise RuntimeError('The segment name is wrongly defined in the SCL file: ' + seg_info) 1769 1770 return ret_val 1771 1772#---------------------------------------------------------------------------- 1773# Pad a file with specific number of bytes 1774# Note: Assumes the fp is seeked to the correct location of padding 1775#---------------------------------------------------------------------------- 1776def pad_file(fp, num_bytes, value): 1777 1778 if num_bytes < 0: 1779 raise RuntimeError("Number of bytes to pad must be greater than zero") 1780 1781 while num_bytes > 0: 1782 fp.write('%c' % value) 1783 num_bytes -= 1 1784 1785 return 1786 1787#---------------------------------------------------------------------------- 1788# Concatenates the files listed in 'sources' in order and writes to 'target' 1789#---------------------------------------------------------------------------- 1790def concat_files (target, sources): 1791 if type(sources) is not list: 1792 sources = [sources] 1793 1794 target_file = OPEN(target,'wb') 1795 1796 for fname in sources: 1797 file = OPEN(fname,'rb') 1798 while True: 1799 bin_data = file.read(65536) 1800 if not bin_data: 1801 break 1802 target_file.write(bin_data) 1803 file.close() 1804 target_file.close() 1805 1806#---------------------------------------------------------------------------- 1807# Parse build configurable values and assign to global variables for tools 1808#---------------------------------------------------------------------------- 1809def init_build_vars(env): 1810 1811 # Maximum size of Certificate Chain used in Secure Boot 1812 global CERT_CHAIN_ONEROOT_MAXSIZE 1813 CERT_CHAIN_ONEROOT_MAXSIZE = get_dict_value(env['GLOBAL_DICT'], 'CERT_CHAIN_MAXSIZE', (6*1024)) 1814 1815 # Maximum size of the XML Header used in encrypted ELF images 1816 global XML_HEADER_MAXSIZE 1817 XML_HEADER_MAXSIZE = get_dict_value(env['GLOBAL_DICT'], 'XML_HEADER_MAXSIZE', (2*1024)) 1818 1819#---------------------------------------------------------------------------- 1820# Generates the global dictionary and add to the environment 1821#---------------------------------------------------------------------------- 1822def generate_global_dict(env): 1823 1824 # Get file names for 'cust' and 'targ' auto-generated files inside 'build/ms' 1825 cust_h = env.subst('CUST${BUILD_ID}.H').lower() 1826 targ_h = env.subst('TARG${BUILD_ID}.H').lower() 1827 cust_file_name = str(env.FindFile(cust_h, "${INC_ROOT}/build/ms")) 1828 targ_file_name = str(env.FindFile(targ_h, "${INC_ROOT}/build/ms")) 1829 1830 # Check that files are present 1831 if (os.path.exists(cust_file_name) is True) and \ 1832 (os.path.exists(targ_file_name) is True): 1833 1834 # Populate the dictionary from the auto-generated files 1835 global_dict = populate_dictionary(targ_file_name, cust_file_name) 1836 else: 1837 global_dict = {} 1838 1839 # Add the dictionary to the environment 1840 env.Replace(GLOBAL_DICT = global_dict) 1841 1842#---------------------------------------------------------------------------- 1843# Populate the dictionary from a list of input files 1844#---------------------------------------------------------------------------- 1845def populate_dictionary(*args): 1846 1847 if len(args) < 1: 1848 raise RuntimeError("At least 1 file must be specified as an input") 1849 1850 global_dict = {} 1851 Fields = ["Define", "Key", "Value"] 1852 1853 # For each input file 1854 for i in range(len(args)): 1855 1856 template_file_path = args[i] 1857 instream = OPEN(template_file_path, 'r') 1858 # Tokenize each line with a white space 1859 values = csv.DictReader(instream, Fields, delimiter=" ") 1860 1861 for values in itertools.izip(values): 1862 new_entry = values[0] 1863 # Verify the parsed tokens 1864 if (new_entry['Define'] == '#define') and \ 1865 (new_entry['Key'] != None) and \ 1866 (new_entry['Value'] != None): 1867 1868 new_key = new_entry['Key'].strip() 1869 new_value = new_entry['Value'].strip() 1870 1871 # If value pair is empty string, assume feature definition is true 1872 if new_value == '': 1873 new_value = 'yes' 1874 1875 # Check for and handle text replacements as we parse 1876 if global_dict is not None and len(global_dict.keys()) > 0: 1877 for key in global_dict: 1878 new_value = new_value.replace(key, str(global_dict.get(key))) 1879 1880 # Attempt to evaluate value 1881 try: 1882 new_value = eval(new_value) 1883 # Catch exceptions and do not evaluate 1884 except: 1885 pass 1886 1887 # Add to global dictionary 1888 global_dict[new_key] = new_value 1889 instream.close() 1890 1891 return global_dict 1892 1893#---------------------------------------------------------------------------- 1894# Filter out a generic dictionary from the global dictionary 1895#---------------------------------------------------------------------------- 1896def filter_dictionary(env, global_dict, **kwargs): 1897 1898 # Check for Image Type 1899 # If IMAGE_TYPE parameter is not provided, raise error 1900 if not kwargs.has_key('IMAGE_TYPE'): 1901 raise RuntimeError("IMAGE_TYPE must be defined to use FilterDictionary.") 1902 else: 1903 image_type = kwargs.get('IMAGE_TYPE') 1904 if type(image_type) is not str: 1905 raise RuntimeError("IMAGE_TYPE must be of string type.") 1906 1907 # Check for Flash Type 1908 # If FLASH_TYPE parameter is not provided, default to 'nand' 1909 if not kwargs.has_key('FLASH_TYPE'): 1910 flash_type = 'nand' 1911 else: 1912 flash_type = kwargs.get('FLASH_TYPE') 1913 if type(flash_type) is not str: 1914 raise RuntimeError("FLASH_TYPE must be of string type. ") 1915 1916 # Check for MBN Type 1917 # If MBN_TYPE parameter is not provided, default to 'elf' 1918 if not kwargs.has_key('MBN_TYPE'): 1919 mbn_type = 'elf' 1920 else: 1921 mbn_type = kwargs.get('MBN_TYPE') 1922 if mbn_type != 'elf' and mbn_type != 'bin': 1923 raise RuntimeError("MBN_TYPE currently not supported: " + mbn_type) 1924 1925 # Check for Image ID 1926 # If IMAGE_ID parameter is not provided, default to ID 0 1927 if not kwargs.has_key('IMAGE_ID'): 1928 image_id = ImageType.NONE_IMG 1929 else: 1930 image_id = kwargs.get('IMAGE_ID') 1931 if type(image_id) is not int: 1932 raise RuntimeError("IMAGE_ID must be of integer type.") 1933 1934 # Initialize 1935 gen_dict = {} 1936 image_dest = 0 1937 image_source = 0 1938 1939 # Check for image_type 1940 if image_type not in image_id_table: 1941 id = image_id 1942 id_match_str = image_type.upper() + "_IMG" 1943 id_mbn_type = mbn_type 1944 else: 1945 id = image_id_table[image_type][0] 1946 id_match_str = image_id_table[image_type][1] 1947 id_mbn_type = image_id_table[image_type][2] 1948 1949 # Handle MBN Type and assign image destination address 1950 if id_mbn_type == 'elf': 1951 pass 1952 elif id_mbn_type == 'bin': 1953 template_key_match = 'IMAGE_KEY_' + id_match_str + "_DEST_ADDR" 1954 if template_key_match in global_dict: 1955 image_dest = global_dict[template_key_match] 1956 else: 1957 raise RuntimeError("Builds file does not have IMAGE_KEY pair for: " + image_type) 1958 else: 1959 raise RuntimeError("MBN_TYPE currently not supported: " + mbn_type) 1960 1961 # Assign generic dictionary key/value pairs 1962 gen_dict['IMAGE_KEY_IMAGE_ID'] = id 1963 gen_dict['IMAGE_KEY_IMAGE_DEST'] = image_dest 1964 gen_dict['IMAGE_KEY_IMAGE_SOURCE'] = image_source 1965 gen_dict['IMAGE_KEY_FLASH_TYPE'] = flash_type 1966 gen_dict['IMAGE_KEY_MBN_TYPE'] = id_mbn_type 1967 gen_dict['IMAGE_KEY_ID_MATCH_STR'] = id_match_str 1968 gen_dict['IMAGE_KEY_FLASH_AUTO_DETECT_MAX_PAGE'] = \ 1969 get_dict_value(global_dict,'FLASH_AUTO_DETECT_MAX_PAGE', 8192) 1970 gen_dict['IMAGE_KEY_FLASH_AUTO_DETECT_MIN_PAGE'] = \ 1971 get_dict_value(global_dict,'FLASH_AUTO_DETECT_MIN_PAGE', 2048) 1972 gen_dict['IMAGE_KEY_MAX_SIZE_OF_VERIFY_BUFFER'] = \ 1973 get_dict_value(global_dict,'MAX_SIZE_OF_VERIFY_BUFFER', 8192) 1974 gen_dict['IMAGE_KEY_BOOT_SMALL_PREAMBLE'] = \ 1975 get_dict_value(global_dict,'BOOT_SMALL_PREAMBLE', 1) 1976 1977 # Get OEM root certificate select and number 1978 oem_root_cert_sel = get_dict_value(global_dict,'OEM_ROOT_CERT_SEL', 1) 1979 oem_num_root_certs = get_dict_value(global_dict,'OEM_NUM_ROOT_CERTS', 1) 1980 1981 # Error checking for OEM configurable values 1982 if oem_root_cert_sel in range(1, MAX_NUM_ROOT_CERTS + 1) and \ 1983 oem_num_root_certs in range(1, MAX_NUM_ROOT_CERTS + 1) and \ 1984 oem_root_cert_sel <= oem_num_root_certs: 1985 1986 gen_dict['IMAGE_KEY_OEM_ROOT_CERT_SEL'] = oem_root_cert_sel 1987 gen_dict['IMAGE_KEY_OEM_NUM_ROOT_CERTS'] = oem_num_root_certs 1988 1989 else: 1990 raise RuntimeError("Invalid OEM root certificate configuration values") 1991 1992 # Assign additional dictionary key/values pair as needed by tools. 1993 1994 return gen_dict 1995 1996 1997#---------------------------------------------------------------------------- 1998# Get index value from dictionary if exists, otherwise return default 1999#---------------------------------------------------------------------------- 2000def get_dict_value(dict, key_string, default): 2001 2002 key = 'IMAGE_KEY_' + key_string 2003 2004 if key in dict: 2005 return dict[key] 2006 else: 2007 return default 2008 2009#---------------------------------------------------------------------------- 2010# Preprocess an ELF file and return the ELF Header Object and an 2011# array of ELF Program Header Objects 2012#---------------------------------------------------------------------------- 2013def preprocess_elf_file(elf_file_name): 2014 2015 # Initialize 2016 elf_fp = OPEN(elf_file_name, 'rb') 2017 elf_header = Elf_Ehdr_common(elf_fp.read(ELF_HDR_COMMON_SIZE)) 2018 2019 if verify_elf_header(elf_header) is False: 2020 raise RuntimeError("ELF file failed verification: " + elf_file_name) 2021 2022 elf_fp.seek(0) 2023 2024 if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: 2025 elf_header = Elf64_Ehdr(elf_fp.read(ELF64_HDR_SIZE)) 2026 else: 2027 elf_header = Elf32_Ehdr(elf_fp.read(ELF32_HDR_SIZE)) 2028 2029 phdr_table = [] 2030 2031 # Verify ELF header information 2032 if verify_elf_header(elf_header) is False: 2033 raise RuntimeError("ELF file failed verification: " + elf_file_name) 2034 2035 # Get program header size 2036 phdr_size = elf_header.e_phentsize 2037 2038 # Find the program header offset 2039 file_offset = elf_header.e_phoff 2040 elf_fp.seek(file_offset) 2041 2042 # Read in the program headers 2043 for i in range(elf_header.e_phnum): 2044 if elf_header.e_ident[ELFINFO_CLASS_INDEX] == ELFINFO_CLASS_64: 2045 phdr_table.append(Elf64_Phdr(elf_fp.read(phdr_size))) 2046 else: 2047 phdr_table.append(Elf32_Phdr(elf_fp.read(phdr_size))) 2048 2049 elf_fp.close() 2050 return [elf_header, phdr_table] 2051 2052#---------------------------------------------------------------------------- 2053# Get the hash table address from an input ELF file 2054#---------------------------------------------------------------------------- 2055def get_hash_address(elf_file_name): 2056 2057 [elf_header, phdr_table] = preprocess_elf_file(elf_file_name) 2058 2059 last_paddr = 0 2060 last_paddr_segment = 0 2061 2062 # Find the segment with the largest physical address. 2063 # Hash segment's physical address will be immediately after this segment. 2064 for i in range(elf_header.e_phnum): 2065 curr_phdr = phdr_table[i] 2066 if curr_phdr.p_paddr > last_paddr: 2067 # Skip the demand paging segment as it would be outside the physical RAM location 2068 if MI_PBT_SEGMENT_TYPE_VALUE(curr_phdr.p_flags) != MI_PBT_XBL_SEC_SEGMENT: 2069 last_paddr = curr_phdr.p_paddr; 2070 last_paddr_segment = i; 2071 2072 max_phdr = phdr_table[last_paddr_segment] 2073 2074 ret_val = (((max_phdr.p_paddr + max_phdr.p_memsz - 1) & \ 2075 ~(ELF_BLOCK_ALIGN-1)) + ELF_BLOCK_ALIGN) 2076 2077 return ret_val 2078 2079#---------------------------------------------------------------------------- 2080# Verify ELF header contents from an input ELF file 2081#---------------------------------------------------------------------------- 2082def verify_elf_header(elf_header): 2083 if (elf_header.e_ident[ELFINFO_MAG0_INDEX] != ELFINFO_MAG0): 2084 print("MAG0[{:d}]\n".format((elf_header.e_ident[ELFINFO_MAG0_INDEX]))) 2085 return False 2086 if (elf_header.e_ident[ELFINFO_MAG1_INDEX] != ELFINFO_MAG1): 2087 print("MAG1[{:d}]\n".format((elf_header.e_ident[ELFINFO_MAG1_INDEX]))) 2088 return False 2089 if (elf_header.e_ident[ELFINFO_MAG2_INDEX] != ELFINFO_MAG2): 2090 print("MAG2[{:d}]\n".format((elf_header.e_ident[ELFINFO_MAG2_INDEX]))) 2091 return False 2092 if (elf_header.e_ident[ELFINFO_MAG3_INDEX] != ELFINFO_MAG3): 2093 print("MAG3[{:d}]\n".format((elf_header.e_ident[ELFINFO_MAG3_INDEX]))) 2094 return False 2095 if ((elf_header.e_ident[ELFINFO_CLASS_INDEX] != ELFINFO_CLASS_64) and \ 2096 (elf_header.e_ident[ELFINFO_CLASS_INDEX] != ELFINFO_CLASS_32)): 2097 print("ELFINFO_CLASS_INDEX[{:d}]\n".format((elf_header.e_ident[ELFINFO_CLASS_INDEX]))) 2098 return False 2099 if (elf_header.e_ident[ELFINFO_VERSION_INDEX] != ELFINFO_VERSION_CURRENT): 2100 print("ELFINFO_VERSION_INDEX[{:d}]\n".format((elf_header.e_ident[ELFINFO_VERSION_INDEX]))) 2101 return False 2102 return True 2103 2104#---------------------------------------------------------------------------- 2105# Perform file copy given offsets and the number of bytes to copy 2106#---------------------------------------------------------------------------- 2107def file_copy_offset(in_fp, in_off, out_fp, out_off, num_bytes): 2108 in_fp.seek(in_off) 2109 read_in = in_fp.read(num_bytes) 2110 out_fp.seek(out_off) 2111 out_fp.write(read_in) 2112 2113 return num_bytes 2114 2115#---------------------------------------------------------------------------- 2116# sha1/sha256 hash routine wrapper 2117#---------------------------------------------------------------------------- 2118def header_size(header_version): 2119 if header_version >= 6: 2120 return 48 2121 else: 2122 return 40 2123 2124#---------------------------------------------------------------------------- 2125# sha1/sha256 hash routine wrapper 2126#---------------------------------------------------------------------------- 2127def generate_hash(in_buf, sha_algo): 2128 # Initialize a SHA1 object from the Python hash library 2129 if sha_algo == 'SHA384': 2130 m = hashlib.sha384() 2131 elif sha_algo == 'SHA256': 2132 m = hashlib.sha256() 2133 else: 2134 m = hashlib.sha1() 2135 2136 # Set the input buffer and return the output digest 2137 m.update(in_buf) 2138 return m.digest() 2139 2140#---------------------------------------------------------------------------- 2141# Initialize the hash program header. 2142#---------------------------------------------------------------------------- 2143def initialize_hash_phdr(elf_in_file_name, hash_tbl_size, hdr_size, hdr_offset, is_elf64): 2144 # Set hash header offset to page size boundary. Hash table will be 2145 # located at first segment of elf image. 2146 hash_hdr_size = hdr_size 2147 hash_hdr_offset = hdr_offset 2148 hash_tbl_offset = hash_hdr_offset + hash_hdr_size 2149 hash_tbl_end_addr = hash_tbl_offset + hash_tbl_size; 2150 pad_hash_segment = (hash_tbl_end_addr) & (ELF_BLOCK_ALIGN-1) 2151 2152 # Update the hash table program header 2153 if is_elf64 is True: 2154 hash_Phdr = Elf64_Phdr(b'\0'*ELF64_PHDR_SIZE) 2155 else: 2156 hash_Phdr = Elf32_Phdr(b'\0'*ELF32_PHDR_SIZE) 2157 hash_Phdr.p_flags = MI_PBT_ELF_HASH_SEGMENT 2158 hash_Phdr.p_align = ELF_BLOCK_ALIGN 2159 hash_Phdr.p_offset = hash_hdr_offset 2160 hash_Phdr.p_memsz = hash_hdr_size + hash_tbl_size + (ELF_BLOCK_ALIGN - pad_hash_segment) 2161 hash_Phdr.p_filesz = hash_hdr_size + hash_tbl_size 2162 hash_Phdr.p_type = NULL_TYPE 2163 hash_Phdr.p_vaddr = get_hash_address(elf_in_file_name) 2164 hash_Phdr.p_paddr = hash_Phdr.p_vaddr 2165 2166 return [hash_Phdr, pad_hash_segment, hash_tbl_end_addr, hash_tbl_offset] 2167 2168#---------------------------------------------------------------------------- 2169# image_preamble 2170#---------------------------------------------------------------------------- 2171def image_preamble(gen_dict, preamble_file_name, boot_sbl_header, num_of_pages=None): 2172 # Generate the preamble file 2173 preamble_fp = OPEN(preamble_file_name, 'wb') 2174 2175 # Initialize 2176 max_size_verify = gen_dict['IMAGE_KEY_MAX_SIZE_OF_VERIFY_BUFFER'] 2177 flash_max_page = gen_dict['IMAGE_KEY_FLASH_AUTO_DETECT_MAX_PAGE'] 2178 flash_min_page = gen_dict['IMAGE_KEY_FLASH_AUTO_DETECT_MIN_PAGE'] 2179 autodetectpage = [int('0xFFFFFFFF',16)] * max_size_verify 2180 2181 # The first three entries in the preamble must include the following values 2182 autodetectpage[0] = FLASH_CODE_WORD 2183 autodetectpage[1] = MAGIC_NUM 2184 if (num_of_pages == 64): 2185 autodetectpage[2] = AUTODETECT_PAGE_SIZE_MAGIC_NUM64 2186 elif (num_of_pages == 128): 2187 autodetectpage[2] = AUTODETECT_PAGE_SIZE_MAGIC_NUM128 2188 else: 2189 autodetectpage[2] = AUTODETECT_PAGE_SIZE_MAGIC_NUM 2190 2191 # Package the list into binary data to be written to the preamble 2192 s = struct.Struct('I' * max_size_verify) 2193 packed_data = s.pack(*autodetectpage) 2194 2195 # Output preamble pages based on maximum/minimum page size support 2196 for i in range(flash_max_page/flash_min_page): 2197 preamble_fp.write(packed_data[:flash_min_page]) 2198 2199 # Determine appropriate amount of padding for the preamble and 2200 # update the boot_sbl_header accordingly 2201 if gen_dict['IMAGE_KEY_BOOT_SMALL_PREAMBLE'] == 1: 2202 boot_sbl_header.image_src += (flash_max_page + flash_min_page) 2203 amount_to_write = flash_min_page 2204 else: 2205 boot_sbl_header.image_src += flash_max_page * 2 2206 amount_to_write = flash_max_page 2207 2208 pad_file(preamble_fp, amount_to_write, PAD_BYTE_1) 2209 preamble_fp.close() 2210 2211 return boot_sbl_header 2212 2213#---------------------------------------------------------------------------- 2214# Helper functions to parse ELF program headers 2215#---------------------------------------------------------------------------- 2216def MI_PBT_SEGMENT_TYPE_VALUE(x): 2217 return ( ((x) & MI_PBT_FLAG_SEGMENT_TYPE_MASK) >> MI_PBT_FLAG_SEGMENT_TYPE_SHIFT ) 2218 2219def MI_PBT_PAGE_MODE_VALUE(x): 2220 return ( ((x) & MI_PBT_FLAG_PAGE_MODE_MASK) >> MI_PBT_FLAG_PAGE_MODE_SHIFT ) 2221 2222def MI_PBT_ACCESS_TYPE_VALUE(x): 2223 return ( ((x) & MI_PBT_FLAG_ACCESS_TYPE_MASK) >> MI_PBT_FLAG_ACCESS_TYPE_SHIFT ) 2224 2225def MI_PBT_CHECK_FLAG_TYPE(x): 2226 return (MI_PBT_SEGMENT_TYPE_VALUE(x) != MI_PBT_HASH_SEGMENT) and \ 2227 (MI_PBT_ACCESS_TYPE_VALUE(x) != MI_PBT_NOTUSED_SEGMENT) and \ 2228 (MI_PBT_ACCESS_TYPE_VALUE(x) != MI_PBT_SHARED_SEGMENT) 2229 2230 2231#---------------------------------------------------------------------------- 2232# Helper functions to open a file and return a valid file object 2233#---------------------------------------------------------------------------- 2234def OPEN(file_name, mode): 2235 try: 2236 fp = open(file_name, mode) 2237 except IOError: 2238 raise RuntimeError("The file could not be opened: " + file_name) 2239 2240 # File open has succeeded with the given mode, return the file object 2241 return fp 2242 2243#---------------------------------------------------------------------------- 2244# Helper functions to insert MCs in SBL1(Badger) if ENABLE_VIRTUAL_BLK is ON 2245#---------------------------------------------------------------------------- 2246def insert_SBL1_magicCookie (env, target): 2247 file = open(target, "rb") 2248 #read the file contents 2249 filedata = file.read() 2250 length = len(filedata) 2251 file.close() 2252 2253 if (length <= VIRTUAL_BLOCK_SIZE): 2254 return None 2255 else: 2256 #remove the previous file 2257 os.remove(target) 2258 #generate new file for appending target data + required MCs 2259 file = open(target, "ab") 2260 2261 while length > VIRTUAL_BLOCK_SIZE: 2262 filedata_till_128kb = filedata[0:VIRTUAL_BLOCK_SIZE] 2263 filedata_after_128kb = filedata[VIRTUAL_BLOCK_SIZE:length] 2264 2265 a = str(hex(FLASH_CODE_WORD)) 2266 mc1 = chr(int(a[8:10],16)) + chr(int(a[6:8],16)) + chr(int(a[4:6],16)) + chr(int(a[2:4],16)) 2267 2268 b = str(hex(MAGIC_NUM)) 2269 mc2 = chr(int(b[8:10],16)) + chr(int(b[6:8],16)) + chr(int(b[4:6],16)) + chr(int(b[2:4],16)) 2270 2271 c = str(hex(SBL_VIRTUAL_BLOCK_MAGIC_NUM)) 2272 mc3 = chr(int(c[8:10],16)) + chr(int(c[6:8],16)) + chr(int(c[4:6],16)) + chr(int(c[2:4],16)) 2273 2274 MC_inserted_data = filedata_till_128kb + mc1 + mc2 + mc3 2275 file.write(MC_inserted_data) 2276 2277 filedata = filedata_after_128kb 2278 length = len(filedata) 2279 2280 #copy the leftover data (<128KB) in output file 2281 if length > 0: 2282 file.write(filedata) 2283 2284 #close the final output file 2285 file.close() 2286 # MC_insertion code end 2287 2288#---------------------------------------------------------------------------- 2289# Helper functions to remove MCs in SBL1(Badger) 2290#---------------------------------------------------------------------------- 2291def remove_SBL1_magicCookie (env, target, dest): 2292 file = open(target, "rb") 2293 #read the file contents 2294 filedata = file.read() 2295 length = len(filedata) 2296 file.close() 2297 2298 #generate new file for appending target data + required MCs 2299 file = open(dest, "ab") 2300 2301 while length > VIRTUAL_BLOCK_SIZE: 2302 filedata_till_128kb = filedata[0:VIRTUAL_BLOCK_SIZE] 2303 # skipped 12 byte of Virtual Block Magic Cookie Header 2304 filedata_after_128kb = filedata[VIRTUAL_BLOCK_SIZE+MAGIC_COOKIE_LENGTH:length] 2305 2306 file.write(filedata_till_128kb) 2307 2308 filedata = filedata_after_128kb 2309 length = len(filedata) 2310 2311 #copy the leftover data (<128KB) in output file 2312 if length > 0: 2313 file.write(filedata) 2314 2315 #close the final output file 2316 file.close() 2317 2318 # MC_removal code end 2319 2320#---------------------------------------------------------------------------- 2321# Helper functions to pad SBL1 image 2322# min_size defaults to 256k 2323# If page_size or num_of_pages is set to 0, the variable is unset 2324#---------------------------------------------------------------------------- 2325def pad_SBL1_image (env, target, min_size_with_pad=MIN_IMAGE_SIZE_WITH_PAD, page_size=0, num_of_pages=0): 2326 file = open(target, "rb") 2327 #read the file contents 2328 filedata = file.read() 2329 length = len(filedata) 2330 file.close() 2331 2332 multiple = 1 2333 alignment = page_size * num_of_pages 2334 2335 if (length > alignment and alignment > 0): 2336 import math 2337 multiple = math.ceil(length/float(alignment)) 2338 2339 final_image_size = max(min_size_with_pad, multiple * alignment) 2340 2341 if length < final_image_size: 2342 sbl1_fp = open(target, 'ab') 2343 pad_file (sbl1_fp, (final_image_size-length), PAD_BYTE_0) 2344 sbl1_fp.close() 2345 2346 # SBL1 pad code end 2347#---------------------------------------------------------------------------- 2348# HELPER FUNCTIONS END 2349#---------------------------------------------------------------------------- 2350