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