diff --git a/Bootloader/Adapters/Src/system_adapter.c b/Bootloader/Adapters/Src/system_adapter.c index 6041bbe..d3a5aca 100644 --- a/Bootloader/Adapters/Src/system_adapter.c +++ b/Bootloader/Adapters/Src/system_adapter.c @@ -35,7 +35,14 @@ #include "main.h" #include "system_adapter.h" +#include "binary_update.h" + +extern __attribute__ ((section(".restart_info"))) +volatile bootInfo_S boot_info; + void SystemAdapter_reset(void) { + + boot_info.end = 0xFF; // Resolve known issue with STM32H7 MCUs. Memory must be written before reset to ensure data retention. HAL_NVIC_SystemReset(); } diff --git a/Bootloader/Inc/binary_update.h b/Bootloader/Inc/binary_update.h index ccc469d..4920d05 100644 --- a/Bootloader/Inc/binary_update.h +++ b/Bootloader/Inc/binary_update.h @@ -41,9 +41,9 @@ #pragma pack(push, 1) typedef struct bootInfo { - uint32_t jump_address; //!< Address for BL to jump - bool skip_bl_loop; //!< Flag to skip BL loop - uint8_t end; // FIXME: added here because after restart something is messing up with data in the structure and if there is an extra byte at the end it messes only with it + uint32_t jump_address; //!< Address for BL to jump + bool skip_bl_loop; //!< Flag to skip BL loop + uint8_t end; //!< MCUs like the STM32H7 have issues preserving certain data unless an additional byte is written before reset. } bootInfo_S; #pragma pack(pop) diff --git a/Bootloader/Src/binary_update.c b/Bootloader/Src/binary_update.c index bc2d430..c538d5b 100644 --- a/Bootloader/Src/binary_update.c +++ b/Bootloader/Src/binary_update.c @@ -40,10 +40,11 @@ __attribute__ ((section(".restart_info"))) volatile bootInfo_S boot_info; //!< Instruction on where to jump after the restart -static uint64_t s_address; //!< Address from where to erase flash and write binary +static uintptr_t s_address; //!< Address from where to erase flash and write binary static signatureType_E s_detected_binary; //!< Detected binary static bool BinaryUpdate_writeToFlash(uint8_t* write_buffer, const uint32_t data_length); +static bool BinaryUpdate_writeToRam(uint8_t* write_buffer, const uint32_t data_length); bool BinaryUpdate_handleDetectedBinary(signatureType_E detected_binary) { @@ -150,12 +151,15 @@ BinaryUpdate_erase(uint32_t firmware_size) { bool BinaryUpdate_write(uint8_t* write_buffer, const uint32_t packet_length) { - bool success = false; + bool success = true; + uint32_t data_length = packet_length; + uint8_t* data = write_buffer; bool is_secured = Security_isSecured(); if (is_secured) { + success = false; uint32_t data_length = packet_length - (MAC_SIZE + NONCE_SIZE); if (data_length > 0U) { @@ -172,12 +176,31 @@ BinaryUpdate_write(uint8_t* write_buffer, const uint32_t packet_length) { success = Security_decrypt(mac, nonce, encrypted_data, decrypted_data, data_length); if (success) { - success = BinaryUpdate_writeToFlash(decrypted_data, data_length); + data = decrypted_data; } } - } else { - success = BinaryUpdate_writeToFlash(write_buffer, packet_length); + } + + if (success) { + + switch (s_detected_binary) { + + case signatureType_FIRMWARE_FLASH: + case signatureType_BOOTLOADER_FLASH: + case signatureType_UNKNOWN: + success = BinaryUpdate_writeToFlash(data, data_length); + break; + + case signatureType_FIRMWARE_RAM: + case signatureType_BOOTLOADER_RAM: + success = BinaryUpdate_writeToRam(data, data_length); + break; + + default: + success = false; + break; + } } return success; @@ -227,8 +250,6 @@ BinaryUpdate_finish(void) { break; } - boot_info.end = 0xFF; - return success; } @@ -257,3 +278,18 @@ BinaryUpdate_writeToFlash(uint8_t* write_buffer, const uint32_t data_length) { return success; } + +bool +BinaryUpdate_writeToRam(uint8_t* write_buffer, const uint32_t data_length) { + + bool success = false; + + memcpy ((void*)s_address, write_buffer, data_length); + + if (0 == memcmp ((void*)s_address, write_buffer, data_length)) { + success = true; + s_address += data_length; + } + + return success; +} diff --git a/Linker/STM32F7xx.ld b/Linker/STM32F7xx.ld index 7c4d570..36b32b8 100644 --- a/Linker/STM32F7xx.ld +++ b/Linker/STM32F7xx.ld @@ -45,6 +45,13 @@ MEMORY /* Sections */ SECTIONS { + .restart_info (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.restart_info)) + . = ALIGN(4); + } >RAM1 + /* The startup code into "FLASH" Rom type memory */ .isr_vector : { @@ -127,11 +134,6 @@ SECTIONS /* Used by the startup to initialize data */ _sidata = LOADADDR(.data); - .restart_info : ALIGN(4) - { - KEEP(*(.restart_info)) - } >RAM1 AT> FLASH - /* Initialized data sections into "RAM" Ram type memory */ .data : { diff --git a/Linker/STM32F7xx_RAM.ld b/Linker/STM32F7xx_RAM.ld index a7137a8..695f8ab 100644 --- a/Linker/STM32F7xx_RAM.ld +++ b/Linker/STM32F7xx_RAM.ld @@ -45,6 +45,13 @@ MEMORY /* Sections */ SECTIONS { + .restart_info (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.restart_info)) + . = ALIGN(4); + } >RAM1 + /* The startup code into "RAM" Ram type memory */ .isr_vector : { @@ -129,11 +136,6 @@ SECTIONS /* Used by the startup to initialize data */ _sidata = LOADADDR(.data); - .restart_info : ALIGN(4) - { - KEEP(*(.restart_info)) - } >RAM1 AT> RAM2 - /* Initialized data sections into "RAM" Ram type memory */ .data : { @@ -161,7 +163,7 @@ SECTIONS . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; - } >RAM1 AT> RAM2 + } >RAM1 /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ ._user_heap_stack : @@ -172,7 +174,7 @@ SECTIONS . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); - } >RAM1 AT> RAM2 + } >RAM1 /* Remove information from the compiler libraries */ /DISCARD/ : diff --git a/Linker/STM32F7xx_RAM_SIGNATURE.ld b/Linker/STM32F7xx_RAM_SIGNATURE.ld index 3f90248..05fe263 100644 --- a/Linker/STM32F7xx_RAM_SIGNATURE.ld +++ b/Linker/STM32F7xx_RAM_SIGNATURE.ld @@ -51,6 +51,13 @@ SECTIONS KEEP(*(.bl_ram_signature)) } >SIGNATURE + .restart_info (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.restart_info)) + . = ALIGN(4); + } >RAM1 + /* The startup code into "RAM" Ram type memory */ .isr_vector : { @@ -131,15 +138,10 @@ SECTIONS PROVIDE_HIDDEN (__fini_array_end = .); . = ALIGN(4); } >RAM2 - + /* Used by the startup to initialize data */ _sidata = LOADADDR(.data); - .restart_info : ALIGN(4) - { - KEEP(*(.restart_info)) - } >RAM1 AT> RAM2 - /* Initialized data sections into "RAM" Ram type memory */ .data : { @@ -167,7 +169,7 @@ SECTIONS . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; - } >RAM1 AT> RAM2 + } >RAM1 /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ ._user_heap_stack : @@ -178,7 +180,7 @@ SECTIONS . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); - } >RAM1 AT> RAM2 + } >RAM1 /* Remove information from the compiler libraries */ /DISCARD/ : diff --git a/Linker/STM32F7xx_SIGNATURE.ld b/Linker/STM32F7xx_SIGNATURE.ld index cf65a24..7a40c45 100644 --- a/Linker/STM32F7xx_SIGNATURE.ld +++ b/Linker/STM32F7xx_SIGNATURE.ld @@ -51,6 +51,13 @@ SECTIONS KEEP(*(.bl_flash_signature)) } >SIGNATURE + .restart_info (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.restart_info)) + . = ALIGN(4); + } >RAM1 + /* The startup code into "FLASH" Rom type memory */ .isr_vector : { @@ -133,11 +140,6 @@ SECTIONS /* Used by the startup to initialize data */ _sidata = LOADADDR(.data); - .restart_info : ALIGN(4) - { - KEEP(*(.restart_info)) - } >RAM1 AT> FLASH - /* Initialized data sections into "RAM" Ram type memory */ .data : { diff --git a/Linker/STM32H7xx.ld b/Linker/STM32H7xx.ld index 2071745..cfa41bf 100644 --- a/Linker/STM32H7xx.ld +++ b/Linker/STM32H7xx.ld @@ -66,13 +66,19 @@ RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 128K RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K -SIGNATURE (rx) : ORIGIN = 0x07FFFFC0, LENGTH = 64 /* Never written to the FLASH, it is for binary signature. */ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K } /* Define output sections */ SECTIONS { + .restart_info (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.restart_info)) + . = ALIGN(4); + } >DTCMRAM + /* The startup code goes first into FLASH */ .isr_vector : { @@ -139,14 +145,9 @@ SECTIONS KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - .restart_info : ALIGN(4) - { - KEEP(*(.restart_info)) - } >DTCMRAM AT> FLASH + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code */ .data : @@ -160,7 +161,6 @@ SECTIONS _edata = .; /* define a global symbol at data end */ } >DTCMRAM AT> FLASH - /* Uninitialized data section */ . = ALIGN(4); .bss : diff --git a/Linker/STM32H7xx_RAM.ld b/Linker/STM32H7xx_RAM.ld index 8eb5c90..1239bad 100644 --- a/Linker/STM32H7xx_RAM.ld +++ b/Linker/STM32H7xx_RAM.ld @@ -53,7 +53,7 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ -_estack = 0x20020000; /* end of RAM */ +_estack = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM); /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ @@ -62,8 +62,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */ MEMORY { DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K -SIGNATURE (rx) : ORIGIN = 0x23FFFFC0, LENGTH = 64 /* Never written to the RAM, it is for binary signature. */ -RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K +RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 128K RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K @@ -73,6 +72,13 @@ FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K /* Define output sections */ SECTIONS { + .restart_info (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.restart_info)) + . = ALIGN(4); + } >DTCMRAM + /* The startup code goes first into RAM_D1 */ .isr_vector : { @@ -139,14 +145,16 @@ SECTIONS KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); } >RAM_D1 - - /* used by the startup to initialize data */ - _sidata = LOADADDR(.data); - .restart_info : ALIGN(4) + .restart_info (NOLOAD) : { + . = ALIGN(4); KEEP(*(.restart_info)) - } >DTCMRAM AT> RAM_D1 + . = ALIGN(4); + } >DTCMRAM + + /* used by the startup to initialize data */ + _sidata = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code */ .data : @@ -156,11 +164,11 @@ SECTIONS *(.data) /* .data sections */ *(.data*) /* .data* sections */ - . = ALIGN(4); + . = ALIGN(8); + . = . + 4; /* Workaround for AXISRAM preserving data after reset*/ _edata = .; /* define a global symbol at data end */ } >DTCMRAM AT> RAM_D1 - /* Uninitialized data section */ . = ALIGN(4); .bss : @@ -175,7 +183,7 @@ SECTIONS . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; - } >DTCMRAM AT> RAM_D1 + } >DTCMRAM /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : @@ -186,7 +194,7 @@ SECTIONS . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); - } >DTCMRAM AT> RAM_D1 + } >DTCMRAM /* Remove information from the standard libraries */ diff --git a/Linker/STM32H7xx_RAM_SIGNATURE.ld b/Linker/STM32H7xx_RAM_SIGNATURE.ld index 02c948c..11c37cf 100644 --- a/Linker/STM32H7xx_RAM_SIGNATURE.ld +++ b/Linker/STM32H7xx_RAM_SIGNATURE.ld @@ -53,7 +53,7 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ -_estack = 0x20010000; /* end of RAM */ +_estack = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM); /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ @@ -63,7 +63,7 @@ MEMORY { DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K SIGNATURE (rx) : ORIGIN = 0x23FFFFC0, LENGTH = 64 /* Never written to the RAM, it is for binary signature. */ -RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K +RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 128K RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K @@ -78,6 +78,13 @@ SECTIONS KEEP(*(.bl_ram_signature)) } >SIGNATURE + .restart_info (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.restart_info)) + . = ALIGN(4); + } >DTCMRAM + /* The startup code goes first into RAM_D1 */ .isr_vector : { @@ -113,7 +120,7 @@ SECTIONS } >RAM_D1 .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */ - { + { *(.ARM.extab* .gnu.linkonce.armextab.*) } >RAM_D1 @@ -144,13 +151,8 @@ SECTIONS KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); } >RAM_D1 - - .restart_info : ALIGN(4) - { - KEEP(*(.restart_info)) - } >DTCMRAM AT> RAM_D1 - /* used by the startup to initialize data */ + /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code */ @@ -161,10 +163,10 @@ SECTIONS *(.data) /* .data sections */ *(.data*) /* .data* sections */ - . = ALIGN(4); + . = ALIGN(8); + . = . + 4; /* Workaround for AXISRAM preserving data after reset */ _edata = .; /* define a global symbol at data end */ } >DTCMRAM AT> RAM_D1 - /* Uninitialized data section */ . = ALIGN(4); @@ -180,7 +182,7 @@ SECTIONS . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; - } >DTCMRAM AT> RAM_D1 + } >DTCMRAM /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : @@ -191,7 +193,7 @@ SECTIONS . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); - } >DTCMRAM AT> RAM_D1 + } >DTCMRAM /* Remove information from the standard libraries */ diff --git a/Linker/STM32H7xx_SIGNATURE.ld b/Linker/STM32H7xx_SIGNATURE.ld index d28de17..e124bb5 100644 --- a/Linker/STM32H7xx_SIGNATURE.ld +++ b/Linker/STM32H7xx_SIGNATURE.ld @@ -53,7 +53,7 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ -_estack = 0x20020000; /* end of RAM */ +_estack = ORIGIN(DTCMRAM) + LENGTH(DTCMRAM); /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ @@ -62,7 +62,7 @@ _Min_Stack_Size = 0x400; /* required amount of stack */ MEMORY { DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K -RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K +RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 128K RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K @@ -77,7 +77,14 @@ SECTIONS { KEEP(*(.bl_flash_signature)) } >SIGNATURE - + + .restart_info (NOLOAD) : + { + . = ALIGN(4); + KEEP(*(.restart_info)) + . = ALIGN(4); + } >DTCMRAM + /* The startup code goes first into FLASH */ .isr_vector : { @@ -145,11 +152,6 @@ SECTIONS PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH - .restart_info : ALIGN(4) - { - KEEP(*(.restart_info)) - } >DTCMRAM AT> FLASH - /* used by the startup to initialize data */ _sidata = LOADADDR(.data); @@ -165,7 +167,6 @@ SECTIONS _edata = .; /* define a global symbol at data end */ } >DTCMRAM AT> FLASH - /* Uninitialized data section */ . = ALIGN(4); .bss : diff --git a/Linker/STM32L4xx.ld b/Linker/STM32L4xx.ld index beb5dd0..34c7f38 100644 --- a/Linker/STM32L4xx.ld +++ b/Linker/STM32L4xx.ld @@ -52,7 +52,7 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ -_estack = 0x20050000; /* end of RAM */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ diff --git a/Linker/STM32L4xx_SIGNATURE.ld b/Linker/STM32L4xx_SIGNATURE.ld index 17d8d8e..aeda6a6 100644 --- a/Linker/STM32L4xx_SIGNATURE.ld +++ b/Linker/STM32L4xx_SIGNATURE.ld @@ -52,7 +52,7 @@ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ -_estack = 0x20050000; /* end of RAM */ +_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ diff --git a/Makefile b/Makefile index 6431107..f3e5f14 100644 --- a/Makefile +++ b/Makefile @@ -103,7 +103,8 @@ format: .PHONY: cppcheck misra cppcheck: $(call colorecho,'Checking code with cppcheck') - @cppcheck --error-exitcode=1 Bootloader -DSECURED + @cppcheck --error-exitcode=1 Bootloader -DSECURED \ + -i Bootloader/Utility misra: $(call colorecho,'Checking MISRA C:2012 with cppcheck')