3rdparty/blobs: Update submodule to upstream main
[coreboot.git] / util / qualcomm / mbn_tools.py
blob9abb96c72a11c7d81e49c82d3f65e3f52286d93c
1 #!/usr/bin/env python3
2 #===============================================================================
4 # MBN TOOLS
6 # GENERAL DESCRIPTION
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
28 # Sahara mode
29 # 10/20/11 dxiang Clean up
30 #===============================================================================
32 import stat
33 import csv
34 import itertools
35 import struct
36 import os
37 import shutil
38 import hashlib
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
68 # ELF Definitions
69 ELF_HDR_COMMON_SIZE = 24
70 ELF32_HDR_SIZE = 52
71 ELF32_PHDR_SIZE = 32
72 ELF64_HDR_SIZE = 64
73 ELF64_PHDR_SIZE = 56
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
79 ELFINFO_MAG1 = 69 # E
80 ELFINFO_MAG2 = 76 # L
81 ELFINFO_MAG3 = 70 # F
82 ELFINFO_CLASS_INDEX = 4
83 ELFINFO_CLASS_32 = 1
84 ELFINFO_CLASS_64 = 2
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'
94 ELFINFO_SHOFF = 0x00
95 ELFINFO_PHNUM = b'\x01\x00'
96 ELFINFO_RESERVED = 0x00
98 # ELF Program Header Types
99 NULL_TYPE = 0x0
100 LOAD_TYPE = 0x1
101 DYNAMIC_TYPE = 0x2
102 INTERP_TYPE = 0x3
103 NOTE_TYPE = 0x4
104 SHLIB_TYPE = 0x5
105 PHDR_TYPE = 0x6
106 TLS_TYPE = 0x7
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
121 values.
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
136 # Segment Type
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
147 # Page/Non-Page Type
148 MI_PBT_NON_PAGED_SEGMENT = 0x0
149 MI_PBT_PAGED_SEGMENT = 0x1
151 # Access Type
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 #----------------------------------------------------------------------------
198 # OS Type ID Class
199 #----------------------------------------------------------------------------
200 class 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
208 #----------------------------------------------------------------------------
209 # Image Type ID Class - These values must be kept consistent with mibib.h
210 #----------------------------------------------------------------------------
211 class 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
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 #----------------------------------------------------------------------------
246 image_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
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 #----------------------------------------------------------------------------
293 # ELF Header Class
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():
310 print(attr, value)
314 #----------------------------------------------------------------------------
315 # ELF Header Class
316 #----------------------------------------------------------------------------
317 class Elf32_Ehdr:
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():
342 print(attr, value)
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
365 return (Elf32_Ehdr.s).pack(*values)
367 #----------------------------------------------------------------------------
368 # ELF Program Header Class
369 #----------------------------------------------------------------------------
370 class Elf32_Phdr:
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():
390 print(attr, value)
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
403 return (Elf32_Phdr.s).pack(*values)
405 #----------------------------------------------------------------------------
406 # ELF Header Class
407 #----------------------------------------------------------------------------
408 class Elf64_Ehdr:
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():
433 print(attr, value)
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
456 return (Elf64_Ehdr.s).pack(*values)
458 #----------------------------------------------------------------------------
459 # ELF Program Header Class
460 #----------------------------------------------------------------------------
461 class Elf64_Phdr:
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():
481 print(attr, value)
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
494 return (Elf64_Phdr.s).pack(*values)
497 #----------------------------------------------------------------------------
498 # ELF Segment Information Class
499 #----------------------------------------------------------------------------
500 class SegmentInfo:
501 def __init__(self):
502 self.flag = 0
503 def printValues(self):
504 print('Flag: ' + str(self.flag))
506 #----------------------------------------------------------------------------
507 # Regular Boot Header Class
508 #----------------------------------------------------------------------------
509 class 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
532 def getLength(self):
533 return BOOT_HEADER_LENGTH
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 ]
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)
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())
581 packed_data = s.pack(*values)
583 fp = OPEN(target,'wb')
584 fp.write(packed_data)
585 fp.close()
587 return s.size
589 #----------------------------------------------------------------------------
590 # SBL Boot Header Class
591 #----------------------------------------------------------------------------
592 class 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
615 def getLength(self):
616 return SBL_HEADER_LENGTH
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 ]
640 s = struct.Struct('I' * self.getLength())
641 packed_data = s.pack(*values)
643 fp = OPEN(target,'wb')
644 fp.write(packed_data)
645 fp.close()
647 return s.size
649 #----------------------------------------------------------------------------
650 # CLASS DEFINITIONS END
651 #----------------------------------------------------------------------------
653 #------------------------------------------------------------------------------
654 # Hooks for Scons
655 #------------------------------------------------------------------------------
656 def exists(env):
657 return env.Detect('mbn_tools')
659 def generate(env):
661 #----------------------------------------------------------------------------
662 # Generate Global Dictionary
663 #----------------------------------------------------------------------------
664 generate_global_dict(env)
666 #----------------------------------------------------------------------------
667 # Assign Build Configurable Values
668 #----------------------------------------------------------------------------
669 init_build_vars(env)
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")
694 return None
696 #----------------------------------------------------------------------------
697 # BOOT TOOLS BEGIN
698 #----------------------------------------------------------------------------
700 #----------------------------------------------------------------------------
701 # generate_meta_data
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)
712 # Initialize
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()
724 else:
725 xml_target_file.close()
726 raise RuntimeError("XML Size too large: " + str(xml_header_size))
728 #----------------------------------------------------------------------------
729 # encrypt_mbn
730 #----------------------------------------------------------------------------
731 def 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+")
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)
742 # Close Files
743 mbn_in_fp.close()
744 mbn_out_fp.close()
746 # Clean up encryption files
747 env.SSDDeInit()
749 #----------------------------------------------------------------------------
750 # get_ssd_se_fname
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,
759 elf_out_file_name):
761 # Open Files
762 elf_in_fp = OPEN(elf_in_file_name, "rb")
763 elf_out_fp = OPEN(elf_out_file_name, "wb+")
765 # Initialize
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)
793 # Close Files
794 elf_in_fp.close()
795 elf_out_fp.close()
797 # Clean up encryption files
798 env.SSDDeInit()
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,
812 image_dest,
813 image_size,
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):
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)))
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)))
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))
886 elf_fp.close()
887 return 0
889 #----------------------------------------------------------------------------
890 # image_header
891 #----------------------------------------------------------------------------
892 def 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):
906 # Preliminary checks
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")
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)
922 image_dest = 0
923 image_source = 0
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
937 if header_version:
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)
1003 else:
1004 raise RuntimeError("Header format not supported: " + str(header_format))
1005 return 0
1008 #----------------------------------------------------------------------------
1009 # pboot_gen_elf
1010 #----------------------------------------------------------------------------
1011 def 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'
1025 if header_version >= 6:
1026 sha_algo = 'SHA384'
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
1033 else:
1034 mi_prog_boot_digest_size = 20
1036 # Open Files
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+")
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
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
1060 hash = b'\0' * mi_prog_boot_digest_size
1061 phdr_start = 0
1062 bytes_to_pad = 0
1063 hash_seg_end = 0
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
1093 hash_size = 0
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)
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
1111 else:
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)
1119 else:
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)
1138 else:
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
1214 continue
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:
1236 continue
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())
1244 # Update phdr_start
1245 phdr_start += phdr_size
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())
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)
1260 hash = generate_hash(elfhdr_buff + proghdr_buff, sha_algo)
1262 # Write hash to file as first hash table entry
1263 hash_out_fp.seek(0)
1264 hash_out_fp.write(hash)
1266 # Close files
1267 elf_in_fp.close()
1268 hash_out_fp.close()
1270 if elf_out_file_name is not None:
1271 elf_out_fp.close()
1273 return 0
1276 #----------------------------------------------------------------------------
1277 # pboot_add_hash
1278 #----------------------------------------------------------------------------
1279 def pboot_add_hash(env, elf_in_file_name,
1280 hash_tbl_file_name,
1281 elf_out_file_name):
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+")
1288 # Initialize
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
1299 break
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)
1309 else:
1310 raise RuntimeError("Hash segment program header not found in file " + elf_in_file_name)
1312 # Close files
1313 elf_in_fp.close()
1314 hash_tbl_fp.close()
1315 elf_out_fp.close()
1317 return 0
1319 #----------------------------------------------------------------------------
1320 # image_auth
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
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
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
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)
1367 cert_fp.close()
1368 else:
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])
1374 return 0
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
1385 # Initialize
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
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
1397 # Open files
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
1410 else:
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
1443 # Close files
1444 elf_in_fp.close()
1447 return 0
1450 #----------------------------------------------------------------------------
1451 # modify_elf_flags
1452 #----------------------------------------------------------------------------
1453 def modify_elf_flags(env, elf_in_file_name,
1454 scl_file_name):
1456 # Initialize
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
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
1469 # Open files
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
1494 # Close files
1495 elf_in_fp.close()
1497 return 0
1499 #----------------------------------------------------------------------------
1500 # generate_code_hash
1501 #----------------------------------------------------------------------------
1502 def generate_code_hash(env, elf_in_file_name):
1504 # Initialize
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
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
1516 # Open files
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
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
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;
1538 hash_seg_idx = -1
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):
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))
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):
1557 hash_seg_idx = -1
1558 break;
1560 if (hash_seg_idx != -1):
1561 break
1563 if (hash_seg_idx == -1):
1564 # return if there is no hash segment.
1565 return 0
1567 hash_phdr = phdr_table[hash_seg_idx]
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
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')
1582 code_seg_idx = i
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
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
1603 # And write them to the hash segment
1604 elf_in_fp.seek(hash_phdr.p_offset)
1606 for h in hashes[:]:
1607 elf_in_fp.write(h)
1609 # Close files
1610 elf_in_fp.close()
1612 return 0
1614 #----------------------------------------------------------------------------
1615 # BOOT TOOLS END
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')
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 = []
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
1658 if len(tokens) < 2:
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
1669 i+=1
1671 scl_fp.close()
1672 return seg_list
1674 #----------------------------------------------------------------------------
1675 # Given a string parsed from a SCL file, returns the ELF segment flags
1676 #----------------------------------------------------------------------------
1677 def getSegmentFlag(seg_info):
1679 ret_val = None
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"
1699 # New definitions for EOS demand paging
1700 NONPAGE = "NONPAGE"
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:
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
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
1734 else:
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
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
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
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
1767 else:
1768 raise RuntimeError('The segment name is wrongly defined in the SCL file: ' + seg_info)
1770 return ret_val
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):
1778 if num_bytes < 0:
1779 raise RuntimeError("Number of bytes to pad must be greater than zero")
1781 while num_bytes > 0:
1782 fp.write('%c' % value)
1783 num_bytes -= 1
1785 return
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:
1792 sources = [sources]
1794 target_file = OPEN(target,'wb')
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()
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)
1836 else:
1837 global_dict = {}
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):
1847 if len(args) < 1:
1848 raise RuntimeError("At least 1 file must be specified as an input")
1850 global_dict = {}
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
1872 if new_value == '':
1873 new_value = 'yes'
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
1881 try:
1882 new_value = eval(new_value)
1883 # Catch exceptions and do not evaluate
1884 except:
1885 pass
1887 # Add to global dictionary
1888 global_dict[new_key] = new_value
1889 instream.close()
1891 return global_dict
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.")
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.")
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. ")
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)
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.")
1934 # Initialize
1935 gen_dict = {}
1936 image_dest = 0
1937 image_source = 0
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]
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)
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
1989 else:
1990 raise RuntimeError("Invalid OEM root certificate configuration values")
1992 # Assign additional dictionary key/values pair as needed by tools.
1994 return gen_dict
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
2004 if key in dict:
2005 return dict[key]
2006 else:
2007 return default
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):
2015 # Initialize
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)
2022 elf_fp.seek(0)
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))
2029 phdr_table = []
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)))
2046 else:
2047 phdr_table.append(Elf32_Phdr(elf_fp.read(phdr_size)))
2049 elf_fp.close()
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)
2059 last_paddr = 0
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)
2077 return ret_val
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])))
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
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):
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)
2113 return num_bytes
2115 #----------------------------------------------------------------------------
2116 # sha1/sha256 hash routine wrapper
2117 #----------------------------------------------------------------------------
2118 def header_size(header_version):
2119 if header_version >= 6:
2120 return 48
2121 else:
2122 return 40
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()
2133 else:
2134 m = hashlib.sha1()
2136 # Set the input buffer and return the output digest
2137 m.update(in_buf)
2138 return m.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)
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
2166 return [hash_Phdr, pad_hash_segment, hash_tbl_end_addr, hash_tbl_offset]
2168 #----------------------------------------------------------------------------
2169 # image_preamble
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')
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
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
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
2204 else:
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)
2209 preamble_fp.close()
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):
2235 try:
2236 fp = open(file_name, mode)
2237 except IOError:
2238 raise RuntimeError("The file could not be opened: " + file_name)
2240 # File open has succeeded with the given mode, return the file object
2241 return fp
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)
2251 file.close()
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")
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
2281 if length > 0:
2282 file.write(filedata)
2284 #close the final output file
2285 file.close()
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)
2296 file.close()
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
2312 if length > 0:
2313 file.write(filedata)
2315 #close the final output file
2316 file.close()
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)
2330 file.close()
2332 multiple = 1
2333 alignment = page_size * num_of_pages
2335 if (length > alignment and alignment > 0):
2336 import math
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)
2344 sbl1_fp.close()
2346 # SBL1 pad code end
2347 #----------------------------------------------------------------------------
2348 # HELPER FUNCTIONS END
2349 #----------------------------------------------------------------------------