John Stultz | b2313ea | 2017-08-08 14:18:44 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | import os |
| 4 | import os.path |
| 5 | import sys, getopt |
| 6 | import binascii |
| 7 | import struct |
| 8 | import string |
| 9 | |
| 10 | # -------------------------- |
| 11 | # | loader | BL1 | NS BL1U | |
| 12 | # -------------------------- |
| 13 | |
| 14 | class 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 | |
| 156 | def 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 | |
| 183 | if __name__ == "__main__": |
| 184 | main(sys.argv[1:]) |