1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-15 04:15:32 +03:00
betaflight-configurator/src/js/ConfigInserter.js
2021-12-18 08:21:05 +01:00

107 lines
3 KiB
JavaScript

'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++);
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.');
}
// Add 0 terminator
input = input + '\0';
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, input) {
console.time(CONFIG_LABEL);
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;
};