blob: 14b7e92e79d833d2781cf94b1e046e0386c91890 [file] [log] [blame]
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301######################################################################
2# Copyright (c) 2017, The Linux Foundation. All rights reserved.
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05303#
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05304# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License version 2 and
6# only version 2 as published by the Free Software Foundation.
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05307#
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05308# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#####################################################################
13
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053014"""
15Script to create a U-Boot flashable multi-image blob.
16
17This script creates a multi-image blob, from a bunch of images, and
18adds a U-Boot shell script to the blob, that can flash the images from
19within U-Boot. The procedure to use this script is listed below.
20
21 1. Create an images folder. Ex: my-pack
22
23 2. Copy all the images to be flashed into the folder.
24
25 3. Copy the partition MBN file into the folder. The file should be
26 named 'partition.mbn'. This is used to determine the offsets for
27 each of the named partitions.
28
29 4. Create a flash configuration file, specifying the images be
30 flashed, and the partition in which the images is to be
31 flashed. The flash configuration file can be specified using the
32 -f option, default is flash.conf.
33
34 5. Invoke 'pack' with the folder name as argument, pass flash
35 parameters as arguments if required. A single image file will
36 be created, out side the images folder, with .img suffix. Ex:
37 my-pack.img
38
39 6. Transfer the file into a valid SDRAM address and invoke the
40 following U-Boot command to flash the images. Replace 0x41000000,
41 with address location where the image has been loaded. The script
42 expects the variable 'imgaddr' to be set.
43
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +053044 u-boot> imgaddr=0x88000000 source $imgaddr:script
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053045
46Host-side Pre-req
47
48 * Python >= 2.6
49 * ordereddict >= 1.1 (for Python 2.6)
50 * mkimage >= 2012.07
51 * dtc >= 1.2.0
52
53Target-side Pre-req
54
55The following U-Boot config macros should be enabled, for the
56generated flashing script to work.
57
58 * CONFIG_FIT -- FIT image format support
59 * CONFIG_SYS_HUSH_PARSER -- bash style scripting support
60 * CONFIG_SYS_NULLDEV -- redirecting command output support
61 * CONFIG_CMD_XIMG -- extracting sub-images support
62 * CONFIG_CMD_NAND -- NAND Flash commands support
63 * CONFIG_CMD_NAND_YAFFS -- NAND YAFFS2 write support
64 * CONFIG_CMD_SF -- SPI Flash commands support
65"""
66
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053067from os.path import getsize
68from getopt import getopt
69from getopt import GetoptError
70from collections import namedtuple
71from string import Template
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053072
73import os
74import sys
75import os.path
76import subprocess
77import struct
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053078import hashlib
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +053079import xml.etree.ElementTree as ET
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053080
81version = "1.1"
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +053082ARCH_NAME = ""
83SRC_DIR = ""
84MODE = ""
Saravanan Jaganathan7d086402017-09-22 15:35:01 +053085image_type = "all"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053086#
87# Python 2.6 and earlier did not have OrderedDict use the backport
88# from ordereddict package. If that is not available report error.
89#
90try:
91 from collections import OrderedDict
92except ImportError:
93 try:
94 from ordereddict import OrderedDict
95 except ImportError:
96 print "error: this script requires the 'ordereddict' class."
97 print "Try 'pip install --user ordereddict'"
98 print "Or 'easy_install --user ordereddict'"
99 sys.exit(1)
100
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530101def error(msg, ex=None):
102 """Print an error message and exit.
103
104 msg -- string, the message to print
105 ex -- exception, the associate exception, if any
106 """
107
108 sys.stderr.write("pack: %s" % msg)
109 if ex != None: sys.stderr.write(": %s" % str(ex))
110 sys.stderr.write("\n")
111 sys.exit(1)
112
113FlashInfo = namedtuple("FlashInfo", "type pagesize blocksize chipsize")
114ImageInfo = namedtuple("ProgInfo", "name filename type")
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530115PartInfo = namedtuple("PartInfo", "name offset length which_flash")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530116
117def roundup(value, roundto):
118 """Return the next largest multiple of 'roundto'."""
119
120 return ((value + roundto - 1) // roundto) * roundto
121
122class GPT(object):
123 GPTheader = namedtuple("GPTheader", "signature revision header_size"
124 " crc32 current_lba backup_lba first_usable_lba"
125 " last_usable_lba disk_guid start_lba_part_entry"
126 " num_part_entry part_entry_size part_crc32")
127 GPT_SIGNATURE = 'EFI PART'
128 GPT_REVISION = '\x00\x00\x01\x00'
129 GPT_HEADER_SIZE = 0x5C
130 GPT_HEADER_FMT = "<8s4sLL4xQQQQ16sQLLL"
131
132 GPTtable = namedtuple("GPTtable", "part_type unique_guid first_lba"
133 " last_lba attribute_flag part_name")
134 GPT_TABLE_FMT = "<16s16sQQQ72s"
135
136 def __init__(self, filename, pagesize, blocksize, chipsize):
137 self.filename = filename
138 self.pagesize = pagesize
139 self.blocksize = blocksize
140 self.chipsize = chipsize
141 self.__partitions = OrderedDict()
142
143 def __validate_and_read_parts(self, part_fp):
144 """Validate the GPT and read the partition"""
145 part_fp.seek(self.blocksize, os.SEEK_SET)
146 gptheader_str = part_fp.read(struct.calcsize(GPT.GPT_HEADER_FMT))
147 gptheader = struct.unpack(GPT.GPT_HEADER_FMT, gptheader_str)
148 gptheader = GPT.GPTheader._make(gptheader)
149
150 if gptheader.signature != GPT.GPT_SIGNATURE:
151 error("Invalid signature")
152
153 if gptheader.revision != GPT.GPT_REVISION:
154 error("Unsupported GPT Revision")
155
156 if gptheader.header_size != GPT.GPT_HEADER_SIZE:
157 error("Invalid Header size")
158
159 # Adding GPT partition info. This has to be flashed first.
160 # GPT Header starts at LBA1 so (current_lba -1) will give the
161 # starting of primary GPT.
162 # blocksize will equal to gptheader.first_usuable_lba - current_lba + 1
163
164 name = "0:GPT"
165 block_start = gptheader.current_lba - 1
166 block_count = gptheader.first_usable_lba - gptheader.current_lba + 1
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530167 which_flash = 0
168 part_info = PartInfo(name, block_start, block_count, which_flash)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530169 self.__partitions[name] = part_info
170
171 part_fp.seek(2 * self.blocksize, os.SEEK_SET)
172
173 for i in range(gptheader.num_part_entry):
174 gpt_table_str = part_fp.read(struct.calcsize(GPT.GPT_TABLE_FMT))
175 gpt_table = struct.unpack(GPT.GPT_TABLE_FMT, gpt_table_str)
176 gpt_table = GPT.GPTtable._make(gpt_table)
177
178 block_start = gpt_table.first_lba
179 block_count = gpt_table.last_lba - gpt_table.first_lba + 1
180
181 part_name = gpt_table.part_name.strip(chr(0))
182 name = part_name.replace('\0','')
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530183 part_info = PartInfo(name, block_start, block_count, which_flash)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530184 self.__partitions[name] = part_info
185
186 # Adding the GPT Backup partition.
187 # GPT header backup_lba gives block number where the GPT backup header will be.
188 # GPT Backup header will start from offset of 32 blocks before
189 # the GPTheader.backup_lba. Backup GPT size is 33 blocks.
190 name = "0:GPTBACKUP"
191 block_start = gptheader.backup_lba - 32
192 block_count = 33
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530193 part_info = PartInfo(name, block_start, block_count, which_flash)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530194 self.__partitions[name] = part_info
195
196 def get_parts(self):
197 """Returns a list of partitions present in the GPT."""
198
199 try:
200 with open(self.filename, "r") as part_fp:
201 self.__validate_and_read_parts(part_fp)
202 except IOError, e:
203 error("error opening %s" % self.filename, e)
204
205 return self.__partitions
206
207class MIBIB(object):
208 Header = namedtuple("Header", "magic1 magic2 version age")
209 HEADER_FMT = "<LLLL"
210 HEADER_MAGIC1 = 0xFE569FAC
211 HEADER_MAGIC2 = 0xCD7F127A
212 HEADER_VERSION = 4
213
214 Table = namedtuple("Table", "magic1 magic2 version numparts")
215 TABLE_FMT = "<LLLL"
216 TABLE_MAGIC1 = 0x55EE73AA
217 TABLE_MAGIC2 = 0xE35EBDDB
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530218 TABLE_VERSION_IPQ806X = 3
219 TABLE_VERSION_OTHERS = 4
220
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530221
222 Entry = namedtuple("Entry", "name offset length"
223 " attr1 attr2 attr3 which_flash")
224 ENTRY_FMT = "<16sLLBBBB"
225
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530226 def __init__(self, filename, pagesize, blocksize, chipsize, nand_blocksize, nand_chipsize, root_part):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530227 self.filename = filename
228 self.pagesize = pagesize
229 self.blocksize = blocksize
230 self.chipsize = chipsize
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530231 self.nand_blocksize = nand_blocksize
232 self.nand_chipsize = nand_chipsize
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530233 self.__partitions = OrderedDict()
234
235 def __validate(self, part_fp):
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530236 """Validate the MIBIB by checking for magic bytes."""
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530237
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530238 mheader_str = part_fp.read(struct.calcsize(MIBIB.HEADER_FMT))
239 mheader = struct.unpack(MIBIB.HEADER_FMT, mheader_str)
240 mheader = MIBIB.Header._make(mheader)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530241
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530242 if (mheader.magic1 != MIBIB.HEADER_MAGIC1
243 or mheader.magic2 != MIBIB.HEADER_MAGIC2):
244 """ mheader.magic1 = MIBIB.HEADER_MAGIC1
245 mheader.magic2 = MIBIB.HEADER_MAGIC2 """
246 error("invalid partition table, magic byte not present")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530247
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530248 if mheader.version != MIBIB.HEADER_VERSION:
249 error("unsupport mibib version")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530250
251 def __read_parts(self, part_fp):
252 """Read the partitions from the MIBIB."""
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530253 global ARCH_NAME
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530254 part_fp.seek(self.pagesize, os.SEEK_SET)
255 mtable_str = part_fp.read(struct.calcsize(MIBIB.TABLE_FMT))
256 mtable = struct.unpack(MIBIB.TABLE_FMT, mtable_str)
257 mtable = MIBIB.Table._make(mtable)
258
259 if (mtable.magic1 != MIBIB.TABLE_MAGIC1
260 or mtable.magic2 != MIBIB.TABLE_MAGIC2):
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530261 """ mtable.magic1 = MIBIB.TABLE_MAGIC1
262 mtable.magic2 = MIBIB.TABLE_MAGIC2 """
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530263 error("invalid sys part. table, magic byte not present")
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530264 if ARCH_NAME == "ipq806x":
265 if mtable.version != MIBIB.TABLE_VERSION_IPQ806X:
266 error("unsupported partition table version")
267 else:
268 if mtable.version != MIBIB.TABLE_VERSION_OTHERS:
269 error("unsupported partition table version")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530270
271 for i in range(mtable.numparts):
272 mentry_str = part_fp.read(struct.calcsize(MIBIB.ENTRY_FMT))
273 mentry = struct.unpack(MIBIB.ENTRY_FMT, mentry_str)
274 mentry = MIBIB.Entry._make(mentry)
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530275 self.flash_flag = self.blocksize
276 self.chip_flag = self.chipsize
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530277
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530278 if mentry.which_flash != 0:
279 self.flash_flag = self.nand_blocksize
280 self.chip_flag = self.nand_chipsize
281
282 byte_offset = mentry.offset * self.flash_flag
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530283
284 if mentry.length == 0xFFFFFFFF:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530285 byte_length = self.chip_flag - byte_offset
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530286 else:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530287 byte_length = mentry.length * self.flash_flag
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530288
289 part_name = mentry.name.strip(chr(0))
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530290 part_info = PartInfo(part_name, byte_offset, byte_length, mentry.which_flash)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530291 self.__partitions[part_name] = part_info
292
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530293 def get_parts(self):
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530294 """Returns a list of partitions present in the MIBIB. CE """
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530295
296 try:
297 with open(self.filename, "r") as part_fp:
298 self.__validate(part_fp)
299 self.__read_parts(part_fp)
300 except IOError, e:
301 error("error opening %s" % self.filename, e)
302
303 return self.__partitions
304
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530305class FlashScript(object):
306 """Base class for creating flash scripts."""
307
308 def __init__(self, flinfo):
309 self.pagesize = flinfo.pagesize
310 self.blocksize = flinfo.blocksize
311 self.script = []
312 self.parts = []
313 self.curr_stdout = "serial"
314 self.activity = None
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530315 self.flash_type = flinfo.type
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530316
317 self.script.append('if test "x$verbose" = "x"; then\n')
318 self.script.append("failedmsg='[failed]'\n")
319 self.script.append('else\n')
320 self.script.append("failedmsg='%s Failed'\n" % ("#" * 40))
321 self.script.append('fi\n')
322
323 def append(self, cmd, fatal=True):
324 """Add a command to the script.
325
326 Add additional code, to terminate on error. This can be
327 supressed by passing 'fatal' as False.
328 """
329
330 if fatal:
331 self.script.append(cmd
332 + ' || setenv stdout serial'
333 + ' && echo "$failedmsg"'
334 + ' && exit 1\n')
335 else:
336 self.script.append(cmd + "\n")
337
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530338 def dumps(self):
339 """Return the created script as a string."""
340 return "".join(self.script)
341
342 def redirect(self, dev):
343 """Generate code, to redirect command output to a device."""
344
345 if self.curr_stdout == dev:
346 return
347
348 self.append("setenv stdout %s" % dev, fatal=False)
349 self.curr_stdout = dev
350
351 def start_activity(self, activity):
352 """Generate code, to indicate start of an activity."""
353
354 self.script.append('if test "x$verbose" = "x"; then\n')
355 self.echo("'%-40.40s'" % activity, nl=False)
356 self.script.append('else\n')
357 self.echo("'%s %s Started'" % ("#" * 40, activity), verbose=True)
358 self.script.append('fi\n')
359 self.activity = activity
360
361 def finish_activity(self):
362 """Generate code, to indicate end of an activity."""
363
364 self.script.append('if test "x$verbose" = "x"; then\n')
365 self.echo("'[ done ]'")
366 self.redirect("serial")
367 self.script.append('else\n')
368 self.echo("'%s %s Done'" % ("#" * 40, self.activity), verbose=True)
369 self.script.append('fi\n')
370
371 def imxtract(self, part):
372 """Generate code, to extract image location, from a multi-image blob.
373
374 part -- string, name of the sub-image
375
376 Sets the $fileaddr environment variable, to point to the
377 location of the sub-image.
378 """
379
380 self.append("imxtract $imgaddr %s" % part)
381
382 def echo(self, msg, nl=True, verbose=False):
383 """Generate code, to print a message.
384
385 nl -- bool, indicates whether newline is to be printed
386 verbose -- bool, indicates whether printing in verbose mode
387 """
388
389 if not verbose:
390 self.redirect("serial")
391
392 if nl:
393 self.append("echo %s" % msg, fatal=False)
394 else:
395 self.append("echo %s%s" % (r"\\c", msg), fatal=False)
396
397 if not verbose:
398 self.redirect("nulldev")
399
400 def end(self):
401 """Generate code, to indicate successful completion of script."""
402
403 self.append("exit 0\n", fatal=False)
404
405 def start_if(self, var, value):
406 """Generate code, to check an environment variable.
407
408 var -- string, variable to check
409 value -- string, the value to compare with
410 """
411
412 self.append('if test "$%s" = "%s"; then\n' % (var, value),
413 fatal=False)
414
415 def end_if(self):
416 """Generate code, to end if statement."""
417
418 self.append('fi\n', fatal=False)
419
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530420class Flash_Script(FlashScript):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530421 """Class for creating NAND flash scripts."""
422
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530423 def __init__(self, *args):
424 FlashScript.__init__(self, args[0])
425 if args[0].type == "nand":
426 self.ipq_nand = args[1]
427 elif args[0].type == "nor" or args[0].type == "norplusnand":
428 self.nand_pagesize = args[1]
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530429
430 def erase(self, offset, size):
431 """Generate code, to erase the specified partition."""
432
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530433 if self.flash_type != "emmc":
434 size = roundup(size, self.blocksize)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530435
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530436 if self.flash_type == "nand":
437 self.append("nand device 0 && nand erase 0x%08x 0x%08x" % (offset, size))
438 elif self.flash_type == "nor":
439 self.append("sf erase 0x%08x +0x%08x" % (offset, size))
440 elif self.flash_type == "emmc":
441 self.append("mmc erase 0x%08x %x" % (offset, size))
442
443 def nand_write(self, offset, part_size, img_size, spi_nand):
444 """Handle the NOR + NAND case
445 All binaries upto HLOS will go to NOR and Root FS will go to NAND
446 Assumed all nand page sizes are less than are equal to 8KB
447 """
448
449 if spi_nand == "true":
450 self.append("nand device 1 && nand erase 0x%08x 0x%08x" % (offset, part_size))
451 else:
452 self.append("nand device 0 && nand erase 0x%08x 0x%08x" % (offset, part_size))
453
454 if img_size > 0:
455 self.append("nand write $fileaddr 0x%08x 0x%08x" % (offset, img_size))
456
457 def write(self, offset, size):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530458 """Generate code, to write to a partition."""
459
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530460 if self.flash_type == "nand":
461 if size > 0:
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530462 size = roundup(size, self.pagesize)
463 self.append("nand write $fileaddr 0x%08x 0x%08x" % (offset, size))
464
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530465 elif self.flash_type == "nor":
466 if size > 0:
467 self.append("sf write $fileaddr 0x%08x 0x%08x" % (offset, size))
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530468
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530469 elif self.flash_type == "emmc":
470 if size > 0:
471 size = roundup(size, self.blocksize)
472 blk_cnt = size / self.blocksize
473 self.append("mmc write $fileaddr 0x%08x %x" % (offset, blk_cnt))
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530474
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530475 def probe(self):
476 if self.flash_type == "nand":
477 pass
478 elif self.flash_type == "nor":
479 self.append("sf probe")
480 else:
481 pass
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +0530482
483 def switch_layout(self, layout):
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530484 if self.flash_type == "nand":
485 self.append("ipq_nand %s" % layout)
486 else:
487 pass
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530488
489its_tmpl = Template("""
490/dts-v1/;
491
492/ {
493 description = "${desc}";
494 images {
495${images}
496 };
497};
498""")
499
500its_image_tmpl = Template("""
501 ${name} {
502 description = "${desc}";
503 data = /incbin/("./${fname}");
504 type = "${imtype}";
505 arch = "arm";
506 compression = "none";
507 hash@1 { algo = "crc32"; };
508 };
509""")
510
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530511def sha1(message):
512 """Returns SHA1 digest in hex format of the message."""
513
514 m = hashlib.sha1()
515 m.update(message)
516 return m.hexdigest()
517
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530518class Pack(object):
519 """Class to create a flashable, multi-image blob.
520
521 Combine multiple images present in a directory, and generate a
522 U-Boot script to flash the images.
523 """
524 # The maximum rootfs size is 64MB
525 norplusnand_rootfs_img_size = (64 * 1024 * 1024)
526
527 def __init__(self):
528 self.flinfo = None
529 self.images_dname = None
530 self.ipq_nand = None
531 self.partitions = {}
532
533 self.fconf_fname = None
534 self.scr_fname = None
535 self.its_fname = None
536 self.img_fname = None
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530537 self.emmc_page_size = 512
538 self.emmc_block_size = 512
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530539
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530540 def __get_machid(self, section):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530541 """Get the machid for a section.
542
543 info -- ConfigParser object, containing image flashing info
544 section -- section to retreive the machid from
545 """
546 try:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530547 machid = int(section.find("./machid").text, 0)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530548 machid = "%x" % machid
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530549 except ValueError, e:
550 error("invalid value for machid, should be integer")
551
552 return machid
553
554 def __get_img_size(self, filename):
555 """Get the size of the image to be flashed
556
557 filaneme -- string, filename of the image to be flashed
558 """
559
560 if filename.lower() == "none":
561 return 0
562 try:
563 return getsize(os.path.join(self.images_dname, filename))
564 except OSError, e:
565 error("error getting image size '%s'" % filename, e)
566
567 def __get_part_info(self, partition):
568 """Return partition info for the specified partition.
569
570 partition -- string, partition name
571 """
572 try:
573 return self.partitions[partition]
574 except KeyError, e:
575 return None
576
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530577 def __gen_flash_script_cdt(self, entries, partition, flinfo, script):
578 global ARCH_NAME
579 for section in entries:
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530580
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530581 machid = int(section.find(".//machid").text, 0)
582 machid = "%x" % machid
583 board = section.find(".//board").text
584 spi_nand = section.find(".//spi_nand").text
585 if ARCH_NAME != "ipq806x":
586 try:
587 memory = section.find(".//memory").text
588 except AttributeError, e:
589 memory = "128M16"
590 filename = "cdt-" + board + "_" + memory + ".bin"
591 else:
592 filename = "cdt-" + board + ".bin"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530593
594 img_size = self.__get_img_size(filename)
595 part_info = self.__get_part_info(partition)
596
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530597 section_label = partition.split(":")
598 if len(section_label) != 1:
599 section_conf = section_label[1]
600 else:
601 section_conf = section_label[0]
602
603 section_conf = section_conf.lower()
604
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530605 if self.flinfo.type == 'nand':
606 size = roundup(img_size, flinfo.pagesize)
607 tr = ' | tr \"\\000\" \"\\377\"'
608
609 if self.flinfo.type == 'emmc':
610 size = roundup(img_size, flinfo.blocksize)
611 tr = ''
612
613 if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
614 pad_size = size - img_size
615 filename_abs = os.path.join(self.images_dname, filename)
616 filename_abs_pad = filename_abs + ".padded"
617 cmd = 'cat %s > %s' % (filename_abs, filename_abs_pad)
618 ret = subprocess.call(cmd, shell=True)
619 if ret != 0:
620 error("failed to copy image")
621 cmd = 'dd if=/dev/zero count=1 bs=%s %s >> %s' % (pad_size, tr, filename_abs_pad)
622 cmd = '(' + cmd + ') 1>/dev/null 2>/dev/null'
623 ret = subprocess.call(cmd, shell=True)
624 if ret != 0:
625 error("failed to create padded image from script")
626
627 if self.flinfo.type != "emmc":
628 if part_info == None:
629 if self.flinfo.type == 'norplusnand':
630 if count > 2:
631 error("More than 2 NAND images for NOR+NAND is not allowed")
632 elif img_size > part_info.length:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530633 error("img size is larger than part. len in '%s'" % section_conf)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530634 else:
635 if part_info != None:
636 if (img_size > 0):
637 if img_size > (part_info.length * self.flinfo.blocksize):
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530638 error("img size is larger than part. len in '%s'" % section_conf)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530639
640 if part_info == None and self.flinfo.type != 'norplusnand':
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530641 print "Flash type is norplusemmc"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530642 continue
643
644 if machid:
645 script.start_if("machid", machid)
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530646 if ARCH_NAME != "ipq806x":
647 script.start_activity("Flashing ddr-%s_%s:" % ( board, memory ))
648 if img_size > 0:
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +0530649 filename_pad = filename + ".padded"
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530650 if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
651 script.imxtract("ddr-" + board + "_" + memory + "-" + sha1(filename_pad))
652 else:
653 script.imxtract("ddr-" + board + "_" + memory + "-" + sha1(filename))
654 """ script.imxtract("cdt-" + board + "_" + memory + ".bin-" + sha1(filename_pad))
655 else:
656 script.imxtract("cdt-" + board + "_" + memory + ".bin-" + sha1(filename)) """
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530657
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530658 else:
659 script.start_activity("Flashing ddr-%s:" % (board))
660 script.switch_layout("sbl")
661 if img_size > 0:
662 filename_pad = filename + ".padded"
663 if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
664 script.imxtract("ddr-" + board + "-" + sha1(filename_pad))
665 else:
666 script.imxtract("ddr-" + board + "-" + sha1(filename))
667 """ script.imxtract("cdt-" + board + ".bin-" + sha1(filename_pad))
668 else:
669 script.imxtract("cdt-" + board + ".bin-" + sha1(filename)) """
670
671 part_size = Pack.norplusnand_rootfs_img_size
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530672 if part_info == None:
673 if self.flinfo.type == 'norplusnand':
674 offset = count * Pack.norplusnand_rootfs_img_size
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530675 script.nand_write(offset, part_size, img_size, spi_nand)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530676 count = count + 1
677 else:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530678 if part_info.which_flash == 0:
679 offset = part_info.offset
680 script.erase(offset, part_info.length)
681 script.write(offset, img_size)
682 else:
683 offset = part_info.offset
684 script.nand_write(offset, part_info.length, img_size, spi_nand)
685
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530686 script.finish_activity()
687
688 if machid:
689 script.end_if()
690
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530691 def __gen_flash_script(self, script, flinfo, root):
692 """Generate the script to flash the images.
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530693
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530694 info -- ConfigParser object, containing image flashing info
695 script -- Script object, to append commands to
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530696 """
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530697 global MODE
698 global SRC_DIR
699 global ARCH_NAME
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530700
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530701 diff_files = ""
702 count = 0
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530703
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530704 if self.flash_type == "norplusemmc" and flinfo.type == "emmc":
705 srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + flinfo.type + "-partition.xml"
706 else:
707 srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + self.flash_type.lower() + "-partition.xml"
708
709 root_part = ET.parse(srcDir_part)
710 if self.flash_type != "emmc" and flinfo.type != "emmc":
711 parts = root_part.findall(".//partitions/partition")
712 elif self.flash_type != "emmc" and flinfo.type == "emmc":
713 parts = root_part.findall(".//physical_partition[@ref='norplusemmc']/partition")
714 else:
715 parts = root_part.findall(".//physical_partition[@ref='emmc']/partition")
716 if flinfo.type == "emmc":
717 parts_length = len(parts) + 2
718 else:
719 parts_length = len(parts)
720 entries = root.findall(".//data[@type='MACH_ID_BOARD_MAP']/entry")
721
722 first = False
723 section = None
724 part_index = 0
725
726 if flinfo.type == "emmc":
727 first = True
728
729 for index in range(parts_length):
730
731 if first:
732 if self.flash_type == "norplusemmc":
733 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
734 else:
735 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
736 part_fname = part_info.find(".//partition_mbn")
737 filename = part_fname.text
738 partition = "0:GPT"
739 first = False
740
741 elif index == (parts_length - 1) and flinfo.type == "emmc":
742 if self.flash_type == "norplusemmc":
743 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
744 else:
745 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
746 part_fname = part_info.find(".//partition_mbn_backup")
747 filename = part_fname.text
748 partition = "0:GPTBACKUP"
749
750 else:
751 section = parts[part_index]
752 part_index += 1
753 if flinfo.type != "emmc":
754 try:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +0530755 if image_type == "all" or section[8].attrib['image_type'] == image_type:
756 filename = section[8].text
757 try:
758 if section[8].attrib['mode'] != MODE:
759 filename = section[9].text
760 else:
761 pass
762 except AttributeError, e:
763 pass
764 except KeyError, e:
765 pass
766 else:
767 continue
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530768 except IndexError, e:
769 if index == (parts_length - 1):
770 return
771 else:
772 continue
Saravanan Jaganathan7d086402017-09-22 15:35:01 +0530773 except KeyError, e:
774 continue
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530775 partition = section[0].text
776 else:
777 try:
778 diff_files = section.attrib['diff_files']
779 except KeyError, e:
780 try:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +0530781 if image_type == "all" or section.attrib['image_type'] == image_type:
782 filename = section.attrib['filename']
783 partition = section.attrib['label']
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530784 if filename == "":
785 continue
786 except KeyError, e:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +0530787 print "Skipping partition '%s'" % section.attrib['label']
788 pass
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530789
790 if diff_files == "true":
791 try:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +0530792 if image_type == "all" or section.attrib['image_type'] == image_type:
793 filename = section.attrib['filename_' + MODE]
794 partition = section.attrib['label']
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530795 if filename == "":
796 continue
797 except KeyError, e:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +0530798 print "Skipping partition '%s'" % section.attrib['label']
799 pass
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530800 diff_files = "" # Clear for next iteration
801
802 # Get machID
803 if partition != "0:CDT" and partition != "0:DDRCONFIG":
804 machid = None
805 else:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +0530806 try:
807 if image_type == "all" or section.attrib['image_type'] == image_type:
808 self.__gen_flash_script_cdt(entries, partition, flinfo, script)
809 continue
810 except KeyError, e:
811 continue
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530812
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530813 if ARCH_NAME == "ipq806x":
814 # Get Layout
815 try:
816 layout = section[9].text
817 except:
818 layout = None
819
820 if layout not in ("sbl", "linux", None):
821 error("invalid layout in '%s'" % section)
822
823 img_size = self.__get_img_size(filename)
824 part_info = self.__get_part_info(partition)
825
826 section_label = partition.split(":")
827 if len(section_label) != 1:
828 section_conf = section_label[1]
829 else:
830 section_conf = section_label[0]
831
832 section_conf = section_conf.lower()
833 spi_nand = False
834
835 if self.flinfo.type == 'nand':
836 size = roundup(img_size, flinfo.pagesize)
837 tr = ' | tr \"\\000\" \"\\377\"'
838
839 if self.flinfo.type == 'emmc':
840 size = roundup(img_size, flinfo.blocksize)
841 tr = ''
842
843 if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
844 pad_size = size - img_size
845 filename_abs = os.path.join(self.images_dname, filename)
846 filename_abs_pad = filename_abs + ".padded"
847 cmd = 'cat %s > %s' % (filename_abs, filename_abs_pad)
848 ret = subprocess.call(cmd, shell=True)
849 if ret != 0:
850 error("failed to copy image")
851 cmd = 'dd if=/dev/zero count=1 bs=%s %s >> %s' % (pad_size, tr, filename_abs_pad)
852 cmd = '(' + cmd + ') 1>/dev/null 2>/dev/null'
853 ret = subprocess.call(cmd, shell=True)
854 if ret != 0:
855 error("failed to create padded image from script")
856
857 if self.flinfo.type != "emmc":
858 if part_info == None:
859 if self.flinfo.type == 'norplusnand':
860 if count > 2:
861 error("More than 2 NAND images for NOR+NAND is not allowed")
862 elif img_size > part_info.length:
863 error("img size is larger than part. len in '%s'" % section_conf)
864 else:
865 if part_info != None:
866 if (img_size > 0):
867 if img_size > (part_info.length * self.flinfo.blocksize):
868 error("img size is larger than part. len in '%s'" % section_conf)
869
870 if part_info == None and self.flinfo.type != 'norplusnand':
871 print "Flash type is norplusemmc"
872 continue
873
874 if machid:
875 script.start_if("machid", machid)
876
877 if section_conf == "qsee":
878 section_conf = "tz"
879 elif section_conf == "appsbl":
880 section_conf = "u-boot"
Aditya Kumar Patra S75bf44b2017-07-12 12:07:04 +0530881 elif section_conf == "rootfs" and (self.flash_type == "nand" or self.flash_type == "norplusnand"):
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530882 section_conf = "ubi"
Venkat Raju Sana2b68fba2017-12-06 17:46:47 -0800883 elif section_conf == "wififw" and (self.flash_type == "nand" or self.flash_type == "norplusnand"):
884 section_conf = "wififw_ubi"
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530885
886 script.start_activity("Flashing %s:" % section_conf)
887
888 if ARCH_NAME == "ipq806x":
889 script.switch_layout(layout)
890 if img_size > 0:
891 filename_pad = filename + ".padded"
892 if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
893 script.imxtract(section_conf + "-" + sha1(filename_pad))
894 else:
895 script.imxtract(section_conf + "-" + sha1(filename))
896
897 part_size = Pack.norplusnand_rootfs_img_size
898 if part_info == None:
899 if self.flinfo.type == 'norplusnand':
900 offset = count * Pack.norplusnand_rootfs_img_size
901 img_size = Pack.norplusnand_rootfs_img_size
902 script.nand_write(offset, part_size, img_size, spi_nand)
903 count = count + 1
904 else:
905 if part_info.which_flash == 0:
906 offset = part_info.offset
907 script.erase(offset, part_info.length)
908 script.write(offset, img_size)
909 else:
910 offset = part_info.offset
911 script.nand_write(offset, part_info.length, img_size, spi_nand)
912
913 script.finish_activity()
914
915 if machid:
916 script.end_if()
917
918 def __gen_script_cdt(self, images, flinfo, root, section_conf, partition):
919 global ARCH_NAME
920
921 entries = root.findall(".//data[@type='MACH_ID_BOARD_MAP']/entry")
922
923 for section in entries:
924
925 board = section.find(".//board").text
926 if ARCH_NAME != "ipq806x":
927 try:
928 memory = section.find(".//memory").text
929 except AttributeError, e:
930 memory = "128M16"
931
932 filename = "cdt-" + board + "_" + memory + ".bin"
933 file_info = "ddr-" + board + "_" + memory
934 else:
935 filename = "cdt-" + board + ".bin"
936 file_info = "ddr-" + board
937
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +0530938 part_info = self.__get_part_info(partition)
939
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530940 if part_info == None and self.flinfo.type != 'norplusnand':
941 continue
942
943 if self.flinfo.type == 'nand':
944 img_size = self.__get_img_size(filename)
945 size = roundup(img_size, flinfo.pagesize)
946 if ( size != img_size ):
947 filename = filename + ".padded"
948 if self.flinfo.type == 'emmc':
949 img_size = self.__get_img_size(filename)
950 size = roundup(img_size, flinfo.blocksize)
951 if ( size != img_size ):
952 filename = filename + ".padded"
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530953 image_info = ImageInfo(file_info + "-" + sha1(filename),
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +0530954 filename, "firmware")
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530955 if filename.lower() != "none":
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530956 if image_info not in images:
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +0530957 images.append(image_info)
958
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530959 def __gen_script(self, script_fp, script, images, flinfo, root):
960 """Generate the script to flash the multi-image blob.
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +0530961
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530962 script_fp -- file object, to write script to
963 info_fp -- file object, to read flashing information from
964 script -- Script object, to append the commands to
965 images -- list of ImageInfo, appended to, based on images in config
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +0530966 """
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +0530967 global MODE
968 global SRC_DIR
969
970 diff_files = ""
971 self.__gen_flash_script(script, flinfo, root)
972 if (self.flash_type == "norplusemmc" and flinfo.type == "emmc") or (self.flash_type != "norplusemmc"):
973 if flinfo.type == "emmc":
974 script.start_activity("Flashing rootfs_data:")
975 part_info = self.partitions["rootfs_data"]
976 script.erase(part_info.offset, part_info.length)
977 script.finish_activity()
978 script.end()
979
980 if self.flash_type == "norplusemmc" and flinfo.type == "emmc":
981 srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + flinfo.type + "-partition.xml"
982 else:
983 srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + self.flash_type.lower() + "-partition.xml"
984 root_part = ET.parse(srcDir_part)
985 if self.flash_type != "emmc" and flinfo.type != "emmc":
986 parts = root_part.findall(".//partitions/partition")
987 elif self.flash_type != "emmc" and flinfo.type == "emmc":
988 parts = root_part.findall(".//physical_partition[@ref='norplusemmc']/partition")
989 else:
990 parts = root_part.findall(".//physical_partition[@ref='emmc']/partition")
991 if flinfo.type == "emmc":
992 parts_length = len(parts) + 2
993 else:
994 parts_length = len(parts)
995
996 first = False
997 section = None
998 part_index = 0
999
1000 if flinfo.type == "emmc":
1001 first = True
1002
1003 for index in range(parts_length):
1004
1005 if first:
1006 if self.flash_type == "norplusemmc":
1007 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
1008 else:
1009 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
1010 part_fname = part_info.find(".//partition_mbn")
1011 filename = part_fname.text
1012 partition = "0:GPT"
1013 first = False
1014
1015 elif index == (parts_length - 1) and flinfo.type == "emmc":
1016 if self.flash_type == "norplusemmc":
1017 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
1018 else:
1019 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
1020 part_fname = part_info.find(".//partition_mbn_backup")
1021 filename = part_fname.text
1022 partition = "0:GPTBACKUP"
1023
1024 else:
1025 section = parts[part_index]
1026 part_index += 1
1027 if flinfo.type != "emmc":
1028 try:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301029 if image_type == "all" or section[8].attrib['image_type'] == image_type:
1030 filename = section[8].text
1031 try:
1032 if section[8].attrib['mode'] != MODE:
1033 filename = section[9].text
1034 except AttributeError, e:
1035 pass
1036 except KeyError, e:
1037 pass
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301038 except IndexError, e:
1039 if index == (parts_length - 1):
1040 return
1041 else:
1042 continue
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301043 except KeyError, e:
1044 continue
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301045 partition = section[0].text
1046 else:
1047
1048 try:
1049 diff_files = section.attrib['diff_files']
1050 except KeyError, e:
1051 try:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301052 if image_type == "all" or section.attrib['image_type'] == image_type:
1053 filename = section.attrib['filename']
1054 partition = section.attrib['label']
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301055 if filename == "":
1056 continue
1057 except KeyError, e:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301058 print "Skipping partition '%s'" % section.attrib['label']
1059 pass
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301060
1061 if diff_files == "true":
1062 try:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301063 if image_type == "all" or section.attrib['image_type'] == image_type:
1064 filename = section.attrib['filename_' + MODE]
1065 partition = section.attrib['label']
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301066 if filename == "":
1067 continue
1068
1069 except KeyError, e:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301070 print "Skipping partition '%s'" % section.attrib['label']
1071 pass
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301072 diff_files = "" # Clear for next iteration
1073
1074 part_info = self.__get_part_info(partition)
1075
1076 section_label = partition.split(":")
1077 if len(section_label) != 1:
1078 section_conf = section_label[1]
1079 else:
1080 section_conf = section_label[0]
1081
1082 section_conf = section_conf.lower()
1083
1084 if section_conf == "cdt" or section_conf == "ddrconfig":
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301085 try:
1086 if image_type == "all" or section[8].attrib['image_type'] == image_type:
1087 self.__gen_script_cdt(images, flinfo, root, section_conf, partition)
1088 continue
1089 except KeyError, e:
1090 continue
1091
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301092
1093 if part_info == None and self.flinfo.type != 'norplusnand':
1094 continue
1095
1096 if self.flinfo.type == 'nand':
1097 img_size = self.__get_img_size(filename)
1098 size = roundup(img_size, flinfo.pagesize)
1099 if ( size != img_size ):
1100 filename = filename + ".padded"
1101 if self.flinfo.type == 'emmc':
1102 img_size = self.__get_img_size(filename)
1103 size = roundup(img_size, flinfo.blocksize)
1104 if ( size != img_size ):
1105 filename = filename + ".padded"
1106 if section_conf == "qsee":
1107 section_conf = "tz"
1108 elif section_conf == "appsbl":
1109 section_conf = "u-boot"
Aditya Kumar Patra S75bf44b2017-07-12 12:07:04 +05301110 elif section_conf == "rootfs" and (self.flash_type == "nand" or self.flash_type == "norplusnand"):
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301111 section_conf = "ubi"
Venkat Raju Sana2b68fba2017-12-06 17:46:47 -08001112 elif section_conf == "wififw" and (self.flash_type == "nand" or self.flash_type == "norplusnand"):
1113 section_conf = "wififw_ubi"
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301114 image_info = ImageInfo(section_conf + "-" + sha1(filename),
1115 filename, "firmware")
1116 if filename.lower() != "none":
1117 if image_info not in images:
1118 images.append(image_info)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301119
1120 def __mkimage(self, images):
1121 """Create the multi-image blob.
1122
1123 images -- list of ImageInfo, containing images to be part of the blob
1124 """
1125 try:
1126 its_fp = open(self.its_fname, "wb")
1127 except IOError, e:
1128 error("error opening its file '%s'" % self.its_fname, e)
1129
1130 desc = "Flashing %s %x %x"
1131 desc = desc % (self.flinfo.type, self.flinfo.pagesize,
1132 self.flinfo.blocksize)
1133
1134 image_data = []
1135 for (section, fname, imtype) in images:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301136 fname = fname.replace("\\", "\\\\")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301137 subs = dict(name=section, desc=fname, fname=fname, imtype=imtype)
1138 image_data.append(its_image_tmpl.substitute(subs))
1139
1140 image_data = "".join(image_data)
1141 its_data = its_tmpl.substitute(desc=desc, images=image_data)
1142
1143 its_fp.write(its_data)
1144 its_fp.close()
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301145
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301146 try:
1147 cmd = ["mkimage", "-f", self.its_fname, self.img_fname]
1148 ret = subprocess.call(cmd)
1149 if ret != 0:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301150 print ret
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301151 error("failed to create u-boot image from script")
1152 except OSError, e:
1153 error("error executing mkimage", e)
1154
1155 def __create_fnames(self):
1156 """Populate the filenames."""
1157
1158 self.scr_fname = os.path.join(self.images_dname, "flash.scr")
1159 self.its_fname = os.path.join(self.images_dname, "flash.its")
1160
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301161 def __gen_board_script(self, flinfo, part_fname, images, root):
1162 global SRC_DIR
1163 global ARCH_NAME
1164
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301165 """Generate the flashing script for one board.
1166
1167 board_section -- string, board section in board config file
1168 machid -- string, board machine ID in hex format
1169 flinfo -- FlashInfo object, contains board specific flash params
1170 part_fname -- string, partition file specific to the board
1171 fconf_fname -- string, flash config file specific to the board
1172 images -- list of ImageInfo, append images used by the board here
1173 """
1174 script_fp = open(self.scr_fname, "a")
1175
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301176 if flinfo.type != "emmc":
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301177 flash_param = root.find(".//data[@type='NAND_PARAMETER']")
1178 pagesize = int(flash_param.find(".//page_size").text)
1179 pages_per_block = int(flash_param.find(".//pages_per_block").text)
1180 blocksize = pages_per_block * pagesize
1181 blocks_per_chip = int(flash_param.find(".//total_block").text)
1182 chipsize = blocks_per_chip * blocksize
1183
1184 srcDir_part = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + flinfo.type + "-partition.xml"
1185 root_part = ET.parse(srcDir_part)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301186 mibib = MIBIB(part_fname, flinfo.pagesize, flinfo.blocksize,
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301187 flinfo.chipsize, blocksize, chipsize, root_part)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301188 self.partitions = mibib.get_parts()
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301189 if flinfo.type == "nand":
1190 script = Flash_Script(flinfo, self.ipq_nand)
1191 elif flinfo.type == "nor":
1192 script = Flash_Script(flinfo, pagesize)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301193 else:
1194 gpt = GPT(part_fname, flinfo.pagesize, flinfo.blocksize, flinfo.chipsize)
1195 self.partitions = gpt.get_parts()
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301196 script = Flash_Script(flinfo)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301197
1198 self.flinfo = flinfo
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301199
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301200 script.probe()
1201 self.__gen_script(script_fp, script, images, flinfo, root)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301202
1203 try:
1204 script_fp.write(script.dumps())
1205 except IOError, e:
1206 error("error writing to script '%s'" % script_fp.name, e)
1207
1208 script_fp.close()
1209
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301210 def __process_board_flash_emmc(self, ftype, images, root):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301211 """Extract board info from config and generate the flash script.
1212
1213 ftype -- string, flash type 'emmc'
1214 board_section -- string, board section in config file
1215 machid -- string, board machine ID in hex format
1216 images -- list of ImageInfo, append images used by the board here
1217 """
1218
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301219 try:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301220 part_info = root.find(".//data[@type='" + self.flash_type.upper() + "_PARAMETER']")
1221 part_fname = part_info.find(".//partition_mbn")
1222 part_fname = part_fname.text
1223 part_fname = os.path.join(self.images_dname, part_fname)
1224 if ftype == "norplusemmc":
1225 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
1226 pagesize = int(part_info.find(".//page_size_flash").text)
1227 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
1228 else:
1229 pagesize = self.emmc_page_size
1230 blocksize = self.emmc_block_size
1231 chipsize = int(part_info.find(".//total_block").text)
1232 if ftype.lower() == "norplusemmc":
1233 ftype = "emmc"
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301234
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301235 except ValueError, e:
1236 error("invalid flash info in section '%s'" % board_section.find('machid').text, e)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301237
1238 flinfo = FlashInfo(ftype, pagesize, blocksize, chipsize)
1239
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301240 self.__gen_board_script(flinfo, part_fname, images, root)
1241
1242 def __process_board_flash(self, ftype, images, root):
1243 global SRC_DIR
1244 global ARCH_NAME
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301245
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301246 try:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301247 part_info = root.find(".//data[@type='" + ftype.upper() + "_PARAMETER']")
1248 part_file = SRC_DIR + "/" + ARCH_NAME + "/flash_partition/" + ftype + "-partition.xml"
1249 part_xml = ET.parse(part_file)
1250 partition = part_xml.find(".//partitions/partition[2]")
1251 part_fname = partition[8].text
1252 part_fname = os.path.join(self.images_dname, part_fname)
1253 pagesize = int(part_info.find(".//page_size").text)
1254 pages_per_block = int(part_info.find(".//pages_per_block").text)
1255 blocks_per_chip = int(part_info.find(".//total_block").text)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301256
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301257 if ftype == "norplusnand" or ftype == "norplusemmc":
1258 ftype = "nor"
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301259
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301260 except ValueError, e:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301261 error("invalid flash info in section '%s'" % board_section.find('machid').text, e)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301262
1263 blocksize = pages_per_block * pagesize
1264 chipsize = blocks_per_chip * blocksize
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301265
1266 flinfo = FlashInfo(ftype, pagesize, blocksize, chipsize)
1267
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301268 self.__gen_board_script(flinfo, part_fname, images, root)
1269
1270 def __process_board(self, images, root):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301271
1272 try:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301273 if self.flash_type in [ "nand", "nor", "norplusnand" ]:
1274 self.__process_board_flash(self.flash_type, images, root)
1275 elif self.flash_type == "emmc":
1276 self.__process_board_flash_emmc(self.flash_type, images, root)
1277 elif self.flash_type == "norplusemmc":
1278 self.__process_board_flash("norplusemmc", images, root)
1279 self.__process_board_flash_emmc("norplusemmc", images, root)
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301280 except ValueError, e:
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301281 error("error getting board info in section '%s'" % board_section.find('machid').text, e)
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301282
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301283 def main_bconf(self, flash_type, images_dname, out_fname, root):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301284 """Start the packing process, using board config.
1285
1286 flash_type -- string, indicates flash type, 'nand' or 'nor' or 'emmc' or 'norplusnand'
1287 images_dname -- string, name of images directory
1288 out_fname -- string, output file path
1289 """
1290 self.flash_type = flash_type
1291 self.images_dname = images_dname
1292 self.img_fname = out_fname
1293
1294 self.__create_fnames()
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301295 try:
1296 os.unlink(self.scr_fname)
1297 except OSError, e:
1298 pass
1299
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301300 images = []
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301301 self.__process_board(images, root)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301302 images.insert(0, ImageInfo("script", "flash.scr", "script"))
1303 self.__mkimage(images)
1304
1305class UsageError(Exception):
1306 """Indicates error in command arguments."""
1307 pass
1308
1309class ArgParser(object):
1310 """Class to parse command-line arguments."""
1311
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301312 DEFAULT_TYPE = "nor,nand,norplusnand,emmc,norplusemmc"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301313
1314 def __init__(self):
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301315 self.flash_type = None
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301316 self.images_dname = None
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301317 self.out_dname = None
1318 self.scr_fname = None
1319 self.its_fname = None
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301320
1321 def parse(self, argv):
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301322 global MODE
1323 global SRC_DIR
1324 global ARCH_NAME
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301325 global image_type
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301326
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301327 """Start the parsing process, and populate members with parsed value.
1328
1329 argv -- list of string, the command line arguments
1330 """
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301331
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301332 cdir = os.path.abspath(os.path.dirname(""))
1333 if len(sys.argv) > 1:
1334 try:
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301335 opts, args = getopt(sys.argv[1:], "", ["arch=", "fltype=", "srcPath=", "inImage=", "outImage=", "image_type="])
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301336 except GetoptError, e:
1337 raise UsageError(e.msg)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301338
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301339 for option, value in opts:
1340 if option == "--arch":
1341 ARCH_NAME = value
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301342
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301343 elif option == "--fltype":
1344 self.flash_type = value
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301345
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301346 elif option == "--srcPath":
1347 SRC_DIR = os.path.abspath(value)
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301348
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301349 elif option == "--inImage":
1350 self.images_dname = os.path.join(cdir, value)
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301351
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301352 elif option == "--outImage":
1353 self.out_dname = os.path.join(cdir, value)
1354
Saravanan Jaganathan7d086402017-09-22 15:35:01 +05301355 elif option == "--image_type":
1356 image_type = value
1357
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301358#Verify Arguments passed by user
1359
1360# Verify arch type
1361 if ARCH_NAME not in ["ipq40xx", "ipq806x", "ipq807x", "ipq807x_64"]:
1362 raise UsageError("Invalid arch type '%s'" % arch)
1363
1364 if ARCH_NAME == "ipq807x":
1365 MODE = "32"
1366 elif ARCH_NAME == "ipq807x_64":
1367 MODE = "64"
1368 ARCH_NAME = "ipq807x"
1369
1370# Set flash type to default type (nand) if not given by user
1371 if self.flash_type == None:
1372 self.flash_type = ArgParser.DEFAULT_TYPE
1373 for flash_type in self.flash_type.split(","):
1374 if flash_type not in [ "nand", "nor", "emmc", "norplusnand", "norplusemmc" ]:
1375 raise UsageError("invalid flash type '%s'" % flash_type)
1376
1377# Verify src Path
1378 if SRC_DIR == "":
1379 raise UsageError("Source Path is not provided")
1380
1381#Verify input image path
1382 if self.images_dname == None:
1383 raise UsageError("input images' Path is not provided")
1384
1385#Verify Output image path
1386 if self.out_dname == None:
1387 raise UsageError("Output Path is not provided")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301388
1389 def usage(self, msg):
1390 """Print error message and command usage information.
1391
1392 msg -- string, the error message
1393 """
1394 print "pack: %s" % msg
1395 print
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301396 print "Usage:"
1397 print "python pack_hk.py [options] [Value] ..."
1398 print
1399 print "options:"
1400 print " --arch \tARCH_TYPE [ipq40xx/ipq806x/ipq807x/ipq807x_64]"
1401 print
1402 print " --fltype \tFlash Type [nor/nand/emmc/norplusnand/norplusemmc]"
1403 print " \t\tMultiple flashtypes can be passed by a comma separated string"
1404 print " \t\tDefault is all. i.e If \"--fltype\" is not passed image for all the flash-type will be created.\n"
1405 print " --srcPath \tPath to the directory containg the meta scripts and configs"
1406 print
1407 print " --inImage \tPath to the direcory containg binaries and images needed for singleimage"
1408 print
1409 print " --outImage \tPath to the directory where single image will be generated"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301410 print
1411 print "Pack Version: %s" % version
1412
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301413def main():
1414 """Main script entry point.
1415
1416 Created to avoid polluting the global namespace.
1417 """
1418 try:
1419 parser = ArgParser()
1420 parser.parse(sys.argv)
1421 except UsageError, e:
1422 parser.usage(e.args[0])
1423 sys.exit(1)
1424
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301425 pack = Pack()
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301426
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301427 if not os.path.exists(parser.out_dname):
1428 os.makedirs(parser.out_dname)
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301429
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301430 config = SRC_DIR + "/" + ARCH_NAME + "/config.xml"
1431 root = ET.parse(config)
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301432
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301433# Format the output image name from Arch, flash type and mode
1434 for flash_type in parser.flash_type.split(","):
1435 if MODE == "64":
1436 parser.out_fname = flash_type + "-" + ARCH_NAME + "_" + MODE + "-single.img"
1437 else:
1438 parser.out_fname = flash_type + "-" + ARCH_NAME + "-single.img"
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301439
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301440 parser.out_fname = os.path.join(parser.out_dname, parser.out_fname)
Aditya Kumar Patra S117caa32017-03-21 12:19:27 +05301441
Aditya Kumar Patra Sd6885532017-05-30 12:09:25 +05301442 pack.main_bconf(flash_type, parser.images_dname,
1443 parser.out_fname, root)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301444
1445if __name__ == "__main__":
1446 main()