Skip to content

Commit eff3b9a

Browse files
committed
Verify target has all addresses found in the hex file instead of
verifying the size. As noted in PR betaflight#2512 simply verifying the size of the hex file is not extensible and is not how hex files are designed to be used. A hex file can contains many non-contiguous blocks of data. This also supports targets with any partition layout. Additionally, this provides a more flexible way of providing hex files which can now contain data for non-contiguous blocks, e.g. firmware + config or firmware + osd fonts.
1 parent b1481ad commit eff3b9a

File tree

2 files changed

+70
-33
lines changed

2 files changed

+70
-33
lines changed

locales/en/messages.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,7 +666,10 @@
666666
"dfu_device_flash_info": {
667667
"message": "Detected device with total flash size $1 KiB"
668668
},
669-
"dfu_error_image_size": {
669+
"dfu_hex_address_errors": {
670+
"message": "<span class=\"message-negative\">Error</span>: Firmware image contains addresses not found on target device"
671+
},
672+
"dfu_error_image_size": {
670673
"message": "<span class=\"message-negative\">Error</span>: Supplied image is larger then flash available on the chip! Image: $1 KiB, limit = $2 KiB"
671674
},
672675

src/js/protocols/stm32usbdfu.js

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,47 @@ STM32DFU_protocol.prototype.verify_flash = function (first_array, second_array)
549549
return true;
550550
};
551551

552+
STM32DFU_protocol.prototype.isBlockUsable = function(startAddress, length) {
553+
var self = this;
554+
555+
let result = false;
556+
557+
let searchAddress = startAddress;
558+
let remainingLength = length;
559+
560+
let restart;
561+
do {
562+
restart = false;
563+
564+
for (const sector of self.flash_layout.sectors) {
565+
const sectorStart = sector.start_address;
566+
const sectorLength = sector.num_pages * sector.page_size;
567+
const sectorEnd = sectorStart + sectorLength - 1; // - 1 for inclusive
568+
569+
const addressInSector = (searchAddress >= sectorStart) && (searchAddress <= sectorEnd);
570+
571+
if (addressInSector) {
572+
const endAddress = searchAddress + remainingLength - 1; // - 1 for inclusive
573+
574+
const endAddressInSector = (endAddress <= sectorEnd);
575+
if (endAddressInSector) {
576+
result = true;
577+
restart = false;
578+
break;
579+
}
580+
581+
// some of the block is in this sector, search for the another sector that contains the next part of the block
582+
searchAddress = sectorEnd + 1;
583+
remainingLength -= sectorLength;
584+
restart = true;
585+
break;
586+
}
587+
}
588+
} while (restart);
589+
590+
return result;
591+
};
592+
552593
STM32DFU_protocol.prototype.upload_procedure = function (step) {
553594
var self = this;
554595

@@ -559,59 +600,52 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
559600
console.log('Failed to detect chip info, resultCode: ' + resultCode);
560601
self.cleanup();
561602
} else {
603+
let nextAction;
604+
562605
if (typeof chipInfo.internal_flash !== "undefined") {
563606
// internal flash
564-
self.chipInfo = chipInfo;
607+
nextAction = 1;
565608

609+
self.chipInfo = chipInfo;
566610
self.flash_layout = chipInfo.internal_flash;
567-
self.available_flash_size = self.flash_layout.total_size - (self.hex.start_linear_address - self.flash_layout.start_address);
568611

569-
GUI.log(i18n.getMessage('dfu_device_flash_info', (self.flash_layout.total_size / 1024).toString()));
570-
571-
if (self.hex.bytes_total > self.available_flash_size) {
572-
GUI.log(i18n.getMessage('dfu_error_image_size',
573-
[(self.hex.bytes_total / 1024.0).toFixed(1),
574-
(self.available_flash_size / 1024.0).toFixed(1)]));
575-
self.cleanup();
576-
} else {
577-
self.getFunctionalDescriptor(0, function (descriptor, resultCode) {
578-
self.transferSize = resultCode ? 2048 : descriptor.wTransferSize;
579-
console.log('Using transfer size: ' + self.transferSize);
580-
self.clearStatus(function () {
581-
self.upload_procedure(1);
582-
});
583-
});
584-
}
585612
} else if (typeof chipInfo.external_flash !== "undefined") {
586-
// external flash, flash to the 3rd partition.
613+
// external flash
614+
nextAction = 2; // no option bytes
615+
587616
self.chipInfo = chipInfo;
588617
self.flash_layout = chipInfo.external_flash;
618+
} else {
619+
console.log('Failed to detect internal or external flash');
620+
self.cleanup();
621+
}
589622

590-
var firmware_partition_index = 2;
591-
var firmware_sectors = self.flash_layout.sectors[firmware_partition_index];
592-
var firmware_partition_size = firmware_sectors.total_size;
623+
if (typeof nextAction !== "undefined") {
624+
GUI.log(i18n.getMessage('dfu_device_flash_info', (self.flash_layout.total_size / 1024).toString()));
593625

594-
self.available_flash_size = firmware_partition_size;
626+
// verify all addresses in the hex are writable.
595627

596-
GUI.log(i18n.getMessage('dfu_device_flash_info', (self.flash_layout.total_size / 1024).toString()));
628+
const unusableBlocks = [];
629+
630+
for (const block of self.hex.data) {
631+
const usable = self.isBlockUsable(block.address, block.bytes);
632+
if (!usable) {
633+
unusableBlocks.push(block);
634+
}
635+
}
597636

598-
if (self.hex.bytes_total > self.available_flash_size) {
599-
GUI.log(i18n.getMessage('dfu_error_image_size',
600-
[(self.hex.bytes_total / 1024.0).toFixed(1),
601-
(self.available_flash_size / 1024.0).toFixed(1)]));
637+
if (unusableBlocks.length > 0) {
638+
GUI.log(i18n.getMessage('dfu_hex_address_errors'));
602639
self.cleanup();
603640
} else {
604641
self.getFunctionalDescriptor(0, function (descriptor, resultCode) {
605642
self.transferSize = resultCode ? 2048 : descriptor.wTransferSize;
606643
console.log('Using transfer size: ' + self.transferSize);
607644
self.clearStatus(function () {
608-
self.upload_procedure(2); // no option bytes to deal with
645+
self.upload_procedure(nextAction);
609646
});
610647
});
611648
}
612-
} else {
613-
console.log('Failed to detect internal or external flash');
614-
self.cleanup();
615649
}
616650
}
617651
});

0 commit comments

Comments
 (0)