bootloader checksum (#279)

* blindly implement checksum

* extra erase of checksum page

* don't need to write the sum ourselves

* maybe implement bootloader crc correctly

* minus is not plus

* modify build script to properly embed checksum

* cleanup

* use lma instead of vma

* implement bootloader blinky

* stub firmwareError

* static blinky
This commit is contained in:
Matthew Kennedy 2023-11-02 02:16:56 -07:00 committed by GitHub
parent 9dc183a173
commit 0bedacc298
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 92 additions and 15 deletions

View File

@ -8,12 +8,48 @@ extern "C" {
#include "shared_params.h" #include "shared_params.h"
} }
class BlinkyThread : public chibios_rt::BaseStaticThread<256> {
protected:
void main(void) override {
Gpio yellow = getWarningLedPin();
Gpio blue = getCommsLedPin();
Gpio green = getRunningLedPin();
efiSetPadMode("yellow", yellow, PAL_MODE_OUTPUT_PUSHPULL);
efiSetPadMode("blue", blue, PAL_MODE_OUTPUT_PUSHPULL);
efiSetPadMode("green", green, PAL_MODE_OUTPUT_PUSHPULL);
auto yellowPort = getBrainPinPort(yellow);
auto yellowPin = getBrainPinIndex(yellow);
auto bluePort = getBrainPinPort(blue);
auto bluePin = getBrainPinIndex(blue);
auto greenPort = getBrainPinPort(green);
auto greenPin = getBrainPinIndex(green);
palSetPad(yellowPort, yellowPin);
palSetPad(bluePort, bluePin);
palSetPad(greenPort, greenPin);
while (true) {
palTogglePad(yellowPort, yellowPin);
palTogglePad(bluePort, bluePin);
palTogglePad(greenPort, greenPin);
chThdSleepMilliseconds(250);
}
}
};
static BlinkyThread blinky;
int main(void) { int main(void) {
halInit(); halInit();
chSysInit(); chSysInit();
baseMCUInit(); baseMCUInit();
// start the blinky thread
blinky.start(NORMALPRIO + 10);
// Init openblt shared params // Init openblt shared params
SharedParamsInit(); SharedParamsInit();
@ -25,7 +61,7 @@ int main(void) {
} }
} }
// very basic version, supports on chip pins only (really only used for USB) // very basic version, supports on chip pins only (really only used for USB, LEDs)
void efiSetPadMode(const char* msg, brain_pin_e brainPin, iomode_t mode) { void efiSetPadMode(const char* msg, brain_pin_e brainPin, iomode_t mode) {
ioportid_t port = getHwPort(msg, brainPin); ioportid_t port = getHwPort(msg, brainPin);
ioportmask_t pin = getHwPin(msg, brainPin); ioportmask_t pin = getHwPin(msg, brainPin);

View File

@ -14,6 +14,9 @@ void chDbgPanic3(const char* /*msg*/, const char* /*file*/, int /*line*/) {
void logHardFault(uint32_t type, uintptr_t faultAddress, struct port_extctx* ctx, uint32_t csfr) { } void logHardFault(uint32_t type, uintptr_t faultAddress, struct port_extctx* ctx, uint32_t csfr) { }
void firmwareError(ObdCode code, const char *fmt, ...) {
}
// this is supposed to be taken from chconf_common.h but it does not work? I am not sure why :( // this is supposed to be taken from chconf_common.h but it does not work? I am not sure why :(
// TODO: make this be defined by chconf_common.h? // TODO: make this be defined by chconf_common.h?
//#if ! ENABLE_PERF_TRACE //#if ! ENABLE_PERF_TRACE

View File

@ -1,6 +1,8 @@
#include "pch.h" #include "pch.h"
#include "flash_int.h" #include "flash_int.h"
#include <rusefi/crc.h>
extern "C" { extern "C" {
#include "boot.h" #include "boot.h"
#include "flash.h" #include "flash.h"
@ -20,16 +22,15 @@ blt_addr FlashGetUserProgBaseAddress() {
blt_bool FlashWrite(blt_addr addr, blt_int32u len, blt_int8u *data) { blt_bool FlashWrite(blt_addr addr, blt_int32u len, blt_int8u *data) {
return (FLASH_RETURN_SUCCESS == intFlashWrite(addr, (const char*)data, len)) ? BLT_TRUE : BLT_FALSE; return (FLASH_RETURN_SUCCESS == intFlashWrite(addr, (const char*)data, len)) ? BLT_TRUE : BLT_FALSE;
return BLT_TRUE;
} }
blt_bool FlashErase(blt_addr addr, blt_int32u len) { blt_bool FlashErase(blt_addr addr, blt_int32u len) {
if (!intFlashIsErased(addr, len)) { if (intFlashIsErased(addr, len)) {
return (FLASH_RETURN_SUCCESS == intFlashErase(addr, len)) ? BLT_TRUE : BLT_FALSE; // Already blank, we can skip the expensive erase operation
return BLT_TRUE;
} }
return BLT_TRUE; return (FLASH_RETURN_SUCCESS == intFlashErase(addr, len)) ? BLT_TRUE : BLT_FALSE;
} }
blt_bool FlashDone() { blt_bool FlashDone() {
@ -42,5 +43,28 @@ blt_bool FlashWriteChecksum() {
blt_bool FlashVerifyChecksum() { blt_bool FlashVerifyChecksum() {
// Naive check: if the first block is blank, there's no code there // Naive check: if the first block is blank, there's no code there
return intFlashIsErased(FlashGetUserProgBaseAddress(), 4) ? BLT_FALSE : BLT_TRUE; if (intFlashIsErased(FlashGetUserProgBaseAddress(), 4)) {
return BLT_FALSE;
}
static const size_t checksumOffset = 0x1C;
// Now do the actual CRC check to ensure we didn't get stuck with a half-written firmware image
uint8_t* start = reinterpret_cast<uint8_t*>(FlashGetUserProgBaseAddress());
size_t imageSize = *reinterpret_cast<size_t*>(start + checksumOffset + 4);
if (imageSize > 1024 * 1024) {
// impossibly large size, invalid
return BLT_FALSE;
}
// part before checksum+size
uint32_t calcChecksum = crc32(start, checksumOffset);
// part after checksum+size
calcChecksum = crc32inc(start + checksumOffset + 4, calcChecksum, imageSize - (checksumOffset + 4));
uint32_t storedChecksum = *reinterpret_cast<uint32_t*>(start + checksumOffset);
return calcChecksum == storedChecksum ? BLT_TRUE : BLT_FALSE;
} }

View File

@ -31,8 +31,25 @@ chmod u+x $HEX2DFU
mkdir -p deliver mkdir -p deliver
rm -f deliver/* rm -f deliver/*
echo "$SCRIPT_NAME: invoking hex2dfu for incremental rusEFI image" # delete everything we're going to regenerate
$HEX2DFU -i build/fome.hex -C 0x1C -o build/fome.dfu rm build/fome.bin build/fome.srec
# Extract the firmware's base address from the elf - it may be different depending on exact CPU
firmwareBaseAddress="$(objdump -h -j .vectors build/fome.elf | awk '/.vectors/ {print $5 }')"
checksumAddress="$(printf "%X\n" $((0x$firmwareBaseAddress+0x1c)))"
echo "Base address is 0x$firmwareBaseAddress"
echo "Checksum address is 0x$checksumAddress"
echo "$SCRIPT_NAME: invoking hex2dfu to place image checksum"
$HEX2DFU -i build/fome.hex -c $checksumAddress -b build/fome.bin
rm build/fome.hex
# re-make hex, srec with the checksum in place
objcopy -I binary -O ihex --change-addresses=0x$firmwareBaseAddress build/fome.bin build/fome.hex
objcopy -I binary -O srec --change-addresses=0x$firmwareBaseAddress build/fome.bin build/fome.srec
# make DFU
$HEX2DFU -i build/fome.hex -o build/fome.dfu
if [ "$USE_OPENBLT" = "yes" ]; then if [ "$USE_OPENBLT" = "yes" ]; then
# this image is suitable for update through bootloader only # this image is suitable for update through bootloader only
@ -45,9 +62,8 @@ else
# cp build/fome.hex deliver/ # cp build/fome.hex deliver/
fi fi
# bootloader and composite image # bootloader and combined image
if [ "$USE_OPENBLT" = "yes" ]; then if [ "$USE_OPENBLT" = "yes" ]; then
rm -f deliver/fome_bl.dfu
echo "$SCRIPT_NAME: invoking hex2dfu for OpenBLT" echo "$SCRIPT_NAME: invoking hex2dfu for OpenBLT"
$HEX2DFU -i bootloader/blbuild/fome_bl.hex -o bootloader/blbuild/fome_bl.dfu $HEX2DFU -i bootloader/blbuild/fome_bl.hex -o bootloader/blbuild/fome_bl.dfu
@ -56,10 +72,8 @@ if [ "$USE_OPENBLT" = "yes" ]; then
cp bootloader/blbuild/fome_bl.dfu deliver/fome_bl.dfu cp bootloader/blbuild/fome_bl.dfu deliver/fome_bl.dfu
#cp bootloader/blbuild/fome_bl.hex deliver/fome_bl.hex #cp bootloader/blbuild/fome_bl.hex deliver/fome_bl.hex
rm -f deliver/fome_openblt.dfu echo "$SCRIPT_NAME: invoking hex2dfu for combined OpenBLT+FOME image"
echo "$SCRIPT_NAME: invoking hex2dfu for composite rusEFI+OpenBLT image" $HEX2DFU -i bootloader/blbuild/fome_bl.hex -i build/fome.hex -o deliver/fome.dfu -b deliver/fome.bin
$HEX2DFU -i bootloader/blbuild/fome_bl.hex -i build/fome.hex -C 0x1C -o deliver/fome.dfu -b deliver/fome.bin
#todo: how to create 'signed' hex and srec? Do we need?
fi fi
echo "$SCRIPT_NAME: build folder content:" echo "$SCRIPT_NAME: build folder content:"