1#!/usr/bin/env python 2 3import os 4import os.path 5import sys, getopt 6import binascii 7import struct 8import string 9 10# -------------------------- 11# | loader | BL1 | NS BL1U | 12# -------------------------- 13 14class generator(object): 15 # 16 # struct l_loader_head { 17 # unsigned int first_instr; 18 # unsigned char magic[16]; @ BOOTMAGICNUMBER! 19 # unsigned int l_loader_start; @ start of loader 20 # unsigned int l_loader_end; @ end of BL1 (without ns_bl1u) 21 # }; 22 file_header = [0, 0, 0, 0, 0, 0, 0] 23 24 # 25 # struct entry_head { 26 # unsigned char magic[8]; @ ENTY 27 # unsigned char name[8]; @ loader/bl1/ns_bl1u 28 # unsigned int start_lba; 29 # unsigned int count_lba; 30 # unsigned int flag; @ boot partition or not 31 # }; 32 # size of struct entry_head is 28 33 # 34 35 s1_entry_name = ['loader', 'bl1', 'ns_bl1u'] 36 37 block_size = 512 38 39 # set in self.add() 40 idx = 0 41 42 # file pointer 43 p_entry = 0 # pointer in header 44 p_file = 0 # pointer in file 45 p_loader_end = 0 # pointer in header 46 47 def __init__(self, out_img): 48 try: 49 self.fp = open(out_img, "wb+") 50 except IOError, e: 51 print "*** file open error:", e 52 sys.exit(3) 53 else: 54 self.entry_hd = [[0 for col in range(7)] for row in range(5)] 55 56 def __del__(self): 57 self.fp.close() 58 59 def add(self, lba, fname): 60 try: 61 fsize = os.path.getsize(fname) 62 except IOError, e: 63 print "*** file open error:", e 64 sys.exit(4) 65 else: 66 blocks = (fsize + self.block_size - 1) / self.block_size 67 # Boot Area1 in eMMC 68 bootp = 1 69 if self.idx == 0: 70 # both loader and bl1.bin locates in l-loader.bin bias 2KB 71 self.p_entry = 28 72 elif (self.idx > 1): 73 # image: ns_bl1u 74 # Record the end of loader & BL1. ns_bl1u won't be loaded by BootROM. 75 self.p_loader_end = self.p_file 76 # ns_bl1u should locates in l-loader.bin bias 2KB too 77 if (self.p_file < (lba * self.block_size - 2048)): 78 self.p_file = lba * self.block_size - 2048 79 80 # Maybe the file size isn't aligned. So pad it. 81 if (self.idx == 0): 82 if fsize > 2048: 83 print 'loader size exceeds 2KB. file size: ', fsize 84 sys.exit(4) 85 else: 86 left_bytes = 2048 - fsize 87 else: 88 left_bytes = fsize % self.block_size 89 if left_bytes: 90 left_bytes = self.block_size - left_bytes 91 print 'lba: ', lba, 'blocks: ', blocks, 'bootp: ', bootp, 'fname: ', fname 92 # write images 93 fimg = open(fname, "rb") 94 for i in range (0, blocks): 95 buf = fimg.read(self.block_size) 96 # loader's p_file is 0 at here 97 self.fp.seek(self.p_file) 98 self.fp.write(buf) 99 # p_file is the file pointer of the new binary file 100 # At last, it means the total block size of the new binary file 101 self.p_file += self.block_size 102 103 if (self.idx == 0): 104 self.p_file = 2048 105 print 'p_file: ', self.p_file, 'last block is ', fsize % self.block_size, 'bytes', ' tell: ', self.fp.tell(), 'left_bytes: ', left_bytes 106 if left_bytes: 107 for i in range (0, left_bytes): 108 zero = struct.pack('x') 109 self.fp.write(zero) 110 print 'p_file: ', self.p_file, ' pad to: ', self.fp.tell() 111 112 # write entry information at the header 113 byte = struct.pack('8s8siii', 'ENTRYHDR', self.s1_entry_name[self.idx], lba, blocks, bootp) 114 self.fp.seek(self.p_entry) 115 self.fp.write(byte) 116 self.p_entry += 28 117 self.idx += 1 118 119 fimg.close() 120 121 def hex2(self, data): 122 return data > 0 and hex(data) or hex(data & 0xffffffff) 123 124 def end(self): 125 self.fp.seek(20) 126 start,end = struct.unpack("ii", self.fp.read(8)) 127 print "start: ", self.hex2(start), 'end: ', self.hex2(end) 128 end = start + self.p_loader_end 129 print "start: ", self.hex2(start), 'end: ', self.hex2(end) 130 self.fp.seek(24) 131 byte = struct.pack('i', end) 132 self.fp.write(byte) 133 self.fp.close() 134 135 def create(self, img_loader, img_bl1, img_ns_bl1u, output_img): 136 print '+-----------------------------------------------------------+' 137 print ' Input Images:' 138 print ' loader: ', img_loader 139 print ' bl1: ', img_bl1 140 print ' ns_bl1u: ', img_ns_bl1u 141 print ' Ouput Image: ', output_img 142 print '+-----------------------------------------------------------+\n' 143 144 self.stage = 1 145 146 # The first 2KB is reserved 147 # The next 2KB is for loader image 148 self.add(4, img_loader) 149 print 'self.idx: ', self.idx 150 # bl1.bin starts from 4KB 151 self.add(8, img_bl1) 152 if img_ns_bl1u != 0: 153 # ns_bl1u.bin starts from 96KB 154 self.add(192, img_ns_bl1u) 155 156def main(argv): 157 img_ns_bl1u = 0 158 try: 159 opts, args = getopt.getopt(argv,"ho:",["img_loader=","img_bl1=","img_ns_bl1u="]) 160 except getopt.GetoptError: 161 print 'gen_loader.py -o <l-loader.bin> --img_loader <l-loader> --img_bl1 <bl1.bin> --img_ns_bl1u <ns_bl1u.bin>' 162 sys.exit(2) 163 for opt, arg in opts: 164 if opt == '-h': 165 print 'gen_loader.py -o <l-loader.bin> --img_loader <l-loader> --img_bl1 <bl1.bin> --img_ns_bl1u <ns_bl1u.bin>' 166 sys.exit(1) 167 elif opt == '-o': 168 output_img = arg 169 elif opt in ("--img_loader"): 170 img_loader = arg 171 elif opt in ("--img_bl1"): 172 img_bl1 = arg 173 elif opt in ("--img_ns_bl1u"): 174 img_ns_bl1u = arg 175 176 loader = generator(output_img) 177 loader.idx = 0 178 179 loader.create(img_loader, img_bl1, img_ns_bl1u, output_img) 180 181 loader.end() 182 183if __name__ == "__main__": 184 main(sys.argv[1:]) 185