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