2 #===============================================================================
7 # Contains all MBN Utilities for image generation
9 # SPDX-License-Identifier: BSD-3-Clause
11 #-------------------------------------------------------------------------------
12 # EDIT HISTORY FOR FILE
14 # This section contains comments describing changes made to the module.
15 # Notice that changes are listed in reverse chronological order.
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
29 # 10/20/11 dxiang Clean up
30 #===============================================================================
40 #----------------------------------------------------------------------------
41 # GLOBAL VARIABLES BEGIN
42 #----------------------------------------------------------------------------
43 PAD_BYTE_1
= 255 # Padding byte 1s
44 PAD_BYTE_0
= 0 # Padding byte 0s
45 SHA256_SIGNATURE_SIZE
= 256 # Support SHA256
46 MAX_NUM_ROOT_CERTS
= 4 # Maximum number of OEM root certificates
47 MI_BOOT_SBL_HDR_SIZE
= 80 # sizeof(sbl_header)
48 BOOT_HEADER_LENGTH
= 20 # Boot Header Number of Elements
49 SBL_HEADER_LENGTH
= 20 # SBL Header Number of Elements
50 MAX_PHDR_COUNT
= 100 # Maximum allowable program headers
51 CERT_CHAIN_ONEROOT_MAXSIZE
= 6*1024 # Default Cert Chain Max Size for one root
52 VIRTUAL_BLOCK_SIZE
= 131072 # Virtual block size for MCs insertion in SBL1 if ENABLE_VIRTUAL_BLK ON
53 MAGIC_COOKIE_LENGTH
= 12 # Length of magic Cookie inserted per VIRTUAL_BLOCK_SIZE
54 MIN_IMAGE_SIZE_WITH_PAD
= 256*1024 # Minimum image size for sbl1 Nand based OTA feature
56 SBL_AARCH64
= 0xF # Indicate that SBL is a Aarch64 image
57 SBL_AARCH32
= 0x0 # Indicate that SBL is a Aarch32 image
59 # Magic numbers filled in for boot headers
60 FLASH_CODE_WORD
= 0x844BDCD1
61 UNIFIED_BOOT_COOKIE_MAGIC_NUMBER
= 0x33836685
62 MAGIC_NUM
= 0x73D71034
63 AUTODETECT_PAGE_SIZE_MAGIC_NUM
= 0x7D0B435A
64 AUTODETECT_PAGE_SIZE_MAGIC_NUM64
= 0x7D0B5436
65 AUTODETECT_PAGE_SIZE_MAGIC_NUM128
= 0x7D0B6577
66 SBL_VIRTUAL_BLOCK_MAGIC_NUM
= 0xD48B54C6
69 ELF_HDR_COMMON_SIZE
= 24
74 ELFINFO_MAG0_INDEX
= 0
75 ELFINFO_MAG1_INDEX
= 1
76 ELFINFO_MAG2_INDEX
= 2
77 ELFINFO_MAG3_INDEX
= 3
78 ELFINFO_MAG0
= 127 # 0x7F
82 ELFINFO_CLASS_INDEX
= 4
85 ELFINFO_VERSION_INDEX
= 6
86 ELFINFO_VERSION_CURRENT
= 1
87 ELF_BLOCK_ALIGN
= 0x1000
88 ALIGNVALUE_1MB
= 0x100000
89 ALIGNVALUE_4MB
= 0x400000
90 ELFINFO_DATA2LSB
= b
'\x01'
91 ELFINFO_EXEC_ETYPE
= b
'\x02\x00'
92 ELFINFO_ARM_MACHINETYPE
= b
'\x28\x00'
93 ELFINFO_VERSION_EV_CURRENT
= b
'\x01\x00\x00\x00'
95 ELFINFO_PHNUM
= b
'\x01\x00'
96 ELFINFO_RESERVED
= 0x00
98 # ELF Program Header Types
109 The eight bits between 20 and 27 in the p_flags field in ELF program headers
110 is not used by the standard ELF format. We use this byte to hold OS and processor
111 specific fields as recommended by ARM.
113 The bits in this byte are defined as follows:
115 Pool Indx Segment type Access type Page/non page
116 bits in p_flags /-----27-----/----26-24-------/---- 23-21----/------20-------/
118 After parsing segment description strings in the SCL file, the appropriate segment
119 flag values are chosen from the follow definitions. The mask defined below is then
120 used to update the existing p_flags field in the program headers with the updated
123 # Mask for bits 20-27 to parse program header p_flags
124 MI_PBT_FLAGS_MASK
= 0x0FF00000
126 # Helper defines to help parse ELF program headers
127 MI_PBT_FLAG_SEGMENT_TYPE_MASK
= 0x07000000
128 MI_PBT_FLAG_SEGMENT_TYPE_SHIFT
= 0x18
129 MI_PBT_FLAG_PAGE_MODE_MASK
= 0x00100000
130 MI_PBT_FLAG_PAGE_MODE_SHIFT
= 0x14
131 MI_PBT_FLAG_ACCESS_TYPE_MASK
= 0x00E00000
132 MI_PBT_FLAG_ACCESS_TYPE_SHIFT
= 0x15
133 MI_PBT_FLAG_POOL_INDEX_MASK
= 0x08000000
134 MI_PBT_FLAG_POOL_INDEX_SHIFT
= 0x1B
137 MI_PBT_L4_SEGMENT
= 0x0
138 MI_PBT_AMSS_SEGMENT
= 0x1
139 MI_PBT_HASH_SEGMENT
= 0x2
140 MI_PBT_BOOT_SEGMENT
= 0x3
141 MI_PBT_L4BSP_SEGMENT
= 0x4
142 MI_PBT_SWAPPED_SEGMENT
= 0x5
143 MI_PBT_XBL_SEC_SEGMENT
= 0x5
144 MI_PBT_SWAP_POOL_SEGMENT
= 0x6
145 MI_PBT_PHDR_SEGMENT
= 0x7
148 MI_PBT_NON_PAGED_SEGMENT
= 0x0
149 MI_PBT_PAGED_SEGMENT
= 0x1
152 MI_PBT_RW_SEGMENT
= 0x0
153 MI_PBT_RO_SEGMENT
= 0x1
154 MI_PBT_ZI_SEGMENT
= 0x2
155 MI_PBT_NOTUSED_SEGMENT
= 0x3
156 MI_PBT_SHARED_SEGMENT
= 0x4
157 MI_PBT_RWE_SEGMENT
= 0x7
159 # ELF Segment Flag Definitions
160 MI_PBT_ELF_AMSS_NON_PAGED_RO_SEGMENT
= 0x01200000
161 MI_PBT_ELF_AMSS_PAGED_RO_SEGMENT
= 0x01300000
162 MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX0
= 0x06400000
163 MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX0
= 0x05300000
164 MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX1
= 0x0E400000
165 MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX1
= 0x0D300000
166 MI_PBT_ELF_AMSS_NON_PAGED_ZI_SEGMENT
= 0x01400000
167 MI_PBT_ELF_AMSS_PAGED_ZI_SEGMENT
= 0x01500000
168 MI_PBT_ELF_AMSS_NON_PAGED_RW_SEGMENT
= 0x01000000
169 MI_PBT_ELF_AMSS_PAGED_RW_SEGMENT
= 0x01100000
170 MI_PBT_ELF_AMSS_NON_PAGED_NOTUSED_SEGMENT
= 0x01600000
171 MI_PBT_ELF_AMSS_PAGED_NOTUSED_SEGMENT
= 0x01700000
172 MI_PBT_ELF_AMSS_NON_PAGED_SHARED_SEGMENT
= 0x01800000
173 MI_PBT_ELF_AMSS_PAGED_SHARED_SEGMENT
= 0x01900000
174 MI_PBT_ELF_HASH_SEGMENT
= 0x02200000
175 MI_PBT_ELF_BOOT_SEGMENT
= 0x03200000
176 MI_PBT_ELF_PHDR_SEGMENT
= 0x07000000
177 MI_PBT_ELF_NON_PAGED_L4BSP_SEGMENT
= 0x04000000
178 MI_PBT_ELF_PAGED_L4BSP_SEGMENT
= 0x04100000
179 MI_PBT_ELF_AMSS_RELOCATABLE_IMAGE
= 0x8000000
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
186 MI_PBT_ELF_RESIDENT_SEGMENT
= 0x00000000
187 MI_PBT_ELF_PAGED_LOCKED_SEGMENT
= 0x00100000
188 MI_PBT_ELF_PAGED_UNLOCKED_SEGMENT
= 0x01100000
189 MI_PBT_ELF_UNSECURE_SEGMENT
= 0x03100000
190 #----------------------------------------------------------------------------
191 # GLOBAL VARIABLES END
192 #----------------------------------------------------------------------------
194 #----------------------------------------------------------------------------
195 # CLASS DEFINITIONS BEGIN
196 #----------------------------------------------------------------------------
197 #----------------------------------------------------------------------------
199 #----------------------------------------------------------------------------
208 #----------------------------------------------------------------------------
209 # Image Type ID Class - These values must be kept consistent with mibib.h
210 #----------------------------------------------------------------------------
232 BACKUP_RAMFS_IMG
= 20
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 #----------------------------------------------------------------------------
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
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 #----------------------------------------------------------------------------
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
292 #----------------------------------------------------------------------------
294 #----------------------------------------------------------------------------
295 class Elf_Ehdr_common
:
296 # Structure object to align and package the ELF Header
297 s
= struct
.Struct('16sHHI')
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]
307 def printValues(self
):
308 print("ATTRIBUTE / VALUE")
309 for attr
, value
in self
.__dict
__.items():
314 #----------------------------------------------------------------------------
316 #----------------------------------------------------------------------------
318 # Structure object to align and package the ELF Header
319 s
= struct
.Struct('16sHHIIIIIHHHHHH')
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]
339 def printValues(self
):
340 print("ATTRIBUTE / VALUE")
341 for attr
, value
in self
.__dict
__.items():
344 def getPackedData(self
):
345 if type(self
.e_ident
) == str:
346 packvalue
= bytes(self
.e_ident
, 'utf-8')
348 packvalue
= self
.e_ident
365 return (Elf32_Ehdr
.s
).pack(*values
)
367 #----------------------------------------------------------------------------
368 # ELF Program Header Class
369 #----------------------------------------------------------------------------
372 # Structure object to align and package the ELF Program Header
373 s
= struct
.Struct('I' * 8)
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]
387 def printValues(self
):
388 print("ATTRIBUTE / VALUE")
389 for attr
, value
in self
.__dict
__.items():
392 def getPackedData(self
):
393 values
= [self
.p_type
,
403 return (Elf32_Phdr
.s
).pack(*values
)
405 #----------------------------------------------------------------------------
407 #----------------------------------------------------------------------------
409 # Structure object to align and package the ELF Header
410 s
= struct
.Struct('16sHHIQQQIHHHHHH')
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]
430 def printValues(self
):
431 print("ATTRIBUTE / VALUE")
432 for attr
, value
in self
.__dict
__.items():
435 def getPackedData(self
):
436 if type(self
.e_ident
) == str:
437 packvalue
= bytes(self
.e_ident
, 'utf-8')
439 packvalue
= self
.e_ident
456 return (Elf64_Ehdr
.s
).pack(*values
)
458 #----------------------------------------------------------------------------
459 # ELF Program Header Class
460 #----------------------------------------------------------------------------
463 # Structure object to align and package the ELF Program Header
464 s
= struct
.Struct('IIQQQQQQ')
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]
478 def printValues(self
):
479 print("ATTRIBUTE / VALUE")
480 for attr
, value
in self
.__dict
__.items():
483 def getPackedData(self
):
484 values
= [self
.p_type
,
494 return (Elf64_Phdr
.s
).pack(*values
)
497 #----------------------------------------------------------------------------
498 # ELF Segment Information Class
499 #----------------------------------------------------------------------------
503 def printValues(self
):
504 print('Flag: ' + str(self
.flag
))
506 #----------------------------------------------------------------------------
507 # Regular Boot Header Class
508 #----------------------------------------------------------------------------
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
533 return BOOT_HEADER_LENGTH
535 def writePackedData(self
, target
, write_full_hdr
):
536 values
= [self
.image_id
,
537 self
.flash_parti_ver
,
545 self
.cert_chain_size
,
549 self
.boot_apps_parti_entry
,
550 self
.boot_apps_size_entry
,
551 self
.boot_apps_ram_loc
,
557 if self
.flash_parti_ver
>= 6:
558 values
.insert(10, self
.metadata_size_qti
)
559 values
.insert(11, self
.metadata_size
)
561 if self
.image_dest_ptr
>= 0x100000000:
562 values
[3] = 0xFFFFFFFF
564 if self
.cert_chain_ptr
>= 0x100000000:
565 values
[6] = 0xFFFFFFFF
567 if self
.sig_ptr
>= 0x100000000:
568 values
[8] = 0xFFFFFFFF
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)
576 s
= struct
.Struct('I'* 10)
579 s
= struct
.Struct('I' * self
.getLength())
581 packed_data
= s
.pack(*values
)
583 fp
= OPEN(target
,'wb')
584 fp
.write(packed_data
)
589 #----------------------------------------------------------------------------
590 # SBL Boot Header Class
591 #----------------------------------------------------------------------------
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
616 return SBL_HEADER_LENGTH
618 def writePackedData(self
, target
):
619 values
= [self
.codeword
,
631 self
.cert_chain_size
,
632 self
.oem_root_cert_sel
,
633 self
.oem_num_root_certs
,
634 self
.booting_image_config
,
640 s
= struct
.Struct('I' * self
.getLength())
641 packed_data
= s
.pack(*values
)
643 fp
= OPEN(target
,'wb')
644 fp
.write(packed_data
)
649 #----------------------------------------------------------------------------
650 # CLASS DEFINITIONS END
651 #----------------------------------------------------------------------------
653 #------------------------------------------------------------------------------
655 #------------------------------------------------------------------------------
657 return env
.Detect('mbn_tools')
661 #----------------------------------------------------------------------------
662 # Generate Global Dictionary
663 #----------------------------------------------------------------------------
664 generate_global_dict(env
)
666 #----------------------------------------------------------------------------
667 # Assign Build Configurable Values
668 #----------------------------------------------------------------------------
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")
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")
696 #----------------------------------------------------------------------------
698 #----------------------------------------------------------------------------
700 #----------------------------------------------------------------------------
702 #----------------------------------------------------------------------------
703 def generate_meta_data(env
, meta_out_file_name
, add_magic_num
= False):
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.
710 xml_header
= env
.SSDGetMetaData(add_magic_num
)
713 xml_target_file
= open(meta_out_file_name
,'wb')
714 xml_header_size
= len(xml_header
)
716 # Write XML buffer into target file
717 xml_target_file
.write(xml_header
)
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()
725 xml_target_file
.close()
726 raise RuntimeError("XML Size too large: " + str(xml_header_size
))
728 #----------------------------------------------------------------------------
730 #----------------------------------------------------------------------------
731 def encrypt_mbn(env
, mbn_in_file_name
, mbn_out_file_name
):
733 mbn_in_fp
= OPEN(mbn_in_file_name
, "rb")
734 mbn_out_fp
= OPEN(mbn_out_file_name
, "wb+")
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
)
746 # Clean up encryption files
749 #----------------------------------------------------------------------------
751 #----------------------------------------------------------------------------
752 def get_ssd_se_fname(env
):
753 return env
.SSDGetSideEffectFileName()
755 #----------------------------------------------------------------------------
756 # encrypt_elf_segments
757 #----------------------------------------------------------------------------
758 def encrypt_elf_segments(env
, elf_in_file_name
,
762 elf_in_fp
= OPEN(elf_in_file_name
, "rb")
763 elf_out_fp
= OPEN(elf_out_file_name
, "wb+")
766 [elf_header
, phdr_table
] = preprocess_elf_file(elf_in_file_name
)
767 encrypted_seg_counter
= 0
769 # Copy input file to output file
770 shutil
.copyfileobj(elf_in_fp
, elf_out_fp
, os
.path
.getsize(elf_in_file_name
))
772 # Begin ELF segment encryption
773 for i
in range(elf_header
.e_phnum
):
774 curr_phdr
= phdr_table
[i
]
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
:
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
)
785 # Call encryption routine on buffer
786 encrypted_buf
= env
.SSDEncryptSegment(encrypted_seg_counter
, file_buff
, data_len
)
787 encrypted_seg_counter
+= 1
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
)
797 # Clean up encryption files
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 #----------------------------------------------------------------------------
805 def convert_int_to_byte_string(n
, l
):
806 return b
''.join([chr((n
>> ((l
- i
- 1) * 8)) % 256) for i
in xrange(l
)][::-1])
808 #----------------------------------------------------------------------------
809 # Create default elf header
810 #----------------------------------------------------------------------------
811 def create_elf_header( output_file_name
,
814 is_elf_64_bit
= False):
816 if (output_file_name
is None):
817 raise RuntimeError("Requires a ELF header file")
819 # Create a elf header and program header
820 # Write the headers to the output file
821 elf_fp
= file(output_file_name
, "wb")
823 if (is_elf_64_bit
is True):
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
)))
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))
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
)))
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))
889 #----------------------------------------------------------------------------
891 #----------------------------------------------------------------------------
892 def image_header(env
, gen_dict
,
896 header_format
= 'reg',
897 requires_preamble
= False,
898 preamble_file_name
= None,
899 elf_file_name
= None,
900 write_full_hdr
= False,
902 cert_chain_size_in
= CERT_CHAIN_ONEROOT_MAXSIZE
,
904 header_version
= None):
907 if (requires_preamble
is True) and (preamble_file_name
is None):
908 raise RuntimeError("Image Header requires a preamble file")
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")
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")
917 if in_code_size
is not None:
918 code_size
= in_code_size
920 code_size
= os
.path
.getsize(code_file_name
)
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))
935 image_size
= code_size
938 assert header_version
in [3, 5, 6], 'Not a valid MBN header version'
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']
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
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
)
972 # Package up the header and write to output file
973 boot_sbl_header
.writePackedData(target
= output_file_name
)
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
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
992 if header_version
>= 6:
993 boot_header
.metadata_size_qti
= 0 # qti_metadata size
994 boot_header
.metadata_size
= 0 # oem_metadata size
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
)
1000 # Package up the header and write to output file
1001 boot_header
.writePackedData(target
= output_file_name
, write_full_hdr
= write_full_hdr
)
1004 raise RuntimeError("Header format not supported: " + str(header_format
))
1008 #----------------------------------------------------------------------------
1010 #----------------------------------------------------------------------------
1011 def pboot_gen_elf(env
, elf_in_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):
1025 if header_version
>= 6:
1027 image_header_size
= header_size(header_version
)
1029 if (sha_algo
== 'SHA384'):
1030 mi_prog_boot_digest_size
= 48
1031 elif sha_algo
== 'SHA256':
1032 mi_prog_boot_digest_size
= 32
1034 mi_prog_boot_digest_size
= 20
1037 elf_in_fp
= OPEN(elf_in_file_name
, "rb")
1038 hash_out_fp
= OPEN(hash_out_file_name
, "wb+")
1040 if elf_out_file_name
is not None:
1041 elf_out_fp
= OPEN(elf_out_file_name
, "wb+")
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
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
1056 new_phdr
= Elf32_Phdr(b
'\0' * ELF32_PHDR_SIZE
)
1057 elf_header_size
= ELF32_HDR_SIZE
1060 hash = b
'\0' * mi_prog_boot_digest_size
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")
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
1075 # If hash table program header is not found, make sure to include it
1076 elf_header
.e_phnum
+= 2
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
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
1086 # Begin hash table generation
1087 for i
in range(num_phdrs
):
1088 curr_phdr
= phdr_table
[i
]
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
1095 # Check if the vaddr is page aligned
1096 off
= curr_phdr
.p_vaddr
& (ELF_BLOCK_ALIGN
- 1)
1098 seg_size
-= (ELF_BLOCK_ALIGN
- off
)
1099 seg_offset
+= (ELF_BLOCK_ALIGN
- off
)
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!")
1105 off
= seg_offset
+ seg_size
1107 while seg_offset
< off
:
1109 if seg_offset
< ELF_BLOCK_ALIGN
:
1110 hash_size
= seg_offset
1112 hash_size
= ELF_BLOCK_ALIGN
1114 elf_in_fp
.seek(seg_offset
)
1115 fbuf
= elf_in_fp
.read(hash_size
)
1117 if MI_PBT_CHECK_FLAG_TYPE(curr_phdr
.p_flags
) is True:
1118 hash = generate_hash(fbuf
, sha_algo
)
1120 hash = b
'\0' * mi_prog_boot_digest_size
1122 # Write hash to file
1123 hash_out_fp
.write(hash)
1125 hashtable_size
+= mi_prog_boot_digest_size
1126 seg_offset
+= ELF_BLOCK_ALIGN
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
)
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
)
1139 hash = b
'\0' * mi_prog_boot_digest_size
1141 # Write hash to file
1142 hash_out_fp
.write(hash)
1144 hashtable_size
+= mi_prog_boot_digest_size
1145 # End hash table generation
1147 # Generate the rest of the ELF output file if specified
1148 if elf_out_file_name
is not None:
1150 # Preempt hash table size if necessary
1151 if secure_type
== 'secure':
1152 hashtable_size
+= (SHA256_SIGNATURE_SIZE
+ cert_chain_size_in
)
1154 if append_xml_hdr
is True:
1155 hashtable_size
+= XML_HEADER_MAXSIZE
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
)
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
))
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
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
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
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
1193 if min_offset
< hash_seg_end
:
1194 hashtable_shift
= hash_seg_end
- min_offset
1196 # Move program headers to after ELF header
1197 phdr_start
= elf_header_size
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
1204 # Output remaining ELF segments
1205 for i
in range(num_phdrs
):
1207 # Increment the file offset before writing to the destination file
1208 curr_phdr
= phdr_table
[i
]
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
1216 src_offset
= curr_phdr
.p_offset
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
)
1221 # Output remaining program headers and ELF segments
1222 elf_header
.e_phoff
= phdr_start
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
)
1231 # Increment the file offset before writing to the destination file
1232 for i
in range(num_phdrs
):
1233 curr_phdr
= phdr_table
[i
]
1235 if curr_phdr
.p_type
is PHDR_TYPE
:
1238 curr_phdr
.p_offset
+= hashtable_shift
1240 # Copy the program header
1241 elf_out_fp
.seek(phdr_start
)
1242 elf_out_fp
.write(curr_phdr
.getPackedData())
1245 phdr_start
+= phdr_size
1247 # Finally, copy the new ELF header to the destination file
1249 elf_out_fp
.write(elf_header
.getPackedData())
1251 # Recalculate hash of ELF + program headers and output to hash output file
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
)
1260 hash = generate_hash(elfhdr_buff
+ proghdr_buff
, sha_algo
)
1262 # Write hash to file as first hash table entry
1264 hash_out_fp
.write(hash)
1270 if elf_out_file_name
is not None:
1276 #----------------------------------------------------------------------------
1278 #----------------------------------------------------------------------------
1279 def pboot_add_hash(env
, elf_in_file_name
,
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+")
1289 [elf_header
, phdr_table
] = preprocess_elf_file(elf_in_file_name
)
1291 hash_size
= os
.path
.getsize(hash_tbl_file_name
)
1292 hash_segment_found
= False
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
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
))
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
)
1310 raise RuntimeError("Hash segment program header not found in file " + elf_in_file_name
)
1319 #----------------------------------------------------------------------------
1321 #----------------------------------------------------------------------------
1322 def image_auth(env
, *args
):
1324 if len(args
) < 7 or len(args
) > 8:
1325 raise RuntimeError("Usage Invalid")
1327 # Initialize File Names
1330 attestation_cert
= args
[2]
1331 attestation_ca_cert
= args
[3]
1333 cert_chain_out
= args
[5]
1334 signed_image_out
= args
[6]
1336 cert_size_max_in
= args
[7]
1338 cert_size_max_in
= CERT_CHAIN_ONEROOT_MAXSIZE
1340 # Creating list of certificates to support creation of certificate chains
1341 # of lenth 1, 2, or 3 certificates
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
1354 if (num_certs
== 0):
1355 raise RuntimeError("Missing file(s) required for signing.\n")
1357 # Create the Certificate Chain
1358 concat_files (cert_chain_out
, cert_list
)
1360 # Pad to ensure Certificate Chain Size is CERT_CHAIN_MAX_SIZE
1361 cert_size
= os
.path
.getsize(cert_chain_out
)
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
)
1369 raise RuntimeError("Certificate Size too large: " + str(cert_size
))
1371 # Create the Final Signed Image File
1372 concat_files (signed_image_out
, [binary_in
, signature
, cert_chain_out
])
1376 #----------------------------------------------------------------------------
1377 # modify_relocatable_flags
1378 #----------------------------------------------------------------------------
1379 def modify_relocatable_flags(env
, output_elf
):
1381 # Offset into program header where the p_flags field is stored
1382 phdr_align_flag_offset
= 28
1383 phdr_reloc_flag_offset
= 24
1386 [elf_header
, phdr_table
] = preprocess_elf_file(output_elf
)
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
1393 curr_phdr
= Elf32_Phdr('\0' * ELF32_PHDR_SIZE
)
1394 elf_header_size
= ELF32_HDR_SIZE
1398 elf_in_fp
= OPEN(output_elf
, "r+")
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
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]
1407 #default alignment value is 1MB unless otherwise specified
1408 if 'USES_RELOC_ALIGN_VALUE_4MB' in env
:
1409 alignment_value
= ALIGNVALUE_4MB
1411 alignment_value
= ALIGNVALUE_1MB
1415 #create new alignment value
1416 new_align
= (curr_phdr
.p_align
& 0) | alignment_value
1418 # Create structure to package new flag field
1419 s
= struct
.Struct('I')
1420 new_flag_bytes
= s
.pack(new_align
)
1422 # Write the new flag value and incr ement offset
1423 elf_in_fp
.write(new_flag_bytes
)
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
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
)
1435 # Create structure to package new flag field
1436 s
= struct
.Struct('I')
1437 new_flag_bytes
= s
.pack(new_flag
)
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
1450 #----------------------------------------------------------------------------
1452 #----------------------------------------------------------------------------
1453 def modify_elf_flags(env
, elf_in_file_name
,
1457 [elf_header
, phdr_table
] = preprocess_elf_file(elf_in_file_name
)
1458 segment_list
= readSCL(scl_file_name
, env
['GLOBAL_DICT'])
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
1465 curr_phdr
= Elf32_Phdr('\0' * ELF32_PHDR_SIZE
)
1466 # Offset into program header where the p_flags field is stored
1470 elf_in_fp
= OPEN(elf_in_file_name
, "r+")
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!')
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
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
)
1486 # Create structure to package new flag field
1487 s
= struct
.Struct('I')
1488 new_flag_bytes
= s
.pack(new_flag
)
1490 # Write the new flag value and increment offset
1491 elf_in_fp
.write(new_flag_bytes
)
1492 file_offset
+= elf_header
.e_phentsize
1499 #----------------------------------------------------------------------------
1500 # generate_code_hash
1501 #----------------------------------------------------------------------------
1502 def generate_code_hash(env
, elf_in_file_name
):
1505 [elf_header
, phdr_table
] = preprocess_elf_file(elf_in_file_name
)
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
1512 curr_phdr
= Elf32_Phdr('\0' * ELF32_PHDR_SIZE
)
1513 # Offset into program header where the p_flags field is stored
1517 elf_in_fp
= OPEN(elf_in_file_name
, "rb+")
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
1522 # XXX Get these from env?
1523 DP_CODE_ALIGN
= 0x100
1525 DP_HASH_SIZE
= 32 # SHA-256
1526 DP_HASH_MAGIC
= 0xC0DEDEC0
1532 page_size
= DP_PAGE_SIZE
1533 hash_size
= DP_HASH_SIZE
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;
1539 for i
in range(elf_header
.e_phnum
):
1540 curr_phdr
= phdr_table
[i
]
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):
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
)
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
))
1553 hash_data
= struct
.unpack("I" * (curr_phdr
.p_filesz
/ 4), hash_data
)
1555 for v
in hash_data
[:]:
1556 if (v
!= DP_HASH_MAGIC
):
1560 if (hash_seg_idx
!= -1):
1563 if (hash_seg_idx
== -1):
1564 # return if there is no hash segment.
1567 hash_phdr
= phdr_table
[hash_seg_idx
]
1569 # Now find the code segment for the hashes. Look for matching number of pages
1571 code_seg_pages
= hash_phdr
.p_filesz
/ DP_HASH_SIZE
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
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')
1584 if (code_seg_idx
== -1):
1585 raise RuntimeError('No matching code segment found')
1587 code_phdr
= phdr_table
[code_seg_idx
]
1589 # Now hash the pages in the code segment
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
)
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
1603 # And write them to the hash segment
1604 elf_in_fp
.seek(hash_phdr
.p_offset
)
1614 #----------------------------------------------------------------------------
1616 #----------------------------------------------------------------------------
1618 #----------------------------------------------------------------------------
1619 # HELPER FUNCTIONS BEGIN
1620 #----------------------------------------------------------------------------
1622 #----------------------------------------------------------------------------
1623 # Create a list to hold all segment information from an input SCL file
1624 #----------------------------------------------------------------------------
1625 def readSCL(filename
, global_dict
):
1627 scl_fp
= OPEN(filename
,'r')
1630 file_data
= scl_fp
.readlines()
1631 num_lines
= len(file_data
)
1634 strip_chars
= '(){}[]'
1639 # Parse through all lines
1640 while i
< num_lines
:
1642 # Save the last line read
1643 previous_line
= current_line
1644 current_line
= file_data
[i
]
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(' ')
1655 # Check that at least two tokens were parsed
1656 # Token 1: Segment Name
1657 # Token 2: Start Address -- not used in MBN tools
1659 raise RuntimeError('SCL Segment Syntax malformed: ' + previous_line
)
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
)
1665 bracket_counter
+= 1
1666 elif '}' in current_line
:
1667 bracket_counter
-= 1
1674 #----------------------------------------------------------------------------
1675 # Given a string parsed from a SCL file, returns the ELF segment flags
1676 #----------------------------------------------------------------------------
1677 def getSegmentFlag(seg_info
):
1681 # Define string values for various types of segments
1686 NOTPAGEABLE
= "NOTPAGED"
1687 SWAPABLE
= "SWAPPED"
1688 SWAP_POOL
= "SWAP_POOL"
1689 RESERVED
= "RESERVED"
1693 BOOT_SEGMENT
= "BOOT_SEGMENT"
1696 POOL_INDEX_0
= "INDEX_0"
1697 POOL_INDEX_1
= "INDEX_1"
1699 # New definitions for EOS demand paging
1701 PAGEUNLOCKED
= "PAGEUNLOCKED"
1702 PAGELOCKED
= "PAGELOCKED"
1703 UNSECURE
= "UNSECURE"
1705 if seg_info
is None or len(seg_info
) == 0:
1706 raise RuntimeError('Invalid segment information passed: ' + seg_info
)
1708 # Conditional checks and assignments of the corresponding segment flag values
1709 if NOTPAGEABLE
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
1719 ret_val
= MI_PBT_ELF_SWAP_POOL_NON_PAGED_ZI_SEGMENT_INDEX1
1721 ret_val
= MI_PBT_ELF_AMSS_NON_PAGED_ZI_SEGMENT
1723 elif NOTUSED
in seg_info
:
1724 ret_val
= MI_PBT_ELF_AMSS_NON_PAGED_NOTUSED_SEGMENT
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
1735 ret_val
= MI_PBT_ELF_AMSS_NON_PAGED_RW_SEGMENT
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
1743 ret_val
= MI_PBT_ELF_SWAPPED_PAGED_RO_SEGMENT_INDEX1
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
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
1756 ret_val
= MI_PBT_ELF_AMSS_PAGED_RW_SEGMENT
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
1768 raise RuntimeError('The segment name is wrongly defined in the SCL file: ' + seg_info
)
1772 #----------------------------------------------------------------------------
1773 # Pad a file with specific number of bytes
1774 # Note: Assumes the fp is seeked to the correct location of padding
1775 #----------------------------------------------------------------------------
1776 def pad_file(fp
, num_bytes
, value
):
1779 raise RuntimeError("Number of bytes to pad must be greater than zero")
1781 while num_bytes
> 0:
1782 fp
.write('%c' % value
)
1787 #----------------------------------------------------------------------------
1788 # Concatenates the files listed in 'sources' in order and writes to 'target'
1789 #----------------------------------------------------------------------------
1790 def concat_files (target
, sources
):
1791 if type(sources
) is not list:
1794 target_file
= OPEN(target
,'wb')
1796 for fname
in sources
:
1797 file = OPEN(fname
,'rb')
1799 bin_data
= file.read(65536)
1802 target_file
.write(bin_data
)
1806 #----------------------------------------------------------------------------
1807 # Parse build configurable values and assign to global variables for tools
1808 #----------------------------------------------------------------------------
1809 def init_build_vars(env
):
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))
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))
1819 #----------------------------------------------------------------------------
1820 # Generates the global dictionary and add to the environment
1821 #----------------------------------------------------------------------------
1822 def generate_global_dict(env
):
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"))
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):
1834 # Populate the dictionary from the auto-generated files
1835 global_dict
= populate_dictionary(targ_file_name
, cust_file_name
)
1839 # Add the dictionary to the environment
1840 env
.Replace(GLOBAL_DICT
= global_dict
)
1842 #----------------------------------------------------------------------------
1843 # Populate the dictionary from a list of input files
1844 #----------------------------------------------------------------------------
1845 def populate_dictionary(*args
):
1848 raise RuntimeError("At least 1 file must be specified as an input")
1851 Fields
= ["Define", "Key", "Value"]
1853 # For each input file
1854 for i
in range(len(args
)):
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
=" ")
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):
1868 new_key
= new_entry
['Key'].strip()
1869 new_value
= new_entry
['Value'].strip()
1871 # If value pair is empty string, assume feature definition is true
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
)))
1880 # Attempt to evaluate value
1882 new_value
= eval(new_value
)
1883 # Catch exceptions and do not evaluate
1887 # Add to global dictionary
1888 global_dict
[new_key
] = new_value
1893 #----------------------------------------------------------------------------
1894 # Filter out a generic dictionary from the global dictionary
1895 #----------------------------------------------------------------------------
1896 def filter_dictionary(env
, global_dict
, **kwargs
):
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.")
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.")
1907 # Check for Flash Type
1908 # If FLASH_TYPE parameter is not provided, default to 'nand'
1909 if not kwargs
.has_key('FLASH_TYPE'):
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. ")
1916 # Check for MBN Type
1917 # If MBN_TYPE parameter is not provided, default to 'elf'
1918 if not kwargs
.has_key('MBN_TYPE'):
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
)
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
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.")
1939 # Check for image_type
1940 if image_type
not in image_id_table
:
1942 id_match_str
= image_type
.upper() + "_IMG"
1943 id_mbn_type
= mbn_type
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]
1949 # Handle MBN Type and assign image destination address
1950 if id_mbn_type
== 'elf':
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
]
1957 raise RuntimeError("Builds file does not have IMAGE_KEY pair for: " + image_type
)
1959 raise RuntimeError("MBN_TYPE currently not supported: " + mbn_type
)
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)
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)
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
:
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
1990 raise RuntimeError("Invalid OEM root certificate configuration values")
1992 # Assign additional dictionary key/values pair as needed by tools.
1997 #----------------------------------------------------------------------------
1998 # Get index value from dictionary if exists, otherwise return default
1999 #----------------------------------------------------------------------------
2000 def get_dict_value(dict, key_string
, default
):
2002 key
= 'IMAGE_KEY_' + key_string
2009 #----------------------------------------------------------------------------
2010 # Preprocess an ELF file and return the ELF Header Object and an
2011 # array of ELF Program Header Objects
2012 #----------------------------------------------------------------------------
2013 def preprocess_elf_file(elf_file_name
):
2016 elf_fp
= OPEN(elf_file_name
, 'rb')
2017 elf_header
= Elf_Ehdr_common(elf_fp
.read(ELF_HDR_COMMON_SIZE
))
2019 if verify_elf_header(elf_header
) is False:
2020 raise RuntimeError("ELF file failed verification: " + elf_file_name
)
2024 if elf_header
.e_ident
[ELFINFO_CLASS_INDEX
] == ELFINFO_CLASS_64
:
2025 elf_header
= Elf64_Ehdr(elf_fp
.read(ELF64_HDR_SIZE
))
2027 elf_header
= Elf32_Ehdr(elf_fp
.read(ELF32_HDR_SIZE
))
2031 # Verify ELF header information
2032 if verify_elf_header(elf_header
) is False:
2033 raise RuntimeError("ELF file failed verification: " + elf_file_name
)
2035 # Get program header size
2036 phdr_size
= elf_header
.e_phentsize
2038 # Find the program header offset
2039 file_offset
= elf_header
.e_phoff
2040 elf_fp
.seek(file_offset
)
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
)))
2047 phdr_table
.append(Elf32_Phdr(elf_fp
.read(phdr_size
)))
2050 return [elf_header
, phdr_table
]
2052 #----------------------------------------------------------------------------
2053 # Get the hash table address from an input ELF file
2054 #----------------------------------------------------------------------------
2055 def get_hash_address(elf_file_name
):
2057 [elf_header
, phdr_table
] = preprocess_elf_file(elf_file_name
)
2060 last_paddr_segment
= 0
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
;
2072 max_phdr
= phdr_table
[last_paddr_segment
]
2074 ret_val
= (((max_phdr
.p_paddr
+ max_phdr
.p_memsz
- 1) & \
2075 ~
(ELF_BLOCK_ALIGN
-1)) + ELF_BLOCK_ALIGN
)
2079 #----------------------------------------------------------------------------
2080 # Verify ELF header contents from an input ELF file
2081 #----------------------------------------------------------------------------
2082 def 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
])))
2086 if (elf_header
.e_ident
[ELFINFO_MAG1_INDEX
] != ELFINFO_MAG1
):
2087 print("MAG1[{:d}]\n".format((elf_header
.e_ident
[ELFINFO_MAG1_INDEX
])))
2089 if (elf_header
.e_ident
[ELFINFO_MAG2_INDEX
] != ELFINFO_MAG2
):
2090 print("MAG2[{:d}]\n".format((elf_header
.e_ident
[ELFINFO_MAG2_INDEX
])))
2092 if (elf_header
.e_ident
[ELFINFO_MAG3_INDEX
] != ELFINFO_MAG3
):
2093 print("MAG3[{:d}]\n".format((elf_header
.e_ident
[ELFINFO_MAG3_INDEX
])))
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
])))
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
])))
2104 #----------------------------------------------------------------------------
2105 # Perform file copy given offsets and the number of bytes to copy
2106 #----------------------------------------------------------------------------
2107 def file_copy_offset(in_fp
, in_off
, out_fp
, out_off
, num_bytes
):
2109 read_in
= in_fp
.read(num_bytes
)
2110 out_fp
.seek(out_off
)
2111 out_fp
.write(read_in
)
2115 #----------------------------------------------------------------------------
2116 # sha1/sha256 hash routine wrapper
2117 #----------------------------------------------------------------------------
2118 def header_size(header_version
):
2119 if header_version
>= 6:
2124 #----------------------------------------------------------------------------
2125 # sha1/sha256 hash routine wrapper
2126 #----------------------------------------------------------------------------
2127 def 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()
2136 # Set the input buffer and return the output digest
2140 #----------------------------------------------------------------------------
2141 # Initialize the hash program header.
2142 #----------------------------------------------------------------------------
2143 def 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)
2152 # Update the hash table program header
2153 if is_elf64
is True:
2154 hash_Phdr
= Elf64_Phdr(b
'\0'*ELF64_PHDR_SIZE
)
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
2166 return [hash_Phdr
, pad_hash_segment
, hash_tbl_end_addr
, hash_tbl_offset
]
2168 #----------------------------------------------------------------------------
2170 #----------------------------------------------------------------------------
2171 def 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')
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
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
2189 autodetectpage
[2] = AUTODETECT_PAGE_SIZE_MAGIC_NUM
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
)
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
])
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
2205 boot_sbl_header
.image_src
+= flash_max_page
* 2
2206 amount_to_write
= flash_max_page
2208 pad_file(preamble_fp
, amount_to_write
, PAD_BYTE_1
)
2211 return boot_sbl_header
2213 #----------------------------------------------------------------------------
2214 # Helper functions to parse ELF program headers
2215 #----------------------------------------------------------------------------
2216 def MI_PBT_SEGMENT_TYPE_VALUE(x
):
2217 return ( ((x
) & MI_PBT_FLAG_SEGMENT_TYPE_MASK
) >> MI_PBT_FLAG_SEGMENT_TYPE_SHIFT
)
2219 def MI_PBT_PAGE_MODE_VALUE(x
):
2220 return ( ((x
) & MI_PBT_FLAG_PAGE_MODE_MASK
) >> MI_PBT_FLAG_PAGE_MODE_SHIFT
)
2222 def MI_PBT_ACCESS_TYPE_VALUE(x
):
2223 return ( ((x
) & MI_PBT_FLAG_ACCESS_TYPE_MASK
) >> MI_PBT_FLAG_ACCESS_TYPE_SHIFT
)
2225 def 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
)
2231 #----------------------------------------------------------------------------
2232 # Helper functions to open a file and return a valid file object
2233 #----------------------------------------------------------------------------
2234 def OPEN(file_name
, mode
):
2236 fp
= open(file_name
, mode
)
2238 raise RuntimeError("The file could not be opened: " + file_name
)
2240 # File open has succeeded with the given mode, return the file object
2243 #----------------------------------------------------------------------------
2244 # Helper functions to insert MCs in SBL1(Badger) if ENABLE_VIRTUAL_BLK is ON
2245 #----------------------------------------------------------------------------
2246 def insert_SBL1_magicCookie (env
, target
):
2247 file = open(target
, "rb")
2248 #read the file contents
2249 filedata
= file.read()
2250 length
= len(filedata
)
2253 if (length
<= VIRTUAL_BLOCK_SIZE
):
2256 #remove the previous file
2258 #generate new file for appending target data + required MCs
2259 file = open(target
, "ab")
2261 while length
> VIRTUAL_BLOCK_SIZE
:
2262 filedata_till_128kb
= filedata
[0:VIRTUAL_BLOCK_SIZE
]
2263 filedata_after_128kb
= filedata
[VIRTUAL_BLOCK_SIZE
:length
]
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))
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))
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))
2274 MC_inserted_data
= filedata_till_128kb
+ mc1
+ mc2
+ mc3
2275 file.write(MC_inserted_data
)
2277 filedata
= filedata_after_128kb
2278 length
= len(filedata
)
2280 #copy the leftover data (<128KB) in output file
2282 file.write(filedata
)
2284 #close the final output file
2286 # MC_insertion code end
2288 #----------------------------------------------------------------------------
2289 # Helper functions to remove MCs in SBL1(Badger)
2290 #----------------------------------------------------------------------------
2291 def remove_SBL1_magicCookie (env
, target
, dest
):
2292 file = open(target
, "rb")
2293 #read the file contents
2294 filedata
= file.read()
2295 length
= len(filedata
)
2298 #generate new file for appending target data + required MCs
2299 file = open(dest
, "ab")
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
]
2306 file.write(filedata_till_128kb
)
2308 filedata
= filedata_after_128kb
2309 length
= len(filedata
)
2311 #copy the leftover data (<128KB) in output file
2313 file.write(filedata
)
2315 #close the final output file
2318 # MC_removal code end
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 #----------------------------------------------------------------------------
2325 def 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
)
2333 alignment
= page_size
* num_of_pages
2335 if (length
> alignment
and alignment
> 0):
2337 multiple
= math
.ceil(length
/float(alignment
))
2339 final_image_size
= max(min_size_with_pad
, multiple
* alignment
)
2341 if length
< final_image_size
:
2342 sbl1_fp
= open(target
, 'ab')
2343 pad_file (sbl1_fp
, (final_image_size
-length
), PAD_BYTE_0
)
2347 #----------------------------------------------------------------------------
2348 # HELPER FUNCTIONS END
2349 #----------------------------------------------------------------------------