Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/betaflight/betaflight-configurator.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorblckmn <blackman@xtra.com.au>2022-11-05 03:49:13 +0300
committerblckmn <blackman@xtra.com.au>2022-11-05 03:49:13 +0300
commit752cac9b7a4baa3e56f01d9cd8d8b51c90a5f997 (patch)
tree2a6889e590fca4f751f09834900780b7c9c98a9a
parent45cd8bf175327a1471b39d4232da3fc57af70dcb (diff)
Restoring ability to load local configuration for a target
-rw-r--r--locales/en/messages.json3
-rw-r--r--src/js/ConfigInserter.js107
-rw-r--r--src/js/tabs/firmware_flasher.js76
-rw-r--r--src/main.html1
-rw-r--r--src/tabs/firmware_flasher.html3
5 files changed, 182 insertions, 8 deletions
diff --git a/locales/en/messages.json b/locales/en/messages.json
index 9b6d4c7b..2adabf70 100644
--- a/locales/en/messages.json
+++ b/locales/en/messages.json
@@ -6725,5 +6725,8 @@
},
"firmwareFlasherBuildMotorProtocols": {
"message": "Motor Protocols"
+ },
+ "firmwareFlasherConfigurationFile": {
+ "message": "Configuration Filename:"
}
}
diff --git a/src/js/ConfigInserter.js b/src/js/ConfigInserter.js
new file mode 100644
index 00000000..8103df64
--- /dev/null
+++ b/src/js/ConfigInserter.js
@@ -0,0 +1,107 @@
+'use strict';
+
+const ConfigInserter = function () {
+};
+
+const CUSTOM_DEFAULTS_POINTER_ADDRESS = 0x08002800;
+const BLOCK_SIZE = 16384;
+
+function seek(firmware, address) {
+ let index = 0;
+ for (; index < firmware.data.length && address >= firmware.data[index].address + firmware.data[index].bytes; index++) {
+ // empty for loop to increment index
+ }
+
+ const result = {
+ lineIndex: index,
+ };
+
+ if (firmware.data[index] && address >= firmware.data[index].address) {
+ result.byteIndex = address - firmware.data[index].address;
+ }
+
+ return result;
+}
+
+function readUint32(firmware, index) {
+ let result = 0;
+ for (let position = 0; position < 4; position++) {
+ result += firmware.data[index.lineIndex].data[index.byteIndex++] << (8 * position);
+ if (index.byteIndex >= firmware.data[index.lineIndex].bytes) {
+ index.lineIndex++;
+ index.byteIndex = 0;
+ }
+ }
+
+ return result;
+}
+
+function getCustomDefaultsArea(firmware) {
+ const result = {};
+
+ const index = seek(firmware, CUSTOM_DEFAULTS_POINTER_ADDRESS);
+
+ if (index.byteIndex === undefined) {
+ return;
+ }
+
+ result.startAddress = readUint32(firmware, index);
+ result.endAddress = readUint32(firmware, index);
+
+ return result;
+}
+
+function generateData(firmware, input, startAddress) {
+ let address = startAddress;
+
+ const index = seek(firmware, address);
+
+ if (index.byteIndex !== undefined) {
+ throw new Error('Configuration area in firmware not free.');
+ }
+
+ let inputIndex = 0;
+ while (inputIndex < input.length) {
+ const remaining = input.length - inputIndex;
+ const line = {
+ address: address,
+ bytes: BLOCK_SIZE > remaining ? remaining : BLOCK_SIZE,
+ data: [],
+ };
+
+ if (firmware.data[index.lineIndex] && (line.address + line.bytes) > firmware.data[index.lineIndex].address) {
+ throw new Error("Aborting data generation, free area too small.");
+ }
+
+ for (let i = 0; i < line.bytes; i++) {
+ line.data.push(input.charCodeAt(inputIndex++));
+ }
+
+ address = address + line.bytes;
+
+ firmware.data.splice(index.lineIndex++, 0, line);
+ }
+
+ firmware.bytes_total += input.length;
+}
+
+const CONFIG_LABEL = `Custom defaults inserted in`;
+
+ConfigInserter.prototype.insertConfig = function (firmware, config) {
+ console.time(CONFIG_LABEL);
+
+ const input = `# Betaflight\n${config}\0`;
+ const customDefaultsArea = getCustomDefaultsArea(firmware);
+
+ if (!customDefaultsArea || customDefaultsArea.endAddress - customDefaultsArea.startAddress === 0) {
+ return false;
+ } else if (input.length >= customDefaultsArea.endAddress - customDefaultsArea.startAddress) {
+ throw new Error(`Custom defaults area too small (${customDefaultsArea.endAddress - customDefaultsArea.startAddress} bytes), ${input.length + 1} bytes needed.`);
+ }
+
+ generateData(firmware, input, customDefaultsArea.startAddress);
+
+ console.timeEnd(CONFIG_LABEL);
+
+ return true;
+};
diff --git a/src/js/tabs/firmware_flasher.js b/src/js/tabs/firmware_flasher.js
index 0645b3b9..278cc0f4 100644
--- a/src/js/tabs/firmware_flasher.js
+++ b/src/js/tabs/firmware_flasher.js
@@ -9,6 +9,8 @@ const firmware_flasher = {
intel_hex: undefined, // standard intel hex in string format
parsed_hex: undefined, // parsed raw hex in array format
isConfigLocal: false, // Set to true if the user loads one locally
+ configFilename: null,
+ config: {},
developmentFirmwareLoaded: false, // Is the firmware to be flashed from the development branch?
};
@@ -61,6 +63,7 @@ firmware_flasher.initialize = function (callback) {
$('div.release_info .name').text(summary.release).prop('href', summary.releaseUrl);
$('div.release_info .date').text(summary.date);
$('div.release_info #targetMCU').text(summary.mcu);
+ $('div.release_info .configFilename').text(self.isConfigLocal ? self.configFilename : "[default]");
if (summary.cloudBuild) {
$('div.release_info #cloudTargetInfo').show();
@@ -86,6 +89,18 @@ firmware_flasher.initialize = function (callback) {
}
}
+ function clearBoardConfig() {
+ self.config = {};
+ self.isConfigLocal = false;
+ self.configFilename = null;
+ }
+
+ function setBoardConfig(config, filename) {
+ self.config = config;
+ self.isConfigLocal = filename !== undefined;
+ self.configFilename = filename !== undefined ? filename : null;
+ }
+
function processHex(data, key) {
self.intel_hex = data;
@@ -284,7 +299,7 @@ firmware_flasher.initialize = function (callback) {
}
function clearBufferedFirmware() {
- self.isConfigLocal = false;
+ clearBoardConfig();
self.intel_hex = undefined;
self.parsed_hex = undefined;
self.localFirmwareLoaded = false;
@@ -356,6 +371,33 @@ firmware_flasher.initialize = function (callback) {
}
});
+ function cleanUnifiedConfigFile(input) {
+ let output = [];
+ let inComment = false;
+ for (let i=0; i < input.length; i++) {
+ if (input.charAt(i) === "\n" || input.charAt(i) === "\r") {
+ inComment = false;
+ }
+
+ if (input.charAt(i) === "#") {
+ inComment = true;
+ }
+
+ if (!inComment && input.charCodeAt(i) > 255) {
+ self.flashingMessage(i18n.getMessage('firmwareFlasherConfigCorrupted'), self.FLASH_MESSAGE_TYPES.INVALID);
+ GUI.log(i18n.getMessage('firmwareFlasherConfigCorruptedLogMessage'));
+ return null;
+ }
+
+ if (input.charCodeAt(i) > 255) {
+ output.push('_');
+ } else {
+ output.push(input.charAt(i));
+ }
+ }
+ return output.join('');
+ }
+
const portPickerElement = $('div#port-picker #port');
function flashFirmware(firmware) {
const options = {};
@@ -594,7 +636,7 @@ firmware_flasher.initialize = function (callback) {
accepts: [
{
description: 'target files',
- extensions: ['hex'],
+ extensions: ['hex', 'config'],
},
],
}, function (fileEntry) {
@@ -633,7 +675,13 @@ firmware_flasher.initialize = function (callback) {
}
});
} else {
- self.flashingMessage(i18n.getMessage('firmwareFlasherHexCorrupted'), self.FLASH_MESSAGE_TYPES.INVALID);
+ clearBufferedFirmware();
+
+ let config = cleanUnifiedConfigFile(e.target.result);
+ if (config !== null) {
+ setBoardConfig(config, file.name);
+ flashingMessageLocal(file.name);
+ }
}
}
};
@@ -687,6 +735,10 @@ firmware_flasher.initialize = function (callback) {
});
}
+ if (summary.configuration && !self.isConfigLocal) {
+ setBoardConfig(summary.configuration.join('\n'));
+ }
+
$("a.load_remote_file").removeClass('disabled');
}
@@ -794,9 +846,6 @@ firmware_flasher.initialize = function (callback) {
self.releaseLoader.loadTargetHex(summary.url, (hex) => onLoadSuccess(hex, fileName), onLoadFailed);
}
- const target = $('select[name="board"] option:selected').val();
- const release = $('select[name="firmware_version"] option:selected').val();
-
if (self.summary) { // undefined while list is loading or while running offline
$("a.load_remote_file").text(i18n.getMessage('firmwareFlasherButtonDownloading'));
$("a.load_remote_file").addClass('disabled');
@@ -804,9 +853,9 @@ firmware_flasher.initialize = function (callback) {
showReleaseNotes(self.summary);
if (self.summary.cloudBuild === true) {
- self.releaseLoader.loadTarget(target, release, requestCloudBuild, onLoadFailed);
+ requestCloudBuild(self.summary);
} else {
- self.releaseLoader.loadTarget(target, release, requestLegacyBuild, onLoadFailed);
+ requestLegacyBuild(self.summary);
}
} else {
$('span.progressLabel').attr('i18n','firmwareFlasherFailedToLoadOnlineFirmware').removeClass('i18n-replaced');
@@ -926,6 +975,17 @@ firmware_flasher.initialize = function (callback) {
if (!GUI.connect_lock) { // button disabled while flashing is in progress
if (self.parsed_hex) {
try {
+ if (self.config && !self.parsed_hex.configInserted) {
+ const configInserter = new ConfigInserter();
+
+ if (configInserter.insertConfig(self.parsed_hex, self.config)) {
+ self.parsed_hex.configInserted = true;
+ } else {
+ console.log('Firmware does not support custom defaults.');
+ clearBoardConfig();
+ }
+ }
+
flashFirmware(self.parsed_hex);
} catch (e) {
console.log(`Flashing failed: ${e.message}`);
diff --git a/src/main.html b/src/main.html
index 1a9b3cfe..cccddec1 100644
--- a/src/main.html
+++ b/src/main.html
@@ -111,6 +111,7 @@
<script type="text/javascript" src="./js/Beepers.js"></script>
<script type="text/javascript" src="./js/release_checker.js"></script>
<script type="text/javascript" src="./js/release_loader.js"></script>
+ <script type="text/javascript" src="./js/ConfigInserter.js"></script>
<script type="text/javascript" src="./js/Analytics.js"></script>
<script type="text/javascript" src="./js/GitHubApi.js"></script>
<script type="module" src="./js/main.js"></script>
diff --git a/src/tabs/firmware_flasher.html b/src/tabs/firmware_flasher.html
index 96fdc7ad..d03d2f99 100644
--- a/src/tabs/firmware_flasher.html
+++ b/src/tabs/firmware_flasher.html
@@ -223,6 +223,9 @@
<strong i18n="firmwareFlasherReleaseDate"></strong>
<span class="date"></span>
<br />
+ <strong i18n="firmwareFlasherConfigurationFile"></strong>
+ <span class="configFilename"></span>
+ <br />
</div>
<div class="margin-bottom" id="cloudTargetInfo">
<strong i18n="firmwareFlasherCloudBuildDetails"></strong>