Пример #1
0
	def from_csv(cls, csv_contents, partitionTableOffset = None, sectorSize = None, md5Sum = True):
		res = PartitionTable(md5Sum)
		
		lines = csv_contents.splitlines()
		
		def expand_vars(f):
			f = os.path.expandvars(f)
			m = re.match(r'(?<!\\)\$([A-Za-z_][A-Za-z0-9_]*)', f)
			if m:
				raise InputError("unknown variable '%s'" % m.group(1))
			return f
		
		for line_no in range(len(lines)):
			line = expand_vars(lines[line_no]).strip()
			if line.startswith("#") or len(line) == 0:
				continue
			try:
				res.append(PartitionDefinition.from_csv(line, line_no + 1, sectorSize))
			except InputError as e:
				raise InputError("Error at line %d: %s" % (line_no + 1, e))
			except Exception:
				raise InputError("Unexpected error parsing CSV line %d: %s" % (line_no + 1, line))
		
		# To fill automaticaly partition offset fields, partition table offset and sector size must be know.
		if (not (partitionTableOffset and sectorSize)):
			for e in res:
				if (e.offset is None):
					raise InputError("Flash offset of the `%s' partition is empty in the CSV input file.\n"
					                 "So that the gen_partition script automaticaly calculates this offset, you must specify partition table offset (--offset) "
					                 "and flash sector size (--flash-sector-size) from the command line." % e.name)
			return res
		
		# fix up missing offsets
		last_end = partitionTableOffset + res.tableSize()  # first offset after partition table
		last_end = binary.align(last_end, sectorSize)
		for e in res:
			if e.offset is not None and e.offset < last_end:
				if e == res[0]:
					raise InputError("CSV Error: First partition offset 0x%x overlaps end of partition table 0x%x"
					                 % (e.offset, last_end))
				else:
					raise InputError(
						"CSV Error: Partitions overlap. Partition at line %d sets offset 0x%x. Previous partition ends 0x%x"
						% (e.line_no, e.offset, last_end))
			
			if e.offset is None:
				if last_end % sectorSize != 0:
					last_end = binary.align(last_end, sectorSize)
				e.offset = last_end
			
			last_end = e.offset + e.size
		
		return res
Пример #2
0
def operationFunc(args, flash_config=None):

    traces.info('Build flash image')
    
    flashImage = FlashImage(sectorSize = args.blockSize, flashType = args.flashType)
    
    #
    # Bootloader
    #
    endOfSSBLOffset = flashImage.appendBootloader(elf = args.boot_loader)
    traces.info("Partition boot loader size: 0x%X" % endOfSSBLOffset)
    
    #
    # Partition table
    #
    traces.info("\nGenerating partition table:")
    # Check if the partition table is lower than free space in current SSBL flash sector
    if (endOfSSBLOffset + partition.MAX_PARTITION_TABLE_SIZE) > binary.align(endOfSSBLOffset, args.blockSize):
        partitionTableOffset = binary.align(endOfSSBLOffset, args.blockSize)
        traces.info(
            "No free space to store partition table at the end of the SSBL partition, adding padding untill the next sector 0x%X" % partitionTableOffset)
        flashImage.image.padToOffset(partitionTableOffset)
    else:
        partitionTableOffset = endOfSSBLOffset
    
    traces.info("Partition table offset: 0x%X" % partitionTableOffset)
  
    if flash_config and flash_config.get('content/partitions') is not None:
        traces.info('Partition table was provided from configuration file.')
        config_partitions = {}
        table = gen_partition.PartitionTable(md5Sum = True)
        offset = partitionTableOffset + partition.MAX_PARTITION_TABLE_SIZE

        for name, partition_config in flash_config.get('content/partitions').get_items().items():
            if partition_config.get_bool('enabled'):
                path = partition_config.get_str('image')
                type_name = partition_config.get_str('type')
                size = os.path.getsize(path)
                traces.info("Creating partition (name: %s, type: %s, path: %s, offset: 0x%x, size: 0x%x" % (name, type_name, path, offset, size))

                part = partition.PartitionDefinition(
                    name = name,
                    type = partition.DATA_TYPE,
                    subtype = partition.SUBTYPES[partition.DATA_TYPE][type_name],
                    size = size,
                    offset = binary.align(offset, args.blockSize),
                    path = path)
                table.append(part)
                offset = part.offset + part.size

    else:

        if args.partitionTable:
            traces.infoWithoutNewLine('Open partition table: ')
            tableInput = args.partitionTable.read()
            if gen_partition.isBinaryPartitionTable(tableInput):
                # Binary format
                traces.info('Binary table format')
                table = gen_partition.PartitionTable.from_binary(tableInput)
            
            else:
                # CSV Format
                traces.info('CSV table format')
                
                try:
                    tableInput = tableInput.decode()
                except UnicodeDecodeError:
                    raise InputError(
                        '"%s" input file must be a CSV text file or partition table binary.' % args.partitionTable.name)
                
                traces.info('Parsing CSV input...')
                table = gen_partition.PartitionTable.from_csv(tableInput, partitionTableOffset = partitionTableOffset,
                                                            sectorSize = args.blockSize, md5Sum = True)
        
        else:
            # Auto partitioning
            traces.info('Partition table was not provided, generating generic table.')
            table = gen_partition.PartitionTable(md5Sum = True)
            offset = partitionTableOffset + partition.MAX_PARTITION_TABLE_SIZE
            
            if "readfs" in args.partition.keys():
                traces.info("Creating ReadFS partition")
                readFSSize = os.path.getsize(args.partition['readfs'].name)
                traces.info("ReadFS image size: 0x%X" % readFSSize)
                readFSPartition = partition.PartitionDefinition(
                    name = 'readfs',
                    type = partition.DATA_TYPE,
                    subtype = partition.READFS_SUBTYPE,
                    size = readFSSize,
                    offset = binary.align(offset, args.blockSize))
                table.append(readFSPartition)
                offset = readFSPartition.offset + readFSPartition.size
            
            #
            # LittleFS partition
            #
            lfsOffset = binary.align(offset, args.blockSize)
            if "lfs" in args.partition.keys():
                # LittleFS image from CLI
                traces.info("Creating LittleFS partition")
                lfsSize = os.path.getsize(args.partition['lfs'].name)
                traces.info("LittleFS image size: 0x%X" % lfsSize)
            else:
                # No LittleFS image, use of remaining free space
                lfsSize = args.flashSize - lfsOffset
                traces.info("Creating an empty LittleFS partition, using the rest of the flash space: 0x%X" % lfsSize)
            
            lfsPartition = partition.PartitionDefinition(
                name = 'lfs',
                type = partition.DATA_TYPE,
                subtype = partition.LFS_SUBTYPE,
                size = lfsSize,
                offset = binary.align(offset, args.blockSize))
            table.append(lfsPartition)
            offset = lfsPartition.offset + lfsPartition.size
        
    traces.info('Verifying table...')
    traces.info(table.to_csv(simple_formatting = False))
    table.verify(partitionTableOffset = partitionTableOffset, flashSectorSize = args.blockSize,
                 flashSize = args.flashSize)
    
    flashImage.appendPartitionTable(table)
    
    #
    # Writting partition images
    #
    traces.info("Dumping partition image::")

    if flash_config and flash_config.get('content/partitions') is not None:
        for p in table:
            if p.path:
                flashImage.image.padToOffset(p.offset)
                with open(p.path, 'rb') as p_file:
                    flashImage.image += p_file.read()

    else:
        for p in sorted(table, key = lambda x: x.offset):
            if p.name in args.partition.keys():
                traces.info("%s partition [%s]" % (p.name, args.partition[p.name].name))
                flashImage.image.padToOffset(p.offset)
                flashImage.image += args.partition[p.name].read()
            
            else:
                traces.info("%s partition [None]" % p.name)
    
    # add padding to finish on 4 bytes align
    flashImage.image.padToOffset(binary.align(flashImage.getCurrentSize(), 4))
    
    #
    # Write output
    #
    
    traces.info("\nWritting output image to %s, size %uKB." % (args.output, flashImage.getCurrentSize() / 1024))
    flashImage.writeRAWImage(args.output)

    if args.flashStimuliFormat is not None:
        file_name = args.flashStimuliFile
        traces.info("\nWritting output stimuli to %s" %( file_name))
        flashImage.writeStimuli(file_name)