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