Skip to content

Commit 1211ac8

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 5fb3007 commit 1211ac8

File tree

2 files changed

+71
-33
lines changed

2 files changed

+71
-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: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,46 @@ 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+
var result = false
556+
557+
var searchAddress = startAddress;
558+
var remainingLength = length;
559+
560+
var restart;
561+
do {
562+
restart = false;
563+
564+
for (var s = 0; s < self.flash_layout.sectors.length; s++) {
565+
const sectorStart = self.flash_layout.sectors[s].start_address;
566+
const sectorLength = self.flash_layout.sectors[s].num_pages * self.flash_layout.sectors[s].page_size;
567+
const sectorEnd = sectorStart + sectorLength - 1; // - 1 for inclusive
568+
569+
const addressInSector = (searchAddress >= sectorStart) && (searchAddress <= sectorEnd);
570+
571+
if (addressInSector) {
572+
573+
const sectorContainsEndAddress = (searchAddress + remainingLength <= sectorEnd);
574+
if (sectorContainsEndAddress) {
575+
result = true;
576+
restart = false;
577+
break;
578+
}
579+
580+
// some of the block is in this sector, search for the another sector that contains the next part of the block
581+
searchAddress = sectorEnd + 1;
582+
remainingLength -= sectorLength;
583+
restart = true;
584+
break;
585+
}
586+
}
587+
} while (restart);
588+
589+
return result;
590+
};
591+
552592
STM32DFU_protocol.prototype.upload_procedure = function (step) {
553593
var self = this;
554594

@@ -559,59 +599,54 @@ STM32DFU_protocol.prototype.upload_procedure = function (step) {
559599
console.log('Failed to detect chip info, resultCode: ' + resultCode);
560600
self.cleanup();
561601
} else {
602+
var nextAction;
603+
562604
if (typeof chipInfo.internal_flash !== "undefined") {
563605
// internal flash
564-
self.chipInfo = chipInfo;
606+
nextAction = 1;
565607

608+
self.chipInfo = chipInfo;
566609
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);
568610

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-
}
585611
} else if (typeof chipInfo.external_flash !== "undefined") {
586-
// external flash, flash to the 3rd partition.
612+
// external flash
613+
nextAction = 2; // no option bytes
614+
587615
self.chipInfo = chipInfo;
588616
self.flash_layout = chipInfo.external_flash;
617+
} else {
618+
console.log('Failed to detect internal or external flash');
619+
self.cleanup();
620+
}
621+
622+
if (typeof nextAction !== "undefined") {
623+
GUI.log(i18n.getMessage('dfu_device_flash_info', (self.flash_layout.total_size / 1024).toString()));
589624

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;
625+
// verify all addresses in the hex are writable.
593626

594-
self.available_flash_size = firmware_partition_size;
627+
var unusableBlocks = [];
595628

596-
GUI.log(i18n.getMessage('dfu_device_flash_info', (self.flash_layout.total_size / 1024).toString()));
629+
for (let h = 0; h < self.hex.data.length; h++) {
630+
const block = self.hex.data[h];
597631

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)]));
632+
let usable = self.isBlockUsable(block.address, block.bytes);
633+
if (!usable) {
634+
unusableBlocks.push(block);
635+
}
636+
}
637+
638+
if (unusableBlocks.length > 0) {
639+
GUI.log(i18n.getMessage('dfu_hex_address_errors'));
602640
self.cleanup();
603641
} else {
604642
self.getFunctionalDescriptor(0, function (descriptor, resultCode) {
605643
self.transferSize = resultCode ? 2048 : descriptor.wTransferSize;
606644
console.log('Using transfer size: ' + self.transferSize);
607645
self.clearStatus(function () {
608-
self.upload_procedure(2); // no option bytes to deal with
646+
self.upload_procedure(nextAction);
609647
});
610648
});
611649
}
612-
} else {
613-
console.log('Failed to detect internal or external flash');
614-
self.cleanup();
615650
}
616651
}
617652
});

0 commit comments

Comments
 (0)