generate method
String
generate({
- String arch = 'NRF52',
- String? appFile,
- int? appVersion,
- int blVersion = 0,
- int blSettVersion = 0,
- int? customBootSettAddr,
- bool noBackup = true,
- int? backupAddress,
- ValidationType appValType = ValidationType.noValidation,
- ValidationType sdValType = ValidationType.noValidation,
- String? sdFile,
- Signing? signer,
Generate settings file from the provided data
Implementation
String generate({
String arch = 'NRF52',
String? appFile,
int? appVersion,
int blVersion = 0,
int blSettVersion = 0,
int? customBootSettAddr,
bool noBackup = true,
int? backupAddress,
ValidationType appValType = ValidationType.noValidation,
ValidationType sdValType = ValidationType.noValidation,
String? sdFile,
Signing? signer
}){
logger?.verbose('Generating Settings');
setArch(arch);
late BLDFUSettingsStructV1 setts;
late Uint8List appBootValidationBytes;
if( customBootSettAddr != null){
logger?.verbose('Setting custom boot address');
blSettAddr = customBootSettAddr;
}
if (blSettVersion == 1){
setts = BLDFUSettingsStructV1(blSettAddr,true);
}
else if(blSettVersion == 2){
setts = BLDFUSettingsStructV2(blSettAddr);
}
else{
throw("Unknown bootloader settings version");
}
logger?.verbose('Convertying bootloader version');
blSettVersion = blSettVersion & 0xffffffff;
blVersion = blVersion & 0xffffffff;
logger?.verbose('Convertying application version');
if (appVersion != null){
appVersion = appVersion & 0xffffffff;
}
else{
appVersion = 0x0 & 0xffffffff;
}
late int appValTypeInt;
if (appFile != null){
logger?.verbose('Generating application file perameters');
//load application to find out size and CRC
Uint8List appBin = NRFPackage.normalizeFirmware(appFile);
//calculate application size and CRC32
appSize = NRFPackage.calculateFileSize(appBin) & 0xffffffff;
appCrc = NRFPackage.calculateCRC(CRCType.crc32, appBin) & 0xffffffff;
bankCode = 0x1 & 0xffffffff;
//Calculate Boot validation fields for app
if (appValType == ValidationType.validateCrc){
appValTypeInt = 1 & 0xffffffff;
appBootValidationBytes = Struct.pack('<I', appCrc);
}
else if (appValType == ValidationType.validateSHA256){
appValTypeInt = 2 & 0xffffffff;
// Package.calculate_sha256_hash gives a reversed
// digest. It need to be reversed back to a normal
// sha256 digest.
appBootValidationBytes = Uint8List.fromList(NRFPackage.calculateSHA256(appBin,FwType.application).reversed.toList());
}
else if (appValType == ValidationType.validateP256 && signer != null){
appValTypeInt = 3 & 0xffffffff;
appBootValidationBytes = NRFPackage.signFirmware(signer, appBin);
}
else{ //This also covers 'NO_VALIDATION' case
appValTypeInt = 0 & 0xffffffff;
appBootValidationBytes = Uint8List(0);
}
}
else{
logger?.verbose('No application file found');
appSize = 0x0 & 0xffffffff;
appCrc = 0x0 & 0xffffffff;
bankCode = 0x0 & 0xffffffff;
appValTypeInt = 0x0 & 0xffffffff;
appBootValidationBytes = Uint8List(0);
}
late Uint8List sdBootValidationBytes;
late int sdValTypeInt;
if (sdFile != null){
logger?.verbose('Generating softdevice file perameters');
// Load SD to calculate CRC
// Load SD hex file and remove MBR before calculating keys
IntelHex ihSD = IntelHex.decodeRecord(sdFile);
IntelHex ihSdNoMbr = IntelHex();
ihSdNoMbr.merge(ihSD..setSubList(0x1000), Overlap.error);
//ihSdNoMbr.write_hexFile(temp_sdFile);
Uint8List sdBin = ihSdNoMbr.toBinArray();
sdSize = NRFPackage.calculateFileSize(sdBin) & 0xffffffff;
// Calculate Boot validation fields for SD
if (sdValType == ValidationType.validateCrc){
sdValTypeInt = 1 & 0xffffffff;
int sdCrc = NRFPackage.calculateCRC(CRCType.crc32, sdBin) & 0xffffffff;
sdBootValidationBytes = Struct.pack('<I', sdCrc);
}
else if (sdValType == ValidationType.validateSHA256){
sdValTypeInt = 2 & 0xffffffff;
// Package.calculate_sha256_hash gives a reversed
// digest. It need to be reversed back to a normal
// sha256 digest.
sdBootValidationBytes = Uint8List.fromList(NRFPackage.calculateSHA256(sdBin,FwType.softdevice).reversed.toList());
}
else if (sdValType == ValidationType.validateP256 && signer != null){
sdValTypeInt = 3 & 0xffffffff;
sdBootValidationBytes = NRFPackage.signFirmware(signer, sdBin);
}
else{ // This also covers 'NO_VALIDATION_CASE'
sdValTypeInt = 0 & 0xffffffff;
sdBootValidationBytes = Uint8List(0);
}
}
else{
logger?.verbose('No softdevice file found');
sdSize = 0x0 & 0xffffffff;
sdValTypeInt = 0 & 0xffffffff;
sdBootValidationBytes = Uint8List(0);
}
// additional hardcoded values
bankLayout = 0x0 & 0xffffffff;
bankCurrent = 0x0 & 0xffffffff;
// Fill the entire settings page with 0's
for(int offset = 0; offset < setts.bytesCount;offset++){ //offset in range(0, setts.bytesCount){
ihex[blSettAddr + offset] = 0x00;
}
// Make sure the hex-file is 32bit-word-aligned
int fillBytes = ((setts.bytesCount + 4 - 1) & ~(4 - 1)) - setts.bytesCount;
for(int offset = setts.bytesCount; offset < setts.bytesCount + fillBytes; offset++){
ihex[blSettAddr + offset] = 0xFF;
}
_addValueToHex(setts.settingsVersion, blSettVersion);
_addValueToHex(setts.appVersion, appVersion);
_addValueToHex(setts.blVersion, blVersion);
_addValueToHex(setts.bankLayout, bankLayout);
_addValueToHex(setts.bankCurrent, bankCurrent);
_addValueToHex(setts.bankImgSize, appSize);
_addValueToHex(setts.bankImgCrc, appCrc);
_addValueToHex(setts.bankCode, bankCode);
_addValueToHex(setts.sdSize, sdSize);
bootValidationCrc = 0x0 & 0xffffffff;
if (blSettVersion == 2){
setts as BLDFUSettingsStructV2;
_addValueToHex(setts.sdValidationType, sdValTypeInt, '<b');
ihex.puts(setts.sdValidationBytes, sdBootValidationBytes);
_addValueToHex(setts.appValidationType, appValTypeInt, '<b');
ihex.puts(setts.appValidationBytes, appBootValidationBytes);
bootValidationCrc = calculateCRC32FromHex(ihex,setts.sdValidationType,setts.lastAddress) & 0xffffffff;
_addValueToHex(setts.bootValidationCrc, bootValidationCrc);
}
crc = calculateCRC32FromHex(ihex,blSettAddr+4,setts.initCmd - 1) & 0xffffffff;
_addValueToHex(setts.crc, crc);
if(backupAddress == null){
backupAddress = blSettAddr - blSettBackupOffset;
}
else{
logger?.verbose('Converting custom backup address');
backupAddress = backupAddress;
}
if(!noBackup){
logger?.verbose('Setting backup');
for (int offset = 0; offset < setts.bytesCount;offset++){ //offset in range(0, setts.bytesCount):
ihex[backupAddress + offset] = ihex[blSettAddr + offset];
}
for (int offset = setts.bytesCount; offset < setts.bytesCount + fillBytes; offset++){ //offset in range(setts.bytesCount, setts.bytesCount + fillBytes):
ihex[backupAddress + offset] = 0xFF;
}
}
logger?.verbose('Coverting data to Hex String');
return ihex.bufferToHex();
}