blob: cda32685601fdd995241f3c115c2f2b906bcf763 [file] [log] [blame]
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301#
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05302# Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05303#
4"""
5Script to create a U-Boot flashable multi-image blob.
6
7This script creates a multi-image blob, from a bunch of images, and
8adds a U-Boot shell script to the blob, that can flash the images from
9within U-Boot. The procedure to use this script is listed below.
10
11 1. Create an images folder. Ex: my-pack
12
13 2. Copy all the images to be flashed into the folder.
14
15 3. Copy the partition MBN file into the folder. The file should be
16 named 'partition.mbn'. This is used to determine the offsets for
17 each of the named partitions.
18
19 4. Create a flash configuration file, specifying the images be
20 flashed, and the partition in which the images is to be
21 flashed. The flash configuration file can be specified using the
22 -f option, default is flash.conf.
23
24 5. Invoke 'pack' with the folder name as argument, pass flash
25 parameters as arguments if required. A single image file will
26 be created, out side the images folder, with .img suffix. Ex:
27 my-pack.img
28
29 6. Transfer the file into a valid SDRAM address and invoke the
30 following U-Boot command to flash the images. Replace 0x41000000,
31 with address location where the image has been loaded. The script
32 expects the variable 'imgaddr' to be set.
33
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +053034 u-boot> imgaddr=0x88000000 source $imgaddr:script
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053035
36Host-side Pre-req
37
38 * Python >= 2.6
39 * ordereddict >= 1.1 (for Python 2.6)
40 * mkimage >= 2012.07
41 * dtc >= 1.2.0
42
43Target-side Pre-req
44
45The following U-Boot config macros should be enabled, for the
46generated flashing script to work.
47
48 * CONFIG_FIT -- FIT image format support
49 * CONFIG_SYS_HUSH_PARSER -- bash style scripting support
50 * CONFIG_SYS_NULLDEV -- redirecting command output support
51 * CONFIG_CMD_XIMG -- extracting sub-images support
52 * CONFIG_CMD_NAND -- NAND Flash commands support
53 * CONFIG_CMD_NAND_YAFFS -- NAND YAFFS2 write support
54 * CONFIG_CMD_SF -- SPI Flash commands support
55"""
56
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053057from os.path import getsize
58from getopt import getopt
59from getopt import GetoptError
60from collections import namedtuple
61from string import Template
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053062
63import os
64import sys
65import os.path
66import subprocess
67import struct
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053068import hashlib
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +053069import xml.etree.ElementTree as ET
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053070
71version = "1.1"
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +053072ARCH_NAME = ""
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053073#
74# Python 2.6 and earlier did not have OrderedDict use the backport
75# from ordereddict package. If that is not available report error.
76#
77try:
78 from collections import OrderedDict
79except ImportError:
80 try:
81 from ordereddict import OrderedDict
82 except ImportError:
83 print "error: this script requires the 'ordereddict' class."
84 print "Try 'pip install --user ordereddict'"
85 print "Or 'easy_install --user ordereddict'"
86 sys.exit(1)
87
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +053088def error(msg, ex=None):
89 """Print an error message and exit.
90
91 msg -- string, the message to print
92 ex -- exception, the associate exception, if any
93 """
94
95 sys.stderr.write("pack: %s" % msg)
96 if ex != None: sys.stderr.write(": %s" % str(ex))
97 sys.stderr.write("\n")
98 sys.exit(1)
99
100FlashInfo = namedtuple("FlashInfo", "type pagesize blocksize chipsize")
101ImageInfo = namedtuple("ProgInfo", "name filename type")
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530102PartInfo = namedtuple("PartInfo", "name offset length which_flash")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530103
104def roundup(value, roundto):
105 """Return the next largest multiple of 'roundto'."""
106
107 return ((value + roundto - 1) // roundto) * roundto
108
109class GPT(object):
110 GPTheader = namedtuple("GPTheader", "signature revision header_size"
111 " crc32 current_lba backup_lba first_usable_lba"
112 " last_usable_lba disk_guid start_lba_part_entry"
113 " num_part_entry part_entry_size part_crc32")
114 GPT_SIGNATURE = 'EFI PART'
115 GPT_REVISION = '\x00\x00\x01\x00'
116 GPT_HEADER_SIZE = 0x5C
117 GPT_HEADER_FMT = "<8s4sLL4xQQQQ16sQLLL"
118
119 GPTtable = namedtuple("GPTtable", "part_type unique_guid first_lba"
120 " last_lba attribute_flag part_name")
121 GPT_TABLE_FMT = "<16s16sQQQ72s"
122
123 def __init__(self, filename, pagesize, blocksize, chipsize):
124 self.filename = filename
125 self.pagesize = pagesize
126 self.blocksize = blocksize
127 self.chipsize = chipsize
128 self.__partitions = OrderedDict()
129
130 def __validate_and_read_parts(self, part_fp):
131 """Validate the GPT and read the partition"""
132 part_fp.seek(self.blocksize, os.SEEK_SET)
133 gptheader_str = part_fp.read(struct.calcsize(GPT.GPT_HEADER_FMT))
134 gptheader = struct.unpack(GPT.GPT_HEADER_FMT, gptheader_str)
135 gptheader = GPT.GPTheader._make(gptheader)
136
137 if gptheader.signature != GPT.GPT_SIGNATURE:
138 error("Invalid signature")
139
140 if gptheader.revision != GPT.GPT_REVISION:
141 error("Unsupported GPT Revision")
142
143 if gptheader.header_size != GPT.GPT_HEADER_SIZE:
144 error("Invalid Header size")
145
146 # Adding GPT partition info. This has to be flashed first.
147 # GPT Header starts at LBA1 so (current_lba -1) will give the
148 # starting of primary GPT.
149 # blocksize will equal to gptheader.first_usuable_lba - current_lba + 1
150
151 name = "0:GPT"
152 block_start = gptheader.current_lba - 1
153 block_count = gptheader.first_usable_lba - gptheader.current_lba + 1
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530154 which_flash = 0
155 part_info = PartInfo(name, block_start, block_count, which_flash)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530156 self.__partitions[name] = part_info
157
158 part_fp.seek(2 * self.blocksize, os.SEEK_SET)
159
160 for i in range(gptheader.num_part_entry):
161 gpt_table_str = part_fp.read(struct.calcsize(GPT.GPT_TABLE_FMT))
162 gpt_table = struct.unpack(GPT.GPT_TABLE_FMT, gpt_table_str)
163 gpt_table = GPT.GPTtable._make(gpt_table)
164
165 block_start = gpt_table.first_lba
166 block_count = gpt_table.last_lba - gpt_table.first_lba + 1
167
168 part_name = gpt_table.part_name.strip(chr(0))
169 name = part_name.replace('\0','')
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530170 part_info = PartInfo(name, block_start, block_count, which_flash)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530171 self.__partitions[name] = part_info
172
173 # Adding the GPT Backup partition.
174 # GPT header backup_lba gives block number where the GPT backup header will be.
175 # GPT Backup header will start from offset of 32 blocks before
176 # the GPTheader.backup_lba. Backup GPT size is 33 blocks.
177 name = "0:GPTBACKUP"
178 block_start = gptheader.backup_lba - 32
179 block_count = 33
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530180 part_info = PartInfo(name, block_start, block_count, which_flash)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530181 self.__partitions[name] = part_info
182
183 def get_parts(self):
184 """Returns a list of partitions present in the GPT."""
185
186 try:
187 with open(self.filename, "r") as part_fp:
188 self.__validate_and_read_parts(part_fp)
189 except IOError, e:
190 error("error opening %s" % self.filename, e)
191
192 return self.__partitions
193
194class MIBIB(object):
195 Header = namedtuple("Header", "magic1 magic2 version age")
196 HEADER_FMT = "<LLLL"
197 HEADER_MAGIC1 = 0xFE569FAC
198 HEADER_MAGIC2 = 0xCD7F127A
199 HEADER_VERSION = 4
200
201 Table = namedtuple("Table", "magic1 magic2 version numparts")
202 TABLE_FMT = "<LLLL"
203 TABLE_MAGIC1 = 0x55EE73AA
204 TABLE_MAGIC2 = 0xE35EBDDB
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530205 TABLE_VERSION = 4
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530206
207 Entry = namedtuple("Entry", "name offset length"
208 " attr1 attr2 attr3 which_flash")
209 ENTRY_FMT = "<16sLLBBBB"
210
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530211 def __init__(self, filename, pagesize, blocksize, chipsize, nand_blocksize, nand_chipsize, root_part):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530212 self.filename = filename
213 self.pagesize = pagesize
214 self.blocksize = blocksize
215 self.chipsize = chipsize
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530216 self.nand_blocksize = nand_blocksize
217 self.nand_chipsize = nand_chipsize
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530218 self.__partitions = OrderedDict()
219
220 def __validate(self, part_fp):
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530221 """Validate the MIBIB by checking for magic bytes."""
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530222
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530223 mheader_str = part_fp.read(struct.calcsize(MIBIB.HEADER_FMT))
224 mheader = struct.unpack(MIBIB.HEADER_FMT, mheader_str)
225 mheader = MIBIB.Header._make(mheader)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530226
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530227 if (mheader.magic1 != MIBIB.HEADER_MAGIC1
228 or mheader.magic2 != MIBIB.HEADER_MAGIC2):
229 """ mheader.magic1 = MIBIB.HEADER_MAGIC1
230 mheader.magic2 = MIBIB.HEADER_MAGIC2 """
231 error("invalid partition table, magic byte not present")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530232
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530233 if mheader.version != MIBIB.HEADER_VERSION:
234 error("unsupport mibib version")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530235
236 def __read_parts(self, part_fp):
237 """Read the partitions from the MIBIB."""
238
239 part_fp.seek(self.pagesize, os.SEEK_SET)
240 mtable_str = part_fp.read(struct.calcsize(MIBIB.TABLE_FMT))
241 mtable = struct.unpack(MIBIB.TABLE_FMT, mtable_str)
242 mtable = MIBIB.Table._make(mtable)
243
244 if (mtable.magic1 != MIBIB.TABLE_MAGIC1
245 or mtable.magic2 != MIBIB.TABLE_MAGIC2):
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530246 """ mtable.magic1 = MIBIB.TABLE_MAGIC1
247 mtable.magic2 = MIBIB.TABLE_MAGIC2 """
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530248 error("invalid sys part. table, magic byte not present")
249
250 if mtable.version != MIBIB.TABLE_VERSION:
251 error("unsupported partition table version")
252
253 for i in range(mtable.numparts):
254 mentry_str = part_fp.read(struct.calcsize(MIBIB.ENTRY_FMT))
255 mentry = struct.unpack(MIBIB.ENTRY_FMT, mentry_str)
256 mentry = MIBIB.Entry._make(mentry)
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530257 self.flash_flag = self.blocksize
258 self.chip_flag = self.chipsize
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530259
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530260 if mentry.which_flash != 0:
261 self.flash_flag = self.nand_blocksize
262 self.chip_flag = self.nand_chipsize
263
264 byte_offset = mentry.offset * self.flash_flag
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530265
266 if mentry.length == 0xFFFFFFFF:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530267 byte_length = self.chip_flag - byte_offset
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530268 else:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530269 byte_length = mentry.length * self.flash_flag
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530270
271 part_name = mentry.name.strip(chr(0))
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530272 part_info = PartInfo(part_name, byte_offset, byte_length, mentry.which_flash)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530273 self.__partitions[part_name] = part_info
274
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530275 def get_parts(self):
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530276 """Returns a list of partitions present in the MIBIB. CE """
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530277
278 try:
279 with open(self.filename, "r") as part_fp:
280 self.__validate(part_fp)
281 self.__read_parts(part_fp)
282 except IOError, e:
283 error("error opening %s" % self.filename, e)
284
285 return self.__partitions
286
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530287class FlashScript(object):
288 """Base class for creating flash scripts."""
289
290 def __init__(self, flinfo):
291 self.pagesize = flinfo.pagesize
292 self.blocksize = flinfo.blocksize
293 self.script = []
294 self.parts = []
295 self.curr_stdout = "serial"
296 self.activity = None
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530297 self.flash_type = flinfo.type
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530298
299 self.script.append('if test "x$verbose" = "x"; then\n')
300 self.script.append("failedmsg='[failed]'\n")
301 self.script.append('else\n')
302 self.script.append("failedmsg='%s Failed'\n" % ("#" * 40))
303 self.script.append('fi\n')
304
305 def append(self, cmd, fatal=True):
306 """Add a command to the script.
307
308 Add additional code, to terminate on error. This can be
309 supressed by passing 'fatal' as False.
310 """
311
312 if fatal:
313 self.script.append(cmd
314 + ' || setenv stdout serial'
315 + ' && echo "$failedmsg"'
316 + ' && exit 1\n')
317 else:
318 self.script.append(cmd + "\n")
319
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530320 def dumps(self):
321 """Return the created script as a string."""
322 return "".join(self.script)
323
324 def redirect(self, dev):
325 """Generate code, to redirect command output to a device."""
326
327 if self.curr_stdout == dev:
328 return
329
330 self.append("setenv stdout %s" % dev, fatal=False)
331 self.curr_stdout = dev
332
333 def start_activity(self, activity):
334 """Generate code, to indicate start of an activity."""
335
336 self.script.append('if test "x$verbose" = "x"; then\n')
337 self.echo("'%-40.40s'" % activity, nl=False)
338 self.script.append('else\n')
339 self.echo("'%s %s Started'" % ("#" * 40, activity), verbose=True)
340 self.script.append('fi\n')
341 self.activity = activity
342
343 def finish_activity(self):
344 """Generate code, to indicate end of an activity."""
345
346 self.script.append('if test "x$verbose" = "x"; then\n')
347 self.echo("'[ done ]'")
348 self.redirect("serial")
349 self.script.append('else\n')
350 self.echo("'%s %s Done'" % ("#" * 40, self.activity), verbose=True)
351 self.script.append('fi\n')
352
353 def imxtract(self, part):
354 """Generate code, to extract image location, from a multi-image blob.
355
356 part -- string, name of the sub-image
357
358 Sets the $fileaddr environment variable, to point to the
359 location of the sub-image.
360 """
361
362 self.append("imxtract $imgaddr %s" % part)
363
364 def echo(self, msg, nl=True, verbose=False):
365 """Generate code, to print a message.
366
367 nl -- bool, indicates whether newline is to be printed
368 verbose -- bool, indicates whether printing in verbose mode
369 """
370
371 if not verbose:
372 self.redirect("serial")
373
374 if nl:
375 self.append("echo %s" % msg, fatal=False)
376 else:
377 self.append("echo %s%s" % (r"\\c", msg), fatal=False)
378
379 if not verbose:
380 self.redirect("nulldev")
381
382 def end(self):
383 """Generate code, to indicate successful completion of script."""
384
385 self.append("exit 0\n", fatal=False)
386
387 def start_if(self, var, value):
388 """Generate code, to check an environment variable.
389
390 var -- string, variable to check
391 value -- string, the value to compare with
392 """
393
394 self.append('if test "$%s" = "%s"; then\n' % (var, value),
395 fatal=False)
396
397 def end_if(self):
398 """Generate code, to end if statement."""
399
400 self.append('fi\n', fatal=False)
401
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530402class Flash_Script(FlashScript):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530403 """Class for creating NAND flash scripts."""
404
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530405 def __init__(self, *args):
406 FlashScript.__init__(self, args[0])
407 if args[0].type == "nand":
408 self.ipq_nand = args[1]
409 elif args[0].type == "nor" or args[0].type == "norplusnand":
410 self.nand_pagesize = args[1]
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530411
412 def erase(self, offset, size):
413 """Generate code, to erase the specified partition."""
414
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530415 if self.flash_type != "emmc":
416 size = roundup(size, self.blocksize)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530417
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530418 if self.flash_type == "nand":
419 self.append("nand erase 0x%08x 0x%08x" % (offset, size))
420 elif self.flash_type == "nor":
421 self.append("sf erase 0x%08x +0x%08x" % (offset, size))
422 elif self.flash_type == "emmc":
423 self.append("mmc erase 0x%08x %x" % (offset, size))
424
425 def nand_write(self, offset, part_size, img_size, spi_nand):
426 """Handle the NOR + NAND case
427 All binaries upto HLOS will go to NOR and Root FS will go to NAND
428 Assumed all nand page sizes are less than are equal to 8KB
429 """
430
431 if spi_nand == "true":
432 self.append("nand device 1 && nand erase 0x%08x 0x%08x" % (offset, part_size))
433 else:
434 self.append("nand device 0 && nand erase 0x%08x 0x%08x" % (offset, part_size))
435
436 if img_size > 0:
437 self.append("nand write $fileaddr 0x%08x 0x%08x" % (offset, img_size))
438
439 def write(self, offset, size):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530440 """Generate code, to write to a partition."""
441
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530442 if self.flash_type == "nand":
443 if size > 0:
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530444 size = roundup(size, self.pagesize)
445 self.append("nand write $fileaddr 0x%08x 0x%08x" % (offset, size))
446
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530447 elif self.flash_type == "nor":
448 if size > 0:
449 self.append("sf write $fileaddr 0x%08x 0x%08x" % (offset, size))
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530450
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530451 elif self.flash_type == "emmc":
452 if size > 0:
453 size = roundup(size, self.blocksize)
454 blk_cnt = size / self.blocksize
455 self.append("mmc write $fileaddr 0x%08x %x" % (offset, blk_cnt))
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530456
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530457 def probe(self):
458 if self.flash_type == "nand":
459 pass
460 elif self.flash_type == "nor":
461 self.append("sf probe")
462 else:
463 pass
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530464
465its_tmpl = Template("""
466/dts-v1/;
467
468/ {
469 description = "${desc}";
470 images {
471${images}
472 };
473};
474""")
475
476its_image_tmpl = Template("""
477 ${name} {
478 description = "${desc}";
479 data = /incbin/("./${fname}");
480 type = "${imtype}";
481 arch = "arm";
482 compression = "none";
483 hash@1 { algo = "crc32"; };
484 };
485""")
486
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530487def sha1(message):
488 """Returns SHA1 digest in hex format of the message."""
489
490 m = hashlib.sha1()
491 m.update(message)
492 return m.hexdigest()
493
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530494class Pack(object):
495 """Class to create a flashable, multi-image blob.
496
497 Combine multiple images present in a directory, and generate a
498 U-Boot script to flash the images.
499 """
500 # The maximum rootfs size is 64MB
501 norplusnand_rootfs_img_size = (64 * 1024 * 1024)
502
503 def __init__(self):
504 self.flinfo = None
505 self.images_dname = None
506 self.ipq_nand = None
507 self.partitions = {}
508
509 self.fconf_fname = None
510 self.scr_fname = None
511 self.its_fname = None
512 self.img_fname = None
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530513 self.emmc_page_size = 512
514 self.emmc_block_size = 512
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530515
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530516 def __get_machid(self, section):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530517 """Get the machid for a section.
518
519 info -- ConfigParser object, containing image flashing info
520 section -- section to retreive the machid from
521 """
522 try:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530523 machid = int(section.find("./machid").text, 0)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530524 machid = "%x" % machid
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530525 except ValueError, e:
526 error("invalid value for machid, should be integer")
527
528 return machid
529
530 def __get_img_size(self, filename):
531 """Get the size of the image to be flashed
532
533 filaneme -- string, filename of the image to be flashed
534 """
535
536 if filename.lower() == "none":
537 return 0
538 try:
539 return getsize(os.path.join(self.images_dname, filename))
540 except OSError, e:
541 error("error getting image size '%s'" % filename, e)
542
543 def __get_part_info(self, partition):
544 """Return partition info for the specified partition.
545
546 partition -- string, partition name
547 """
548 try:
549 return self.partitions[partition]
550 except KeyError, e:
551 return None
552
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530553 def __gen_flash_script_cdt(self, entries, partition, flinfo, script):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530554
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530555 for section in entries:
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530556
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530557 machid = int(section.find(".//machid").text, 0)
558 machid = "%x" % machid
559 board = section.find(".//board").text
560 spi_nand = section.find(".//spi_nand").text
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530561 try:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530562 memory = section.find(".//memory").text
563 except AttributeError, e:
564 memory = "128M16"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530565
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530566 filename = "cdt-" + board + "_" + memory + ".bin"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530567
568 img_size = self.__get_img_size(filename)
569 part_info = self.__get_part_info(partition)
570
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530571 section_label = partition.split(":")
572 if len(section_label) != 1:
573 section_conf = section_label[1]
574 else:
575 section_conf = section_label[0]
576
577 section_conf = section_conf.lower()
578
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530579 if self.flinfo.type == 'nand':
580 size = roundup(img_size, flinfo.pagesize)
581 tr = ' | tr \"\\000\" \"\\377\"'
582
583 if self.flinfo.type == 'emmc':
584 size = roundup(img_size, flinfo.blocksize)
585 tr = ''
586
587 if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
588 pad_size = size - img_size
589 filename_abs = os.path.join(self.images_dname, filename)
590 filename_abs_pad = filename_abs + ".padded"
591 cmd = 'cat %s > %s' % (filename_abs, filename_abs_pad)
592 ret = subprocess.call(cmd, shell=True)
593 if ret != 0:
594 error("failed to copy image")
595 cmd = 'dd if=/dev/zero count=1 bs=%s %s >> %s' % (pad_size, tr, filename_abs_pad)
596 cmd = '(' + cmd + ') 1>/dev/null 2>/dev/null'
597 ret = subprocess.call(cmd, shell=True)
598 if ret != 0:
599 error("failed to create padded image from script")
600
601 if self.flinfo.type != "emmc":
602 if part_info == None:
603 if self.flinfo.type == 'norplusnand':
604 if count > 2:
605 error("More than 2 NAND images for NOR+NAND is not allowed")
606 elif img_size > part_info.length:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530607 error("img size is larger than part. len in '%s'" % section_conf)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530608 else:
609 if part_info != None:
610 if (img_size > 0):
611 if img_size > (part_info.length * self.flinfo.blocksize):
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530612 error("img size is larger than part. len in '%s'" % section_conf)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530613
614 if part_info == None and self.flinfo.type != 'norplusnand':
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530615 print "Flash type is norplusemmc"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530616 continue
617
618 if machid:
619 script.start_if("machid", machid)
620
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530621 script.start_activity("Flashing ddr-%s_%s:" % ( board, memory ))
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530622 if img_size > 0:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530623 filename_pad = filename + ".padded"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530624 if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530625 script.imxtract("ddr-" + board + "_" + memory + "-" + sha1(filename_pad))
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530626 else:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530627 script.imxtract("ddr-" + board + "_" + memory + "-" + sha1(filename))
628 """ script.imxtract("cdt-" + board + "_" + memory + ".bin-" + sha1(filename_pad))
629 else:
630 script.imxtract("cdt-" + board + "_" + memory + ".bin-" + sha1(filename)) """
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530631
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530632 part_size = Pack.norplusnand_rootfs_img_size
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530633 if part_info == None:
634 if self.flinfo.type == 'norplusnand':
635 offset = count * Pack.norplusnand_rootfs_img_size
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530636 script.nand_write(offset, part_size, img_size, spi_nand)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530637 count = count + 1
638 else:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530639 if part_info.which_flash == 0:
640 offset = part_info.offset
641 script.erase(offset, part_info.length)
642 script.write(offset, img_size)
643 else:
644 offset = part_info.offset
645 script.nand_write(offset, part_info.length, img_size, spi_nand)
646
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530647 script.finish_activity()
648
649 if machid:
650 script.end_if()
651
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530652 def __gen_flash_script(self, script, flinfo, root):
653 """Generate the script to flash the images.
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530654
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530655 info -- ConfigParser object, containing image flashing info
656 script -- Script object, to append commands to
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530657 """
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530658 count = 0
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530659
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530660 if self.flash_type == "norplusemmc" and flinfo.type == "emmc":
661 srcDir_part = "$$/" + ARCH_NAME + "/flash_partition/" + flinfo.type + "-partition.xml"
662 else:
663 srcDir_part = "$$/" + ARCH_NAME + "/flash_partition/" + self.flash_type.lower() + "-partition.xml"
664 cdir = os.path.abspath("")
665 srcDir_part = srcDir_part.replace('$$', cdir)
666 root_part = ET.parse(srcDir_part)
667 if self.flash_type != "emmc" and flinfo.type != "emmc":
668 parts = root_part.findall(".//partitions/partition")
669 elif self.flash_type != "emmc" and flinfo.type == "emmc":
670 parts = root_part.findall(".//physical_partition[@ref='norplusemmc']/partition")
671 else:
672 parts = root_part.findall(".//physical_partition[@ref='emmc']/partition")
673 if flinfo.type == "emmc":
674 parts_length = len(parts) + 2
675 else:
676 parts_length = len(parts)
677 entries = root.findall(".//data[@type='MACH_ID_BOARD_MAP']/entry")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530678
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530679 first = False
680 section = None
681 part_index = 0
682
683 if flinfo.type == "emmc":
684 first = True
685
686 for index in range(parts_length):
687
688 if first:
689 if self.flash_type == "norplusemmc":
690 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
691 else:
692 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
693 part_fname = part_info.find(".//partition_mbn")
694 filename = part_fname.text
695 partition = "0:GPT"
696 first = False
697
698 elif index == (parts_length - 1) and flinfo.type == "emmc":
699 if self.flash_type == "norplusemmc":
700 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
701 else:
702 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
703 part_fname = part_info.find(".//partition_mbn_backup")
704 filename = part_fname.text
705 partition = "0:GPTBACKUP"
706
707 else:
708 section = parts[part_index]
709 part_index += 1
710 if flinfo.type != "emmc":
711 try:
712 filename = section[8].text
713 except IndexError, e:
714 if index == (parts_length - 1):
715 return
716 else:
717 continue
718 partition = section[0].text
719 else:
720 if section.attrib['label'] == "0:CDT" or section.attrib['filename'] != "":
721 try:
722 filename = section.attrib['filename']
723 partition = section.attrib['label']
724 except KeyError, e:
725 error("Error getting image info in section '%s'" % section, e)
726 else:
727 continue
728 # Get machID
729 if partition != "0:CDT":
730 machid = None
731 else:
732 self.__gen_flash_script_cdt(entries, partition, flinfo, script)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530733 continue
734
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530735 # Get Layout
736 try:
737 layout = section.attrib['layout']
738 if layout is None:
739 layout = None
740 except KeyError, e:
741 layout = None
742 except AttributeError, e:
743 layout = None
744
745 if layout not in ("sbl", "linux", None):
746 error("invalid layout in '%s'" % section)
747
748 img_size = self.__get_img_size(filename)
749 part_info = self.__get_part_info(partition)
750
751 section_label = partition.split(":")
752 if len(section_label) != 1:
753 section_conf = section_label[1]
754 else:
755 section_conf = section_label[0]
756
757 section_conf = section_conf.lower()
758 spi_nand = False
759
760 if self.flinfo.type == 'nand':
761 size = roundup(img_size, flinfo.pagesize)
762 tr = ' | tr \"\\000\" \"\\377\"'
763
764 if self.flinfo.type == 'emmc':
765 size = roundup(img_size, flinfo.blocksize)
766 tr = ''
767
768 if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
769 pad_size = size - img_size
770 filename_abs = os.path.join(self.images_dname, filename)
771 filename_abs_pad = filename_abs + ".padded"
772 cmd = 'cat %s > %s' % (filename_abs, filename_abs_pad)
773 ret = subprocess.call(cmd, shell=True)
774 if ret != 0:
775 error("failed to copy image")
776 cmd = 'dd if=/dev/zero count=1 bs=%s %s >> %s' % (pad_size, tr, filename_abs_pad)
777 cmd = '(' + cmd + ') 1>/dev/null 2>/dev/null'
778 ret = subprocess.call(cmd, shell=True)
779 if ret != 0:
780 error("failed to create padded image from script")
781
782 if self.flinfo.type != "emmc":
783 if part_info == None:
784 if self.flinfo.type == 'norplusnand':
785 if count > 2:
786 error("More than 2 NAND images for NOR+NAND is not allowed")
787 elif img_size > part_info.length:
788 error("img size is larger than part. len in '%s'" % section_conf)
789 else:
790 if part_info != None:
791 if (img_size > 0):
792 if img_size > (part_info.length * self.flinfo.blocksize):
793 error("img size is larger than part. len in '%s'" % section_conf)
794
795 if part_info == None and self.flinfo.type != 'norplusnand':
796 print "Flash type is norplusemmc"
797 continue
798
799 if machid:
800 script.start_if("machid", machid)
801
802 if section_conf == "qsee":
803 section_conf = "tz"
804 elif section_conf == "appsbl":
805 section_conf = "u-boot"
806 elif section_conf == "rootfs" and flinfo.type != "nor" and self.flash_type != "norplusemmc":
807 section_conf = "ubi"
808
809 script.start_activity("Flashing %s:" % section_conf)
810 if img_size > 0:
811 filename_pad = filename + ".padded"
812 if ((self.flinfo.type == 'nand' or self.flinfo.type == 'emmc') and (size != img_size)):
813 script.imxtract(section_conf + "-" + sha1(filename_pad))
814 else:
815 script.imxtract(section_conf + "-" + sha1(filename))
816
817 part_size = Pack.norplusnand_rootfs_img_size
818 if part_info == None:
819 if self.flinfo.type == 'norplusnand':
820 offset = count * Pack.norplusnand_rootfs_img_size
821 img_size = Pack.norplusnand_rootfs_img_size
822 script.nand_write(offset, part_size, img_size, spi_nand)
823 count = count + 1
824 else:
825 if part_info.which_flash == 0:
826 offset = part_info.offset
827 script.erase(offset, part_info.length)
828 script.write(offset, img_size)
829 else:
830 offset = part_info.offset
831 script.nand_write(offset, part_info.length, img_size, spi_nand)
832
833 script.finish_activity()
834
835 if machid:
836 script.end_if()
837
838 def __gen_script_cdt(self, images, flinfo, root, section_conf, partition):
839
840 entries = root.findall(".//data[@type='MACH_ID_BOARD_MAP']/entry")
841
842 for section in entries:
843
844 board = section.find(".//board").text
845 try:
846 memory = section.find(".//memory").text
847 except AttributeError, e:
848 memory = "128M16"
849
850 filename = "cdt-" + board + "_" + memory + ".bin"
851 file_info = "ddr-" + board + "_" + memory
852
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530853 part_info = self.__get_part_info(partition)
854
855 if part_info == None and self.flinfo.type != 'norplusnand':
856 continue
857
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530858 if self.flinfo.type == 'nand':
859 img_size = self.__get_img_size(filename)
860 size = roundup(img_size, flinfo.pagesize)
861 if ( size != img_size ):
862 filename = filename + ".padded"
863 if self.flinfo.type == 'emmc':
864 img_size = self.__get_img_size(filename)
865 size = roundup(img_size, flinfo.blocksize)
866 if ( size != img_size ):
867 filename = filename + ".padded"
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530868 image_info = ImageInfo(file_info + "-" + sha1(filename),
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530869 filename, "firmware")
870 if filename.lower() != "none":
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530871 if image_info not in images:
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530872 images.append(image_info)
873
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530874 def __gen_script(self, script_fp, script, images, flinfo, root):
875 """Generate the script to flash the multi-image blob.
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530876
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530877 script_fp -- file object, to write script to
878 info_fp -- file object, to read flashing information from
879 script -- Script object, to append the commands to
880 images -- list of ImageInfo, appended to, based on images in config
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530881 """
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +0530882 self.__gen_flash_script(script, flinfo, root)
883 if (self.flash_type == "norplusemmc" and flinfo.type == "emmc") or (self.flash_type != "norplusemmc"):
884 if flinfo.type == "emmc":
885 script.start_activity("Flashing rootfs_data:")
886 part_info = self.partitions["rootfs_data"]
887 script.erase(part_info.offset, part_info.length)
888 script.finish_activity()
889 script.end()
890
891 if self.flash_type == "norplusemmc" and flinfo.type == "emmc":
892 srcDir_part = "$$/" + ARCH_NAME + "/flash_partition/" + flinfo.type + "-partition.xml"
893 else:
894 srcDir_part = "$$/" + ARCH_NAME + "/flash_partition/" + self.flash_type.lower() + "-partition.xml"
895 cdir = os.path.abspath("")
896 srcDir_part = srcDir_part.replace('$$', cdir)
897 root_part = ET.parse(srcDir_part)
898 if self.flash_type != "emmc" and flinfo.type != "emmc":
899 parts = root_part.findall(".//partitions/partition")
900 elif self.flash_type != "emmc" and flinfo.type == "emmc":
901 parts = root_part.findall(".//physical_partition[@ref='norplusemmc']/partition")
902 else:
903 parts = root_part.findall(".//physical_partition[@ref='emmc']/partition")
904 if flinfo.type == "emmc":
905 parts_length = len(parts) + 2
906 else:
907 parts_length = len(parts)
908
909 first = False
910 section = None
911 part_index = 0
912
913 if flinfo.type == "emmc":
914 first = True
915
916 for index in range(parts_length):
917
918 if first:
919 if self.flash_type == "norplusemmc":
920 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
921 else:
922 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
923 part_fname = part_info.find(".//partition_mbn")
924 filename = part_fname.text
925 partition = "0:GPT"
926 first = False
927
928 elif index == (parts_length - 1) and flinfo.type == "emmc":
929 if self.flash_type == "norplusemmc":
930 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
931 else:
932 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
933 part_fname = part_info.find(".//partition_mbn_backup")
934 filename = part_fname.text
935 partition = "0:GPTBACKUP"
936
937 else:
938 section = parts[part_index]
939 part_index += 1
940 if flinfo.type != "emmc":
941 try:
942 filename = section[8].text
943 except IndexError, e:
944 if index == (parts_length - 1):
945 return
946 else:
947 continue
948 partition = section[0].text
949 else:
950 if section.attrib['label'] == "0:CDT" or section.attrib['filename'] != "":
951 try:
952 filename = section.attrib['filename']
953 partition = section.attrib['label']
954 except KeyError, e:
955 error("Error getting image info in section '%s'" % section, e)
956 else:
957 continue
958
959 part_info = self.__get_part_info(partition)
960
961 section_label = partition.split(":")
962 if len(section_label) != 1:
963 section_conf = section_label[1]
964 else:
965 section_conf = section_label[0]
966
967 section_conf = section_conf.lower()
968
969 if section_conf == "cdt":
970 self.__gen_script_cdt(images, flinfo, root, section_conf, partition)
971 continue
972
973 if part_info == None and self.flinfo.type != 'norplusnand':
974 continue
975
976 if self.flinfo.type == 'nand':
977 img_size = self.__get_img_size(filename)
978 size = roundup(img_size, flinfo.pagesize)
979 if ( size != img_size ):
980 filename = filename + ".padded"
981 if self.flinfo.type == 'emmc':
982 img_size = self.__get_img_size(filename)
983 size = roundup(img_size, flinfo.blocksize)
984 if ( size != img_size ):
985 filename = filename + ".padded"
986 if section_conf == "qsee":
987 section_conf = "tz"
988 elif section_conf == "appsbl":
989 section_conf = "u-boot"
990 elif section_conf == "rootfs" and flinfo.type != "nor" and self.flash_type != "norplusemmc":
991 section_conf = "ubi"
992 image_info = ImageInfo(section_conf + "-" + sha1(filename),
993 filename, "firmware")
994 if filename.lower() != "none":
995 if image_info not in images:
996 images.append(image_info)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +0530997
998 def __mkimage(self, images):
999 """Create the multi-image blob.
1000
1001 images -- list of ImageInfo, containing images to be part of the blob
1002 """
1003 try:
1004 its_fp = open(self.its_fname, "wb")
1005 except IOError, e:
1006 error("error opening its file '%s'" % self.its_fname, e)
1007
1008 desc = "Flashing %s %x %x"
1009 desc = desc % (self.flinfo.type, self.flinfo.pagesize,
1010 self.flinfo.blocksize)
1011
1012 image_data = []
1013 for (section, fname, imtype) in images:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301014 fname = fname.replace("\\", "\\\\")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301015 subs = dict(name=section, desc=fname, fname=fname, imtype=imtype)
1016 image_data.append(its_image_tmpl.substitute(subs))
1017
1018 image_data = "".join(image_data)
1019 its_data = its_tmpl.substitute(desc=desc, images=image_data)
1020
1021 its_fp.write(its_data)
1022 its_fp.close()
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301023
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301024 try:
1025 cmd = ["mkimage", "-f", self.its_fname, self.img_fname]
1026 ret = subprocess.call(cmd)
1027 if ret != 0:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301028 print ret
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301029 error("failed to create u-boot image from script")
1030 except OSError, e:
1031 error("error executing mkimage", e)
1032
1033 def __create_fnames(self):
1034 """Populate the filenames."""
1035
1036 self.scr_fname = os.path.join(self.images_dname, "flash.scr")
1037 self.its_fname = os.path.join(self.images_dname, "flash.its")
1038
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301039 def __gen_board_script(self, flinfo, part_fname, images, root):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301040 """Generate the flashing script for one board.
1041
1042 board_section -- string, board section in board config file
1043 machid -- string, board machine ID in hex format
1044 flinfo -- FlashInfo object, contains board specific flash params
1045 part_fname -- string, partition file specific to the board
1046 fconf_fname -- string, flash config file specific to the board
1047 images -- list of ImageInfo, append images used by the board here
1048 """
1049 script_fp = open(self.scr_fname, "a")
1050
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301051 if flinfo.type != "emmc":
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301052 flash_param = root.find(".//data[@type='NAND_PARAMETER']")
1053 pagesize = int(flash_param.find(".//page_size").text)
1054 pages_per_block = int(flash_param.find(".//pages_per_block").text)
1055 blocksize = pages_per_block * pagesize
1056 blocks_per_chip = int(flash_param.find(".//total_block").text)
1057 chipsize = blocks_per_chip * blocksize
1058
1059 srcDir_part = "$$/" + ARCH_NAME + "/flash_partition/" + flinfo.type + "-partition.xml"
1060 cdir = os.path.abspath("")
1061 srcDir_part = srcDir_part.replace('$$', cdir)
1062 root_part = ET.parse(srcDir_part)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301063 mibib = MIBIB(part_fname, flinfo.pagesize, flinfo.blocksize,
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301064 flinfo.chipsize, blocksize, chipsize, root_part)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301065 self.partitions = mibib.get_parts()
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301066 if flinfo.type == "nand":
1067 script = Flash_Script(flinfo, self.ipq_nand)
1068 elif flinfo.type == "nor":
1069 script = Flash_Script(flinfo, pagesize)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301070 else:
1071 gpt = GPT(part_fname, flinfo.pagesize, flinfo.blocksize, flinfo.chipsize)
1072 self.partitions = gpt.get_parts()
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301073 script = Flash_Script(flinfo)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301074
1075 self.flinfo = flinfo
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301076
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301077 script.probe()
1078 self.__gen_script(script_fp, script, images, flinfo, root)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301079
1080 try:
1081 script_fp.write(script.dumps())
1082 except IOError, e:
1083 error("error writing to script '%s'" % script_fp.name, e)
1084
1085 script_fp.close()
1086
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301087 def __process_board_flash_emmc(self, ftype, images, root):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301088 """Extract board info from config and generate the flash script.
1089
1090 ftype -- string, flash type 'emmc'
1091 board_section -- string, board section in config file
1092 machid -- string, board machine ID in hex format
1093 images -- list of ImageInfo, append images used by the board here
1094 """
1095
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301096 try:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301097 part_info = root.find(".//data[@type='" + self.flash_type.upper() + "_PARAMETER']")
1098 part_fname = part_info.find(".//partition_mbn")
1099 cdir = os.path.abspath(os.path.dirname(""))
1100 part_fname = part_fname.text
1101 part_fname = os.path.join(self.images_dname, part_fname)
1102 if ftype == "norplusemmc":
1103 part_info = root.find(".//data[@type='NORPLUSEMMC_PARAMETER']")
1104 pagesize = int(part_info.find(".//page_size_flash").text)
1105 part_info = root.find(".//data[@type='EMMC_PARAMETER']")
1106 else:
1107 pagesize = self.emmc_page_size
1108 blocksize = self.emmc_block_size
1109 chipsize = int(part_info.find(".//total_block").text)
1110 if ftype.lower() == "norplusemmc":
1111 ftype = "emmc"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301112
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301113 except ValueError, e:
1114 error("invalid flash info in section '%s'" % board_section.find('machid').text, e)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301115
1116 flinfo = FlashInfo(ftype, pagesize, blocksize, chipsize)
1117
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301118 self.__gen_board_script(flinfo, part_fname, images, root)
1119
1120 def __process_board_flash(self, ftype, images, root):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301121 try:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301122 part_info = root.find(".//data[@type='" + ftype.upper() + "_PARAMETER']")
1123 cdir = os.path.abspath(os.path.dirname(""))
1124 part_file = "$$/" + ARCH_NAME + "/flash_partition/" + ftype + "-partition.xml"
1125 cdir = os.path.abspath("")
1126 part_file = part_file.replace('$$', cdir)
1127 part_xml = ET.parse(part_file)
1128 partition = part_xml.find(".//partitions/partition[2]")
1129 part_fname = partition[8].text
1130 part_fname = os.path.join(self.images_dname, part_fname)
1131 pagesize = int(part_info.find(".//page_size").text)
1132 pages_per_block = int(part_info.find(".//pages_per_block").text)
1133 blocks_per_chip = int(part_info.find(".//total_block").text)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301134
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301135 if ftype == "norplusnand" or ftype == "norplusemmc":
1136 ftype = "nor"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301137
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301138 except ValueError, e:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301139 error("invalid flash info in section '%s'" % board_section.find('machid').text, e)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301140
1141 blocksize = pages_per_block * pagesize
1142 chipsize = blocks_per_chip * blocksize
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301143
1144 flinfo = FlashInfo(ftype, pagesize, blocksize, chipsize)
1145
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301146 self.__gen_board_script(flinfo, part_fname, images, root)
1147
1148 def __process_board(self, images, root):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301149
1150 try:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301151 if self.flash_type in [ "nand", "nor", "norplusnand" ]:
1152 self.__process_board_flash(self.flash_type, images, root)
1153 elif self.flash_type == "emmc":
1154 self.__process_board_flash_emmc(self.flash_type, images, root)
1155 elif self.flash_type == "norplusemmc":
1156 self.__process_board_flash("norplusemmc", images, root)
1157 self.__process_board_flash_emmc("norplusemmc", images, root)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301158 except ValueError, e:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301159 error("error getting board info in section '%s'" % board_section.find('machid').text, e)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301160
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301161 def main_bconf(self, flash_type, images_dname, out_fname):
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301162 """Start the packing process, using board config.
1163
1164 flash_type -- string, indicates flash type, 'nand' or 'nor' or 'emmc' or 'norplusnand'
1165 images_dname -- string, name of images directory
1166 out_fname -- string, output file path
1167 """
1168 self.flash_type = flash_type
1169 self.images_dname = images_dname
1170 self.img_fname = out_fname
1171
1172 self.__create_fnames()
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301173 global ARCH_NAME
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301174 try:
1175 os.unlink(self.scr_fname)
1176 except OSError, e:
1177 pass
1178
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301179 cdir = os.path.abspath("")
1180 if len(sys.argv) > 1:
1181 try:
1182 opts, args = getopt(sys.argv[1:], "t:o:c:")
1183 except GetoptError, e:
1184 print "Configuration xml file is needed to generate cdt files"
1185 raise
1186 for option, value in opts:
1187 if option == "-c":
1188 srcDir = value
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301189 else:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301190 srcDir = '$$/common/config.xml'
1191 srcDir = srcDir.replace('$$', cdir)
1192 root = ET.parse(srcDir)
1193
1194 arch = root.find(".//data[@type='ARCH']/SOC")
1195 ARCH_NAME = str(arch.text)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301196
1197 images = []
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301198 self.__process_board(images, root)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301199 images.insert(0, ImageInfo("script", "flash.scr", "script"))
1200 self.__mkimage(images)
1201
1202class UsageError(Exception):
1203 """Indicates error in command arguments."""
1204 pass
1205
1206class ArgParser(object):
1207 """Class to parse command-line arguments."""
1208
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301209 DEFAULT_TYPE = "nand"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301210
1211 def __init__(self):
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301212 self.flash_type = None
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301213 self.images_dname = None
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301214 self.out_dname = None
1215 self.scr_fname = None
1216 self.its_fname = None
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301217
1218 def parse(self, argv):
1219 """Start the parsing process, and populate members with parsed value.
1220
1221 argv -- list of string, the command line arguments
1222 """
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301223
1224 try:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301225 opts, args = getopt(argv[1:], "t:o:c:")
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301226 except GetoptError, e:
1227 raise UsageError(e.msg)
1228
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301229 if len(args) != 2:
1230 raise UsageError("Insufficient arguments")
1231 else:
1232 cdir = os.path.abspath(os.path.dirname(""))
1233 self.images_dname = os.path.join(cdir, args[0])
1234 self.out_dname = os.path.join(cdir, args[1])
1235
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301236 for option, value in opts:
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301237
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301238 if option == "-t":
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301239 if value == None:
1240 self.flash_type = ArgParser.DEFAULT_TYPE
1241 elif value in [ "nand", "nor", "emmc", "norplusnand", "norplusemmc" ]:
1242 self.flash_type = value
1243 else:
1244 raise UsageError("invalid flash type '%s'" % self.flash_type)
1245
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301246 elif option == "-o":
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301247 if value == None:
1248 fmt = "%s-%s%simg"
1249 self.out_fname = fmt % (self.out_dname, self.flash_type,
1250 os.path.extsep)
1251 elif os.path.isabs(value):
1252 self.out_fname = value
1253 else:
1254 self.out_fname = os.path.join(self.out_dname, value)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301255
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301256 if not os.path.exists(self.out_dname):
1257 os.makedirs(self.out_dname)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301258
1259 def usage(self, msg):
1260 """Print error message and command usage information.
1261
1262 msg -- string, the error message
1263 """
1264 print "pack: %s" % msg
1265 print
1266 print "Usage: pack [options] IDIR"
1267 print
1268 print "where IDIR is the path containing the images."
1269 print
1270 print " -t TYPE specifies partition type, 'nand' or 'nor',"
1271 print " default is '%s'." % ArgParser.DEFAULT_TYPE
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301272 print " -o FILE specifies the output filename"
1273 print " default is IDIR-TYPE-SIZE-COUNT.img"
1274 print " if the filename is relative, it is relative"
1275 print " to the parent of IDIR."
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301276 print " -c FILE specifies the config filename"
1277 print " default is common/config.xml"
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301278 print
1279 print "Pack Version: %s" % version
1280
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301281def main():
1282 """Main script entry point.
1283
1284 Created to avoid polluting the global namespace.
1285 """
1286 try:
1287 parser = ArgParser()
1288 parser.parse(sys.argv)
1289 except UsageError, e:
1290 parser.usage(e.args[0])
1291 sys.exit(1)
1292
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301293 pack = Pack()
Aditya Kumar Patra Sb68f13e2017-03-08 14:07:23 +05301294 pack.main_bconf(parser.flash_type, parser.images_dname,
1295 parser.out_fname)
Aditya Kumar Patra S12f0be02016-10-25 18:41:15 +05301296
1297if __name__ == "__main__":
1298 main()