def generate(self, arch, app_file, app_ver, bl_ver, bl_sett_ver, custom_bl_sett_addr): """ Populates the settings object based on the given parameters. :param arch: Architecture family string, e.g. NRF51 :param app_file: Path to application file :param app_ver: Application version number :param bl_ver: Bootloader version number :param bl_sett_ver: Bootloader settings version number :param custom_bl_sett_addr: Custom start address for the settings page :return: """ # Set the architecture self.set_arch(arch) if custom_bl_sett_addr is not None: self.bl_sett_addr = custom_bl_sett_addr if bl_sett_ver == 1: self.setts = BLDFUSettingsStructV1() else: raise NordicSemiException("Unknown bootloader settings version") self.bl_sett_ver = bl_sett_ver & 0xffffffff self.bl_ver = bl_ver & 0xffffffff if app_ver is not None: self.app_ver = app_ver & 0xffffffff else: self.app_ver = 0x0 & 0xffffffff if app_file is not None: # load application to find out size and CRC self.temp_dir = tempfile.mkdtemp(prefix="nrf_dfu_bl_sett_") self.app_bin = Package.normalize_firmware_to_bin(self.temp_dir, app_file) # calculate application size and CRC32 self.app_sz = int(Package.calculate_file_size(self.app_bin)) & 0xffffffff self.app_crc = int(Package.calculate_crc(32, self.app_bin)) & 0xffffffff self.bank0_bank_code = 0x1 & 0xffffffff else: self.app_sz = 0x0 & 0xffffffff self.app_crc = 0x0 & 0xffffffff self.bank0_bank_code = 0x0 & 0xffffffff # build the uint32_t array arr = [0x0] * self.setts.uint32_count # additional harcoded values self.bank_layout = 0x0 & 0xffffffff self.bank_current = 0x0 & 0xffffffff # fill in the settings arr[self.setts.offs_sett_ver] = self.bl_sett_ver arr[self.setts.offs_app_ver] = self.app_ver arr[self.setts.offs_bl_ver] = self.bl_ver arr[self.setts.offs_bank_layout] = self.bank_layout arr[self.setts.offs_bank_current] = self.bank_current arr[self.setts.offs_bank0_img_sz] = self.app_sz arr[self.setts.offs_bank0_img_crc] = self.app_crc arr[self.setts.offs_bank0_bank_code] = self.bank0_bank_code # calculate the CRC32 from the filled-in settings crc_format_str = '<' + ('I' * (self.setts.uint32_count - 1)) crc_arr = arr[1:] crc_data = struct.pack(crc_format_str, *crc_arr) self.crc = binascii.crc32(crc_data) & 0xffffffff # fill in the calculated CRC32 arr[self.setts.offs_crc] = self.crc format_str = '<' + ('I' * self.setts.uint32_count) # Get the packed data to insert into the hex instance data = struct.pack(format_str, *arr) # insert the data at the correct address self.ihex.puts(self.bl_sett_addr, data)
def generate(self, arch, app_file, app_ver, bl_ver, bl_sett_ver): # Set the architecture self.set_arch(arch) if bl_sett_ver == 1: self.setts = BLDFUSettingsStructV1() else: raise NordicSemiException("Unknown bootloader settings version") self.bl_sett_ver = bl_sett_ver & 0xffffffff self.bl_ver = bl_ver & 0xffffffff if app_ver is not None: self.app_ver = app_ver & 0xffffffff else: self.app_ver = 0x0 & 0xffffffff if app_file is not None: # load application to find out size and CRC self.temp_dir = tempfile.mkdtemp(prefix="nrf_dfu_bl_sett_") self.app_bin = Package.normalize_firmware_to_bin(self.temp_dir, app_file) # calculate application size and CRC32 self.app_sz = int(Package.calculate_file_size(self.app_bin)) & 0xffffffff self.app_crc = int(Package.calculate_crc(32, self.app_bin)) & 0xffffffff else: self.app_sz = 0x0 & 0xffffffff self.app_crc = 0x0 & 0xffffffff # build the uint32_t array arr = [0x0] * self.setts.uint32_count # additional harcoded values self.bank_layout = 0x0 & 0xffffffff self.bank_current = 0x0 & 0xffffffff self.bank0_bank_code = 0x1 & 0xffffffff # fill in the settings arr[self.setts.offs_sett_ver] = self.bl_sett_ver arr[self.setts.offs_app_ver] = self.app_ver arr[self.setts.offs_bl_ver] = self.bl_ver arr[self.setts.offs_bank_layout] = self.bank_layout arr[self.setts.offs_bank_current] = self.bank_current arr[self.setts.offs_bank0_img_sz] = self.app_sz arr[self.setts.offs_bank0_img_crc] = self.app_crc arr[self.setts.offs_bank0_bank_code] = self.bank0_bank_code # calculate the CRC32 from the filled-in settings crc_format_str = '<' + ('I' * (self.setts.uint32_count - 1)) crc_arr = arr[1:] crc_data = struct.pack(crc_format_str, *crc_arr) self.crc = binascii.crc32(crc_data) & 0xffffffff # fill in the calculated CRC32 arr[self.setts.offs_crc] = self.crc format_str = '<' + ('I' * self.setts.uint32_count) # Get the packed data to insert into the hex instance data = struct.pack(format_str, *arr) # insert the data at the correct address self.ihex.puts(self.bl_sett_addr, data)
def generate(self, arch, app_file, app_ver, bl_ver, bl_sett_ver, custom_bl_sett_addr, no_backup, backup_address, app_boot_validation_type, sd_boot_validation_type, sd_file, key_file): self.set_arch(arch) if custom_bl_sett_addr is not None: self.bl_sett_addr = custom_bl_sett_addr if bl_sett_ver == 1: self.setts = BLDFUSettingsStructV1(self.bl_sett_addr) elif bl_sett_ver == 2: self.setts = BLDFUSettingsStructV2(self.bl_sett_addr) else: raise NordicSemiException("Unknown bootloader settings version") self.bl_sett_ver = bl_sett_ver & 0xffffffff self.bl_ver = bl_ver & 0xffffffff if app_ver is not None: self.app_ver = app_ver & 0xffffffff else: self.app_ver = 0x0 & 0xffffffff if app_file is not None: # load application to find out size and CRC self.temp_dir = tempfile.mkdtemp(prefix="nrf_dfu_bl_sett_") self.app_bin = Package.normalize_firmware_to_bin( self.temp_dir, app_file) # calculate application size and CRC32 self.app_sz = int(Package.calculate_file_size( self.app_bin)) & 0xffffffff self.app_crc = int(Package.calculate_crc( 32, self.app_bin)) & 0xffffffff self.bank0_bank_code = 0x1 & 0xffffffff # Calculate Boot validation fields for app if app_boot_validation_type == 'VALIDATE_GENERATED_CRC': self.app_boot_validation_type = 1 & 0xffffffff self.app_boot_validation_bytes = struct.pack( '<I', self.app_crc) elif app_boot_validation_type == 'VALIDATE_GENERATED_SHA256': self.app_boot_validation_type = 2 & 0xffffffff sha256 = Package.calculate_sha256_hash(self.app_bin) self.app_boot_validation_bytes = bytearray([ int(binascii.hexlify(i), 16) for i in list(sha256) ][31::-1]) elif app_boot_validation_type == 'VALIDATE_ECDSA_P256_SHA256': self.app_boot_validation_type = 3 & 0xffffffff ecdsa = Package.sign_firmware(key_file, self.app_bin) self.app_boot_validation_bytes = bytearray( [int(binascii.hexlify(i), 16) for i in list(ecdsa)]) else: # This also covers 'NO_VALIDATION' case self.app_boot_validation_type = 0 & 0xffffffff self.app_boot_validation_bytes = bytearray(0) else: self.app_sz = 0x0 & 0xffffffff self.app_crc = 0x0 & 0xffffffff self.bank0_bank_code = 0x0 & 0xffffffff self.app_boot_validation_type = 0x0 & 0xffffffff self.app_boot_validation_bytes = bytearray(0) if sd_file is not None: # Load SD to calculate CRC self.temp_dir = tempfile.mkdtemp(prefix="nrf_dfu_bl_sett") temp_sd_file = os.path.join(os.getcwd(), 'temp_sd_file.hex') # Load SD hex file and remove MBR before calculating keys ih_sd = intelhex.IntelHex(sd_file) ih_sd_no_mbr = intelhex.IntelHex() ih_sd_no_mbr.merge(ih_sd[0x1000:], overlap='error') ih_sd_no_mbr.write_hex_file(temp_sd_file) self.sd_bin = Package.normalize_firmware_to_bin( self.temp_dir, temp_sd_file) os.remove(temp_sd_file) self.sd_sz = int(Package.calculate_file_size( self.sd_bin)) & 0xffffffff # Calculate Boot validation fields for SD if sd_boot_validation_type == 'VALIDATE_GENERATED_CRC': self.sd_boot_validation_type = 1 & 0xffffffff sd_crc = int(Package.calculate_crc(32, self.sd_bin)) & 0xffffffff self.sd_boot_validation_bytes = struct.pack('<I', sd_crc) elif sd_boot_validation_type == 'VALIDATE_GENERATED_SHA256': self.sd_boot_validation_type = 2 & 0xffffffff sha256 = Package.calculate_sha256_hash(self.sd_bin) self.sd_boot_validation_bytes = bytearray([ int(binascii.hexlify(i), 16) for i in list(sha256) ][31::-1]) elif sd_boot_validation_type == 'VALIDATE_ECDSA_P256_SHA256': self.sd_boot_validation_type = 3 & 0xffffffff ecdsa = Package.sign_firmware(key_file, self.sd_bin) self.sd_boot_validation_bytes = bytearray( [int(binascii.hexlify(i), 16) for i in list(ecdsa)]) else: # This also covers 'NO_VALIDATION_CASE' self.sd_boot_validation_type = 0 & 0xffffffff self.sd_boot_validation_bytes = bytearray(0) else: self.sd_sz = 0x0 & 0xffffffff self.sd_boot_validation_type = 0 & 0xffffffff self.sd_boot_validation_bytes = bytearray(0) # additional harcoded values self.bank_layout = 0x0 & 0xffffffff self.bank_current = 0x0 & 0xffffffff # Fill the entire settings page with 0's for offset in range(0, self.setts.bytes_count): self.ihex[self.bl_sett_addr + offset] = 0x00 self._add_value_tohex(self.setts.sett_ver, self.bl_sett_ver) self._add_value_tohex(self.setts.app_ver, self.app_ver) self._add_value_tohex(self.setts.bl_ver, self.bl_ver) self._add_value_tohex(self.setts.bank_layout, self.bank_layout) self._add_value_tohex(self.setts.bank_current, self.bank_current) self._add_value_tohex(self.setts.bank0_img_sz, self.app_sz) self._add_value_tohex(self.setts.bank0_img_crc, self.app_crc) self._add_value_tohex(self.setts.bank0_bank_code, self.bank0_bank_code) self._add_value_tohex(self.setts.sd_sz, self.sd_sz) self.boot_validation_crc = 0x0 & 0xffffffff if self.bl_sett_ver == 2: self._add_value_tohex(self.setts.sd_validation_type, self.sd_boot_validation_type, '<b') self.ihex.puts(self.setts.sd_validation_bytes, self.sd_boot_validation_bytes) self._add_value_tohex(self.setts.app_validation_type, self.app_boot_validation_type, '<b') self.ihex.puts(self.setts.app_validation_bytes, self.app_boot_validation_bytes) self.boot_validation_crc = self._calculate_crc32_from_hex( self.ihex, start_addr=self.setts.sd_validation_type, end_addr=self.setts.last_addr) & 0xffffffff self._add_value_tohex(self.setts.boot_validataion_crc, self.boot_validation_crc) self.crc = self._calculate_crc32_from_hex( self.ihex, start_addr=self.bl_sett_addr + 4, end_addr=self.setts.init_cmd - 1) & 0xffffffff self._add_value_tohex(self.setts.crc, self.crc) if backup_address is None: self.backup_address = self.bl_sett_addr - self.bl_sett_backup_offset else: self.backup_address = backup_address if not no_backup: for offset in range(0, self.setts.bytes_count): self.ihex[self.backup_address + offset] = self.ihex[self.bl_sett_addr + offset]
def generate(self, arch, app_file, app_ver, bl_ver, bl_sett_ver, custom_bl_sett_addr, no_backup, backup_address, app_boot_validation_type, sd_boot_validation_type, sd_file, key_file): self.set_arch(arch) if custom_bl_sett_addr is not None: self.bl_sett_addr = custom_bl_sett_addr if bl_sett_ver == 1: self.setts = BLDFUSettingsStructV1(self.bl_sett_addr) elif bl_sett_ver == 2: self.setts = BLDFUSettingsStructV2(self.bl_sett_addr) else: raise NordicSemiException("Unknown bootloader settings version") self.bl_sett_ver = bl_sett_ver & 0xffffffff self.bl_ver = bl_ver & 0xffffffff if app_ver is not None: self.app_ver = app_ver & 0xffffffff else: self.app_ver = 0x0 & 0xffffffff if app_file is not None: # load application to find out size and CRC self.temp_dir = tempfile.mkdtemp(prefix="nrf_dfu_bl_sett_") self.app_bin = Package.normalize_firmware_to_bin(self.temp_dir, app_file) # calculate application size and CRC32 self.app_sz = int(Package.calculate_file_size(self.app_bin)) & 0xffffffff self.app_crc = int(Package.calculate_crc(32, self.app_bin)) & 0xffffffff self.bank0_bank_code = 0x1 & 0xffffffff # Calculate Boot validation fields for app if app_boot_validation_type == 'VALIDATE_GENERATED_CRC': self.app_boot_validation_type = 1 & 0xffffffff self.app_boot_validation_bytes = struct.pack('<I', self.app_crc) elif app_boot_validation_type == 'VALIDATE_GENERATED_SHA256': self.app_boot_validation_type = 2 & 0xffffffff sha256 = Package.calculate_sha256_hash(self.app_bin) self.app_boot_validation_bytes = bytearray([int(binascii.hexlify(i), 16) for i in list(sha256)][31::-1]) elif app_boot_validation_type == 'VALIDATE_ECDSA_P256_SHA256': self.app_boot_validation_type = 3 & 0xffffffff ecdsa = Package.sign_firmware(key_file, self.app_bin) self.app_boot_validation_bytes = bytearray([int(binascii.hexlify(i), 16) for i in list(ecdsa)]) else: # This also covers 'NO_VALIDATION' case self.app_boot_validation_type = 0 & 0xffffffff self.app_boot_validation_bytes = bytearray(0) else: self.app_sz = 0x0 & 0xffffffff self.app_crc = 0x0 & 0xffffffff self.bank0_bank_code = 0x0 & 0xffffffff self.app_boot_validation_type = 0x0 & 0xffffffff self.app_boot_validation_bytes = bytearray(0) if sd_file is not None: # Load SD to calculate CRC self.temp_dir = tempfile.mkdtemp(prefix="nrf_dfu_bl_sett") temp_sd_file = os.path.join(os.getcwd(), 'temp_sd_file.hex') # Load SD hex file and remove MBR before calculating keys ih_sd = intelhex.IntelHex(sd_file) ih_sd_no_mbr = intelhex.IntelHex() ih_sd_no_mbr.merge(ih_sd[0x1000:], overlap='error') ih_sd_no_mbr.write_hex_file(temp_sd_file) self.sd_bin = Package.normalize_firmware_to_bin(self.temp_dir, temp_sd_file) os.remove(temp_sd_file) self.sd_sz = int(Package.calculate_file_size(self.sd_bin)) & 0xffffffff # Calculate Boot validation fields for SD if sd_boot_validation_type == 'VALIDATE_GENERATED_CRC': self.sd_boot_validation_type = 1 & 0xffffffff sd_crc = int(Package.calculate_crc(32, self.sd_bin)) & 0xffffffff self.sd_boot_validation_bytes = struct.pack('<I', sd_crc) elif sd_boot_validation_type == 'VALIDATE_GENERATED_SHA256': self.sd_boot_validation_type = 2 & 0xffffffff sha256 = Package.calculate_sha256_hash(self.sd_bin) self.sd_boot_validation_bytes = bytearray([int(binascii.hexlify(i), 16) for i in list(sha256)][31::-1]) elif sd_boot_validation_type == 'VALIDATE_ECDSA_P256_SHA256': self.sd_boot_validation_type = 3 & 0xffffffff ecdsa = Package.sign_firmware(key_file, self.sd_bin) self.sd_boot_validation_bytes = bytearray([int(binascii.hexlify(i), 16) for i in list(ecdsa)]) else: # This also covers 'NO_VALIDATION_CASE' self.sd_boot_validation_type = 0 & 0xffffffff self.sd_boot_validation_bytes = bytearray(0) else: self.sd_sz = 0x0 & 0xffffffff self.sd_boot_validation_type = 0 & 0xffffffff self.sd_boot_validation_bytes = bytearray(0) # additional harcoded values self.bank_layout = 0x0 & 0xffffffff self.bank_current = 0x0 & 0xffffffff # Fill the entire settings page with 0's for offset in range(0, self.setts.bytes_count): self.ihex[self.bl_sett_addr + offset] = 0x00 self._add_value_tohex(self.setts.sett_ver, self.bl_sett_ver) self._add_value_tohex(self.setts.app_ver, self.app_ver) self._add_value_tohex(self.setts.bl_ver, self.bl_ver) self._add_value_tohex(self.setts.bank_layout, self.bank_layout) self._add_value_tohex(self.setts.bank_current, self.bank_current) self._add_value_tohex(self.setts.bank0_img_sz, self.app_sz) self._add_value_tohex(self.setts.bank0_img_crc, self.app_crc) self._add_value_tohex(self.setts.bank0_bank_code, self.bank0_bank_code) self._add_value_tohex(self.setts.sd_sz, self.sd_sz) self.boot_validation_crc = 0x0 & 0xffffffff if self.bl_sett_ver == 2: self._add_value_tohex(self.setts.sd_validation_type, self.sd_boot_validation_type, '<b') self.ihex.puts(self.setts.sd_validation_bytes, self.sd_boot_validation_bytes) self._add_value_tohex(self.setts.app_validation_type, self.app_boot_validation_type, '<b') self.ihex.puts(self.setts.app_validation_bytes, self.app_boot_validation_bytes) self.boot_validation_crc = self._calculate_crc32_from_hex(self.ihex, start_addr=self.setts.sd_validation_type, end_addr=self.setts.last_addr) & 0xffffffff self._add_value_tohex(self.setts.boot_validataion_crc, self.boot_validation_crc) self.crc = self._calculate_crc32_from_hex(self.ihex, start_addr=self.bl_sett_addr+4, end_addr=self.setts.init_cmd - 1) & 0xffffffff self._add_value_tohex(self.setts.crc, self.crc) if backup_address is None: self.backup_address = self.bl_sett_addr - self.bl_sett_backup_offset else: self.backup_address = backup_address if not no_backup: for offset in range(0, self.setts.bytes_count): self.ihex[self.backup_address + offset] = self.ihex[self.bl_sett_addr + offset]