From add3fd7d56fa761df11044e0bb8a6ba5b98e1551 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Mon, 11 Sep 2023 09:47:27 +0200 Subject: [PATCH] cleaning, ejected dfu --- core/SConscript.ble_bootloader | 46 +- core/SConscript.ble_firmware | 8 +- core/embed/ble_bootloader/dfu/dfu-cc.options | 5 + core/embed/ble_bootloader/dfu/dfu-cc.pb.c | 31 + core/embed/ble_bootloader/dfu/dfu-cc.pb.h | 239 +++++ core/embed/ble_bootloader/dfu/dfu-cc.proto | 76 ++ core/embed/ble_bootloader/dfu/nrf_dfu.c | 98 ++ core/embed/ble_bootloader/dfu/nrf_dfu.h | 85 ++ core/embed/ble_bootloader/dfu/nrf_dfu_flash.c | 167 ++++ core/embed/ble_bootloader/dfu/nrf_dfu_flash.h | 132 +++ .../dfu/nrf_dfu_handling_error.c | 61 ++ .../dfu/nrf_dfu_handling_error.h | 125 +++ core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c | 105 +++ core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h | 90 ++ .../ble_bootloader/dfu/nrf_dfu_req_handler.c | 864 ++++++++++++++++++ .../ble_bootloader/dfu/nrf_dfu_req_handler.h | 346 +++++++ .../ble_bootloader/dfu/nrf_dfu_settings.c | 423 +++++++++ .../ble_bootloader/dfu/nrf_dfu_settings.h | 212 +++++ .../dfu/nrf_dfu_settings_svci.c | 185 ++++ core/embed/ble_bootloader/dfu/nrf_dfu_svci.c | 87 ++ .../ble_bootloader/dfu/nrf_dfu_svci_handler.c | 212 +++++ .../ble_bootloader/dfu/nrf_dfu_transport.c | 91 ++ .../ble_bootloader/dfu/nrf_dfu_transport.h | 134 +++ .../ble_bootloader/dfu/nrf_dfu_trigger_usb.c | 244 +++++ .../ble_bootloader/dfu/nrf_dfu_trigger_usb.h | 74 ++ core/embed/ble_bootloader/dfu/nrf_dfu_types.h | 342 +++++++ core/embed/ble_bootloader/dfu/nrf_dfu_utils.c | 220 +++++ core/embed/ble_bootloader/dfu/nrf_dfu_utils.h | 154 ++++ .../{ => dfu}/nrf_dfu_validation.c | 12 +- .../ble_bootloader/dfu/nrf_dfu_validation.h | 199 ++++ .../dfu/nrf_dfu_ver_validation.c | 311 +++++++ .../dfu/nrf_dfu_ver_validation.h | 64 ++ core/embed/ble_bootloader/memory.ld | 2 +- core/embed/ble_bootloader/sdk_config.h | 2 +- core/embed/ble_firmware/memory.ld | 2 +- .../uecc/.gitignore | 0 .../uecc/LICENSE.txt | 0 .../uecc/README.md | 0 .../uecc/asm_arm.inc | 0 .../uecc/asm_arm_mult_square.inc | 0 .../uecc/asm_arm_mult_square_umaal.inc | 0 .../uecc/asm_avr.inc | 0 .../uecc/asm_avr_mult_square.inc | 0 .../uecc/curve-specific.inc | 0 .../uecc/emk_project.py | 0 .../uecc/emk_rules.py | 0 .../uecc/examples/ecc_test/ecc_test.ino | 0 .../uecc/library.properties | 0 .../uecc/platform-specific.inc | 0 .../uecc/scripts/mult_arm.py | 0 .../uecc/scripts/mult_avr.py | 0 .../uecc/scripts/mult_avr_extra.py | 0 .../uecc/scripts/square_arm.py | 0 .../uecc/scripts/square_avr.py | 0 .../uecc/test/ecdsa_test_vectors.c | 0 .../uecc/test/emk_rules.py | 0 .../uecc/test/public_key_test_vectors.c | 0 .../uecc/test/test_compress.c | 0 .../uecc/test/test_compute.c | 0 .../uecc/test/test_ecdh.c | 0 .../uecc/test/test_ecdsa.c | 0 .../test/test_ecdsa_deterministic.c.example | 0 .../uecc/types.h | 0 .../uecc/uECC.c | 0 .../uecc/uECC.h | 0 .../uecc/uECC_vli.h | 0 .../libraries/bootloader/dfu/dfu-cc.pb.c | 130 ++- .../libraries/bootloader/dfu/dfu-cc.pb.h | 432 ++++----- .../libraries/bootloader/dfu/dfu-cc.proto | 10 +- .../bootloader/dfu/nrf_dfu_req_handler.c | 2 +- .../bootloader/dfu/nrf_dfu_settings.c | 16 +- .../libraries/bootloader/dfu/nrf_dfu_types.h | 2 +- .../bootloader/dfu/nrf_dfu_validation.h | 2 +- .../bootloader/dfu/nrf_dfu_ver_validation.c | 36 +- .../bootloader/dfu/nrf_dfu_ver_validation.h | 2 +- .../modules/nrfx/mdk/gcc_startup_nrf52833.S | 4 +- tools/style.c.exclude | 3 +- 77 files changed, 5783 insertions(+), 304 deletions(-) create mode 100644 core/embed/ble_bootloader/dfu/dfu-cc.options create mode 100644 core/embed/ble_bootloader/dfu/dfu-cc.pb.c create mode 100644 core/embed/ble_bootloader/dfu/dfu-cc.pb.h create mode 100644 core/embed/ble_bootloader/dfu/dfu-cc.proto create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_flash.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_flash.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_settings.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_settings.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_settings_svci.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_svci.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_svci_handler.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_transport.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_transport.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_types.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_utils.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_utils.h rename core/embed/ble_bootloader/{ => dfu}/nrf_dfu_validation.c (98%) create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_validation.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.h rename core/embed/{ble_bootloader => ble_firmware}/uecc/.gitignore (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/LICENSE.txt (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/README.md (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/asm_arm.inc (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/asm_arm_mult_square.inc (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/asm_arm_mult_square_umaal.inc (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/asm_avr.inc (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/asm_avr_mult_square.inc (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/curve-specific.inc (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/emk_project.py (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/emk_rules.py (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/examples/ecc_test/ecc_test.ino (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/library.properties (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/platform-specific.inc (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/scripts/mult_arm.py (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/scripts/mult_avr.py (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/scripts/mult_avr_extra.py (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/scripts/square_arm.py (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/scripts/square_avr.py (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/test/ecdsa_test_vectors.c (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/test/emk_rules.py (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/test/public_key_test_vectors.c (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/test/test_compress.c (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/test/test_compute.c (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/test/test_ecdh.c (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/test/test_ecdsa.c (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/test/test_ecdsa_deterministic.c.example (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/types.h (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/uECC.c (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/uECC.h (100%) rename core/embed/{ble_bootloader => ble_firmware}/uecc/uECC_vli.h (100%) diff --git a/core/SConscript.ble_bootloader b/core/SConscript.ble_bootloader index fded4c37c4..78db2adfb4 100644 --- a/core/SConscript.ble_bootloader +++ b/core/SConscript.ble_bootloader @@ -43,6 +43,8 @@ CPPDEFINES_MOD += [ 'MBR_PRESENT', 'SVC_INTERFACE_CALL_AS_NORMAL_FUNCTION', ('__HEAP_SIZE','0'), + '__STARTUP_CLEAR_BSS', + ('__START', 'main'), ('uECC_ENABLE_VLI_API', '0'), ('uECC_OPTIMIZATION_LEVEL', '3'), @@ -67,48 +69,35 @@ SOURCE_MOD += [ CPPPATH_MOD += [ 'embed/sdk/nrf52/modules/nrfx/drivers/include', - 'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc', 'embed/sdk/nrf52/components/libraries/memobj', 'embed/sdk/nrf52/components/libraries/crc32', - 'embed/sdk/nrf52/components/libraries/sha256', 'embed/sdk/nrf52/components/libraries/experimental_section_vars', 'embed/sdk/nrf52/components/libraries/mem_manager', 'embed/sdk/nrf52/components/libraries/fstorage', 'embed/sdk/nrf52/components/libraries/util', 'embed/sdk/nrf52/modules/nrfx', 'embed/sdk/nrf52/external/nrf_oberon/include', - 'embed/sdk/nrf52/components/libraries/crypto/backend/oberon', - 'embed/sdk/nrf52/components/libraries/crypto/backend/cifra', 'embed/sdk/nrf52/components/libraries/atomic', 'embed/sdk/nrf52/integration/nrfx', 'embed/sdk/nrf52/components/libraries/crypto/backend/cc310_bl', 'embed/sdk/nrf52/components/drivers_nrf/nrf_soc_nosd', 'embed/sdk/nrf52/components/libraries/log/src', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu', 'embed/sdk/nrf52/components/libraries/bootloader/serial_dfu', - 'embed/sdk/nrf52/external/nrf_cc310_bl/include', 'embed/sdk/nrf52/external/segger_rtt', 'embed/sdk/nrf52/components/libraries/delay', 'embed/sdk/nrf52/integration/nrfx/legacy', 'embed/sdk/nrf52/modules/nrfx/hal', - 'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_hw', 'embed/sdk/nrf52/components/libraries/log', 'embed/sdk/nrf52/components/libraries/strerror', - 'embed/sdk/nrf52/components/libraries/crypto/backend/mbedtls', - 'embed/sdk/nrf52/components/libraries/crypto/backend/cc310', 'embed/sdk/nrf52/components/libraries/bootloader', 'embed/sdk/nrf52/components/softdevice/mbr/headers', - 'embed/sdk/nrf52/components/libraries/crypto', - 'embed/sdk/nrf52/components/libraries/crypto/backend/optiga', 'embed/sdk/nrf52/components/libraries/scheduler', 'embed/sdk/nrf52/components/libraries/slip', 'embed/sdk/nrf52/external/fprintf', 'embed/sdk/nrf52/components/toolchain/cmsis/include', 'embed/sdk/nrf52/components/libraries/balloc', 'embed/sdk/nrf52/components/libraries/stack_info', - 'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_sw', 'embed/sdk/nrf52/modules/nrfx/mdk', - 'embed/sdk/nrf52/external/nrf_cc310/include', 'embed/sdk/nrf52/components/libraries/queue', 'embed/sdk/nrf52/components/libraries/mutex', 'embed/sdk/nrf52/components/libraries/ringbuf', @@ -165,27 +154,28 @@ SOURCE_NRFHAL = [ 'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_fw_activation.c', 'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_info.c', 'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_wdt.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_flash.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_handling_error.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_mbr.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_settings.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_transport.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_utils.c', - 'embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c', 'embed/sdk/nrf52/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c', ] SOURCE_BLE_BOOTLOADER = [ 'embed/ble_bootloader/main.c', - 'embed/ble_bootloader/uecc/uECC.c', 'embed/ble_bootloader/dfu_public_key.c', # originally embed/sdk/nrf52/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_uart.c', 'embed/ble_bootloader/nrf_dfu_serial_uart.c', 'embed/ble_bootloader/nrf_bootloader.c', - 'embed/ble_bootloader/nrf_dfu_validation.c', + # ejected from embed/sdk/nrf52/components/libraries/bootloader/dfu + 'embed/ble_bootloader/dfu/nrf_dfu_validation.c', + 'embed/ble_bootloader/dfu/dfu-cc.pb.c', + 'embed/ble_bootloader/dfu/nrf_dfu.c', + 'embed/ble_bootloader/dfu/nrf_dfu_flash.c', + 'embed/ble_bootloader/dfu/nrf_dfu_handling_error.c', + 'embed/ble_bootloader/dfu/nrf_dfu_mbr.c', + 'embed/ble_bootloader/dfu/nrf_dfu_req_handler.c', + 'embed/ble_bootloader/dfu/nrf_dfu_settings.c', + 'embed/ble_bootloader/dfu/nrf_dfu_transport.c', + 'embed/ble_bootloader/dfu/nrf_dfu_utils.c', + 'embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c', + 'vendor/trezor-crypto/blake2s.c', 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c', 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c', @@ -255,11 +245,11 @@ CPU_CCFLAGS = '-mthumb -mabi=aapcs -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-s env.Replace( - COPT=env.get('ENV').get('OPTIMIZE', '-Og'), + COPT=env.get('ENV').get('OPTIMIZE', '-Os'), CCFLAGS='$COPT ' '-g3 ' '-nostdlib ' - '-std=gnu99 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -Wno-unused-function ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -Wno-unused-function ' '-fdata-sections -ffunction-sections ' '-fno-strict-aliasing ' '-fno-builtin ' @@ -268,7 +258,7 @@ env.Replace( LINKFLAGS='-Lembed/sdk/nrf52/modules/nrfx/mdk -T embed/ble_bootloader/memory.ld -Wl,--gc-sections --specs=nano.specs -Wl,-Map=build/ble_bootloader/ble_bootloader.map -Wl,--warn-common -Wl,--print-memory-usage', CPPPATH=[ 'embed/ble_bootloader', - 'embed/ble_bootloader/uecc', + 'embed/ble_bootloader/dfu', 'embed/sdk/nrf52', ] + CPPPATH_MOD, CPPDEFINES=[ diff --git a/core/SConscript.ble_firmware b/core/SConscript.ble_firmware index b2bf46163d..16911ba6fb 100644 --- a/core/SConscript.ble_firmware +++ b/core/SConscript.ble_firmware @@ -46,6 +46,8 @@ CPPDEFINES_MOD += [ 'S140', ('__HEAP_SIZE','8192'), ('__STACK_SIZE','8192'), + '__STARTUP_CLEAR_BSS', + ('__START', 'main'), ('uECC_ENABLE_VLI_API', '0'), ('uECC_OPTIMIZATION_LEVEL', '3'), @@ -323,9 +325,9 @@ SOURCE_BLE_FIRMWARE = [ 'embed/ble_firmware/power.c', 'embed/ble_firmware/advertising.c', 'embed/ble_firmware/connection.c', + 'embed/ble_firmware/uecc/uECC.c', 'embed/bootloader/protob/messages.pb.c', 'embed/lib/protob_helpers.c', - 'embed/ble_bootloader/uecc/uECC.c', ] if MMD: @@ -384,7 +386,7 @@ env.Replace( COPT=env.get('ENV').get('OPTIMIZE', '-Og'), CCFLAGS='$COPT ' '-g3 ' - '-std=c99 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -Wno-unused-function ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -Wno-unused-function ' '-fdata-sections -ffunction-sections ' '-fno-strict-aliasing ' '-fno-builtin ' @@ -397,7 +399,7 @@ env.Replace( 'embed/sdk/nrf52', 'embed/lib', 'vendor/nanopb', - 'embed/ble_bootloader/uecc', + 'embed/ble_firmware/uecc', ] + CPPPATH_MOD, CPPDEFINES=[ 'BLE_FIRMWARE', diff --git a/core/embed/ble_bootloader/dfu/dfu-cc.options b/core/embed/ble_bootloader/dfu/dfu-cc.options new file mode 100644 index 0000000000..de4fcdb86b --- /dev/null +++ b/core/embed/ble_bootloader/dfu/dfu-cc.options @@ -0,0 +1,5 @@ +dfu.Hash.hash max_size:32 +dfu.SignedCommand.signature max_size:64 +dfu.InitCommand.sd_req max_count:16 +dfu.InitCommand.boot_validation max_count:3 +dfu.BootValidation.bytes max_size:64 \ No newline at end of file diff --git a/core/embed/ble_bootloader/dfu/dfu-cc.pb.c b/core/embed/ble_bootloader/dfu/dfu-cc.pb.c new file mode 100644 index 0000000000..79d9e5d2d0 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/dfu-cc.pb.c @@ -0,0 +1,31 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.5 */ + +#include "dfu-cc.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(dfu_Hash, dfu_Hash, AUTO) + + +PB_BIND(dfu_BootValidation, dfu_BootValidation, AUTO) + + +PB_BIND(dfu_InitCommand, dfu_InitCommand, 2) + + +PB_BIND(dfu_Command, dfu_Command, 2) + + +PB_BIND(dfu_SignedCommand, dfu_SignedCommand, 2) + + +PB_BIND(dfu_Packet, dfu_Packet, 2) + + + + + + + diff --git a/core/embed/ble_bootloader/dfu/dfu-cc.pb.h b/core/embed/ble_bootloader/dfu/dfu-cc.pb.h new file mode 100644 index 0000000000..c22c5fe5c0 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/dfu-cc.pb.h @@ -0,0 +1,239 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.5 */ + +#ifndef PB_DFU_DFU_CC_PB_H_INCLUDED +#define PB_DFU_DFU_CC_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +typedef enum _dfu_FwType { + dfu_FwType_APPLICATION = 0, + dfu_FwType_SOFTDEVICE = 1, + dfu_FwType_BOOTLOADER = 2, + dfu_FwType_SOFTDEVICE_BOOTLOADER = 3, + dfu_FwType_EXTERNAL_APPLICATION = 4 +} dfu_FwType; + +typedef enum _dfu_HashType { + dfu_HashType_NO_HASH = 0, + dfu_HashType_CRC = 1, + dfu_HashType_SHA128 = 2, + dfu_HashType_SHA256 = 3, + dfu_HashType_SHA512 = 4 +} dfu_HashType; + +typedef enum _dfu_OpCode { + dfu_OpCode_INIT = 1 +} dfu_OpCode; + +typedef enum _dfu_ValidationType { + dfu_ValidationType_NO_VALIDATION = 0, + dfu_ValidationType_VALIDATE_GENERATED_CRC = 1, + dfu_ValidationType_VALIDATE_SHA256 = 2, + dfu_ValidationType_VALIDATE_ECDSA_P256_SHA256 = 3 +} dfu_ValidationType; + +/* Struct definitions */ +typedef PB_BYTES_ARRAY_T(64) dfu_BootValidation_bytes_t; +typedef struct _dfu_BootValidation { + uint32_t sigmask; + dfu_BootValidation_bytes_t bytes; +} dfu_BootValidation; + +typedef PB_BYTES_ARRAY_T(32) dfu_Hash_hash_t; +typedef struct _dfu_Hash { + dfu_HashType hash_type; + dfu_Hash_hash_t hash; +} dfu_Hash; + +/* Commands data */ +typedef struct _dfu_InitCommand { + bool has_fw_version; + uint32_t fw_version; + bool has_hw_version; + uint32_t hw_version; + pb_size_t sd_req_count; + uint32_t sd_req[16]; + bool has_type; + dfu_FwType type; + bool has_sd_size; + uint32_t sd_size; + bool has_bl_size; + uint32_t bl_size; + bool has_app_size; + uint32_t app_size; + bool has_hash; + dfu_Hash hash; + bool has_is_debug; + bool is_debug; + pb_size_t boot_validation_count; + dfu_BootValidation boot_validation[3]; +} dfu_InitCommand; + +/* Command type */ +typedef struct _dfu_Command { + bool has_op_code; + dfu_OpCode op_code; + bool has_init; + dfu_InitCommand init; +} dfu_Command; + +typedef PB_BYTES_ARRAY_T(64) dfu_SignedCommand_signature_t; +typedef struct _dfu_SignedCommand { + dfu_Command command; + uint32_t sigmask; + dfu_SignedCommand_signature_t signature; +} dfu_SignedCommand; + +/* Parent packet type */ +typedef struct _dfu_Packet { + bool has_command; + dfu_Command command; + bool has_signed_command; + dfu_SignedCommand signed_command; +} dfu_Packet; + + +/* Helper constants for enums */ +#define _dfu_FwType_MIN dfu_FwType_APPLICATION +#define _dfu_FwType_MAX dfu_FwType_EXTERNAL_APPLICATION +#define _dfu_FwType_ARRAYSIZE ((dfu_FwType)(dfu_FwType_EXTERNAL_APPLICATION+1)) + +#define _dfu_HashType_MIN dfu_HashType_NO_HASH +#define _dfu_HashType_MAX dfu_HashType_SHA512 +#define _dfu_HashType_ARRAYSIZE ((dfu_HashType)(dfu_HashType_SHA512+1)) + +#define _dfu_OpCode_MIN dfu_OpCode_INIT +#define _dfu_OpCode_MAX dfu_OpCode_INIT +#define _dfu_OpCode_ARRAYSIZE ((dfu_OpCode)(dfu_OpCode_INIT+1)) + +#define _dfu_ValidationType_MIN dfu_ValidationType_NO_VALIDATION +#define _dfu_ValidationType_MAX dfu_ValidationType_VALIDATE_ECDSA_P256_SHA256 +#define _dfu_ValidationType_ARRAYSIZE ((dfu_ValidationType)(dfu_ValidationType_VALIDATE_ECDSA_P256_SHA256+1)) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define dfu_Hash_init_default {_dfu_HashType_MIN, {0, {0}}} +#define dfu_BootValidation_init_default {0, {0, {0}}} +#define dfu_InitCommand_init_default {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, _dfu_FwType_MIN, false, 0, false, 0, false, 0, false, dfu_Hash_init_default, false, false, 0, {dfu_BootValidation_init_default, dfu_BootValidation_init_default, dfu_BootValidation_init_default}} +#define dfu_Command_init_default {false, _dfu_OpCode_MIN, false, dfu_InitCommand_init_default} +#define dfu_SignedCommand_init_default {dfu_Command_init_default, 0, {0, {0}}} +#define dfu_Packet_init_default {false, dfu_Command_init_default, false, dfu_SignedCommand_init_default} +#define dfu_Hash_init_zero {_dfu_HashType_MIN, {0, {0}}} +#define dfu_BootValidation_init_zero {0, {0, {0}}} +#define dfu_InitCommand_init_zero {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, _dfu_FwType_MIN, false, 0, false, 0, false, 0, false, dfu_Hash_init_zero, false, 0, 0, {dfu_BootValidation_init_zero, dfu_BootValidation_init_zero, dfu_BootValidation_init_zero}} +#define dfu_Command_init_zero {false, _dfu_OpCode_MIN, false, dfu_InitCommand_init_zero} +#define dfu_SignedCommand_init_zero {dfu_Command_init_zero, 0, {0, {0}}} +#define dfu_Packet_init_zero {false, dfu_Command_init_zero, false, dfu_SignedCommand_init_zero} + +/* Field tags (for use in manual encoding/decoding) */ +#define dfu_BootValidation_sigmask_tag 1 +#define dfu_BootValidation_bytes_tag 2 +#define dfu_Hash_hash_type_tag 1 +#define dfu_Hash_hash_tag 2 +#define dfu_InitCommand_fw_version_tag 1 +#define dfu_InitCommand_hw_version_tag 2 +#define dfu_InitCommand_sd_req_tag 3 +#define dfu_InitCommand_type_tag 4 +#define dfu_InitCommand_sd_size_tag 5 +#define dfu_InitCommand_bl_size_tag 6 +#define dfu_InitCommand_app_size_tag 7 +#define dfu_InitCommand_hash_tag 8 +#define dfu_InitCommand_is_debug_tag 9 +#define dfu_InitCommand_boot_validation_tag 10 +#define dfu_Command_op_code_tag 1 +#define dfu_Command_init_tag 2 +#define dfu_SignedCommand_command_tag 1 +#define dfu_SignedCommand_sigmask_tag 2 +#define dfu_SignedCommand_signature_tag 3 +#define dfu_Packet_command_tag 1 +#define dfu_Packet_signed_command_tag 2 + +/* Struct field encoding specification for nanopb */ +#define dfu_Hash_FIELDLIST(X, a) \ +X(a, STATIC, REQUIRED, UENUM, hash_type, 1) \ +X(a, STATIC, REQUIRED, BYTES, hash, 2) +#define dfu_Hash_CALLBACK NULL +#define dfu_Hash_DEFAULT NULL + +#define dfu_BootValidation_FIELDLIST(X, a) \ +X(a, STATIC, REQUIRED, UINT32, sigmask, 1) \ +X(a, STATIC, REQUIRED, BYTES, bytes, 2) +#define dfu_BootValidation_CALLBACK NULL +#define dfu_BootValidation_DEFAULT NULL + +#define dfu_InitCommand_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, UINT32, fw_version, 1) \ +X(a, STATIC, OPTIONAL, UINT32, hw_version, 2) \ +X(a, STATIC, REPEATED, UINT32, sd_req, 3) \ +X(a, STATIC, OPTIONAL, UENUM, type, 4) \ +X(a, STATIC, OPTIONAL, UINT32, sd_size, 5) \ +X(a, STATIC, OPTIONAL, UINT32, bl_size, 6) \ +X(a, STATIC, OPTIONAL, UINT32, app_size, 7) \ +X(a, STATIC, OPTIONAL, MESSAGE, hash, 8) \ +X(a, STATIC, OPTIONAL, BOOL, is_debug, 9) \ +X(a, STATIC, REPEATED, MESSAGE, boot_validation, 10) +#define dfu_InitCommand_CALLBACK NULL +#define dfu_InitCommand_DEFAULT (const pb_byte_t*)"\x48\x00\x00" +#define dfu_InitCommand_hash_MSGTYPE dfu_Hash +#define dfu_InitCommand_boot_validation_MSGTYPE dfu_BootValidation + +#define dfu_Command_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, UENUM, op_code, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, init, 2) +#define dfu_Command_CALLBACK NULL +#define dfu_Command_DEFAULT (const pb_byte_t*)"\x08\x01\x00" +#define dfu_Command_init_MSGTYPE dfu_InitCommand + +#define dfu_SignedCommand_FIELDLIST(X, a) \ +X(a, STATIC, REQUIRED, MESSAGE, command, 1) \ +X(a, STATIC, REQUIRED, UINT32, sigmask, 2) \ +X(a, STATIC, REQUIRED, BYTES, signature, 3) +#define dfu_SignedCommand_CALLBACK NULL +#define dfu_SignedCommand_DEFAULT NULL +#define dfu_SignedCommand_command_MSGTYPE dfu_Command + +#define dfu_Packet_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, command, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, signed_command, 2) +#define dfu_Packet_CALLBACK NULL +#define dfu_Packet_DEFAULT NULL +#define dfu_Packet_command_MSGTYPE dfu_Command +#define dfu_Packet_signed_command_MSGTYPE dfu_SignedCommand + +extern const pb_msgdesc_t dfu_Hash_msg; +extern const pb_msgdesc_t dfu_BootValidation_msg; +extern const pb_msgdesc_t dfu_InitCommand_msg; +extern const pb_msgdesc_t dfu_Command_msg; +extern const pb_msgdesc_t dfu_SignedCommand_msg; +extern const pb_msgdesc_t dfu_Packet_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define dfu_Hash_fields &dfu_Hash_msg +#define dfu_BootValidation_fields &dfu_BootValidation_msg +#define dfu_InitCommand_fields &dfu_InitCommand_msg +#define dfu_Command_fields &dfu_Command_msg +#define dfu_SignedCommand_fields &dfu_SignedCommand_msg +#define dfu_Packet_fields &dfu_Packet_msg + +/* Maximum encoded size of messages (where known) */ +#define dfu_BootValidation_size 72 +#define dfu_Command_size 395 +#define dfu_Hash_size 36 +#define dfu_InitCommand_size 390 +#define dfu_Packet_size 871 +#define dfu_SignedCommand_size 470 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/core/embed/ble_bootloader/dfu/dfu-cc.proto b/core/embed/ble_bootloader/dfu/dfu-cc.proto new file mode 100644 index 0000000000..db864c10ac --- /dev/null +++ b/core/embed/ble_bootloader/dfu/dfu-cc.proto @@ -0,0 +1,76 @@ +package dfu; + +// Version 0.1 + +enum FwType { + APPLICATION = 0; + SOFTDEVICE = 1; + BOOTLOADER = 2; + SOFTDEVICE_BOOTLOADER = 3; + EXTERNAL_APPLICATION = 4; +} + +enum HashType { + NO_HASH = 0; + CRC = 1; + SHA128 = 2; + SHA256 = 3; + SHA512 = 4; +} + +enum OpCode { + INIT = 1; +} + +enum ValidationType { + NO_VALIDATION = 0; + VALIDATE_GENERATED_CRC = 1; + VALIDATE_SHA256 = 2; + VALIDATE_ECDSA_P256_SHA256 = 3; +} + +message Hash { + required HashType hash_type = 1; + required bytes hash = 2; +} + +message BootValidation { + + required uint32 sigmask = 1; + required bytes bytes = 2; +} + +// Commands data +message InitCommand { + optional uint32 fw_version = 1; + optional uint32 hw_version = 2; + repeated uint32 sd_req = 3 [packed = true]; + optional FwType type = 4; + + optional uint32 sd_size = 5; + optional uint32 bl_size = 6; + optional uint32 app_size = 7; + + optional Hash hash = 8; + + optional bool is_debug = 9 [default = false]; + repeated BootValidation boot_validation = 10; +} + +// Command type +message Command { + optional OpCode op_code = 1; + optional InitCommand init = 2; +} + +message SignedCommand { + required Command command = 1; + required uint32 sigmask = 2; + required bytes signature = 3; +} + +// Parent packet type +message Packet { + optional Command command = 1; + optional SignedCommand signed_command = 2; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu.c b/core/embed/ble_bootloader/dfu/nrf_dfu.c new file mode 100644 index 0000000000..c03ad0b9fd --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu.c @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu.h" + +#include "nrf_dfu_utils.h" +#include "nrf_dfu_transport.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_log.h" + +static nrf_dfu_observer_t m_user_observer; // +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NRF_DFU_SCHED_EVENT_DATA_SIZE (sizeof(nrf_dfu_request_t)) + + +/** @brief Function for initializing a DFU operation. + * + * This function initializes a DFU operation and any transports that are registered + * in the system. + * + * @param[in] observer Callback function for receiving DFU notifications. + * + * @retval NRF_SUCCESS If the DFU operation was successfully initialized. + */ +uint32_t nrf_dfu_init(nrf_dfu_observer_t observer); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_flash.c b/core/embed/ble_bootloader/dfu/nrf_dfu_flash.c new file mode 100644 index 0000000000..562249485f --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_flash.c @@ -0,0 +1,167 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_flash.h" +#include "nrf_dfu_types.h" + +#include "nrf_fstorage.h" +#include "nrf_fstorage_sd.h" +#include "nrf_fstorage_nvmc.h" + + +#define NRF_LOG_MODULE_NAME nrf_dfu_flash +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +void dfu_fstorage_evt_handler(nrf_fstorage_evt_t * p_evt); + + +NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) = +{ + .evt_handler = dfu_fstorage_evt_handler, + .start_addr = MBR_SIZE, + .end_addr = BOOTLOADER_SETTINGS_ADDRESS + BOOTLOADER_SETTINGS_PAGE_SIZE +}; + +static uint32_t m_flash_operations_pending; + +void dfu_fstorage_evt_handler(nrf_fstorage_evt_t * p_evt) +{ + if (NRF_LOG_ENABLED && (m_flash_operations_pending > 0)) + { + m_flash_operations_pending--; + } + + if (p_evt->result == NRF_SUCCESS) + { + NRF_LOG_DEBUG("Flash %s success: addr=%p, pending %d", + (p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) ? "write" : "erase", + p_evt->addr, m_flash_operations_pending); + } + else + { + NRF_LOG_DEBUG("Flash %s failed (0x%x): addr=%p, len=0x%x bytes, pending %d", + (p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) ? "write" : "erase", + p_evt->result, p_evt->addr, p_evt->len, m_flash_operations_pending); + } + + if (p_evt->p_param) + { + //lint -save -e611 (Suspicious cast) + ((nrf_dfu_flash_callback_t)(p_evt->p_param))((void*)p_evt->p_src); + //lint -restore + } +} + + +ret_code_t nrf_dfu_flash_init(bool sd_irq_initialized) +{ + nrf_fstorage_api_t * p_api_impl; + + /* Setup the desired API implementation. */ +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + if (sd_irq_initialized) + { + NRF_LOG_DEBUG("Initializing nrf_fstorage_sd backend."); + p_api_impl = &nrf_fstorage_sd; + } + else +#endif + { + NRF_LOG_DEBUG("Initializing nrf_fstorage_nvmc backend."); + p_api_impl = &nrf_fstorage_nvmc; + } + + return nrf_fstorage_init(&m_fs, p_api_impl, NULL); +} + + +ret_code_t nrf_dfu_flash_store(uint32_t dest, + void const * p_src, + uint32_t len, + nrf_dfu_flash_callback_t callback) +{ + ret_code_t rc; + + NRF_LOG_DEBUG("nrf_fstorage_write(addr=%p, src=%p, len=%d bytes), queue usage: %d", + dest, p_src, len, m_flash_operations_pending); + + //lint -save -e611 (Suspicious cast) + rc = nrf_fstorage_write(&m_fs, dest, p_src, len, (void *)callback); + //lint -restore + + if ((NRF_LOG_ENABLED) && (rc == NRF_SUCCESS)) + { + m_flash_operations_pending++; + } + else + { + NRF_LOG_WARNING("nrf_fstorage_write() failed with error 0x%x.", rc); + } + + return rc; +} + + +ret_code_t nrf_dfu_flash_erase(uint32_t page_addr, + uint32_t num_pages, + nrf_dfu_flash_callback_t callback) +{ + ret_code_t rc; + + NRF_LOG_DEBUG("nrf_fstorage_erase(addr=0x%p, len=%d pages), queue usage: %d", + page_addr, num_pages, m_flash_operations_pending); + + //lint -save -e611 (Suspicious cast) + rc = nrf_fstorage_erase(&m_fs, page_addr, num_pages, (void *)callback); + //lint -restore + + if ((NRF_LOG_ENABLED) && (rc == NRF_SUCCESS)) + { + m_flash_operations_pending++; + } + else + { + NRF_LOG_WARNING("nrf_fstorage_erase() failed with error 0x%x.", rc); + } + + return rc; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_flash.h b/core/embed/ble_bootloader/dfu/nrf_dfu_flash.h new file mode 100644 index 0000000000..79d7dec1ee --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_flash.h @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_flash Flash operations + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_FLASH_H__ +#define NRF_DFU_FLASH_H__ + +#include +#include +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief nrf_fstorage event handler function for DFU fstorage operations. + * + * This function will be called after a flash operation has completed. + */ +typedef void (*nrf_dfu_flash_callback_t)(void * p_buf); + + +/**@brief Function for initializing the flash module. + * + * Depending on whether or not the SoftDevice is present and its IRQ have been initialized, + * this function initializes the correct @ref nrf_fstorage backend. + * + * @param[in] sd_irq_initialized Whether or not the SoftDevice IRQ have been initialized. + * + * @retval NRF_SUCCESS If the operation was successful. + */ +ret_code_t nrf_dfu_flash_init(bool sd_irq_initialized); + + +/**@brief Function for storing data to flash. + * + * This functions is asynchronous when the SoftDevice is enabled and synchronous when + * the SoftDevice is not present or disabled. In both cases, if a callback function is provided, + * it will be called when the operation has completed. + * + * @note The content of @p p_src should be kept in memory until the operation has completed. + * + * @param[in] dest The address where the data should be stored. + * @param[in] p_src Pointer to the address where the data should be copied from. + * This address can be in flash or RAM. + * @param[in] len The number of bytes to be copied from @p p_src to @p dest. + * @param[in] callback Callback function. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_STATE If nrf_dfu_flash is not initialized. + * @retval NRF_ERROR_INVALID_ADDR If @p p_src or @p dest is not word-aligned. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero. + * @retval NRF_ERROR_NULL If @p p_src is NULL. + * @retval NRF_ERROR_NO_MEM If nrf_fstorage is out of memory. + */ +ret_code_t nrf_dfu_flash_store(uint32_t dest, + void const * p_src, + uint32_t len, + nrf_dfu_flash_callback_t callback); + + +/**@brief Function for erasing data from flash. + * + * This functions is asynchronous when the SoftDevice is enabled and synchronous when + * the SoftDevice is not present or disabled. In both cases, if a callback function is provided, + * it will be called when the operation has completed. + * + * @param[in] page_addr The address of the first flash page to be deleted. + * @param[in] num_pages The number of flash pages to be deleted. + * @param[in] callback Callback function. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_STATE If nrf_dfu_flash is not initialized. + * @retval NRF_ERROR_INVALID_ADDR If @p page_addr is not aligned to a page boundary or the + * operation would go beyond the flash memory boundaries. + * @retval NRF_ERROR_INVALID_LENGTH If @p num_pages is zero. + * @retval NRF_ERROR_NULL If @p page_addr is NULL. + * @retval NRF_ERROR_NO_MEM If the queue of nrf_fstorage is full. + */ +ret_code_t nrf_dfu_flash_erase(uint32_t page_addr, uint32_t num_pages, nrf_dfu_flash_callback_t callback); + + +#ifdef __cplusplus +} +#endif + + +#endif // NRF_DFU_FLASH_H__ +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.c b/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.c new file mode 100644 index 0000000000..3103f591cb --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.c @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_handling_error.h" + +#include "nrf_log.h" +#include "nrf_dfu_req_handler.h" + +static nrf_dfu_ext_error_code_t m_last_error = NRF_DFU_EXT_ERROR_NO_ERROR; + +nrf_dfu_result_t ext_error_set(nrf_dfu_ext_error_code_t error_code) +{ + m_last_error = error_code; + + return NRF_DFU_RES_CODE_EXT_ERROR; +} + +nrf_dfu_ext_error_code_t ext_error_get() +{ + nrf_dfu_ext_error_code_t last_error = m_last_error; + m_last_error = NRF_DFU_EXT_ERROR_NO_ERROR; + + return last_error; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.h b/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.h new file mode 100644 index 0000000000..5249d39614 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.h @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + /**@file + * + * @defgroup nrf_dfu_rescodes DFU result codes + * @{ + * @ingroup sdk_nrf_dfu_transport + * @brief When the DFU controller sends requests to the DFU bootloader on + * the DFU target, the DFU bootloader answers with any of these result codes. + */ + + +#ifndef DFU_HANDLING_ERROR_H__ +#define DFU_HANDLING_ERROR_H__ + +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/**@brief DFU request extended result codes. + * + * @details When an event returns @ref NRF_DFU_RES_CODE_EXT_ERROR, it also stores an extended error code. + * The transport layer can then send the extended error code together with the error code to give + * the controller additional information about the cause of the error. + */ +typedef enum +{ + NRF_DFU_EXT_ERROR_NO_ERROR = 0x00, /**< No extended error code has been set. This error indicates an implementation problem. */ + NRF_DFU_EXT_ERROR_INVALID_ERROR_CODE = 0x01, /**< Invalid error code. This error code should never be used outside of development. */ + NRF_DFU_EXT_ERROR_WRONG_COMMAND_FORMAT = 0x02, /**< The format of the command was incorrect. This error code is not used in the + current implementation, because @ref NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED + and @ref NRF_DFU_RES_CODE_INVALID_PARAMETER cover all + possible format errors. */ + NRF_DFU_EXT_ERROR_UNKNOWN_COMMAND = 0x03, /**< The command was successfully parsed, but it is not supported or unknown. */ + NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID = 0x04, /**< The init command is invalid. The init packet either has + an invalid update type or it is missing required fields for the update type + (for example, the init packet for a SoftDevice update is missing the SoftDevice size field). */ + NRF_DFU_EXT_ERROR_FW_VERSION_FAILURE = 0x05, /**< The firmware version is too low. For an application or SoftDevice, the version must be greater than + or equal to the current version. For a bootloader, it must be greater than the current version. + to the current version. This requirement prevents downgrade attacks.*/ + NRF_DFU_EXT_ERROR_HW_VERSION_FAILURE = 0x06, /**< The hardware version of the device does not match the required + hardware version for the update. */ + NRF_DFU_EXT_ERROR_SD_VERSION_FAILURE = 0x07, /**< The array of supported SoftDevices for the update does not contain + the FWID of the current SoftDevice or the first FWID is '0' on a + bootloader which requires the SoftDevice to be present. */ + NRF_DFU_EXT_ERROR_SIGNATURE_MISSING = 0x08, /**< The init packet does not contain a signature. This error code is not used in the + current implementation, because init packets without a signature + are regarded as invalid. */ + NRF_DFU_EXT_ERROR_WRONG_HASH_TYPE = 0x09, /**< The hash type that is specified by the init packet is not supported by the DFU bootloader. */ + NRF_DFU_EXT_ERROR_HASH_FAILED = 0x0A, /**< The hash of the firmware image cannot be calculated. */ + NRF_DFU_EXT_ERROR_WRONG_SIGNATURE_TYPE = 0x0B, /**< The type of the signature is unknown or not supported by the DFU bootloader. */ + NRF_DFU_EXT_ERROR_VERIFICATION_FAILED = 0x0C, /**< The hash of the received firmware image does not match the hash in the init packet. */ + NRF_DFU_EXT_ERROR_INSUFFICIENT_SPACE = 0x0D, /**< The available space on the device is insufficient to hold the firmware. */ +} nrf_dfu_ext_error_code_t; + + +/**@brief Function for setting an extended error code that can be retrieved later. + * + * @details When an extended error occurs in the DFU process, this function can be used to store the error. + * + * @param error_code The error code to store. + * + * @retval NRF_DFU_RES_CODE_EXT_ERROR + */ +nrf_dfu_result_t ext_error_set(nrf_dfu_ext_error_code_t error_code); + +/**@brief Function for getting the most recent extended error code. + * + * @details This function is used by the transport layer to fetch the most recent extended error code. + * + * @return The most recent error code. If the function is called again before a new error occurs, @ref NRF_DFU_EXT_ERROR_NO_ERROR is returned. + */ +nrf_dfu_ext_error_code_t ext_error_get( void ); + + +#ifdef __cplusplus +} +#endif + +#endif // DFU_HANDLING_ERROR_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c b/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c new file mode 100644 index 0000000000..3644ca3e0d --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_mbr.h" +#include "nrf_mbr.h" +#include "nrf_dfu_types.h" +#include "nrf_log.h" +#include "nrf_bootloader_info.h" + +#define MBR_IRQ_FORWARD_ADDRESS_ADDRESS (0x20000000) //!< The address of the variable that decides where the MBR forwards interrupts + +uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len) +{ + uint32_t ret_val; + uint32_t const len_words = len / sizeof(uint32_t); + + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_COPY_BL, + .params.copy_bl.bl_src = p_src, + .params.copy_bl.bl_len = len_words + }; + + ret_val = sd_mbr_command(&command); + + return ret_val; +} + + +uint32_t nrf_dfu_mbr_init_sd(void) +{ + uint32_t ret_val; + + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_INIT_SD + }; + + ret_val = sd_mbr_command(&command); + + return ret_val; +} + + +uint32_t nrf_dfu_mbr_irq_forward_address_set(void) +{ + uint32_t ret_val = NRF_ERROR_INVALID_PARAM; + uint32_t address = MBR_SIZE; + +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, + .params.irq_forward_address_set.address = address, + }; + + ret_val = sd_mbr_command(&command); +#endif + + if (ret_val == NRF_ERROR_INVALID_PARAM) + { + // Manually set the forward address if this MBR doesn't have the command. + *(uint32_t *)(MBR_IRQ_FORWARD_ADDRESS_ADDRESS) = address; + + ret_val = NRF_SUCCESS; + } + + return ret_val; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h b/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h new file mode 100644 index 0000000000..ac72088951 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_mbr MBR functions + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_MBR_H__ +#define NRF_DFU_MBR_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Function for copying the bootloader using an MBR command. + * + * @param[in] p_src Source address of the bootloader data to copy. + * @param[in] len Length of the data to copy in bytes. + * + * @return This function will return only if the command request could not be run. + * See @ref sd_mbr_command_copy_bl_t for possible return values. + */ +uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len); + + +/** @brief Function for initializing the SoftDevice using an MBR command. + * + * @retval NRF_SUCCESS If the SoftDevice was initialized successfully. + * Any other return value indicates that the SoftDevice + * could not be initialized. + */ +uint32_t nrf_dfu_mbr_init_sd(void); + + +/** @brief Function for setting the address of the IRQ table to the app's using an MBR command. + * + * @retval NRF_SUCCESS If the address of the new irq table was set. Any other + * return value indicates that the address could not be set. + */ +uint32_t nrf_dfu_mbr_irq_forward_address_set(void); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_MBR_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.c b/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.c new file mode 100644 index 0000000000..1124369b64 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.c @@ -0,0 +1,864 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include "sdk_config.h" +#include "nrf_dfu.h" +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_dfu_handling_error.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_flash.h" +#include "nrf_fstorage.h" +#include "nrf_bootloader_info.h" +#include "app_util.h" +#include "pb.h" +#include "pb_common.h" +#include "pb_decode.h" +#include "dfu-cc.pb.h" +#include "crc32.h" +#include "app_scheduler.h" +#include "sdk_macros.h" +#include "nrf_assert.h" +#include "nrf_dfu_validation.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_req_handler +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define NRF_DFU_PROTOCOL_VERSION (0x01) + +#ifndef NRF_DFU_PROTOCOL_REDUCED +#define NRF_DFU_PROTOCOL_REDUCED 0 +#endif + +STATIC_ASSERT(dfu_SignedCommand_size <= INIT_COMMAND_MAX_SIZE); + +static uint32_t m_firmware_start_addr; /**< Start address of the current firmware image. */ +static uint32_t m_firmware_size_req; /**< The size of the entire firmware image. Defined by the init command. */ + +static nrf_dfu_observer_t m_observer; + + +static void on_dfu_complete(nrf_fstorage_evt_t * p_evt) +{ + UNUSED_PARAMETER(p_evt); + + NRF_LOG_DEBUG("All flash operations have completed. DFU completed."); + + m_observer(NRF_DFU_EVT_DFU_COMPLETED); +} + + +static nrf_dfu_result_t ext_err_code_handle(nrf_dfu_result_t ret_val) +{ + if (ret_val < NRF_DFU_RES_CODE_EXT_ERROR) + { + return ret_val; + } + else + { + nrf_dfu_ext_error_code_t ext_err = + (nrf_dfu_ext_error_code_t)((uint8_t)ret_val - (uint8_t)NRF_DFU_RES_CODE_EXT_ERROR); + return ext_error_set(ext_err); + } +} + + +#if !NRF_DFU_PROTOCOL_REDUCED +static void on_protocol_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_PROTOCOL_VERSION"); + + if (NRF_DFU_PROTOCOL_VERSION_MSG) + { + p_res->protocol.version = NRF_DFU_PROTOCOL_VERSION; + } + else + { + NRF_LOG_DEBUG("NRF_DFU_OP_PROTOCOL_VERSION disabled."); + p_res->result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED; + } +} + + +static void on_hw_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_HARDWARE_VERSION"); + + p_res->hardware.part = NRF_FICR->INFO.PART; + p_res->hardware.variant = NRF_FICR->INFO.VARIANT; + + /* FICR values are in Kilobytes, we report them in bytes. */ + p_res->hardware.memory.ram_size = NRF_FICR->INFO.RAM * 1024; + p_res->hardware.memory.rom_size = NRF_FICR->INFO.FLASH * 1024; + p_res->hardware.memory.rom_page_size = NRF_FICR->CODEPAGESIZE; +} + + +static void on_fw_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_FIRMWARE_VERSION"); + NRF_LOG_DEBUG("Firmware image requested: %d", p_req->firmware.image_number); + + if (NRF_DFU_PROTOCOL_FW_VERSION_MSG) + { + uint8_t fw_count = 1; + + if (SD_PRESENT) + { + fw_count++; + } + + if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP) + { + fw_count++; + } + + p_res->result = NRF_DFU_RES_CODE_SUCCESS; + + if (p_req->firmware.image_number == 0) + { + /* Bootloader is always present and it is always image zero. */ + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_BOOTLOADER; + p_res->firmware.version = s_dfu_settings.bootloader_version; + p_res->firmware.addr = BOOTLOADER_START_ADDR; + p_res->firmware.len = BOOTLOADER_SIZE; + } + else if ((p_req->firmware.image_number == 1) && SD_PRESENT) + { + /* If a SoftDevice is present, it will be firmware image one. */ + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_SOFTDEVICE; + p_res->firmware.version = SD_VERSION_GET(MBR_SIZE); + p_res->firmware.addr = MBR_SIZE; + p_res->firmware.len = SD_SIZE_GET(MBR_SIZE); + } + else if ((p_req->firmware.image_number < fw_count)) + { + /* Either there is no SoftDevice and the firmware image requested is one, + * or there is a SoftDevice and the firmware image requested is two. + */ + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_APPLICATION; + p_res->firmware.version = s_dfu_settings.app_version; + p_res->firmware.addr = nrf_dfu_app_start_address(); + p_res->firmware.len = s_dfu_settings.bank_0.image_size; + } + else + { + NRF_LOG_DEBUG("No such firmware image"); + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_UNKNOWN; + p_res->firmware.version = 0x00; + p_res->firmware.addr = 0x00; + p_res->firmware.len = 0x00; + } + } + else + { + NRF_LOG_DEBUG("NRF_DFU_OP_FIRMWARE_VERSION disabled."); + p_res->result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED; + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_UNKNOWN; + } +} + + +static void on_ping_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_PING"); + p_res->ping.id = p_req->ping.id; +} + + +static void on_mtu_get_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_MTU_GET"); + p_res->mtu.size = p_req->mtu.size; +} +#endif // !NRF_DFU_PROTOCOL_REDUCED + + +static void on_prn_set_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + UNUSED_PARAMETER(p_res); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_RECEIPT_NOTIF_SET"); +} + + +static void on_abort_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + UNUSED_PARAMETER(p_res); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_ABORT"); + + m_observer(NRF_DFU_EVT_DFU_ABORTED); +} + + +/* Set offset and CRC fields in the response for a 'command' message. */ +static void cmd_response_offset_and_crc_set(nrf_dfu_response_t * const p_res) +{ + ASSERT(p_res); + + /* Copy the CRC and offset of the init packet. */ + p_res->crc.offset = s_dfu_settings.progress.command_offset; + p_res->crc.crc = s_dfu_settings.progress.command_crc; +} + + +static void on_cmd_obj_select_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_SELECT (command)"); + + p_res->select.max_size = INIT_COMMAND_MAX_SIZE; + cmd_response_offset_and_crc_set(p_res); +} + + +static void on_cmd_obj_create_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_CREATE (command)"); + + m_observer(NRF_DFU_EVT_DFU_STARTED); + + nrf_dfu_result_t ret_val = nrf_dfu_validation_init_cmd_create(p_req->create.object_size); + p_res->result = ext_err_code_handle(ret_val); +} + + +static void on_cmd_obj_write_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_req->write.p_data); + ASSERT(p_req->write.len); + ASSERT(p_res); + + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_WRITE (command)"); + + nrf_dfu_result_t ret_val; + + ret_val = nrf_dfu_validation_init_cmd_append(p_req->write.p_data, p_req->write.len); + p_res->result = ext_err_code_handle(ret_val); + + /* Update response. This is only used when the PRN is triggered and the 'write' message + * is answered with a CRC message and these field are copied into the response. */ + cmd_response_offset_and_crc_set(p_res); + + /* If a callback to free the request payload buffer was provided, invoke it now. */ + if (p_req->callback.write) + { + p_req->callback.write((void*)p_req->write.p_data); + } +} + + +static void on_cmd_obj_execute_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_EXECUTE (command)"); + + nrf_dfu_result_t ret_val; + ret_val = nrf_dfu_validation_init_cmd_execute(&m_firmware_start_addr, &m_firmware_size_req); + p_res->result = ext_err_code_handle(ret_val); + + if (p_res->result == NRF_DFU_RES_CODE_SUCCESS) + { + if (nrf_dfu_settings_write_and_backup(NULL) == NRF_SUCCESS) + { + /* Setting DFU to initialized */ + NRF_LOG_DEBUG("Writing valid init command to flash."); + } + else + { + p_res->result = NRF_DFU_RES_CODE_OPERATION_FAILED; + } + } +} + + +static void on_cmd_obj_crc_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_CRC_GET (command)"); + + cmd_response_offset_and_crc_set(p_res); +} + + +/** @brief Function handling command requests from the transport layer. + * + * @param p_req[in] Pointer to the structure holding the DFU request. + * @param p_res[out] Pointer to the structure holding the DFU response. + * + * @retval NRF_SUCCESS If the command request was executed successfully. + * Any other error code indicates that the data request + * could not be handled. + */ +static void nrf_dfu_command_req(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + switch (p_req->request) + { + case NRF_DFU_OP_OBJECT_CREATE: + { + on_cmd_obj_create_request(p_req, p_res); + } break; + + case NRF_DFU_OP_CRC_GET: + { + on_cmd_obj_crc_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + on_cmd_obj_write_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_EXECUTE: + { + on_cmd_obj_execute_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + on_cmd_obj_select_request(p_req, p_res); + } break; + + default: + { + ASSERT(false); + } break; + } +} + + +static void on_data_obj_select_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_SELECT (data)"); + + p_res->select.crc = s_dfu_settings.progress.firmware_image_crc; + p_res->select.offset = s_dfu_settings.progress.firmware_image_offset; + + p_res->select.max_size = DATA_OBJECT_MAX_SIZE; + + NRF_LOG_DEBUG("crc = 0x%x, offset = 0x%x, max_size = 0x%x", + p_res->select.crc, + p_res->select.offset, + p_res->select.max_size); +} + + +static void on_data_obj_create_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_CREATE (data)"); + + if (!nrf_dfu_validation_init_cmd_present()) + { + /* Can't accept data because DFU isn't initialized by init command. */ + NRF_LOG_ERROR("Cannot create data object without valid init command"); + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return; + } + + if (p_req->create.object_size == 0) + { + NRF_LOG_ERROR("Object size cannot be 0.") + p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER; + return; + } + + if ( ((p_req->create.object_size & (CODE_PAGE_SIZE - 1)) != 0) + && (s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size != m_firmware_size_req)) + { + NRF_LOG_ERROR("Object size must be page aligned"); + p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER; + return; + } + + if (p_req->create.object_size > DATA_OBJECT_MAX_SIZE) + { + /* It is impossible to handle the command because the size is too large */ + NRF_LOG_ERROR("Invalid size for object (too large)"); + p_res->result = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + return; + } + + if ((s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size) > + m_firmware_size_req) + { + NRF_LOG_ERROR("Creating the object with size 0x%08x would overflow firmware size. " + "Offset is 0x%08x and firmware size is 0x%08x.", + p_req->create.object_size, + s_dfu_settings.progress.firmware_image_offset_last, + m_firmware_size_req); + + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return; + } + + s_dfu_settings.progress.data_object_size = p_req->create.object_size; + s_dfu_settings.progress.firmware_image_crc = s_dfu_settings.progress.firmware_image_crc_last; + s_dfu_settings.progress.firmware_image_offset = s_dfu_settings.progress.firmware_image_offset_last; + s_dfu_settings.write_offset = s_dfu_settings.progress.firmware_image_offset_last; + + /* Erase the page we're at. */ + if (nrf_dfu_flash_erase((m_firmware_start_addr + s_dfu_settings.progress.firmware_image_offset), + CEIL_DIV(p_req->create.object_size, CODE_PAGE_SIZE), NULL) != NRF_SUCCESS) + { + NRF_LOG_ERROR("Erase operation failed"); + p_res->result = NRF_DFU_RES_CODE_INVALID_OBJECT; + return; + } + + NRF_LOG_DEBUG("Creating object with size: %d. Offset: 0x%08x, CRC: 0x%08x", + s_dfu_settings.progress.data_object_size, + s_dfu_settings.progress.firmware_image_offset, + s_dfu_settings.progress.firmware_image_crc); +} + + +static void on_data_obj_write_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_WRITE (data)"); + + if (!nrf_dfu_validation_init_cmd_present()) + { + /* Can't accept data because DFU isn't initialized by init command. */ + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return; + } + + uint32_t const data_object_offset = s_dfu_settings.progress.firmware_image_offset - + s_dfu_settings.progress.firmware_image_offset_last; + + if ((p_req->write.len + data_object_offset) > s_dfu_settings.progress.data_object_size) + { + /* Can't accept data because too much data has been received. */ + NRF_LOG_ERROR("Write request too long"); + p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER; + return; + } + + uint32_t const write_addr = m_firmware_start_addr + s_dfu_settings.write_offset; + /* CRC must be calculated before handing off the data to fstorage because the data is + * freed on write completion. + */ + uint32_t const next_crc = + crc32_compute(p_req->write.p_data, p_req->write.len, &s_dfu_settings.progress.firmware_image_crc); + + ASSERT(p_req->callback.write); + + ret_code_t ret = + nrf_dfu_flash_store(write_addr, p_req->write.p_data, p_req->write.len, p_req->callback.write); + + if (ret != NRF_SUCCESS) + { + /* When nrf_dfu_flash_store() fails because there is no space in the queue, + * stop processing the request so that the peer can detect a CRC error + * and retransmit this object. Remember to manually free the buffer ! + */ + p_req->callback.write((void*)p_req->write.p_data); + return; + } + + /* Update the CRC of the firmware image. */ + s_dfu_settings.write_offset += p_req->write.len; + s_dfu_settings.progress.firmware_image_offset += p_req->write.len; + s_dfu_settings.progress.firmware_image_crc = next_crc; + + /* This is only used when the PRN is triggered and the 'write' message + * is answered with a CRC message and these field are copied into the response. + */ + p_res->write.crc = s_dfu_settings.progress.firmware_image_crc; + p_res->write.offset = s_dfu_settings.progress.firmware_image_offset; +} + + +static void on_data_obj_crc_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_CRC_GET (data)"); + NRF_LOG_DEBUG("Offset:%d, CRC:0x%08x", + s_dfu_settings.progress.firmware_image_offset, + s_dfu_settings.progress.firmware_image_crc); + + p_res->crc.crc = s_dfu_settings.progress.firmware_image_crc; + p_res->crc.offset = s_dfu_settings.progress.firmware_image_offset; +} + + +static void on_data_obj_execute_request_sched(void * p_evt, uint16_t event_length) +{ + UNUSED_PARAMETER(event_length); + + ret_code_t ret; + nrf_dfu_request_t * p_req = (nrf_dfu_request_t *)(p_evt); + + /* Wait for all buffers to be written in flash. */ + if (nrf_fstorage_is_busy(NULL)) + { + ret = app_sched_event_put(p_req, sizeof(nrf_dfu_request_t), on_data_obj_execute_request_sched); + if (ret != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed to schedule object execute: 0x%x.", ret); + } + return; + } + + nrf_dfu_response_t res = + { + .request = NRF_DFU_OP_OBJECT_EXECUTE, + }; + + if (s_dfu_settings.progress.firmware_image_offset == m_firmware_size_req) + { + NRF_LOG_DEBUG("Whole firmware image received. Postvalidating."); + + #if NRF_DFU_IN_APP + res.result = nrf_dfu_validation_post_data_execute(m_firmware_start_addr, m_firmware_size_req); + #else + res.result = nrf_dfu_validation_activation_prepare(m_firmware_start_addr, m_firmware_size_req); + #endif + + res.result = ext_err_code_handle(res.result); + + /* Provide response to transport */ + p_req->callback.response(&res, p_req->p_context); + + ret = nrf_dfu_settings_write_and_backup((nrf_dfu_flash_callback_t)on_dfu_complete); + UNUSED_RETURN_VALUE(ret); + } + else + { + res.result = NRF_DFU_RES_CODE_SUCCESS; + + /* Provide response to transport */ + p_req->callback.response(&res, p_req->p_context); + + if (NRF_DFU_SAVE_PROGRESS_IN_FLASH) + { + /* Allowing skipping settings backup to save time and flash wear. */ + ret = nrf_dfu_settings_write_and_backup(NULL); + UNUSED_RETURN_VALUE(ret); + } + } + + NRF_LOG_DEBUG("Request handling complete. Result: 0x%x", res.result); +} + + +static bool on_data_obj_execute_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_EXECUTE (data)"); + + uint32_t const data_object_size = s_dfu_settings.progress.firmware_image_offset - + s_dfu_settings.progress.firmware_image_offset_last; + + if (s_dfu_settings.progress.data_object_size != data_object_size) + { + /* The size of the written object was not as expected. */ + NRF_LOG_ERROR("Invalid data. expected: %d, got: %d", + s_dfu_settings.progress.data_object_size, + data_object_size); + + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return true; + } + + /* Update the offset and crc values for the last object written. */ + s_dfu_settings.progress.data_object_size = 0; + s_dfu_settings.progress.firmware_image_crc_last = s_dfu_settings.progress.firmware_image_crc; + s_dfu_settings.progress.firmware_image_offset_last = s_dfu_settings.progress.firmware_image_offset; + + on_data_obj_execute_request_sched(p_req, 0); + + m_observer(NRF_DFU_EVT_OBJECT_RECEIVED); + + return false; +} + + +static bool nrf_dfu_data_req(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + bool response_ready = true; + + switch (p_req->request) + { + case NRF_DFU_OP_OBJECT_CREATE: + { + on_data_obj_create_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + on_data_obj_write_request(p_req, p_res); + } break; + + case NRF_DFU_OP_CRC_GET: + { + on_data_obj_crc_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_EXECUTE: + { + response_ready = on_data_obj_execute_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + on_data_obj_select_request(p_req, p_res); + } break; + + default: + { + ASSERT(false); + } break; + } + + return response_ready; +} + + +/**@brief Function for handling requests to manipulate data or command objects. + * + * @param[in] p_req Request. + * @param[out] p_res Response. + * + * @return Whether response is ready to be sent. + */ +static bool nrf_dfu_obj_op(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + /* Keep track of the current object type since write and execute requests don't contain it. */ + static nrf_dfu_obj_type_t current_object = NRF_DFU_OBJ_TYPE_COMMAND; + + if ( (p_req->request == NRF_DFU_OP_OBJECT_SELECT) + || (p_req->request == NRF_DFU_OP_OBJECT_CREATE)) + { + STATIC_ASSERT(offsetof(nrf_dfu_request_select_t, object_type) == + offsetof(nrf_dfu_request_create_t, object_type), + "Wrong object_type offset!"); + + current_object = (nrf_dfu_obj_type_t)(p_req->select.object_type); + } + + bool response_ready = true; + + switch (current_object) + { + case NRF_DFU_OBJ_TYPE_COMMAND: + nrf_dfu_command_req(p_req, p_res); + break; + + case NRF_DFU_OBJ_TYPE_DATA: + response_ready = nrf_dfu_data_req(p_req, p_res); + break; + + default: + /* The select request had an invalid object type. */ + NRF_LOG_ERROR("Invalid object type in request."); + current_object = NRF_DFU_OBJ_TYPE_INVALID; + p_res->result = NRF_DFU_RES_CODE_INVALID_OBJECT; + break; + } + + return response_ready; +} + + +static void nrf_dfu_req_handler_req_process(nrf_dfu_request_t * p_req) +{ + ASSERT(p_req->callback.response); + + bool response_ready = true; + + /* The request handlers assume these values to be set. */ + nrf_dfu_response_t response = + { + .request = p_req->request, + .result = NRF_DFU_RES_CODE_SUCCESS, + }; + + + switch (p_req->request) + { +#if !NRF_DFU_PROTOCOL_REDUCED + case NRF_DFU_OP_PROTOCOL_VERSION: + { + on_protocol_version_request(p_req, &response); + } break; + + case NRF_DFU_OP_HARDWARE_VERSION: + { + on_hw_version_request(p_req, &response); + } break; + + case NRF_DFU_OP_FIRMWARE_VERSION: + { + on_fw_version_request(p_req, &response); + } break; + + case NRF_DFU_OP_PING: + { + on_ping_request(p_req, &response); + } break; + + case NRF_DFU_OP_MTU_GET: + { + on_mtu_get_request(p_req, &response); + } break; +#endif + case NRF_DFU_OP_RECEIPT_NOTIF_SET: + { + on_prn_set_request(p_req, &response); + } break; + + case NRF_DFU_OP_ABORT: + { + on_abort_request(p_req, &response); + } break; + + case NRF_DFU_OP_OBJECT_CREATE: + /* Restart the inactivity timer on CREATE messages. */ + /* Fallthrough. */ + case NRF_DFU_OP_OBJECT_SELECT: + case NRF_DFU_OP_OBJECT_WRITE: + case NRF_DFU_OP_OBJECT_EXECUTE: + case NRF_DFU_OP_CRC_GET: + { + response_ready = nrf_dfu_obj_op(p_req, &response); + } break; + + default: + NRF_LOG_INFO("Invalid opcode received: 0x%x.", p_req->request); + response.result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED; + break; + } + + if (response_ready) + { + NRF_LOG_DEBUG("Request handling complete. Result: 0x%x", response.result); + + p_req->callback.response(&response, p_req->p_context); + + if (response.result != NRF_DFU_RES_CODE_SUCCESS) + { + m_observer(NRF_DFU_EVT_DFU_FAILED); + } + } +} + + +static void nrf_dfu_req_handler_req(void * p_evt, uint16_t event_length) +{ + nrf_dfu_request_t * p_req = (nrf_dfu_request_t *)(p_evt); + nrf_dfu_req_handler_req_process(p_req); +} + + +ret_code_t nrf_dfu_req_handler_on_req(nrf_dfu_request_t * p_req) +{ + ret_code_t ret; + + if (p_req->callback.response == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + ret = app_sched_event_put(p_req, sizeof(nrf_dfu_request_t), nrf_dfu_req_handler_req); + if (ret != NRF_SUCCESS) + { + NRF_LOG_WARNING("Scheduler ran out of space!"); + } + + return ret; +} + + +ret_code_t nrf_dfu_req_handler_init(nrf_dfu_observer_t observer) +{ + ret_code_t ret_val; + nrf_dfu_result_t result; + + if (observer == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + ret_val = nrf_dfu_flash_init(true); +#else + ret_val = nrf_dfu_flash_init(false); +#endif + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + nrf_dfu_validation_init(); + if (nrf_dfu_validation_init_cmd_present()) + { + /* Execute a previously received init packed. Subsequent executes will have no effect. */ + result = nrf_dfu_validation_init_cmd_execute(&m_firmware_start_addr, &m_firmware_size_req); + if (result != NRF_DFU_RES_CODE_SUCCESS) + { + /* Init packet in flash is not valid! */ + return NRF_ERROR_INTERNAL; + } + } + + m_observer = observer; + + /* Initialize extended error handling with "No error" as the most recent error. */ + result = ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR); + UNUSED_RETURN_VALUE(result); + + return NRF_SUCCESS; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.h b/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.h new file mode 100644 index 0000000000..e9eb5c4f4a --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.h @@ -0,0 +1,346 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_req_handler Request handling + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_REQ_HANDLER_H__ +#define NRF_DFU_REQ_HANDLER_H__ + +#include +#include +#include "app_util_platform.h" +#include "nrf_dfu_flash.h" +#include "nrf_dfu_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +ANON_UNIONS_ENABLE; + +/** + * @brief DFU object types. + */ +typedef enum +{ + NRF_DFU_OBJ_TYPE_INVALID, //!< Invalid object type. + NRF_DFU_OBJ_TYPE_COMMAND, //!< Command object. + NRF_DFU_OBJ_TYPE_DATA, //!< Data object. +} nrf_dfu_obj_type_t; + +/** + * @brief DFU protocol operation. + */ +typedef enum +{ + NRF_DFU_OP_PROTOCOL_VERSION = 0x00, //!< Retrieve protocol version. + NRF_DFU_OP_OBJECT_CREATE = 0x01, //!< Create selected object. + NRF_DFU_OP_RECEIPT_NOTIF_SET = 0x02, //!< Set receipt notification. + NRF_DFU_OP_CRC_GET = 0x03, //!< Request CRC of selected object. + NRF_DFU_OP_OBJECT_EXECUTE = 0x04, //!< Execute selected object. + NRF_DFU_OP_OBJECT_SELECT = 0x06, //!< Select object. + NRF_DFU_OP_MTU_GET = 0x07, //!< Retrieve MTU size. + NRF_DFU_OP_OBJECT_WRITE = 0x08, //!< Write selected object. + NRF_DFU_OP_PING = 0x09, //!< Ping. + NRF_DFU_OP_HARDWARE_VERSION = 0x0A, //!< Retrieve hardware version. + NRF_DFU_OP_FIRMWARE_VERSION = 0x0B, //!< Retrieve firmware version. + NRF_DFU_OP_ABORT = 0x0C, //!< Abort the DFU procedure. + NRF_DFU_OP_RESPONSE = 0x60, //!< Response. + NRF_DFU_OP_INVALID = 0xFF, +} nrf_dfu_op_t; + +/** + * @brief DFU operation result code. + */ +typedef enum +{ + NRF_DFU_RES_CODE_INVALID = 0x00, //!< Invalid opcode. + NRF_DFU_RES_CODE_SUCCESS = 0x01, //!< Operation successful. + NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED = 0x02, //!< Opcode not supported. + NRF_DFU_RES_CODE_INVALID_PARAMETER = 0x03, //!< Missing or invalid parameter value. + NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES = 0x04, //!< Not enough memory for the data object. + NRF_DFU_RES_CODE_INVALID_OBJECT = 0x05, //!< Data object does not match the firmware and hardware requirements, the signature is wrong, or parsing the command failed. + NRF_DFU_RES_CODE_UNSUPPORTED_TYPE = 0x07, //!< Not a valid object type for a Create request. + NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED = 0x08, //!< The state of the DFU process does not allow this operation. + NRF_DFU_RES_CODE_OPERATION_FAILED = 0x0A, //!< Operation failed. + NRF_DFU_RES_CODE_EXT_ERROR = 0x0B, //!< Extended error. The next byte of the response contains the error code of the extended error (see @ref nrf_dfu_ext_error_code_t. + NRF_DFU_ERROR_INVALID_SIGNATURE = 0x0C, //!< The provided signature is wrong. +} nrf_dfu_result_t; + +typedef enum +{ + NRF_DFU_FIRMWARE_TYPE_SOFTDEVICE = 0x00, + NRF_DFU_FIRMWARE_TYPE_APPLICATION = 0x01, + NRF_DFU_FIRMWARE_TYPE_BOOTLOADER = 0x02, + NRF_DFU_FIRMWARE_TYPE_UNKNOWN = 0xFF, +} nrf_dfu_firmware_type_t; + +/** + * @brief @ref NRF_DFU_OP_PROTOCOL_VERSION response details. + */ +typedef struct +{ + uint8_t version; //!< Protocol version. +} nrf_dfu_response_protocol_t; + +/** + * @brief @ref NRF_DFU_OP_HARDWARE_VERSION response details. + */ +typedef struct +{ + uint32_t part; //!< Hardware part, from FICR register. + uint32_t variant; //!< Hardware variant, from FICR register. + struct + { + uint32_t rom_size; //!< ROM size, in bytes. + uint32_t ram_size; //!< RAM size, in bytes. + uint32_t rom_page_size; //!< ROM flash page size, in bytes. + } memory; +} nrf_dfu_response_hardware_t; + +/** + * @brief @ref NRF_DFU_OP_FIRMWARE_VERSION response details. + */ +typedef struct +{ + nrf_dfu_firmware_type_t type; //!< Firmware type. + uint32_t version; //!< Firmware version. + uint32_t addr; //!< Firmware address in flash. + uint32_t len; //!< Firmware length in bytes. +} nrf_dfu_response_firmware_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_SELECT response details. + */ +typedef struct +{ + uint32_t offset; //!< Current offset. + uint32_t crc; //!< Current CRC. + uint32_t max_size; //!< Maximum size of selected object. +} nrf_dfu_response_select_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_CREATE response details. + */ +typedef struct +{ + uint32_t offset; //!< Current offset + uint32_t crc; //!< Current CRC. +} nrf_dfu_response_create_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_WRITE response details. + */ +typedef struct +{ + uint32_t offset; //!< Used only when packet receipt notification is used. + uint32_t crc; //!< Used only when packet receipt notification is used. +} nrf_dfu_response_write_t; + +/** + * @brief @ref NRF_DFU_OP_CRC_GET response details. + */ +typedef struct +{ + uint32_t offset; //!< Current offset. + uint32_t crc; //!< Current CRC. +} nrf_dfu_response_crc_t; + +/** + * @brief @ref NRF_DFU_OP_PING response details. + */ +typedef struct +{ + uint8_t id; //!< The received ID which is echoed back. +} nrf_dfu_response_ping_t; + +/** + * @brief @ref NRF_DFU_OP_MTU_GET response details. + */ +typedef struct +{ + uint16_t size; //!< The MTU size as specified by the local transport. +} nrf_dfu_response_mtu_t; + +/** + * @brief DFU response message. + */ +typedef struct +{ + nrf_dfu_op_t request; //!< Requested operation. + nrf_dfu_result_t result; //!< Result of the operation. + union + { + nrf_dfu_response_protocol_t protocol; //!< Protocol version response. + nrf_dfu_response_hardware_t hardware; //!< Hardware version response. + nrf_dfu_response_firmware_t firmware; //!< Firmware version response. + nrf_dfu_response_select_t select; //!< Select object response.. + nrf_dfu_response_create_t create; //!< Create object response.. + nrf_dfu_response_write_t write; //!< Write object response. + nrf_dfu_response_crc_t crc; //!< CRC response. + nrf_dfu_response_ping_t ping; //!< Ping response. + nrf_dfu_response_mtu_t mtu; //!< MTU response. + }; +} nrf_dfu_response_t; + +/** + * @brief @ref NRF_DFU_OP_FIRMWARE_VERSION request details. + */ +typedef struct +{ + uint8_t image_number; //!< Index of the firmware. +} nrf_dfu_request_firmware_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_SELECT request details. + */ +typedef struct +{ + uint32_t object_type; //!< Object type. See @ref nrf_dfu_obj_type_t. +} nrf_dfu_request_select_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_CREATE request details. + */ +typedef struct +{ + uint32_t object_type; //!< Object type. See @ref nrf_dfu_obj_type_t. + uint32_t object_size; //!< Object size in bytes. +} nrf_dfu_request_create_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_WRITE request details. + */ +typedef struct +{ + uint8_t const * p_data; //!< Data. + uint16_t len; //!< Length of data in @ref nrf_dfu_request_write_t::p_data. +} nrf_dfu_request_write_t; + +/** + * @brief @ref NRF_DFU_OP_PING request details. + */ +typedef struct +{ + uint8_t id; //!< Ping ID that will be returned in response. +} nrf_dfu_request_ping_t; + +/** + * @brief @ref NRF_DFU_OP_MTU_GET request details. + */ +typedef struct +{ + uint16_t size; //!< Transport MTU size in bytes. +} nrf_dfu_request_mtu_t; + +/** + * @brief @ref NRF_DFU_OP_RECEIPT_NOTIF_SET request details. + */ +typedef struct +{ + uint32_t target; //!< Target PRN. +} nrf_dfu_request_prn_t; + + +typedef void (*nrf_dfu_response_callback_t)(nrf_dfu_response_t * p_res, void * p_context); + +/** + *@brief DFU request. + */ +typedef struct +{ + nrf_dfu_op_t request; //!< Requested operation. + void * p_context; + struct + { + nrf_dfu_response_callback_t response; //!< Callback to call to send the response. + nrf_dfu_flash_callback_t write; + } callback; + union + { + nrf_dfu_request_firmware_t firmware; //!< Firmware version request. + nrf_dfu_request_select_t select; //!< Select object request. + nrf_dfu_request_create_t create; //!< Create object request. + nrf_dfu_request_write_t write; //!< Write object request. + nrf_dfu_request_ping_t ping; //!< Ping. + nrf_dfu_request_mtu_t mtu; //!< MTU size request. + nrf_dfu_request_prn_t prn; //!< Set receipt notification request. + }; +} nrf_dfu_request_t; + + +/**@brief Function for initializing the request handling module. + * + * @param observer Callback function for receiving notifications. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INTERNAL If the init packet in flash is not valid. + * @retval NRF_ERROR_INVALID_PARAM If observer is not provided. + */ +ret_code_t nrf_dfu_req_handler_init(nrf_dfu_observer_t observer); + + +/**@brief Function for scheduling processing of a DFU request. + * + * Requests are processed asynchronously by the scheduler. + * + * @param[in] p_req Request to be handled. The response callback must be non-null. + * + * @retval NRF_SUCCESS If the command request was executed successfully. + * @retval NRF_ERROR_NO_MEM If the scheduler ran out of memory. + * @retval NRF_ERROR_INVALID_PARAM If the response callback is NULL. + */ +ret_code_t nrf_dfu_req_handler_on_req(nrf_dfu_request_t * p_req); + + +ANON_UNIONS_DISABLE; + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_REQ_HANDLER_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_settings.c b/core/embed/ble_bootloader/dfu/nrf_dfu_settings.c new file mode 100644 index 0000000000..07146a8e2d --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_settings.c @@ -0,0 +1,423 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_settings.h" +#include +#include +#include "nrf_dfu_flash.h" +#include "nrf_soc.h" +#include "crc32.h" +#include "nrf_nvmc.h" +#include "sdk_config.h" + + +#define DFU_SETTINGS_VERSION_OFFSET (offsetof(nrf_dfu_settings_t, settings_version)) //crc != 0xFFFFFFFF) + { + // CRC is set. Content must be valid + uint32_t crc = settings_crc_get(p_settings); + if (crc == p_settings->crc) + { + return true; + } + } + return false; +} + + +static uint32_t boot_validation_crc(nrf_dfu_settings_t const * p_settings) +{ + return crc32_compute((const uint8_t *)&p_settings->boot_validation_softdevice, + DFU_SETTINGS_BOOT_VALIDATION_SIZE - 4, + NULL); +} + + +static bool boot_validation_crc_ok(nrf_dfu_settings_t const * p_settings) +{ + return (boot_validation_crc(p_settings) == p_settings->boot_validation_crc); +} + + +static bool settings_crc_ok(void) +{ + nrf_dfu_settings_t const * p_settings = (nrf_dfu_settings_t const *)m_dfu_settings_buffer; + return crc_ok(p_settings); +} + + +static bool settings_backup_crc_ok(void) +{ + nrf_dfu_settings_t const * p_settings = (nrf_dfu_settings_t const *)mp_dfu_settings_backup_buffer; + return crc_ok(p_settings) && ((p_settings->settings_version == 1) || boot_validation_crc_ok(p_settings)); +} + +#define REGION_COPY_BY_MEMBER(start_member, end_member, p_dst_addr) \ + memcpy(p_dst_addr + offsetof(nrf_dfu_settings_t, start_member), \ + mp_dfu_settings_backup_buffer + offsetof(nrf_dfu_settings_t, start_member), \ + offsetof(nrf_dfu_settings_t, end_member) - offsetof(nrf_dfu_settings_t, start_member)) + + +static void settings_forbidden_parts_copy_from_backup(uint8_t * p_dst_addr) +{ +#if NRF_DFU_IN_APP || NRF_BL_DFU_ALLOW_UPDATE_FROM_APP + REGION_COPY_BY_MEMBER(settings_version, bank_current, p_dst_addr); + REGION_COPY_BY_MEMBER(bank_0, write_offset, p_dst_addr); + REGION_COPY_BY_MEMBER(sd_size, progress, p_dst_addr); + REGION_COPY_BY_MEMBER(boot_validation_crc, peer_data, p_dst_addr); +#else + REGION_COPY_BY_MEMBER(settings_version, enter_buttonless_dfu, p_dst_addr); + REGION_COPY_BY_MEMBER(init_command, peer_data, p_dst_addr); +#endif +} + +void nrf_dfu_settings_reinit(void) +{ + bool settings_valid = settings_crc_ok(); + bool settings_backup_valid = settings_backup_crc_ok(); + + if (settings_valid) + { + NRF_LOG_DEBUG("Using settings page."); + memcpy(&s_dfu_settings, m_dfu_settings_buffer, sizeof(nrf_dfu_settings_t)); + if (settings_backup_valid) + { + NRF_LOG_DEBUG("Copying forbidden parts from backup page."); + settings_forbidden_parts_copy_from_backup((uint8_t *)&s_dfu_settings); + } + } + else if (settings_backup_valid) + { + NRF_LOG_INFO("Restoring settings from backup since the settings page contents are " + "invalid (CRC error)."); + memcpy(&s_dfu_settings, + mp_dfu_settings_backup_buffer, + sizeof(nrf_dfu_settings_t)); + } + else + { + NRF_LOG_WARNING("Resetting bootloader settings since neither the settings page nor the " + "backup are valid (CRC error)."); + memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t)); + s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION; + } + + if (NRF_DFU_SETTINGS_COMPATIBILITY_MODE && !NRF_DFU_IN_APP && (s_dfu_settings.settings_version == 1)) + { + NRF_LOG_WARNING("Resetting bootloader settings since neither the settings page is old."); + memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t)); + s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION; + } + + return; +} + +ret_code_t nrf_dfu_settings_init(bool sd_irq_initialized) +{ + NRF_LOG_DEBUG("Calling nrf_dfu_settings_init()..."); + + ret_code_t err_code = nrf_dfu_flash_init(sd_irq_initialized); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_dfu_flash_init() failed with error: %x", err_code); + return NRF_ERROR_INTERNAL; + } + + nrf_dfu_settings_reinit(); + + err_code = nrf_dfu_settings_write_and_backup(NULL); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_dfu_settings_write_and_backup() failed with error: %x", err_code); + return NRF_ERROR_INTERNAL; + } + + return NRF_SUCCESS; +} + + +static bool settings_forbidden_parts_equal_to_backup(uint8_t * p_compare_addr) +{ + nrf_dfu_settings_t temp_settings; + memcpy(&temp_settings, p_compare_addr, sizeof(nrf_dfu_settings_t)); + settings_forbidden_parts_copy_from_backup((uint8_t *)&temp_settings); + return memcmp(&temp_settings, p_compare_addr, sizeof(nrf_dfu_settings_t)) == 0; +} + + +static ret_code_t settings_write(void * p_dst, + void const * p_src, + nrf_dfu_flash_callback_t callback, + nrf_dfu_settings_t * p_dfu_settings_buffer) +{ + ret_code_t err_code; + + if (memcmp(p_dst, p_src, sizeof(nrf_dfu_settings_t)) == 0) + { + NRF_LOG_DEBUG("Destination settings are identical to source, write not needed. Skipping."); + if (callback != NULL) + { + callback(NULL); + } + return NRF_SUCCESS; + } + + if (NRF_DFU_IN_APP && !settings_forbidden_parts_equal_to_backup((uint8_t *)&s_dfu_settings)) + { + NRF_LOG_WARNING("Settings write aborted since it tries writing to forbidden settings."); + return NRF_ERROR_FORBIDDEN; + } + + NRF_LOG_DEBUG("Writing settings..."); + NRF_LOG_DEBUG("Erasing old settings at: 0x%08x", p_dst); + + // Not setting the callback function because ERASE is required before STORE + // Only report completion on successful STORE. + err_code = nrf_dfu_flash_erase((uint32_t)p_dst, 1, NULL); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not erase the settings page!"); + return NRF_ERROR_INTERNAL; + } + + ASSERT(p_dfu_settings_buffer != NULL); + memcpy(p_dfu_settings_buffer, p_src, sizeof(nrf_dfu_settings_t)); + + err_code = nrf_dfu_flash_store((uint32_t)p_dst, + p_dfu_settings_buffer, + sizeof(nrf_dfu_settings_t), + callback); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not write the DFU settings page!"); + return NRF_ERROR_INTERNAL; + } + + return NRF_SUCCESS; +} + + +ret_code_t nrf_dfu_settings_write(nrf_dfu_flash_callback_t callback) +{ + static nrf_dfu_settings_t dfu_settings_buffer; + s_dfu_settings.crc = settings_crc_get(&s_dfu_settings); + s_dfu_settings.boot_validation_crc = boot_validation_crc(&s_dfu_settings); + return settings_write(m_dfu_settings_buffer, + &s_dfu_settings, + callback, + &dfu_settings_buffer); +} + + +void settings_backup(nrf_dfu_flash_callback_t callback, void * p_src) +{ +#if NRF_DFU_IN_APP + NRF_LOG_INFO("Settings backup not available from app."); +#else + static nrf_dfu_settings_t dfu_settings_buffer; + NRF_LOG_INFO("Backing up settings page to address 0x%x.", mp_dfu_settings_backup_buffer); + ASSERT(crc_ok(p_src)); + ret_code_t err_code = settings_write(mp_dfu_settings_backup_buffer, + p_src, + callback, + &dfu_settings_buffer); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not perform backup of bootloader settings! Error: 0x%x", err_code); + } +#endif +} + + +void nrf_dfu_settings_backup(nrf_dfu_flash_callback_t callback) +{ + settings_backup(callback, m_dfu_settings_buffer); +} + + +ret_code_t nrf_dfu_settings_write_and_backup(nrf_dfu_flash_callback_t callback) +{ +#if NRF_DFU_IN_APP + ret_code_t err_code = nrf_dfu_settings_write(callback); +#else + ret_code_t err_code = nrf_dfu_settings_write(NULL); + if (err_code == NRF_SUCCESS) + { + settings_backup(callback, &s_dfu_settings); + } +#endif + return err_code; +} + + +__WEAK ret_code_t nrf_dfu_settings_additional_erase(void) +{ + NRF_LOG_WARNING("No additional data erased"); + return NRF_SUCCESS; +} + + +void nrf_dfu_settings_progress_reset(void) +{ + memset(s_dfu_settings.init_command, 0xFF, INIT_COMMAND_MAX_SIZE); // Remove the last init command + memset(&s_dfu_settings.progress, 0, sizeof(dfu_progress_t)); + s_dfu_settings.write_offset = 0; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_settings.h b/core/embed/ble_bootloader/dfu/nrf_dfu_settings.h new file mode 100644 index 0000000000..10f2c82e96 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_settings.h @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_dfu_settings DFU settings + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_SETTINGS_H__ +#define NRF_DFU_SETTINGS_H__ + +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_flash.h" +#include "sdk_config.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Global settings. + * + * @note Using this variable is not thread-safe. + * + */ +extern nrf_dfu_settings_t s_dfu_settings; + + +/**@brief Function for writing DFU settings to flash. + * + * @param[in] callback Pointer to a function that is called after completing the write operation. + * + * @retval NRF_SUCCESS If the write process was successfully initiated. + * @retval NRF_ERROR_INTERNAL If a flash error occurred. + */ +ret_code_t nrf_dfu_settings_write(nrf_dfu_flash_callback_t callback); + + +/**@brief Function for backing up the settings. + * + * This function copies the contents of the settings page (in flash) to a separate page (in flash). + * During @ref nrf_dfu_settings_init, the backup is restored if the original is invalid. + * + * @param[in] callback Pointer to a function that is called after completing the write operation. + */ +void nrf_dfu_settings_backup(nrf_dfu_flash_callback_t callback); + + +/**@brief Function for writing DFU settings to flash and to backup. + * + * This function first calls @ref nrf_dfu_settings_write and then @ref nrf_dfu_settings_backup. + * + * @param[in] callback Pointer to a function that is called after completing the write and backup operation. + * + * @retval NRF_SUCCESS If the write process was successfully initiated. + * @retval NRF_ERROR_INTERNAL If a flash error occurred during the first write. + */ +ret_code_t nrf_dfu_settings_write_and_backup(nrf_dfu_flash_callback_t callback); + + +/**@brief Function for initializing the DFU settings structure. + * + * Initializes the RAM structure from the flash contents. + * This function is called as part of @ref nrf_dfu_settings_init. + * + * @retval NRF_SUCCESS If the initialization was successful. + * @retval NRF_ERROR_INTERNAL If a flash error occurred. + */ +void nrf_dfu_settings_reinit(void); + + +/**@brief Function for initializing the DFU settings module. + * + * @retval NRF_SUCCESS If the initialization was successful. + * @retval NRF_ERROR_INTERNAL If a flash error occurred. + */ +ret_code_t nrf_dfu_settings_init(bool sd_irq_initialized); + + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE +/** @brief Function for storing peer data received through an SVCI call in DFU settings. + * + * @note The content of the type can be verified by a CRC value stored inside the struct + * If the CRC value is 0xFFFFFFFF, it means that no data is set. + * + * @note The storage operation is an asynchronous progress. Success will be notified + * through system events raised by the SoftDevice. + * + * @param[in] p_data Peer data to be stored in flash. + * + * @retval NRF_SUCCESS Asynchronous operation was successfully started. + * @retval NRF_ERROR_NULL p_data was NULL. + * @retval Any other error code reported by SoftDevice API calls. + */ +ret_code_t nrf_dfu_settings_peer_data_write(nrf_dfu_peer_data_t * p_data); + + +/** @brief Function for copying peer data from DFU settings to RAM. + * + * @param[in,out] p_data Structure to copy peer data to. + * + * @retval NRF_SUCCESS Peer data was successfully copied. + * @retval NRF_ERROR_NULL p_data was NULL. + */ +ret_code_t nrf_dfu_settings_peer_data_copy(nrf_dfu_peer_data_t * p_data); + + +/** @brief Function for validating peer data in DFU settings. + * + * @retval True if peer data is validated by CRC, false if not. + */ +bool nrf_dfu_settings_peer_data_is_valid(void); + + +/** @brief Function for storing an advertisement name received through an SVCI call in DFU settings. + * + * @note The content of the type is verifyable by a CRC-value stored inside the struct. + * + * @note The storage operation is an asynchronous progress. Success will be notified + * through system events raised by the SoftDevice. + * + * @param[in] p_adv_name Structure holding information about the new advertisement name. + * + * @retval NRF_SUCCESS Asynchronous operation was successfully started. + * @retval NRF_ERROR_NULL p_adv_name was NULL. + * @retval Any other error code reported by SoftDevice API calls. + */ +ret_code_t nrf_dfu_settings_adv_name_write(nrf_dfu_adv_name_t * p_adv_name); + + +/** @brief Function for copying the advertisement name from DFU settings to RAM. + * + * @param[in,out] p_adv_name Structure to copy the new advertisement name to. + * + * @retval NRF_SUCCESS Advertisement name was successfully copied. + * @retval NRF_ERROR_NULL p_adv_name was NULL. + */ +ret_code_t nrf_dfu_settings_adv_name_copy(nrf_dfu_adv_name_t * p_adv_name); + + +/** @brief Function for validating advertisement data in DFU settings. + * + * @retval True if advertisement name is validated by CRC, false if not. + */ +bool nrf_dfu_settings_adv_name_is_valid(void); + +#endif // NRF_DFU_TRANSPORT_BLE + +/** @brief Function for erasing additional data in DFU settings. + * + * @note Erasing additional data in DFU settings is only possible + * if nrf_dfu_flash is initialized to not use SoftDevice calls. + * + * @retval NRF_SUCCESS Additional data was successfully erased. + * @retval Any other error code reported by nrf_dfu_flash + */ +ret_code_t nrf_dfu_settings_additional_erase(void); + +/** @brief Function for resetting both init command and DFU transfer progress inside settings structure. + * + * @note This function does not perform flash operation. + * In order to save the reset state, please use @ref nrf_dfu_settings_write function. + */ +void nrf_dfu_settings_progress_reset(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_SETTINGS_H__ + +/**@} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_settings_svci.c b/core/embed/ble_bootloader/dfu/nrf_dfu_settings_svci.c new file mode 100644 index 0000000000..f16f0b4177 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_settings_svci.c @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include "app_error.h" +#include "sdk_macros.h" +#include "nrf_dfu_settings.h" +#include "nrf_nvmc.h" +#include "crc32.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_settings_svci +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define DFU_SETTINGS_PEER_DATA_OFFSET offsetof(nrf_dfu_settings_t, peer_data) //crc = crc32_compute((uint8_t*)p_data + 4, sizeof(nrf_dfu_peer_data_t) - 4, NULL); + + // Using SoftDevice call since this function cannot use static memory. + ret_val = sd_flash_write(p_peer_data_settings, + (uint32_t*)p_data, + sizeof(nrf_dfu_peer_data_t)/4); + + return ret_val; +} + + +ret_code_t nrf_dfu_settings_peer_data_copy(nrf_dfu_peer_data_t * p_data) +{ + VERIFY_PARAM_NOT_NULL(p_data); + + memcpy(p_data, &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET], sizeof(nrf_dfu_peer_data_t)); + + return NRF_SUCCESS; +} + + +bool nrf_dfu_settings_peer_data_is_valid(void) +{ + nrf_dfu_peer_data_t * p_peer_data = + (nrf_dfu_peer_data_t*) &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET]; + + // Calculate the CRC for the structure excluding the CRC value itself. + uint32_t crc = crc32_compute((uint8_t*)p_peer_data + 4, sizeof(nrf_dfu_peer_data_t) - 4, NULL); + + return (p_peer_data->crc == crc); +} + +#else // not NRF_DFU_BLE_REQUIRES_BONDS + +ret_code_t nrf_dfu_settings_adv_name_write(nrf_dfu_adv_name_t * p_adv_name) +{ + uint32_t ret_val; + + uint32_t * p_adv_name_settings = + (uint32_t*) &m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET]; + + uint32_t crc = (uint32_t)*p_adv_name_settings; + + VERIFY_PARAM_NOT_NULL(p_adv_name); + + if (crc != 0xFFFFFFFF) + { + // Already written to, must be cleared out. + // Reset required + return NRF_ERROR_INVALID_STATE; + } + + // Calculate the CRC for the structure excluding the CRC value itself. + p_adv_name->crc = crc32_compute((uint8_t *)p_adv_name + 4, sizeof(nrf_dfu_adv_name_t) - 4, NULL); + + // Using SoftDevice call since this function cannot use static memory. + ret_val = sd_flash_write(p_adv_name_settings, + (uint32_t*) p_adv_name, + sizeof(nrf_dfu_adv_name_t)/4); + return ret_val; +} + + +ret_code_t nrf_dfu_settings_adv_name_copy(nrf_dfu_adv_name_t * p_adv_name) +{ + VERIFY_PARAM_NOT_NULL(p_adv_name); + memcpy(p_adv_name, &m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET], sizeof(nrf_dfu_adv_name_t)); + + return NRF_SUCCESS; +} + + +bool nrf_dfu_settings_adv_name_is_valid(void) +{ + nrf_dfu_adv_name_t * p_adv_name = + (nrf_dfu_adv_name_t*)&m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET]; + + // Calculate the CRC for the structure excluding the CRC value itself. + uint32_t crc = crc32_compute((uint8_t*)p_adv_name + 4, sizeof(nrf_dfu_adv_name_t) - 4, NULL); + + return (p_adv_name->crc == crc); +} + +#endif + + +//lint -save -e(14) +ret_code_t nrf_dfu_settings_additional_erase(void) +{ + ret_code_t ret_code = NRF_SUCCESS; + + // Check CRC for both types. + if ( (s_dfu_settings.peer_data.crc != 0xFFFFFFFF) + || (s_dfu_settings.adv_name.crc != 0xFFFFFFFF)) + { + NRF_LOG_DEBUG("Erasing settings page additional data."); + + // Erasing and resetting the settings page without the peer data/adv data + nrf_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS); + nrf_nvmc_write_words(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t const *)&s_dfu_settings, DFU_SETTINGS_PEER_DATA_OFFSET / 4); + } + + return ret_code; +} +//lint -restore + diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_svci.c b/core/embed/ble_bootloader/dfu/nrf_dfu_svci.c new file mode 100644 index 0000000000..2821ec3daa --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_svci.c @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include "nrf_log.h" +#include "nrf_sdm.h" +#include "app_util.h" + +#define APP_START_ADDR CODE_START + + +uint32_t nrf_dfu_svci_vector_table_set(void) +{ + uint32_t err_code; + uint32_t bootloader_addr = BOOTLOADER_ADDRESS; + + if (bootloader_addr != 0xFFFFFFFF) + { + NRF_LOG_INFO("Setting vector table to bootloader: 0x%08x", bootloader_addr); + err_code = sd_softdevice_vector_table_base_set(bootloader_addr); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed running sd_softdevice_vector_table_base_set"); + return err_code; + } + + return NRF_SUCCESS; + } + + NRF_LOG_ERROR("No bootloader was found"); + return NRF_ERROR_NO_MEM; +} + + +uint32_t nrf_dfu_svci_vector_table_unset(void) +{ + uint32_t err_code; + + NRF_LOG_INFO("Setting vector table to main app: 0x%08x", APP_START_ADDR); + err_code = sd_softdevice_vector_table_base_set(APP_START_ADDR); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed running sd_softdevice_vector_table_base_set"); + return err_code; + } + + return NRF_SUCCESS; +} + diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_svci_handler.c b/core/embed/ble_bootloader/dfu/nrf_dfu_svci_handler.c new file mode 100644 index 0000000000..bb1768aae4 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_svci_handler.c @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "nrf_svci_async_handler.h" +#include "app_error.h" +#include "nrf_nvmc.h" +#include "nrf_dfu_types.h" +#include "nrf_dfu_ble_svci_bond_sharing.h" +#include "nrf_log.h" +#include "nrf_dfu_settings.h" +#include "sdk_config.h" + + +#if (NRF_DFU_TRANSPORT_BLE && NRF_DFU_BLE_REQUIRES_BONDS) + + +NRF_SVCI_ASYNC_HANDLER_CREATE(NRF_DFU_SVCI_SET_PEER_DATA, + nrf_dfu_set_peer_data, nrf_dfu_peer_data_t, nrf_dfu_peer_data_state_t); + + +static uint32_t nrf_dfu_set_peer_data_handler(nrf_dfu_set_peer_data_svci_async_t * p_async) +{ + VERIFY_PARAM_NOT_NULL(p_async); + + p_async->async_func = nrf_dfu_set_peer_data_on_call; + p_async->sys_evt_handler = nrf_dfu_set_peer_data_on_sys_evt; + p_async->state = DFU_PEER_DATA_STATE_INITIALIZED; + + return NRF_SUCCESS; +} + + +static uint32_t nrf_dfu_set_peer_data_on_call(nrf_dfu_peer_data_t * p_data, + nrf_dfu_peer_data_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_BUSY; + + VERIFY_PARAM_NOT_NULL(p_state); + + switch (*p_state) + { + case DFU_PEER_DATA_STATE_INVALID: + return NRF_ERROR_INVALID_STATE; + + case DFU_PEER_DATA_STATE_INITIALIZED: + ret_val = nrf_dfu_settings_peer_data_write(p_data); + if (ret_val == NRF_SUCCESS) + { + *p_state = DFU_PEER_DATA_STATE_WRITE_REQUESTED; + } + break; + + case DFU_PEER_DATA_STATE_WRITE_REQUESTED: + return NRF_ERROR_BUSY; + + case DFU_PEER_DATA_STATE_WRITE_FINISHED: + return NRF_ERROR_INVALID_STATE; + + case DFU_PEER_DATA_STATE_WRITE_FAILED: + return NRF_ERROR_INVALID_STATE; + } + + return ret_val; +} + + +static uint32_t nrf_dfu_set_peer_data_on_sys_evt(uint32_t sys_event, nrf_dfu_peer_data_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_INVALID_STATE; + + VERIFY_PARAM_NOT_NULL(p_state); + + if (*p_state == DFU_PEER_DATA_STATE_WRITE_REQUESTED) + { + switch (sys_event) + { + case NRF_EVT_FLASH_OPERATION_ERROR: + return NRF_ERROR_BUSY; + + case NRF_EVT_FLASH_OPERATION_SUCCESS: + ret_val = NRF_SUCCESS; + (*p_state) = DFU_PEER_DATA_STATE_WRITE_FINISHED; + break; + + default: + // Event not intended for us + break; + } + } + + return ret_val; +} + +#elif (NRF_DFU_TRANSPORT_BLE && !NRF_DFU_BLE_REQUIRES_BONDS) + + +NRF_SVCI_ASYNC_HANDLER_CREATE(NRF_DFU_SVCI_SET_ADV_NAME, + nrf_dfu_set_adv_name, nrf_dfu_adv_name_t, nrf_dfu_set_adv_name_state_t); + + +static uint32_t nrf_dfu_set_adv_name_handler(nrf_dfu_set_adv_name_svci_async_t * p_async) +{ + VERIFY_PARAM_NOT_NULL(p_async); + + p_async->async_func = nrf_dfu_set_adv_name_on_call; + p_async->sys_evt_handler = nrf_dfu_set_adv_name_on_sys_evt; + p_async->state = DFU_ADV_NAME_STATE_INITIALIZED; + + return NRF_SUCCESS; +} + + +static uint32_t nrf_dfu_set_adv_name_on_call(nrf_dfu_adv_name_t * p_adv_name, + nrf_dfu_set_adv_name_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_BUSY; + + VERIFY_PARAM_NOT_NULL(p_state); + + switch (*p_state) + { + case DFU_ADV_NAME_STATE_INVALID: + return NRF_ERROR_INVALID_STATE; + + case DFU_ADV_NAME_STATE_INITIALIZED: + ret_val = nrf_dfu_settings_adv_name_write(p_adv_name); + if (ret_val == NRF_SUCCESS) + { + *p_state = DFU_ADV_NAME_STATE_WRITE_REQUESTED; + } + break; + + case DFU_ADV_NAME_STATE_WRITE_REQUESTED: + return NRF_ERROR_BUSY; + + case DFU_ADV_NAME_STATE_WRITE_FINISHED: + return NRF_ERROR_INVALID_STATE; + + case DFU_ADV_NAME_STATE_WRITE_FAILED: + return NRF_ERROR_INVALID_STATE; + } + + return ret_val; +} + + +static uint32_t nrf_dfu_set_adv_name_on_sys_evt(uint32_t sys_event, nrf_dfu_set_adv_name_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_INVALID_STATE; + + VERIFY_PARAM_NOT_NULL(p_state); + + if (*p_state == DFU_ADV_NAME_STATE_WRITE_REQUESTED) + { + switch (sys_event) + { + case NRF_EVT_FLASH_OPERATION_ERROR: + return NRF_ERROR_BUSY; + + case NRF_EVT_FLASH_OPERATION_SUCCESS: + ret_val = NRF_SUCCESS; + (*p_state) = DFU_ADV_NAME_STATE_WRITE_FINISHED; + break; + + default: + // Event not intended for us + break; + } + } + + return ret_val; +} + +#endif // NRF_DFU_TRANSPORT_BLE && !NRF_DFU_BLE_REQUIRES_BONDS diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_transport.c b/core/embed/ble_bootloader/dfu/nrf_dfu_transport.c new file mode 100644 index 0000000000..cb6e9a49d4 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_transport.c @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_transport.h" +#include "nrf_log.h" + + +#define DFU_TRANS_SECTION_ITEM_GET(i) NRF_SECTION_ITEM_GET(dfu_trans, nrf_dfu_transport_t, (i)) +#define DFU_TRANS_SECTION_ITEM_COUNT NRF_SECTION_ITEM_COUNT(dfu_trans, nrf_dfu_transport_t) + +NRF_SECTION_DEF(dfu_trans, const nrf_dfu_transport_t); + + +uint32_t nrf_dfu_transports_init(nrf_dfu_observer_t observer) +{ + uint32_t const num_transports = DFU_TRANS_SECTION_ITEM_COUNT; + uint32_t ret_val = NRF_SUCCESS; + + NRF_LOG_DEBUG("Initializing transports (found: %d)", num_transports); + + for (uint32_t i = 0; i < num_transports; i++) + { + nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_ITEM_GET(i); + ret_val = trans->init_func(observer); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_DEBUG("Failed to initialize transport %d, error %d", i, ret_val); + break; + } + } + + return ret_val; +} + + +uint32_t nrf_dfu_transports_close(nrf_dfu_transport_t const * p_exception) +{ + uint32_t const num_transports = DFU_TRANS_SECTION_ITEM_COUNT; + uint32_t ret_val = NRF_SUCCESS; + + NRF_LOG_DEBUG("Shutting down transports (found: %d)", num_transports); + + for (uint32_t i = 0; i < num_transports; i++) + { + nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_ITEM_GET(i); + ret_val = trans->close_func(p_exception); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_DEBUG("Failed to shutdown transport %d, error %d", i, ret_val); + break; + } + } + + return ret_val; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_transport.h b/core/embed/ble_bootloader/dfu/nrf_dfu_transport.h new file mode 100644 index 0000000000..e10723ec5b --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_transport.h @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_transport DFU transport + * @{ + * @ingroup nrf_dfu + * @brief Generic Device Firmware Update (DFU) transport interface. + * + * @details The DFU transport module defines a generic interface that must + * be implemented for each transport layer. + */ + +#ifndef NRF_DFU_TRANSPORT_H__ +#define NRF_DFU_TRANSPORT_H__ + +#include +#include "nrf_section.h" +#include "nrf_dfu_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Forward declaration of nrf_dfu_transport_t */ +typedef struct nrf_dfu_transport_s nrf_dfu_transport_t; + +/** @brief Function type for initializing a DFU transport. + * + * @details This function initializes a DFU transport. The implementation + * of the function must initialize DFU mode and stay in service + * until either the device is reset or the DFU operation is finalized. + * When the DFU transport receives requests, it should call @ref nrf_dfu_req_handler_on_req for handling the requests. + * + * @param observer Callback function for receiving DFU transport notifications. + * + * @retval NRF_SUCCESS If initialization was successful for the transport. Any other return code indicates that the DFU transport could not be initialized. + */ +typedef uint32_t (*nrf_dfu_init_fn_t)(nrf_dfu_observer_t observer); + + +/** @brief Function type for closing down a DFU transport. + * + * @details This function closes down a DFU transport in a gentle way. + * + * @param[in] p_exception If exception matches current transport closing should be omitted. + * + * @retval NRF_SUCCESS If closing was successful for the transport. Any other return code indicates that the DFU transport could not be closed closed down. + */ +typedef uint32_t (*nrf_dfu_close_fn_t)(nrf_dfu_transport_t const * p_exception); + + + +/** @brief DFU transport registration. + * + * @details Every DFU transport must provide a registration of the initialization function. + */ +struct nrf_dfu_transport_s +{ + nrf_dfu_init_fn_t init_func; /**< Registration of the init function to run to initialize a DFU transport. */ + nrf_dfu_close_fn_t close_func; /**< Registration of the close function to close down a DFU transport. */ +}; + + +/** @brief Function for initializing all the registered DFU transports. + * + * @retval NRF_SUCCESS If all DFU transport were initialized successfully. + * Any other error code indicates that at least one DFU + * transport could not be initialized. + */ +uint32_t nrf_dfu_transports_init(nrf_dfu_observer_t observer); + +/** @brief Function for closing down all (with optional exception) the registered DFU transports. + * + * @param[in] p_exception Transport which should not be closed. NULL if all transports should be closed. + * @retval NRF_SUCCESS If all DFU transport were closed down successfully. + * Any other error code indicates that at least one DFU + * transport could not be closed down. + */ +uint32_t nrf_dfu_transports_close(nrf_dfu_transport_t const * p_exception); + + +/** @brief Macro for registering a DFU transport by using section variables. + * + * @details This macro places a variable in a section named "dfu_trans", which + * is initialized by @ref nrf_dfu_transports_init. + */ +#define DFU_TRANSPORT_REGISTER(trans_var) NRF_SECTION_ITEM_REGISTER(dfu_trans, trans_var) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_TRANSPORT_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.c b/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.c new file mode 100644 index 0000000000..90b69290ac --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.c @@ -0,0 +1,244 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_trigger_usb.h" +#include "app_usbd.h" +#include "app_usbd_nrf_dfu_trigger.h" +#include "nrf_drv_clock.h" +#include "nrf_log_ctrl.h" +#include "nrf_gpio.h" +#include "boards.h" +#include "app_util.h" +#include "app_usbd_serial_num.h" +#define NRF_LOG_MODULE_NAME nrf_dfu_trigger_usb +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#ifndef BSP_SELF_PINRESET_PIN +#error "This module is intended to be used with boards that have the GP pin shortened with the RESET pin." +#endif + +/** + * @brief Enable power USB detection. + * + * Configure if the example supports USB port connection. + */ +#ifndef USBD_POWER_DETECTION +#define USBD_POWER_DETECTION true +#endif + +#define DFU_FLASH_PAGE_SIZE (NRF_FICR->CODEPAGESIZE) +#define DFU_FLASH_PAGE_COUNT (NRF_FICR->CODESIZE) + +// Semantic versioning string. +#define VERSION_STRING STRINGIFY(APP_VERSION_MAJOR) "." STRINGIFY(APP_VERSION_MINOR) "." STRINGIFY(APP_VERSION_PATCH) APP_VERSION_PRERELEASE APP_VERSION_METADATA + +static uint8_t m_version_string[] = APP_NAME " " VERSION_STRING; ///< Human-readable version string. +static app_usbd_nrf_dfu_trigger_nordic_info_t m_dfu_info; ///< Struct with various information about the current firmware. + +static void dfu_trigger_evt_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_nrf_dfu_trigger_user_event_t event) +{ + UNUSED_PARAMETER(p_inst); + + switch (event) + { + case APP_USBD_NRF_DFU_TRIGGER_USER_EVT_DETACH: + NRF_LOG_INFO("DFU Detach request received. Triggering a pin reset."); + NRF_LOG_FINAL_FLUSH(); + nrf_gpio_cfg_output(BSP_SELF_PINRESET_PIN); + nrf_gpio_pin_clear(BSP_SELF_PINRESET_PIN); + break; + default: + break; + } +} + + +APP_USBD_NRF_DFU_TRIGGER_GLOBAL_DEF(m_app_dfu, + NRF_DFU_TRIGGER_USB_INTERFACE_NUM, + &m_dfu_info, + m_version_string, + dfu_trigger_evt_handler); + + +static void usbd_user_evt_handler(app_usbd_event_type_t event) +{ + switch (event) + { + case APP_USBD_EVT_DRV_SUSPEND: + break; + case APP_USBD_EVT_DRV_RESUME: + break; + case APP_USBD_EVT_STARTED: + break; + case APP_USBD_EVT_STOPPED: + app_usbd_disable(); + break; + case APP_USBD_EVT_POWER_DETECTED: + NRF_LOG_INFO("USB power detected"); + + if (!nrf_drv_usbd_is_enabled()) + { + app_usbd_enable(); + } + break; + case APP_USBD_EVT_POWER_REMOVED: + NRF_LOG_INFO("USB power removed"); + app_usbd_stop(); + break; + case APP_USBD_EVT_POWER_READY: + NRF_LOG_INFO("USB ready"); + app_usbd_start(); + break; + default: + break; + } +} + + +static void strings_create(void) +{ + uint8_t prev_char = 'a'; // Arbitrary valid char, not '-'. + + // Remove characters that are not supported in semantic version strings. + for (size_t i = strlen(APP_NAME) + 1; i < strlen((char*)m_version_string); i++) + { + if (((m_version_string[i] >= 'a') && (m_version_string[i] <= 'z')) + || ((m_version_string[i] >= 'A') && (m_version_string[i] <= 'Z')) + || ((m_version_string[i] >= '0') && (m_version_string[i] <= '9')) + || (m_version_string[i] == '+') + || (m_version_string[i] == '.') + || (m_version_string[i] == '-')) + { + // Valid semantic version character. + } + else if (prev_char == '-') + { + m_version_string[i] = '0'; + } + else + { + m_version_string[i] = '-'; + } + + prev_char = m_version_string[i]; + } + +#if !NRF_DFU_TRIGGER_USB_USB_SHARED + app_usbd_serial_num_generate(); +#endif +} + +#if !(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) +static void usbd_evt_handler(app_usbd_internal_evt_t const * const p_event) +{ + app_usbd_event_execute(p_event); +} +#endif + +ret_code_t nrf_dfu_trigger_usb_init(void) +{ + ret_code_t ret; + static bool initialized = false; + + if (initialized) + { + return NRF_SUCCESS; + } + + m_dfu_info.wAddress = CODE_START; + m_dfu_info.wFirmwareSize = CODE_SIZE; + m_dfu_info.wVersionMajor = APP_VERSION_MAJOR; + m_dfu_info.wVersionMinor = APP_VERSION_MINOR; + m_dfu_info.wFirmwareID = APP_ID; + m_dfu_info.wFlashPageSize = DFU_FLASH_PAGE_SIZE; + m_dfu_info.wFlashSize = m_dfu_info.wFlashPageSize * DFU_FLASH_PAGE_COUNT; + + strings_create(); + + if (!NRF_DFU_TRIGGER_USB_USB_SHARED) + { + static const app_usbd_config_t usbd_config = { + +#if !(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) + .ev_handler = usbd_evt_handler, +#endif + .ev_state_proc = usbd_user_evt_handler + }; + + ret = nrf_drv_clock_init(); + if ((ret != NRF_SUCCESS) && (ret != NRF_ERROR_MODULE_ALREADY_INITIALIZED)) + { + return ret; + } + + ret = app_usbd_init(&usbd_config); + if (ret != NRF_SUCCESS) + { + return ret; + } + } + + app_usbd_class_inst_t const * class_dfu = app_usbd_nrf_dfu_trigger_class_inst_get(&m_app_dfu); + ret = app_usbd_class_append(class_dfu); + + if (!NRF_DFU_TRIGGER_USB_USB_SHARED) + { + if (USBD_POWER_DETECTION) + { + ret = app_usbd_power_events_enable(); + APP_ERROR_CHECK(ret); + } + else + { + NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now"); + + app_usbd_enable(); + app_usbd_start(); + } + } + + if (ret == NRF_SUCCESS) + { + initialized = true; + } + + return ret; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.h b/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.h new file mode 100644 index 0000000000..01526361ef --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.h @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_DFU_TRIGGER_USB_H +#define NRF_DFU_TRIGGER_USB_H + +#include "sdk_errors.h" + +/** + * @defgroup nrf_dfu_trigger_usb USB DFU trigger library + * @ingroup app_common + * + * @brief @tagAPI52840 USB DFU trigger library is used to enter the bootloader and read the firmware version. + * + * @details See @ref lib_dfu_trigger_usb for additional documentation. + * @{ + */ + +/** + * @brief Function for initializing the USB DFU trigger library. + * + * @note If the USB is also used for other purposes, then this function must be called after USB is + * initialized but before it is enabled. In this case, the configuration flag @ref + * NRF_DFU_TRIGGER_USB_USB_SHARED must be set to 1. + * + * @note Calling this again after the first success has no effect and returns @ref NRF_SUCCESS. + * + * @note If @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE is on (1), USB events must be handled manually. + * See @ref app_usbd_event_queue_process. + * + * @retval NRF_SUCCESS On successful initialization. + * @return An error code on failure, for example if called at a wrong time. + */ +ret_code_t nrf_dfu_trigger_usb_init(void); + +/** @} */ + +#endif //NRF_DFU_TRIGGER_USB_H diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_types.h b/core/embed/ble_bootloader/dfu/nrf_dfu_types.h new file mode 100644 index 0000000000..81bc44d65a --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_types.h @@ -0,0 +1,342 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_types DFU types + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_TYPES_H__ +#define NRF_DFU_TYPES_H__ + +#include +#include + +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_mbr.h" +#include "app_util_platform.h" +#include "sdk_config.h" + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE +#include "ble_gap.h" +#define SYSTEM_SERVICE_ATT_SIZE 8 /**< Size of the system service attribute length including CRC-16 at the end. */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#define INIT_COMMAND_MAX_SIZE 512 /**< Maximum size of the init command stored in dfu_settings. */ +#define INIT_COMMAND_MAX_SIZE_v1 256 /**< Maximum size of the init command in settings version 1. */ + +/** @brief Size of a flash page. This value is used for calculating the size of the reserved + * flash space in the bootloader region. + */ +#if defined(NRF51) + #define CODE_PAGE_SIZE (PAGE_SIZE_IN_WORDS * sizeof(uint32_t)) +#elif defined(NRF52_SERIES) + #define CODE_PAGE_SIZE (MBR_PAGE_SIZE_IN_WORDS * sizeof(uint32_t)) +#else + #error "Architecture not set." +#endif + +/** @brief Maximum size of a data object.*/ +#if defined(NRF51) + #define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE * 4) +#elif defined(NRF52_SERIES) || defined (__SDK_DOXYGEN__) + #define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE) +#else + #error "Architecture not set." +#endif + +/** @brief Page location of the bootloader settings address. + */ +#if defined (NRF51) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0003FC00UL) +#elif defined( NRF52810_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0002F000UL) +#elif defined( NRF52811_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0002F000UL) +#elif defined( NRF52820_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0003F000UL) +#elif defined( NRF52832_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL) +#elif defined( NRF52833_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL) +#elif defined(NRF52840_XXAA) + #define BOOTLOADER_SETTINGS_ADDRESS (0x000FF000UL) +#else + #error No valid target set for BOOTLOADER_SETTINGS_ADDRESS. +#endif + +#define BOOTLOADER_SETTINGS_PAGE_SIZE (CODE_PAGE_SIZE) +#define NRF_MBR_PARAMS_PAGE_SIZE (CODE_PAGE_SIZE) + +/** @brief Page location of the MBR parameters page address. + */ +#if defined(NRF52840_XXAA) || defined(NRF52840_XXAA_ENGA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x000FE000UL) +#elif defined(NRF52832_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL) +#elif defined(NRF52833_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL) +#elif defined(NRF52810_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0002E000UL) +#elif defined(NRF52811_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0002E000UL) +#elif defined(NRF52820_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0003E000UL) +#endif + +#define BOOTLOADER_SETTINGS_BACKUP_ADDRESS NRF_MBR_PARAMS_PAGE_ADDRESS + + +#ifndef NRF_DFU_APP_DATA_AREA_SIZE +#define NRF_DFU_APP_DATA_AREA_SIZE (CODE_PAGE_SIZE * 3) +#endif + +STATIC_ASSERT((NRF_DFU_APP_DATA_AREA_SIZE % CODE_PAGE_SIZE) == 0, "NRF_DFU_APP_DATA_AREA_SIZE must be a multiple of the flash page size."); + +#define DFU_APP_DATA_RESERVED NRF_DFU_APP_DATA_AREA_SIZE // For backward compatibility with 15.0.0. + +/** @brief Total size of the region between the SoftDevice and the bootloader. + */ +#define DFU_REGION_END(bootloader_start_addr) ((bootloader_start_addr) - (NRF_DFU_APP_DATA_AREA_SIZE)) + +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) +#define DFU_REGION_START (nrf_dfu_bank0_start_addr()) +#else +#define DFU_REGION_START (MBR_SIZE) +#endif + +#define DFU_REGION_TOTAL_SIZE ((DFU_REGION_END) - (DFU_REGION_START)) + +#define NRF_DFU_CURRENT_BANK_0 0x00 +#define NRF_DFU_CURRENT_BANK_1 0x01 + +#define NRF_DFU_BANK_LAYOUT_DUAL 0x00 +#define NRF_DFU_BANK_LAYOUT_SINGLE 0x01 + +/** @brief DFU bank state codes. + * + * @details The DFU bank state indicates the content of a bank: + * A valid image of a certain type or an invalid image. + */ + +#define NRF_DFU_BANK_INVALID 0x00 /**< Invalid image. */ +#define NRF_DFU_BANK_VALID_APP 0x01 /**< Valid application. */ +#define NRF_DFU_BANK_VALID_SD 0xA5 /**< Valid SoftDevice. */ +#define NRF_DFU_BANK_VALID_BL 0xAA /**< Valid bootloader. */ +#define NRF_DFU_BANK_VALID_SD_BL 0xAC /**< Valid SoftDevice and bootloader. */ +#define NRF_DFU_BANK_VALID_EXT_APP 0xB1 /**< Valid application designated for a remote node. */ + +/** @brief Description of a single bank. */ +#pragma pack(4) +typedef struct +{ + uint32_t image_size; /**< Size of the image in the bank. */ + uint32_t image_crc; /**< CRC of the image. If set to 0, the CRC is ignored. */ + uint32_t bank_code; /**< Identifier code for the bank. */ +} nrf_dfu_bank_t; + +/**@brief DFU progress. + * + * Be aware of the difference between objects and firmware images. A firmware image consists of multiple objects, each of a maximum size @ref DATA_OBJECT_MAX_SIZE. + * + * @note The union inside this struct is cleared when CREATE_OBJECT of command type is executed, and when there is a valid post-validation. + * In DFU activation (after reset) the @ref dfu_progress_t::update_start_address will be used in case of a SD/SD+BL update. + */ +ANON_UNIONS_ENABLE; +typedef struct +{ + uint32_t command_size; /**< The size of the current init command stored in the DFU settings. */ + uint32_t command_offset; /**< The offset of the currently received init command data. The offset will increase as the init command is received. */ + uint32_t command_crc; /**< The calculated CRC of the init command (calculated after the transfer is completed). */ + uint32_t data_object_size; /**< The size of the last object created. Note that this size is not the size of the whole firmware image.*/ + union + { + struct + { + uint32_t firmware_image_crc; /**< CRC value of the current firmware (continuously calculated as data is received). */ + uint32_t firmware_image_crc_last; /**< The CRC of the last executed object. */ + uint32_t firmware_image_offset; /**< The offset of the current firmware image being transferred. Note that this offset is the offset in the entire firmware image and not only the current object. */ + uint32_t firmware_image_offset_last;/**< The offset of the last executed object from the start of the firmware image. */ + }; + struct + { + uint32_t update_start_address; /**< Value indicating the start address of the new firmware (before copy). It's always used, but it's most important for an SD/SD+BL update where the SD changes size or if the DFU process had a power loss when updating a SD with changed size. */ + }; + }; +} dfu_progress_t; +ANON_UNIONS_DISABLE; + +/** @brief Event types in the bootloader and DFU process. */ +typedef enum +{ + NRF_DFU_EVT_DFU_INITIALIZED, /**< Starting DFU. */ + NRF_DFU_EVT_TRANSPORT_ACTIVATED, /**< Transport activated (e.g. BLE connected, USB plugged in). */ + NRF_DFU_EVT_TRANSPORT_DEACTIVATED, /**< Transport deactivated (e.g. BLE disconnected, USB plugged out). */ + NRF_DFU_EVT_DFU_STARTED, /**< DFU process started. */ + NRF_DFU_EVT_OBJECT_RECEIVED, /**< A DFU data object has been received. */ + NRF_DFU_EVT_DFU_FAILED, /**< DFU process has failed, been interrupted, or hung. */ + NRF_DFU_EVT_DFU_COMPLETED, /**< DFU process completed. */ + NRF_DFU_EVT_DFU_ABORTED, /**< DFU process aborted. */ +} nrf_dfu_evt_type_t; + +/** + * @brief Function for notifying DFU state. + */ +typedef void (*nrf_dfu_observer_t)(nrf_dfu_evt_type_t notification); + +#define NRF_DFU_PEER_DATA_LEN 64 /**< The length in bytes of nrf_dfu_peer_data_t expected by tools manipulating the settings page. Do not change without changing the settings page version. */ +#define NRF_DFU_ADV_NAME_LEN 28 /**< The length in bytes of nrf_dfu_adv_name_t expected by tools manipulating the settings page. Do not change without changing the settings page version. */ + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE + +typedef struct +{ + uint32_t crc; /**< CRC of the rest of the parameters in this struct. */ + ble_gap_id_key_t ble_id; /**< BLE GAP identity key of the device that initiated the DFU process. */ + ble_gap_enc_key_t enc_key; /**< Encryption key structure containing encrypted diversifier and LTK for reestablishing the bond. */ + uint8_t sys_serv_attr[SYSTEM_SERVICE_ATT_SIZE]; /**< System service attributes for restoring of Service Changed Indication setting in DFU mode. */ +} nrf_dfu_peer_data_t; + +typedef enum +{ + DFU_PEER_DATA_STATE_INVALID = 0, + DFU_PEER_DATA_STATE_INITIALIZED = 1, + DFU_PEER_DATA_STATE_WRITE_REQUESTED = 2, + DFU_PEER_DATA_STATE_WRITE_FINISHED = 3, + DFU_PEER_DATA_STATE_WRITE_FAILED = 4, +} nrf_dfu_peer_data_state_t; + +typedef struct +{ + uint32_t crc; /**< CRC of the rest of the parameters in this struct. Calculated by the bootloader. */ + uint8_t name[20]; /**< New advertisement name to set. */ + uint32_t len; /**< Length of the advertisement name. */ +} nrf_dfu_adv_name_t; + +typedef enum +{ + DFU_ADV_NAME_STATE_INVALID = 0, + DFU_ADV_NAME_STATE_INITIALIZED = 1, + DFU_ADV_NAME_STATE_WRITE_REQUESTED = 2, + DFU_ADV_NAME_STATE_WRITE_FINISHED = 3, + DFU_ADV_NAME_STATE_WRITE_FAILED = 4, +} nrf_dfu_set_adv_name_state_t; + +#else +typedef struct +{ + uint8_t dummy_data[NRF_DFU_PEER_DATA_LEN]; +} nrf_dfu_peer_data_t; + +typedef struct +{ + uint8_t dummy_data[NRF_DFU_ADV_NAME_LEN]; +} nrf_dfu_adv_name_t; +#endif // NRF_DFU_TRANSPORT_BLE + +STATIC_ASSERT(sizeof(nrf_dfu_peer_data_t) == NRF_DFU_PEER_DATA_LEN, "nrf_dfu_peer_data_t has unexpected length. This can cause incompatibility with tools."); +STATIC_ASSERT(sizeof(nrf_dfu_adv_name_t) == NRF_DFU_ADV_NAME_LEN, "nrf_dfu_adv_name_t has unexpected length. This can cause incompatibility with tools."); + +#define SETTINGS_RESERVED_AREA_SIZE 16 /**< The number of words in the reserved area of the DFU settings. */ +#define SETTINGS_BOOT_VALIDATION_SIZE 64 /**< The number of bytes reserved for boot_validation value. */ + + +typedef enum +{ + NO_VALIDATION, + VALIDATE_CRC, + VALIDATE_SHA256, + VALIDATE_ECDSA_P256_SHA256, +} boot_validation_type_t; + +typedef struct +{ + uint32_t sigmask; + uint8_t bytes[SETTINGS_BOOT_VALIDATION_SIZE]; +} boot_validation_t; + +/**@brief DFU settings for application and bank data. + */ +typedef struct +{ + uint32_t crc; /**< CRC for the stored DFU settings, not including the CRC itself. If 0xFFFFFFF, the CRC has never been calculated. */ + uint32_t settings_version; /**< Version of the current DFU settings struct layout. */ + uint32_t app_version; /**< Version of the last stored application. */ + uint32_t bootloader_version; /**< Version of the last stored bootloader. */ + + uint32_t bank_layout; /**< Bank layout: single bank or dual bank. This value can change. */ + uint32_t bank_current; /**< The bank that is currently used. */ + + nrf_dfu_bank_t bank_0; /**< Bank 0. */ + nrf_dfu_bank_t bank_1; /**< Bank 1. */ + + uint32_t write_offset; /**< Write offset for the current operation. */ + uint32_t sd_size; /**< Size of the SoftDevice. */ + + dfu_progress_t progress; /**< Current DFU progress. */ + + uint32_t enter_buttonless_dfu; + uint8_t init_command[INIT_COMMAND_MAX_SIZE]; /**< Buffer for storing the init command. */ + + uint32_t boot_validation_crc; + boot_validation_t boot_validation_softdevice; + boot_validation_t boot_validation_app; + boot_validation_t boot_validation_bootloader; + + nrf_dfu_peer_data_t peer_data; /**< Not included in calculated CRC. */ + nrf_dfu_adv_name_t adv_name; /**< Not included in calculated CRC. */ +} nrf_dfu_settings_t; + +#pragma pack() // revert pack settings + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_TYPES_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_utils.c b/core/embed/ble_bootloader/dfu/nrf_dfu_utils.c new file mode 100644 index 0000000000..978369a727 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_utils.c @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_utils.h" + +#include "nrf_dfu_settings.h" +#include "nrf_bootloader_info.h" +#include "crc32.h" +#include "nrf_log.h" +#include "nrf_dfu_validation.h" + +void nrf_dfu_bank_invalidate(nrf_dfu_bank_t * const p_bank) +{ + // Set the bank-code to invalid, and reset size/CRC + memset(p_bank, 0, sizeof(nrf_dfu_bank_t)); + + // Reset write pointer after completed operation + s_dfu_settings.write_offset = 0; +} + + +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) +void nrf_dfu_softdevice_invalidate(void) +{ + static const uint32_t all_zero = 0UL; + + if (SD_PRESENT && !NRF_DFU_IN_APP) + { + ret_code_t err_code = nrf_dfu_flash_store(SD_MAGIC_NUMBER_ABS_OFFSET_GET(MBR_SIZE), &all_zero, 4, NULL); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not invalidate SoftDevice.") + } + else + { + // If there is an app it must be invalidated since its start address can no longer be resolved. + if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP) + { + s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_INVALID; + } + // Since the start of bank 0 has now implicitly been moved to the start + // of the invalidated SoftDevice, its image size must be increased by the + // same amount so the start of bank 1 will be correctly calculated. + s_dfu_settings.bank_0.image_size += SD_SIZE_GET(MBR_SIZE) - MBR_SIZE; + } + } +} +#endif + + +uint32_t nrf_dfu_bank0_start_addr(void) +{ + if (SD_PRESENT) + { + return ALIGN_TO_PAGE(SD_SIZE_GET(MBR_SIZE)); + } + else + { + return MBR_SIZE; + } +} + + +uint32_t nrf_dfu_bank1_start_addr(void) +{ + uint32_t bank0_addr = nrf_dfu_bank0_start_addr(); + return ALIGN_TO_PAGE(bank0_addr + s_dfu_settings.bank_0.image_size); +} + + +uint32_t nrf_dfu_app_start_address(void) +{ + return nrf_dfu_bank0_start_addr(); +} + + +uint32_t nrf_dfu_softdevice_start_address(void) +{ + return MBR_SIZE; +} + + +uint32_t nrf_dfu_cache_prepare(const uint32_t required_size, bool single_bank, bool keep_app, bool keep_softdevice) +{ + ret_code_t err_code; + bool cache_too_small; + enum + { + INITIAL_DELETE_APP = 0, + APP_DELETED_DELETE_SOFTDEVICE = 1, + SOFTDEVICE_DELETED = 2 + } pass; + + NRF_LOG_DEBUG("Enter nrf_dfu_cache_prepare()"); + NRF_LOG_DEBUG("required_size: 0x%x.", required_size); + NRF_LOG_DEBUG("single_bank: %s.", single_bank ? "true" : "false"); + NRF_LOG_DEBUG("keep_app: %s.", keep_app ? "true" : "false"); + NRF_LOG_DEBUG("keep_softdevice: %s.", keep_softdevice ? "true" : "false"); + NRF_LOG_DEBUG("SD_PRESENT: %s.", SD_PRESENT ? "true" : "false"); + NRF_LOG_DEBUG("Bank contents:"); + NRF_LOG_DEBUG("Bank 0 code: 0x%02x: Size: 0x%x", s_dfu_settings.bank_0.bank_code, s_dfu_settings.bank_0.image_size); + NRF_LOG_DEBUG("Bank 1 code: 0x%02x: Size: 0x%x", s_dfu_settings.bank_1.bank_code, s_dfu_settings.bank_1.image_size); + + // Pass 0 deletes the app if necessary or requested, and if so, proceeds to pass 1. + // Pass 1 deletes the SoftDevice if necessary or requested, and if so, proceeds to pass 2. + // Pass 2 does a last size check. + for (pass = INITIAL_DELETE_APP; pass <= SOFTDEVICE_DELETED; pass++) + { + uint32_t cache_address; + const uint32_t bootloader_start_addr = BOOTLOADER_START_ADDR; // Assign to a variable to prevent warning in Keil 4. + bool keep_firmware = true; + bool delete_more; + + switch (pass) + { + case INITIAL_DELETE_APP: + cache_address = nrf_dfu_bank1_start_addr(); + + // If there is no app, keep_app should be assumed false, so we can free up more space. + keep_firmware = keep_app && (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP); + break; + + case APP_DELETED_DELETE_SOFTDEVICE: + cache_address = nrf_dfu_bank0_start_addr(); + + // If there is no SoftDevice, keep_SoftDevice should be assumed true, because there is + // no point to continuing since the SoftDevice is the last firmware that can be deleted. + keep_firmware = keep_softdevice || !SD_PRESENT; + break; + + case SOFTDEVICE_DELETED: + cache_address = nrf_dfu_softdevice_start_address(); + break; + + default: + ASSERT(false); + cache_address = 0; + break; + } + + ASSERT(cache_address <= DFU_REGION_END(bootloader_start_addr)); + cache_too_small = required_size > (DFU_REGION_END(bootloader_start_addr) - cache_address); + delete_more = cache_too_small || single_bank; // Delete app or SoftDevice only if we need more room, or if single bank is requested. + + NRF_LOG_DEBUG("pass: %d.", pass); + NRF_LOG_DEBUG("cache_address: 0x%x.", cache_address); + NRF_LOG_DEBUG("cache_too_small: %s.", cache_too_small ? "true" : "false"); + NRF_LOG_DEBUG("keep_firmware: %s.", keep_firmware ? "true" : "false"); + NRF_LOG_DEBUG("delete_more: %s.", delete_more ? "true" : "false"); + + if (!delete_more || keep_firmware || (pass >= SOFTDEVICE_DELETED)) + { + // Stop, done. + break; + } + } + + if (cache_too_small) + { + NRF_LOG_WARNING("Aborting. Cannot fit new firmware on device"); + err_code = NRF_ERROR_NO_MEM; + } + else + { + // Room was found. Make the necessary preparations for receiving update. + +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) + if (pass >= SOFTDEVICE_DELETED) + { + NRF_LOG_DEBUG("Invalidating SoftDevice."); + nrf_dfu_softdevice_invalidate(); + } +#endif + if (pass >= APP_DELETED_DELETE_SOFTDEVICE) + { + NRF_LOG_DEBUG("Invalidating app."); + nrf_dfu_bank_invalidate(&s_dfu_settings.bank_0); + } + + err_code = NRF_SUCCESS; + } + + return err_code; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_utils.h b/core/embed/ble_bootloader/dfu/nrf_dfu_utils.h new file mode 100644 index 0000000000..0a5c552f54 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_utils.h @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_utils DFU utilities + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_UTILS_H__ +#define NRF_DFU_UTILS_H__ + +#include +#include +#include "nrf_dfu_types.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Round up val to the next page boundary + */ +#define ALIGN_TO_PAGE(val) ALIGN_NUM((CODE_PAGE_SIZE), (val)) + + +/** @brief Function for getting the start address of bank 0. + * + * @note Bank 0 starts after the SoftDevice if a SoftDevice is present. + * + * @return The start address of bank 0. + */ +uint32_t nrf_dfu_bank0_start_addr(void); + + +/** @brief Function for getting the start address of bank 1. + * + * @return The start address of bank 1. + */ +uint32_t nrf_dfu_bank1_start_addr(void); + + +/** @brief Function for getting the start address of the app. + * + * @return The start address of the bootable app. + */ +uint32_t nrf_dfu_app_start_address(void); + + +/** @brief Function for getting the start address of the SoftDevice. + * + * @return The start address of the SoftDevivce. + */ +uint32_t nrf_dfu_softdevice_start_address(void); + + +/** @brief Function for finding and preparing a place in flash in which to store a DFU update. + * + * @details This function checks the size requirements and selects a location for + * placing the cache of the DFU images. + * The function tries to find enough space after the existing firmwares. If there is not + * enough space, the present application is deleted. If there is still not enough space, + * the SoftDevice is deleted. + * If @p single_bank is true, the default behavior is to immediately delete the app and + * SoftDevice as necessary to place the new firmware at its intended location. If the + * intended location cannot be made available, or if the update is a bootloader update, + * the update will be a dual bank update, and nothing will be deleted by this function + * except when needed for size. + * If @p keep_app is true, the app is never deleted by this function. Likewise if @p + * keep_softdevice is true, the SoftDevice is never deleted by this function. + * If the new firmware cannot fit within the constraints, nothing is deleted and the + * function fails. + * + * @param[in] required_size Requirements for the size of the new image. + * @param[in] single_bank Whether to put the firmware directly where it's meant to go. + * @p keep_app and @p keep_softdevice take precedence over this. + * @param[in] keep_app True to ensure the app is not deleted by this function. This + * effectively enforces dual bank update. + * @param[out] keep_softdevice True to ensure the SoftDevice is not deleted by this function. + * + * @retval NRF_SUCCESS If a cache location was found for the DFU process. + * @retval NRF_ERROR_NO_MEM If there is not enough space available to receive the update. + * Nothing has been deleted. + */ +uint32_t nrf_dfu_cache_prepare(uint32_t required_size, bool single_bank, bool keep_app, bool keep_softdevice); + + +/**@brief Function for making sure a SoftDevice is not recognized as such anymore. + * + * @details It works by overwriting the magic number of the SoftDevice with 0s. The + * magic number is used throughout the bootloader to detect whether a SoftDevice + * is present. + * + * @warning This function should only be called when both banks are already invalid. + * because the (implicit) position of the banks will shift when the SoftDevice + * is invalidated. + */ +void nrf_dfu_softdevice_invalidate(void); + + +/**@brief Function for making sure a bank is not copied or booted. + * + * @details This also sets the size of the bank to 0. + * + * @param[in] p_bank Pointer to the bank to be invalidated. + */ +void nrf_dfu_bank_invalidate(nrf_dfu_bank_t * const p_bank); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_UTILS_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/nrf_dfu_validation.c b/core/embed/ble_bootloader/dfu/nrf_dfu_validation.c similarity index 98% rename from core/embed/ble_bootloader/nrf_dfu_validation.c rename to core/embed/ble_bootloader/dfu/nrf_dfu_validation.c index 09b6de086c..fd46fbfcfb 100644 --- a/core/embed/ble_bootloader/nrf_dfu_validation.c +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_validation.c @@ -48,8 +48,6 @@ #include "pb_decode.h" #include "dfu-cc.pb.h" #include "crc32.h" -#include "nrf_crypto.h" -#include "nrf_crypto_shared.h" #include "nrf_assert.h" #include "nrf_dfu_validation.h" #include "nrf_dfu_ver_validation.h" @@ -382,7 +380,7 @@ static nrf_dfu_result_t nrf_dfu_validation_signature_check(uint32_t sigmask, if (sectrue != check_trezor_sig(hash_digest, BLAKE2S_DIGEST_LENGTH, NRF_BOOTLOADER_KEY_M, NRF_BOOTLOADER_KEY_N, sigmask, NRF_BOOTLOADER_KEYS, signature)){ NRF_LOG_ERROR("Signature failed"); - err_code = NRF_ERROR_CRYPTO_ECDSA_INVALID_SIGNATURE; + err_code = NRF_DFU_ERROR_INVALID_SIGNATURE; } if (err_code != NRF_SUCCESS) @@ -635,13 +633,13 @@ static bool nrf_dfu_validation_hash_ok(uint8_t const * p_hash, uint32_t src_addr blake2s( (uint8_t*)src_addr, data_len, hash, BLAKE2S_DIGEST_LENGTH); - if (memcmp(hash, p_hash, NRF_CRYPTO_HASH_SIZE_SHA256) != 0) + if (memcmp(hash, p_hash, BLAKE2S_DIGEST_LENGTH) != 0) { NRF_LOG_WARNING("Hash verification failed."); NRF_LOG_DEBUG("Expected FW hash:") - NRF_LOG_HEXDUMP_DEBUG(p_hash, NRF_CRYPTO_HASH_SIZE_SHA256); + NRF_LOG_HEXDUMP_DEBUG(p_hash, BLAKE2S_DIGEST_LENGTH); NRF_LOG_DEBUG("Actual FW hash:") - NRF_LOG_HEXDUMP_DEBUG(hash, NRF_CRYPTO_HASH_SIZE_SHA256); + NRF_LOG_HEXDUMP_DEBUG(hash, BLAKE2S_DIGEST_LENGTH); NRF_LOG_FLUSH(); result = false; @@ -881,7 +879,7 @@ bool nrf_dfu_validation_boot_validate(boot_validation_t const * p_validation, ui nrf_dfu_result_t res_code = nrf_dfu_validation_signature_check( p_validation->sigmask, p_validation->bytes, - NRF_CRYPTO_ECDSA_SECP256R1_SIGNATURE_SIZE, + 64, p_data, data_len); return (res_code == NRF_DFU_RES_CODE_SUCCESS); diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_validation.h b/core/embed/ble_bootloader/dfu/nrf_dfu_validation.h new file mode 100644 index 0000000000..79fdbc52a3 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_validation.h @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_dfu_validation Validation + * @{ + * @ingroup nrf_dfu + */ + +#ifndef __NRF_DFU_VALIDATION_H +#define __NRF_DFU_VALIDATION_H + +#include "stdint.h" +#include "sdk_errors.h" +#include "dfu-cc.pb.h" +#include "nrf_dfu_handling_error.h" + +/** + * @brief Function for module initialization. + * + * Function checks if there is a valid init packet in DFU settings written in flash. + */ +void nrf_dfu_validation_init(void); + +/** + * @brief Function called on reception of init command creation request. + * + * @param[in] size Size of incoming init packet. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_init_cmd_create(uint32_t size); + +/** + * @brief Function called on reception of fragment of init command. + * + * @param[in] p_data Init command fragment. + * @param[in] length Init command fragment size. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_init_cmd_append(uint8_t const * p_data, uint32_t length); + +/** + * @brief Function for getting init command status. + * + * @param[out] p_offset Current offset. + * @param[out] p_crc Current CRC. + * @param[out] p_max_size Maximum size of init command. + */ +void nrf_dfu_validation_init_cmd_status_get(uint32_t * p_offset, + uint32_t * p_crc, + uint32_t * p_max_size); + +/** + * @brief Function for inquiring whether a valid init command has been received. + * + * @return true if there is a valid init command. This can be true at boot time + * if the device was reset during a DFU operation. + */ +bool nrf_dfu_validation_init_cmd_present(void); + +/** + * @brief Function for validating init command and retrieving the address and length of the firmware. + * + * If init command is successfully validated Bank 1 details are written to out parameters. + * + * Until @ref nrf_dfu_validation_init_cmd_create is called, this function can be called + * again after the first time without side effects to retrieve address and length. + * + * @param[out] p_dst_data_addr Start address of received data, if validation is successful. + * @param[out] p_data_len Expected length of received data, if validation is successful. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_init_cmd_execute(uint32_t * p_dst_data_addr, + uint32_t * p_data_len); + +/** + * @brief Function for validating the init command. + * + * @return Operation result. See @ref nrf_dfu_result_t. + */ +nrf_dfu_result_t nrf_dfu_validation_prevalidate(void); + +/** + * @brief Function for validating the firmware for booting. + * + * @param[in] p_validation Validation parameters. + * @param[in] data_addr Start address of the firmware. + * @param[in] data_len Length of the firmware. + * + * @return Whether the firmware is valid for booting. + */ +bool nrf_dfu_validation_boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len); + +/** + * @brief Function for postvalidating the update after all data is received. + * + * @param[in] data_addr Start address of the received data. + * @param[in] data_len Length of the received data. + * + * @return Operation result. See @ref nrf_dfu_result_t. + */ +nrf_dfu_result_t nrf_dfu_validation_post_data_execute(uint32_t data_addr, uint32_t data_len); + +/** + * @brief Function for preparing the update for activation. + * + * This function is called after a reset, after all data is received. This function also runs + * @ref nrf_dfu_validation_post_data_execute internally. If this succeeds, the update is + * activated by the activation machinery in the bootloader the next time it runs. + * + * @note The caller must have permissions to edit the relevant entries in the settings. + * + * @param[in] data_addr Start address of the received data. + * @param[in] data_len Length of the received data. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_activation_prepare(uint32_t data_addr, uint32_t data_len); + +/** + * @brief Function to execute on a validated external app. + * + * @details This function is called once all data is received with the parameter + * @p is_boot set to false. The function is called during bootup with the parameter + * set to true. + * + * + * + * @note This function requires that @ref NRF_DFU_SUPPORTS_EXTERNAL_APP is set to 1. + * It is up to the user to implement this function. + * + * @warning Parameter @p is_trusted must be used to ensure that no loss of security of process can happen. + * This parameter should only be set if the function is called after a root-of-trust + * reset on the device. + * + * Parameter @p is_trusted can be used for the following: + * - Ensuring that an external application is run only once (after root-of-trust). + * - Ensuring that a bank flag or any other flash access can only happen after root-of-trust. + * - Ensuring that the device reaches the correct state after a power failure on the device. + * + * @param[in] p_init Init command for the firmware upgrade. + * @param[in] is_trusted Must be set to true if this is called after root-of-trust boot. + * Must be set to false if this is called from DFU mode or background + * DFU operation. + * + * @return Operation result. see @ref nrf_dfu_result_t. + */ +nrf_dfu_result_t nrf_dfu_validation_post_external_app_execute(dfu_InitCommand const * p_init, bool is_trusted); + +/** +* @brief Function to check if there is a valid external app in Bank 1. +* +* @returns True if valid external app, otherwise false. +*/ +bool nrf_dfu_validation_valid_external_app(void); + +#endif //__NRF_DFU_VALIDATION_H + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c b/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c new file mode 100644 index 0000000000..3d811a2e24 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c @@ -0,0 +1,311 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_bootloader_info.h" +#include "nrf_assert.h" +#include "dfu-cc.pb.h" +#include "nrf_dfu_ver_validation.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_ver_validation +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +/** @brief Macro for reading the Firmware ID of a SoftDevice at a given base address. + */ +#ifndef _SD_FWID_GET +#define _SD_FWID_GET(baseaddr) SD_OFFSET_GET_UINT16(baseaddr, 0x0C) +#endif + +#define EXT_ERR(err) (nrf_dfu_result_t)((uint32_t)NRF_DFU_RES_CODE_EXT_ERROR + (uint32_t)err) + +static bool sd_req_check(uint32_t const * p_sd_req, uint8_t sd_req_cnt, bool accept_any) +{ + bool result = false; + for (uint8_t i = 0; i < sd_req_cnt; i++) + { + if ((SD_PRESENT && (p_sd_req[i] == _SD_FWID_GET(MBR_SIZE))) || + (accept_any && (p_sd_req[i] == SD_REQ_ANY_VERSION)) + ) + { + // Found a matching sd_req field. sd_req is ok. + result = true; + break; + } + } + return result; +} + + +static bool sd_req_ok(dfu_InitCommand const * p_init) +{ + ASSERT(p_init != NULL); + bool result; +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + // The bootloader needs the SoftDevice, so disabling NRF_DFU_APP_DOWNGRADE_PREVENTION + // should not be applied to SoftDevice updates. + const bool prevent_downgrade = NRF_DFU_APP_DOWNGRADE_PREVENTION || (p_init->type == DFU_FW_TYPE_SOFTDEVICE); +#else + const bool prevent_downgrade = NRF_DFU_APP_DOWNGRADE_PREVENTION; +#endif + + if (SD_PRESENT) + { + if (p_init->sd_req_count == 0) + { + result = false; + } + else if (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD) + { + result = sd_req_check(p_init->sd_req, + p_init->sd_req_count, + (p_init->type == dfu_FwType_EXTERNAL_APPLICATION)); + } + else if (p_init->type == dfu_FwType_APPLICATION) + { + // The application wants to overwrite the SoftDevice. + if (prevent_downgrade && (p_init->sd_req_count > 1) && (p_init->sd_req[0] == SD_REQ_APP_OVERWRITES_SD)) + { + // The application can overwrite the SD if sd_req[0] == 0 and table has the FWID of the current SD. + result = sd_req_check(p_init->sd_req, p_init->sd_req_count, false); + + // Prevent BLE/ANT bootloaders from allowing applications overwriting the SoftDevice. +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + result = false; +#endif + } + else + { + result = true; + } + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + else if(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + // Won't accept FW upgrade using external application to + // enforce replacing SoftDevice (SD_REQ_APP_OVERWRITES_SD) + result = false; + } +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + else + { + // Don't allow SoftDevice updates which assume no SD is present already. + result = !prevent_downgrade || (p_init->type != dfu_FwType_SOFTDEVICE); + } + } + + else + { + if (p_init->sd_req_count && (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD)) + { + // Fail if there is no SD and the update requires SD. The special "any" FWID is valid + // for external apps only. + result = false; +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + result = sd_req_check(p_init->sd_req, + p_init->sd_req_count, + (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)); +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + } + else + { + // If there is no SD and update has SD it is accepted only if it has a fw_version. + result = !prevent_downgrade || p_init->has_fw_version; + } + } + return result; +} + + +static bool fw_hash_type_ok(dfu_InitCommand const * p_init) +{ + ASSERT(p_init != NULL); + + return (p_init->hash.hash_type == dfu_HashType_SHA256); +} + + +static bool fw_version_required(dfu_FwType new_fw_type) +{ + bool result = true; + + if (new_fw_type == dfu_FwType_SOFTDEVICE) + { + result = false; // fw_version is optional in SoftDevice updates. If present, it will be checked against the app version. + } + else if (new_fw_type == dfu_FwType_APPLICATION) + { + result = NRF_DFU_APP_DOWNGRADE_PREVENTION; // fw_version is configurable in app updates. + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP +#if !NRF_DFU_EXTERNAL_APP_VERSIONING + else if (new_fw_type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + return false; + } +#endif //!NRF_DFU_EXTERNAL_APP_VERSIONING +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + + return result; +} + + +static bool fw_type_ok(dfu_InitCommand const * p_init) +{ + ASSERT(p_init != NULL); + + return ((p_init->has_type) + && ( (p_init->type == dfu_FwType_APPLICATION) + || (p_init->type == dfu_FwType_SOFTDEVICE) + || (p_init->type == dfu_FwType_BOOTLOADER) + || (p_init->type == dfu_FwType_SOFTDEVICE_BOOTLOADER) +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + || (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + )); + +} + + +#ifndef NRF_DFU_APP_ACCEPT_SAME_VERSION +#define NRF_DFU_APP_ACCEPT_SAME_VERSION 1 +#endif + + +// This function assumes p_init->has_fw_version. +static bool fw_version_ok(dfu_InitCommand const * p_init) +{ + ASSERT(p_init != NULL); + ASSERT(p_init->has_fw_version); + + if ((p_init->type == dfu_FwType_APPLICATION) || + (p_init->type == dfu_FwType_SOFTDEVICE)) + { + if (!NRF_DFU_APP_DOWNGRADE_PREVENTION) + { + return true; + } + else if ((p_init->fw_version > s_dfu_settings.app_version)) + { + return true; + } + else if ((p_init->fw_version == s_dfu_settings.app_version)) + { + return NRF_DFU_APP_ACCEPT_SAME_VERSION; + } + else + { + return false; + } + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP +#if NRF_DFU_EXTERNAL_APP_VERSIONING + else if (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + return (p_init->fw_version >= s_dfu_settings.app_version); + } +#else + else if(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + return true; + } +#endif // NRF_DFU_EXTERNAL_APP_VERSIONING +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + else + { + return (p_init->fw_version > s_dfu_settings.bootloader_version); + } +} + + +nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_InitCommand const * p_init) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + if (!fw_type_ok(p_init)) + { + NRF_LOG_ERROR("Invalid firmware type."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + } + else if (!fw_hash_type_ok(p_init)) + { + NRF_LOG_ERROR("Invalid hash type."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_WRONG_HASH_TYPE); + } + else if (!NRF_DFU_DEBUG || + (NRF_DFU_DEBUG && ((p_init->has_is_debug == false) || (p_init->is_debug == false)))) + { + if (p_init->has_hw_version == false) + { + NRF_LOG_ERROR("No HW version."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + } + else if (p_init->hw_version != NRF_DFU_HW_VERSION) + { + NRF_LOG_WARNING("Faulty HW version."); + ret_val = EXT_ERR( NRF_DFU_EXT_ERROR_HW_VERSION_FAILURE); + } + + else if (!sd_req_ok(p_init)) + { + NRF_LOG_WARNING("SD req not met."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_SD_VERSION_FAILURE); + } + else if (p_init->has_fw_version) + { + if (!fw_version_ok(p_init)) + { + NRF_LOG_WARNING("FW version too low."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_FW_VERSION_FAILURE); + } + } + else + { + if (fw_version_required(p_init->type)) + { + NRF_LOG_ERROR("FW version missing."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + } + } + } + return ret_val; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.h b/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.h new file mode 100644 index 0000000000..d17d5f02f6 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.h @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __NRF_DFU_VER_VALIDATION_H +#define __NRF_DFU_VER_VALIDATION_H + +#include "stdint.h" +#include "sdk_errors.h" +#include "nrf_dfu_handling_error.h" +#include "dfu-cc.pb.h" + +/** @brief SD_REQ field value which indicates that Softdevice can be overwritten by the application. */ +#define SD_REQ_APP_OVERWRITES_SD 0 + +/** @brief SD_REQ_ANY_VERSION field value which indicates that any SoftDevice version is valid. + * + * @note This is used by external application in case SoftDevice version compatibility isn't needed. + */ +#define SD_REQ_ANY_VERSION (0xFFFE) + +/** + * @brief Function for validating version of new firmware. + * + * @return NRF_DFU_RES_CODE_SUCCESS if successful or error code otherwise + */ +nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_InitCommand const * p_init); + +#endif //__NRF_DFU_VER_VALIDATION_H diff --git a/core/embed/ble_bootloader/memory.ld b/core/embed/ble_bootloader/memory.ld index 5b825a6aab..cba932d57d 100644 --- a/core/embed/ble_bootloader/memory.ld +++ b/core/embed/ble_bootloader/memory.ld @@ -5,7 +5,7 @@ GROUP(-lgcc -lc -lnosys) MEMORY { - FLASH (rx) : ORIGIN = 0x60000, LENGTH = 0x1e000 + FLASH (rx) : ORIGIN = 0x70000, LENGTH = 0xe000 RAM (rwx) : ORIGIN = 0x20002ae8, LENGTH = 0x1d518 uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4 bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 diff --git a/core/embed/ble_bootloader/sdk_config.h b/core/embed/ble_bootloader/sdk_config.h index 245e61ae80..2de38736ea 100644 --- a/core/embed/ble_bootloader/sdk_config.h +++ b/core/embed/ble_bootloader/sdk_config.h @@ -788,7 +788,7 @@ // NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED - Enable the micro-ecc backend. //========================================================== #ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED -#define NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED 1 +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED 0 #endif // NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1_ENABLED - Enable secp192r1 (NIST 192-bit) curve diff --git a/core/embed/ble_firmware/memory.ld b/core/embed/ble_firmware/memory.ld index 5f60d7ab89..6a607e0d97 100644 --- a/core/embed/ble_firmware/memory.ld +++ b/core/embed/ble_firmware/memory.ld @@ -5,7 +5,7 @@ GROUP(-lgcc -lc -lnosys) MEMORY { - FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0x39000 + FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0x49000 RAM (rwx) : ORIGIN = 0x20002ae8, LENGTH = 0x1d518 } diff --git a/core/embed/ble_bootloader/uecc/.gitignore b/core/embed/ble_firmware/uecc/.gitignore similarity index 100% rename from core/embed/ble_bootloader/uecc/.gitignore rename to core/embed/ble_firmware/uecc/.gitignore diff --git a/core/embed/ble_bootloader/uecc/LICENSE.txt b/core/embed/ble_firmware/uecc/LICENSE.txt similarity index 100% rename from core/embed/ble_bootloader/uecc/LICENSE.txt rename to core/embed/ble_firmware/uecc/LICENSE.txt diff --git a/core/embed/ble_bootloader/uecc/README.md b/core/embed/ble_firmware/uecc/README.md similarity index 100% rename from core/embed/ble_bootloader/uecc/README.md rename to core/embed/ble_firmware/uecc/README.md diff --git a/core/embed/ble_bootloader/uecc/asm_arm.inc b/core/embed/ble_firmware/uecc/asm_arm.inc similarity index 100% rename from core/embed/ble_bootloader/uecc/asm_arm.inc rename to core/embed/ble_firmware/uecc/asm_arm.inc diff --git a/core/embed/ble_bootloader/uecc/asm_arm_mult_square.inc b/core/embed/ble_firmware/uecc/asm_arm_mult_square.inc similarity index 100% rename from core/embed/ble_bootloader/uecc/asm_arm_mult_square.inc rename to core/embed/ble_firmware/uecc/asm_arm_mult_square.inc diff --git a/core/embed/ble_bootloader/uecc/asm_arm_mult_square_umaal.inc b/core/embed/ble_firmware/uecc/asm_arm_mult_square_umaal.inc similarity index 100% rename from core/embed/ble_bootloader/uecc/asm_arm_mult_square_umaal.inc rename to core/embed/ble_firmware/uecc/asm_arm_mult_square_umaal.inc diff --git a/core/embed/ble_bootloader/uecc/asm_avr.inc b/core/embed/ble_firmware/uecc/asm_avr.inc similarity index 100% rename from core/embed/ble_bootloader/uecc/asm_avr.inc rename to core/embed/ble_firmware/uecc/asm_avr.inc diff --git a/core/embed/ble_bootloader/uecc/asm_avr_mult_square.inc b/core/embed/ble_firmware/uecc/asm_avr_mult_square.inc similarity index 100% rename from core/embed/ble_bootloader/uecc/asm_avr_mult_square.inc rename to core/embed/ble_firmware/uecc/asm_avr_mult_square.inc diff --git a/core/embed/ble_bootloader/uecc/curve-specific.inc b/core/embed/ble_firmware/uecc/curve-specific.inc similarity index 100% rename from core/embed/ble_bootloader/uecc/curve-specific.inc rename to core/embed/ble_firmware/uecc/curve-specific.inc diff --git a/core/embed/ble_bootloader/uecc/emk_project.py b/core/embed/ble_firmware/uecc/emk_project.py similarity index 100% rename from core/embed/ble_bootloader/uecc/emk_project.py rename to core/embed/ble_firmware/uecc/emk_project.py diff --git a/core/embed/ble_bootloader/uecc/emk_rules.py b/core/embed/ble_firmware/uecc/emk_rules.py similarity index 100% rename from core/embed/ble_bootloader/uecc/emk_rules.py rename to core/embed/ble_firmware/uecc/emk_rules.py diff --git a/core/embed/ble_bootloader/uecc/examples/ecc_test/ecc_test.ino b/core/embed/ble_firmware/uecc/examples/ecc_test/ecc_test.ino similarity index 100% rename from core/embed/ble_bootloader/uecc/examples/ecc_test/ecc_test.ino rename to core/embed/ble_firmware/uecc/examples/ecc_test/ecc_test.ino diff --git a/core/embed/ble_bootloader/uecc/library.properties b/core/embed/ble_firmware/uecc/library.properties similarity index 100% rename from core/embed/ble_bootloader/uecc/library.properties rename to core/embed/ble_firmware/uecc/library.properties diff --git a/core/embed/ble_bootloader/uecc/platform-specific.inc b/core/embed/ble_firmware/uecc/platform-specific.inc similarity index 100% rename from core/embed/ble_bootloader/uecc/platform-specific.inc rename to core/embed/ble_firmware/uecc/platform-specific.inc diff --git a/core/embed/ble_bootloader/uecc/scripts/mult_arm.py b/core/embed/ble_firmware/uecc/scripts/mult_arm.py similarity index 100% rename from core/embed/ble_bootloader/uecc/scripts/mult_arm.py rename to core/embed/ble_firmware/uecc/scripts/mult_arm.py diff --git a/core/embed/ble_bootloader/uecc/scripts/mult_avr.py b/core/embed/ble_firmware/uecc/scripts/mult_avr.py similarity index 100% rename from core/embed/ble_bootloader/uecc/scripts/mult_avr.py rename to core/embed/ble_firmware/uecc/scripts/mult_avr.py diff --git a/core/embed/ble_bootloader/uecc/scripts/mult_avr_extra.py b/core/embed/ble_firmware/uecc/scripts/mult_avr_extra.py similarity index 100% rename from core/embed/ble_bootloader/uecc/scripts/mult_avr_extra.py rename to core/embed/ble_firmware/uecc/scripts/mult_avr_extra.py diff --git a/core/embed/ble_bootloader/uecc/scripts/square_arm.py b/core/embed/ble_firmware/uecc/scripts/square_arm.py similarity index 100% rename from core/embed/ble_bootloader/uecc/scripts/square_arm.py rename to core/embed/ble_firmware/uecc/scripts/square_arm.py diff --git a/core/embed/ble_bootloader/uecc/scripts/square_avr.py b/core/embed/ble_firmware/uecc/scripts/square_avr.py similarity index 100% rename from core/embed/ble_bootloader/uecc/scripts/square_avr.py rename to core/embed/ble_firmware/uecc/scripts/square_avr.py diff --git a/core/embed/ble_bootloader/uecc/test/ecdsa_test_vectors.c b/core/embed/ble_firmware/uecc/test/ecdsa_test_vectors.c similarity index 100% rename from core/embed/ble_bootloader/uecc/test/ecdsa_test_vectors.c rename to core/embed/ble_firmware/uecc/test/ecdsa_test_vectors.c diff --git a/core/embed/ble_bootloader/uecc/test/emk_rules.py b/core/embed/ble_firmware/uecc/test/emk_rules.py similarity index 100% rename from core/embed/ble_bootloader/uecc/test/emk_rules.py rename to core/embed/ble_firmware/uecc/test/emk_rules.py diff --git a/core/embed/ble_bootloader/uecc/test/public_key_test_vectors.c b/core/embed/ble_firmware/uecc/test/public_key_test_vectors.c similarity index 100% rename from core/embed/ble_bootloader/uecc/test/public_key_test_vectors.c rename to core/embed/ble_firmware/uecc/test/public_key_test_vectors.c diff --git a/core/embed/ble_bootloader/uecc/test/test_compress.c b/core/embed/ble_firmware/uecc/test/test_compress.c similarity index 100% rename from core/embed/ble_bootloader/uecc/test/test_compress.c rename to core/embed/ble_firmware/uecc/test/test_compress.c diff --git a/core/embed/ble_bootloader/uecc/test/test_compute.c b/core/embed/ble_firmware/uecc/test/test_compute.c similarity index 100% rename from core/embed/ble_bootloader/uecc/test/test_compute.c rename to core/embed/ble_firmware/uecc/test/test_compute.c diff --git a/core/embed/ble_bootloader/uecc/test/test_ecdh.c b/core/embed/ble_firmware/uecc/test/test_ecdh.c similarity index 100% rename from core/embed/ble_bootloader/uecc/test/test_ecdh.c rename to core/embed/ble_firmware/uecc/test/test_ecdh.c diff --git a/core/embed/ble_bootloader/uecc/test/test_ecdsa.c b/core/embed/ble_firmware/uecc/test/test_ecdsa.c similarity index 100% rename from core/embed/ble_bootloader/uecc/test/test_ecdsa.c rename to core/embed/ble_firmware/uecc/test/test_ecdsa.c diff --git a/core/embed/ble_bootloader/uecc/test/test_ecdsa_deterministic.c.example b/core/embed/ble_firmware/uecc/test/test_ecdsa_deterministic.c.example similarity index 100% rename from core/embed/ble_bootloader/uecc/test/test_ecdsa_deterministic.c.example rename to core/embed/ble_firmware/uecc/test/test_ecdsa_deterministic.c.example diff --git a/core/embed/ble_bootloader/uecc/types.h b/core/embed/ble_firmware/uecc/types.h similarity index 100% rename from core/embed/ble_bootloader/uecc/types.h rename to core/embed/ble_firmware/uecc/types.h diff --git a/core/embed/ble_bootloader/uecc/uECC.c b/core/embed/ble_firmware/uecc/uECC.c similarity index 100% rename from core/embed/ble_bootloader/uecc/uECC.c rename to core/embed/ble_firmware/uecc/uECC.c diff --git a/core/embed/ble_bootloader/uecc/uECC.h b/core/embed/ble_firmware/uecc/uECC.h similarity index 100% rename from core/embed/ble_bootloader/uecc/uECC.h rename to core/embed/ble_firmware/uecc/uECC.h diff --git a/core/embed/ble_bootloader/uecc/uECC_vli.h b/core/embed/ble_firmware/uecc/uECC_vli.h similarity index 100% rename from core/embed/ble_bootloader/uecc/uECC_vli.h rename to core/embed/ble_firmware/uecc/uECC_vli.h diff --git a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.c b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.c index 79d9e5d2d0..769e6d3a20 100644 --- a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.c +++ b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.c @@ -1,31 +1,123 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ +/* Generated by nanopb-0.3.6-dev at Tue Sep 11 14:37:18 2018. */ #include "dfu-cc.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 + +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif -PB_BIND(dfu_Hash, dfu_Hash, AUTO) - - -PB_BIND(dfu_BootValidation, dfu_BootValidation, AUTO) - - -PB_BIND(dfu_InitCommand, dfu_InitCommand, 2) - - -PB_BIND(dfu_Command, dfu_Command, 2) - - -PB_BIND(dfu_SignedCommand, dfu_SignedCommand, 2) - - -PB_BIND(dfu_Packet, dfu_Packet, 2) - +const bool dfu_init_command_is_debug_default = false; +const pb_field_t dfu_hash_fields[3] = { + PB_FIELD( 1, UENUM , REQUIRED, STATIC , FIRST, dfu_hash_t, hash_type, hash_type, 0), + PB_FIELD( 2, BYTES , REQUIRED, STATIC , OTHER, dfu_hash_t, hash, hash_type, 0), + PB_LAST_FIELD +}; + +const pb_field_t dfu_boot_validation_fields[3] = { + PB_FIELD( 1, UENUM , REQUIRED, STATIC , FIRST, dfu_boot_validation_t, type, type, 0), + PB_FIELD( 2, BYTES , REQUIRED, STATIC , OTHER, dfu_boot_validation_t, bytes, type, 0), + PB_LAST_FIELD +}; + +const pb_field_t dfu_init_command_fields[11] = { + PB_FIELD( 1, UINT32 , OPTIONAL, STATIC , FIRST, dfu_init_command_t, fw_version, fw_version, 0), + PB_FIELD( 2, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, hw_version, fw_version, 0), + PB_FIELD( 3, UINT32 , REPEATED, STATIC , OTHER, dfu_init_command_t, sd_req, hw_version, 0), + PB_FIELD( 4, UENUM , OPTIONAL, STATIC , OTHER, dfu_init_command_t, type, sd_req, 0), + PB_FIELD( 5, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, sd_size, type, 0), + PB_FIELD( 6, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, bl_size, sd_size, 0), + PB_FIELD( 7, UINT32 , OPTIONAL, STATIC , OTHER, dfu_init_command_t, app_size, bl_size, 0), + PB_FIELD( 8, MESSAGE , OPTIONAL, STATIC , OTHER, dfu_init_command_t, hash, app_size, &dfu_hash_fields), + PB_FIELD( 9, BOOL , OPTIONAL, STATIC , OTHER, dfu_init_command_t, is_debug, hash, &dfu_init_command_is_debug_default), + PB_FIELD( 10, MESSAGE , REPEATED, STATIC , OTHER, dfu_init_command_t, boot_validation, is_debug, &dfu_boot_validation_fields), + PB_LAST_FIELD +}; + +const pb_field_t dfu_command_fields[3] = { + PB_FIELD( 1, UENUM , OPTIONAL, STATIC , FIRST, dfu_command_t, op_code, op_code, 0), + PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, dfu_command_t, init, op_code, &dfu_init_command_fields), + PB_LAST_FIELD +}; + +const pb_field_t dfu_signed_command_fields[4] = { + PB_FIELD( 1, MESSAGE , REQUIRED, STATIC , FIRST, dfu_signed_command_t, command, command, &dfu_command_fields), + PB_FIELD( 2, UENUM , REQUIRED, STATIC , OTHER, dfu_signed_command_t, signature_type, command, 0), + PB_FIELD( 3, BYTES , REQUIRED, STATIC , OTHER, dfu_signed_command_t, signature, signature_type, 0), + PB_LAST_FIELD +}; + +const pb_field_t dfu_packet_fields[3] = { + PB_FIELD( 1, MESSAGE , OPTIONAL, STATIC , FIRST, dfu_packet_t, command, command, &dfu_command_fields), + PB_FIELD( 2, MESSAGE , OPTIONAL, STATIC , OTHER, dfu_packet_t, signed_command, command, &dfu_signed_command_fields), + PB_LAST_FIELD +}; +/* Check that field information fits in pb_field_t */ +#if !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_32BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in 8 or 16 bit + * field descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(dfu_init_command_t, hash) < 65536 && pb_membersize(dfu_init_command_t, boot_validation[0]) < 65536 && pb_membersize(dfu_command_t, init) < 65536 && pb_membersize(dfu_signed_command_t, command) < 65536 && pb_membersize(dfu_packet_t, command) < 65536 && pb_membersize(dfu_packet_t, signed_command) < 65536), YOU_MUST_DEFINE_PB_FIELD_32BIT_FOR_MESSAGES_dfu_hash_dfu_boot_validation_dfu_init_command_dfu_command_dfu_signed_command_dfu_packet) +#endif + +#if !defined(PB_FIELD_16BIT) && !defined(PB_FIELD_32BIT) +/* If you get an error here, it means that you need to define PB_FIELD_16BIT + * compile-time option. You can do that in pb.h or on compiler command line. + * + * The reason you need to do this is that some of your messages contain tag + * numbers or field sizes that are larger than what can fit in the default + * 8 bit descriptors. + */ +PB_STATIC_ASSERT((pb_membersize(dfu_init_command_t, hash) < 256 && pb_membersize(dfu_init_command_t, boot_validation[0]) < 256 && pb_membersize(dfu_command_t, init) < 256 && pb_membersize(dfu_signed_command_t, command) < 256 && pb_membersize(dfu_packet_t, command) < 256 && pb_membersize(dfu_packet_t, signed_command) < 256), YOU_MUST_DEFINE_PB_FIELD_16BIT_FOR_MESSAGES_dfu_hash_dfu_boot_validation_dfu_init_command_dfu_command_dfu_signed_command_dfu_packet) +#endif +/* @@protoc_insertion_point(eof) */ diff --git a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.h b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.h index c22c5fe5c0..377b5a1574 100644 --- a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.h +++ b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.pb.h @@ -1,239 +1,241 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ +/* Generated by nanopb-0.3.6-dev at Tue Sep 11 14:37:18 2018. */ -#ifndef PB_DFU_DFU_CC_PB_H_INCLUDED -#define PB_DFU_DFU_CC_PB_H_INCLUDED +#ifndef PB_DFU_CC_PB_H_INCLUDED +#define PB_DFU_CC_PB_H_INCLUDED #include -#if PB_PROTO_HEADER_VERSION != 40 +/* @@protoc_insertion_point(includes) */ +#if PB_PROTO_HEADER_VERSION != 30 #error Regenerate this file with the current version of nanopb generator. #endif -/* Enum definitions */ -typedef enum _dfu_FwType { - dfu_FwType_APPLICATION = 0, - dfu_FwType_SOFTDEVICE = 1, - dfu_FwType_BOOTLOADER = 2, - dfu_FwType_SOFTDEVICE_BOOTLOADER = 3, - dfu_FwType_EXTERNAL_APPLICATION = 4 -} dfu_FwType; - -typedef enum _dfu_HashType { - dfu_HashType_NO_HASH = 0, - dfu_HashType_CRC = 1, - dfu_HashType_SHA128 = 2, - dfu_HashType_SHA256 = 3, - dfu_HashType_SHA512 = 4 -} dfu_HashType; - -typedef enum _dfu_OpCode { - dfu_OpCode_INIT = 1 -} dfu_OpCode; - -typedef enum _dfu_ValidationType { - dfu_ValidationType_NO_VALIDATION = 0, - dfu_ValidationType_VALIDATE_GENERATED_CRC = 1, - dfu_ValidationType_VALIDATE_SHA256 = 2, - dfu_ValidationType_VALIDATE_ECDSA_P256_SHA256 = 3 -} dfu_ValidationType; - -/* Struct definitions */ -typedef PB_BYTES_ARRAY_T(64) dfu_BootValidation_bytes_t; -typedef struct _dfu_BootValidation { - uint32_t sigmask; - dfu_BootValidation_bytes_t bytes; -} dfu_BootValidation; - -typedef PB_BYTES_ARRAY_T(32) dfu_Hash_hash_t; -typedef struct _dfu_Hash { - dfu_HashType hash_type; - dfu_Hash_hash_t hash; -} dfu_Hash; - -/* Commands data */ -typedef struct _dfu_InitCommand { - bool has_fw_version; - uint32_t fw_version; - bool has_hw_version; - uint32_t hw_version; - pb_size_t sd_req_count; - uint32_t sd_req[16]; - bool has_type; - dfu_FwType type; - bool has_sd_size; - uint32_t sd_size; - bool has_bl_size; - uint32_t bl_size; - bool has_app_size; - uint32_t app_size; - bool has_hash; - dfu_Hash hash; - bool has_is_debug; - bool is_debug; - pb_size_t boot_validation_count; - dfu_BootValidation boot_validation[3]; -} dfu_InitCommand; - -/* Command type */ -typedef struct _dfu_Command { - bool has_op_code; - dfu_OpCode op_code; - bool has_init; - dfu_InitCommand init; -} dfu_Command; - -typedef PB_BYTES_ARRAY_T(64) dfu_SignedCommand_signature_t; -typedef struct _dfu_SignedCommand { - dfu_Command command; - uint32_t sigmask; - dfu_SignedCommand_signature_t signature; -} dfu_SignedCommand; - -/* Parent packet type */ -typedef struct _dfu_Packet { - bool has_command; - dfu_Command command; - bool has_signed_command; - dfu_SignedCommand signed_command; -} dfu_Packet; - - -/* Helper constants for enums */ -#define _dfu_FwType_MIN dfu_FwType_APPLICATION -#define _dfu_FwType_MAX dfu_FwType_EXTERNAL_APPLICATION -#define _dfu_FwType_ARRAYSIZE ((dfu_FwType)(dfu_FwType_EXTERNAL_APPLICATION+1)) - -#define _dfu_HashType_MIN dfu_HashType_NO_HASH -#define _dfu_HashType_MAX dfu_HashType_SHA512 -#define _dfu_HashType_ARRAYSIZE ((dfu_HashType)(dfu_HashType_SHA512+1)) - -#define _dfu_OpCode_MIN dfu_OpCode_INIT -#define _dfu_OpCode_MAX dfu_OpCode_INIT -#define _dfu_OpCode_ARRAYSIZE ((dfu_OpCode)(dfu_OpCode_INIT+1)) - -#define _dfu_ValidationType_MIN dfu_ValidationType_NO_VALIDATION -#define _dfu_ValidationType_MAX dfu_ValidationType_VALIDATE_ECDSA_P256_SHA256 -#define _dfu_ValidationType_ARRAYSIZE ((dfu_ValidationType)(dfu_ValidationType_VALIDATE_ECDSA_P256_SHA256+1)) - - #ifdef __cplusplus extern "C" { #endif +/* Enum definitions */ +typedef enum +{ + DFU_FW_TYPE_APPLICATION = 0, + DFU_FW_TYPE_SOFTDEVICE = 1, + DFU_FW_TYPE_BOOTLOADER = 2, + DFU_FW_TYPE_SOFTDEVICE_BOOTLOADER = 3, + DFU_FW_TYPE_EXTERNAL_APPLICATION = 4 +} dfu_fw_type_t; +#define DFU_FW_TYPE_MIN DFU_FW_TYPE_APPLICATION +#define DFU_FW_TYPE_MAX DFU_FW_TYPE_EXTERNAL_APPLICATION +#define DFU_FW_TYPE_ARRAYSIZE ((dfu_fw_type_t)(DFU_FW_TYPE_EXTERNAL_APPLICATION+1)) + +typedef enum +{ + DFU_HASH_TYPE_NO_HASH = 0, + DFU_HASH_TYPE_CRC = 1, + DFU_HASH_TYPE_SHA128 = 2, + DFU_HASH_TYPE_SHA256 = 3, + DFU_HASH_TYPE_SHA512 = 4 +} dfu_hash_type_t; +#define DFU_HASH_TYPE_MIN DFU_HASH_TYPE_NO_HASH +#define DFU_HASH_TYPE_MAX DFU_HASH_TYPE_SHA512 +#define DFU_HASH_TYPE_ARRAYSIZE ((dfu_hash_type_t)(DFU_HASH_TYPE_SHA512+1)) + +typedef enum +{ + DFU_OP_CODE_INIT = 1 +} dfu_op_code_t; +#define DFU_OP_CODE_MIN DFU_OP_CODE_INIT +#define DFU_OP_CODE_MAX DFU_OP_CODE_INIT +#define DFU_OP_CODE_ARRAYSIZE ((dfu_op_code_t)(DFU_OP_CODE_INIT+1)) + +typedef enum +{ + DFU_VALIDATION_TYPE_NO_VALIDATION = 0, + DFU_VALIDATION_TYPE_VALIDATE_GENERATED_CRC = 1, + DFU_VALIDATION_TYPE_VALIDATE_SHA256 = 2, + DFU_VALIDATION_TYPE_VALIDATE_ECDSA_P256_SHA256 = 3 +} dfu_validation_type_t; +#define DFU_VALIDATION_TYPE_MIN DFU_VALIDATION_TYPE_NO_VALIDATION +#define DFU_VALIDATION_TYPE_MAX DFU_VALIDATION_TYPE_VALIDATE_ECDSA_P256_SHA256 +#define DFU_VALIDATION_TYPE_ARRAYSIZE ((dfu_validation_type_t)(DFU_VALIDATION_TYPE_VALIDATE_ECDSA_P256_SHA256+1)) + +typedef enum +{ + DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256 = 0, + DFU_SIGNATURE_TYPE_ED25519 = 1 +} dfu_signature_type_t; +#define DFU_SIGNATURE_TYPE_MIN DFU_SIGNATURE_TYPE_ECDSA_P256_SHA256 +#define DFU_SIGNATURE_TYPE_MAX DFU_SIGNATURE_TYPE_ED25519 +#define DFU_SIGNATURE_TYPE_ARRAYSIZE ((dfu_signature_type_t)(DFU_SIGNATURE_TYPE_ED25519+1)) + +/* Struct definitions */ +typedef PB_BYTES_ARRAY_T(64) dfu_boot_validation_bytes_t; +typedef struct { + dfu_validation_type_t type; + dfu_boot_validation_bytes_t bytes; +/* @@protoc_insertion_point(struct:dfu_boot_validation_t) */ +} dfu_boot_validation_t; + +typedef PB_BYTES_ARRAY_T(32) dfu_hash_hash_t; +typedef struct { + dfu_hash_type_t hash_type; + dfu_hash_hash_t hash; +/* @@protoc_insertion_point(struct:dfu_hash_t) */ +} dfu_hash_t; + +typedef struct { + bool has_fw_version; + uint32_t fw_version; + bool has_hw_version; + uint32_t hw_version; + pb_size_t sd_req_count; + uint32_t sd_req[16]; + bool has_type; + dfu_fw_type_t type; + bool has_sd_size; + uint32_t sd_size; + bool has_bl_size; + uint32_t bl_size; + bool has_app_size; + uint32_t app_size; + bool has_hash; + dfu_hash_t hash; + bool has_is_debug; + bool is_debug; + pb_size_t boot_validation_count; + dfu_boot_validation_t boot_validation[3]; +/* @@protoc_insertion_point(struct:dfu_init_command_t) */ +} dfu_init_command_t; + +typedef struct { + bool has_op_code; + dfu_op_code_t op_code; + bool has_init; + dfu_init_command_t init; +/* @@protoc_insertion_point(struct:dfu_command_t) */ +} dfu_command_t; + +typedef PB_BYTES_ARRAY_T(64) dfu_signed_command_signature_t; +typedef struct { + dfu_command_t command; + dfu_signature_type_t signature_type; + dfu_signed_command_signature_t signature; +/* @@protoc_insertion_point(struct:dfu_signed_command_t) */ +} dfu_signed_command_t; + +typedef struct { + bool has_command; + dfu_command_t command; + bool has_signed_command; + dfu_signed_command_t signed_command; +/* @@protoc_insertion_point(struct:dfu_packet_t) */ +} dfu_packet_t; + +/* Default values for struct fields */ +extern const bool dfu_init_command_is_debug_default; + /* Initializer values for message structs */ -#define dfu_Hash_init_default {_dfu_HashType_MIN, {0, {0}}} -#define dfu_BootValidation_init_default {0, {0, {0}}} -#define dfu_InitCommand_init_default {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, _dfu_FwType_MIN, false, 0, false, 0, false, 0, false, dfu_Hash_init_default, false, false, 0, {dfu_BootValidation_init_default, dfu_BootValidation_init_default, dfu_BootValidation_init_default}} -#define dfu_Command_init_default {false, _dfu_OpCode_MIN, false, dfu_InitCommand_init_default} -#define dfu_SignedCommand_init_default {dfu_Command_init_default, 0, {0, {0}}} -#define dfu_Packet_init_default {false, dfu_Command_init_default, false, dfu_SignedCommand_init_default} -#define dfu_Hash_init_zero {_dfu_HashType_MIN, {0, {0}}} -#define dfu_BootValidation_init_zero {0, {0, {0}}} -#define dfu_InitCommand_init_zero {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, _dfu_FwType_MIN, false, 0, false, 0, false, 0, false, dfu_Hash_init_zero, false, 0, 0, {dfu_BootValidation_init_zero, dfu_BootValidation_init_zero, dfu_BootValidation_init_zero}} -#define dfu_Command_init_zero {false, _dfu_OpCode_MIN, false, dfu_InitCommand_init_zero} -#define dfu_SignedCommand_init_zero {dfu_Command_init_zero, 0, {0, {0}}} -#define dfu_Packet_init_zero {false, dfu_Command_init_zero, false, dfu_SignedCommand_init_zero} +#define DFU_HASH_INIT_DEFAULT {(dfu_hash_type_t)0, {0, {0}}} +#define DFU_BOOT_VALIDATION_INIT_DEFAULT {(dfu_validation_type_t)0, {0, {0}}} +#define DFU_INIT_COMMAND_INIT_DEFAULT {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, (dfu_fw_type_t)0, false, 0, false, 0, false, 0, false, DFU_HASH_INIT_DEFAULT, false, false, 0, {DFU_BOOT_VALIDATION_INIT_DEFAULT, DFU_BOOT_VALIDATION_INIT_DEFAULT, DFU_BOOT_VALIDATION_INIT_DEFAULT}} +#define DFU_COMMAND_INIT_DEFAULT {false, (dfu_op_code_t)0, false, DFU_INIT_COMMAND_INIT_DEFAULT} +#define DFU_SIGNED_COMMAND_INIT_DEFAULT {DFU_COMMAND_INIT_DEFAULT, (dfu_signature_type_t)0, {0, {0}}} +#define DFU_PACKET_INIT_DEFAULT {false, DFU_COMMAND_INIT_DEFAULT, false, DFU_SIGNED_COMMAND_INIT_DEFAULT} +#define DFU_HASH_INIT_ZERO {(dfu_hash_type_t)0, {0, {0}}} +#define DFU_BOOT_VALIDATION_INIT_ZERO {(dfu_validation_type_t)0, {0, {0}}} +#define DFU_INIT_COMMAND_INIT_ZERO {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, (dfu_fw_type_t)0, false, 0, false, 0, false, 0, false, DFU_HASH_INIT_ZERO, false, 0, 0, {DFU_BOOT_VALIDATION_INIT_ZERO, DFU_BOOT_VALIDATION_INIT_ZERO, DFU_BOOT_VALIDATION_INIT_ZERO}} +#define DFU_COMMAND_INIT_ZERO {false, (dfu_op_code_t)0, false, DFU_INIT_COMMAND_INIT_ZERO} +#define DFU_SIGNED_COMMAND_INIT_ZERO {DFU_COMMAND_INIT_ZERO, (dfu_signature_type_t)0, {0, {0}}} +#define DFU_PACKET_INIT_ZERO {false, DFU_COMMAND_INIT_ZERO, false, DFU_SIGNED_COMMAND_INIT_ZERO} /* Field tags (for use in manual encoding/decoding) */ -#define dfu_BootValidation_sigmask_tag 1 -#define dfu_BootValidation_bytes_tag 2 -#define dfu_Hash_hash_type_tag 1 -#define dfu_Hash_hash_tag 2 -#define dfu_InitCommand_fw_version_tag 1 -#define dfu_InitCommand_hw_version_tag 2 -#define dfu_InitCommand_sd_req_tag 3 -#define dfu_InitCommand_type_tag 4 -#define dfu_InitCommand_sd_size_tag 5 -#define dfu_InitCommand_bl_size_tag 6 -#define dfu_InitCommand_app_size_tag 7 -#define dfu_InitCommand_hash_tag 8 -#define dfu_InitCommand_is_debug_tag 9 -#define dfu_InitCommand_boot_validation_tag 10 -#define dfu_Command_op_code_tag 1 -#define dfu_Command_init_tag 2 -#define dfu_SignedCommand_command_tag 1 -#define dfu_SignedCommand_sigmask_tag 2 -#define dfu_SignedCommand_signature_tag 3 -#define dfu_Packet_command_tag 1 -#define dfu_Packet_signed_command_tag 2 +#define DFU_BOOT_VALIDATION_TYPE_TAG 1 +#define DFU_BOOT_VALIDATION_BYTES_TAG 2 +#define DFU_HASH_HASH_TYPE_TAG 1 +#define DFU_HASH_HASH_TAG 2 +#define DFU_INIT_COMMAND_FW_VERSION_TAG 1 +#define DFU_INIT_COMMAND_HW_VERSION_TAG 2 +#define DFU_INIT_COMMAND_SD_REQ_TAG 3 +#define DFU_INIT_COMMAND_TYPE_TAG 4 +#define DFU_INIT_COMMAND_SD_SIZE_TAG 5 +#define DFU_INIT_COMMAND_BL_SIZE_TAG 6 +#define DFU_INIT_COMMAND_APP_SIZE_TAG 7 +#define DFU_INIT_COMMAND_HASH_TAG 8 +#define DFU_INIT_COMMAND_IS_DEBUG_TAG 9 +#define DFU_INIT_COMMAND_BOOT_VALIDATION_TAG 10 +#define DFU_COMMAND_OP_CODE_TAG 1 +#define DFU_COMMAND_INIT_TAG 2 +#define DFU_SIGNED_COMMAND_COMMAND_TAG 1 +#define DFU_SIGNED_COMMAND_SIGNATURE_TYPE_TAG 2 +#define DFU_SIGNED_COMMAND_SIGNATURE_TAG 3 +#define DFU_PACKET_COMMAND_TAG 1 +#define DFU_PACKET_SIGNED_COMMAND_TAG 2 /* Struct field encoding specification for nanopb */ -#define dfu_Hash_FIELDLIST(X, a) \ -X(a, STATIC, REQUIRED, UENUM, hash_type, 1) \ -X(a, STATIC, REQUIRED, BYTES, hash, 2) -#define dfu_Hash_CALLBACK NULL -#define dfu_Hash_DEFAULT NULL - -#define dfu_BootValidation_FIELDLIST(X, a) \ -X(a, STATIC, REQUIRED, UINT32, sigmask, 1) \ -X(a, STATIC, REQUIRED, BYTES, bytes, 2) -#define dfu_BootValidation_CALLBACK NULL -#define dfu_BootValidation_DEFAULT NULL - -#define dfu_InitCommand_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, UINT32, fw_version, 1) \ -X(a, STATIC, OPTIONAL, UINT32, hw_version, 2) \ -X(a, STATIC, REPEATED, UINT32, sd_req, 3) \ -X(a, STATIC, OPTIONAL, UENUM, type, 4) \ -X(a, STATIC, OPTIONAL, UINT32, sd_size, 5) \ -X(a, STATIC, OPTIONAL, UINT32, bl_size, 6) \ -X(a, STATIC, OPTIONAL, UINT32, app_size, 7) \ -X(a, STATIC, OPTIONAL, MESSAGE, hash, 8) \ -X(a, STATIC, OPTIONAL, BOOL, is_debug, 9) \ -X(a, STATIC, REPEATED, MESSAGE, boot_validation, 10) -#define dfu_InitCommand_CALLBACK NULL -#define dfu_InitCommand_DEFAULT (const pb_byte_t*)"\x48\x00\x00" -#define dfu_InitCommand_hash_MSGTYPE dfu_Hash -#define dfu_InitCommand_boot_validation_MSGTYPE dfu_BootValidation - -#define dfu_Command_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, UENUM, op_code, 1) \ -X(a, STATIC, OPTIONAL, MESSAGE, init, 2) -#define dfu_Command_CALLBACK NULL -#define dfu_Command_DEFAULT (const pb_byte_t*)"\x08\x01\x00" -#define dfu_Command_init_MSGTYPE dfu_InitCommand - -#define dfu_SignedCommand_FIELDLIST(X, a) \ -X(a, STATIC, REQUIRED, MESSAGE, command, 1) \ -X(a, STATIC, REQUIRED, UINT32, sigmask, 2) \ -X(a, STATIC, REQUIRED, BYTES, signature, 3) -#define dfu_SignedCommand_CALLBACK NULL -#define dfu_SignedCommand_DEFAULT NULL -#define dfu_SignedCommand_command_MSGTYPE dfu_Command - -#define dfu_Packet_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, command, 1) \ -X(a, STATIC, OPTIONAL, MESSAGE, signed_command, 2) -#define dfu_Packet_CALLBACK NULL -#define dfu_Packet_DEFAULT NULL -#define dfu_Packet_command_MSGTYPE dfu_Command -#define dfu_Packet_signed_command_MSGTYPE dfu_SignedCommand - -extern const pb_msgdesc_t dfu_Hash_msg; -extern const pb_msgdesc_t dfu_BootValidation_msg; -extern const pb_msgdesc_t dfu_InitCommand_msg; -extern const pb_msgdesc_t dfu_Command_msg; -extern const pb_msgdesc_t dfu_SignedCommand_msg; -extern const pb_msgdesc_t dfu_Packet_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define dfu_Hash_fields &dfu_Hash_msg -#define dfu_BootValidation_fields &dfu_BootValidation_msg -#define dfu_InitCommand_fields &dfu_InitCommand_msg -#define dfu_Command_fields &dfu_Command_msg -#define dfu_SignedCommand_fields &dfu_SignedCommand_msg -#define dfu_Packet_fields &dfu_Packet_msg +extern const pb_field_t dfu_hash_fields[3]; +extern const pb_field_t dfu_boot_validation_fields[3]; +extern const pb_field_t dfu_init_command_fields[11]; +extern const pb_field_t dfu_command_fields[3]; +extern const pb_field_t dfu_signed_command_fields[4]; +extern const pb_field_t dfu_packet_fields[3]; /* Maximum encoded size of messages (where known) */ -#define dfu_BootValidation_size 72 -#define dfu_Command_size 395 -#define dfu_Hash_size 36 -#define dfu_InitCommand_size 390 -#define dfu_Packet_size 871 -#define dfu_SignedCommand_size 470 +#define DFU_HASH_SIZE 36 +#define DFU_BOOT_VALIDATION_SIZE 68 +#define DFU_INIT_COMMAND_SIZE 378 +#define DFU_COMMAND_SIZE 383 +#define DFU_SIGNED_COMMAND_SIZE 454 +#define DFU_PACKET_SIZE 843 + +/* Message IDs (where set with "msgid" option) */ +#ifdef PB_MSGID + +#define DFU_CC_MESSAGES \ + + +#endif #ifdef __cplusplus } /* extern "C" */ #endif +/* @@protoc_insertion_point(eof) */ #endif diff --git a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.proto b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.proto index db864c10ac..341b4e8f5f 100644 --- a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.proto +++ b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/dfu-cc.proto @@ -36,7 +36,7 @@ message Hash { message BootValidation { - required uint32 sigmask = 1; + required ValidationType type = 1; required bytes bytes = 2; } @@ -63,9 +63,15 @@ message Command { optional InitCommand init = 2; } +// Signed command types +enum SignatureType { + ECDSA_P256_SHA256 = 0; + ED25519 = 1; +} + message SignedCommand { required Command command = 1; - required uint32 sigmask = 2; + required SignatureType signature_type = 2; required bytes signature = 3; } diff --git a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c index 89c5d69260..5b8b7d2be4 100644 --- a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c +++ b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_req_handler.c @@ -71,7 +71,7 @@ NRF_LOG_MODULE_REGISTER(); #define NRF_DFU_PROTOCOL_REDUCED 0 #endif -STATIC_ASSERT(dfu_SignedCommand_size <= INIT_COMMAND_MAX_SIZE); +STATIC_ASSERT(DFU_SIGNED_COMMAND_SIZE <= INIT_COMMAND_MAX_SIZE); static uint32_t m_firmware_start_addr; /**< Start address of the current firmware image. */ static uint32_t m_firmware_size_req; /**< The size of the entire firmware image. Defined by the init command. */ diff --git a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_settings.c b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_settings.c index 07146a8e2d..794dfec9f9 100644 --- a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_settings.c +++ b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_settings.c @@ -258,9 +258,19 @@ void nrf_dfu_settings_reinit(void) if (NRF_DFU_SETTINGS_COMPATIBILITY_MODE && !NRF_DFU_IN_APP && (s_dfu_settings.settings_version == 1)) { - NRF_LOG_WARNING("Resetting bootloader settings since neither the settings page is old."); - memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t)); - s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION; + NRF_LOG_INFO("Old settings page detected. Upgrading info."); + + // Old version. Translate. + memcpy(&s_dfu_settings.peer_data, (uint8_t *)&s_dfu_settings + DFU_SETTINGS_BOND_DATA_OFFSET_V1, NRF_DFU_PEER_DATA_LEN); + memcpy(&s_dfu_settings.adv_name, (uint8_t *)&s_dfu_settings + DFU_SETTINGS_ADV_NAME_OFFSET_V1, NRF_DFU_ADV_NAME_LEN); + + // Initialize with defaults. + s_dfu_settings.boot_validation_softdevice.type = NO_VALIDATION; + s_dfu_settings.boot_validation_app.type = VALIDATE_CRC; + s_dfu_settings.boot_validation_bootloader.type = NO_VALIDATION; + memcpy(s_dfu_settings.boot_validation_app.bytes, &s_dfu_settings.bank_0.image_crc, sizeof(uint32_t)); + + s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION; } return; diff --git a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_types.h b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_types.h index 81bc44d65a..fd15f5597a 100644 --- a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_types.h +++ b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_types.h @@ -295,7 +295,7 @@ typedef enum typedef struct { - uint32_t sigmask; + boot_validation_type_t type; uint8_t bytes[SETTINGS_BOOT_VALIDATION_SIZE]; } boot_validation_t; diff --git a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_validation.h b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_validation.h index 79fdbc52a3..df354272d1 100644 --- a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_validation.h +++ b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_validation.h @@ -185,7 +185,7 @@ nrf_dfu_result_t nrf_dfu_validation_activation_prepare(uint32_t data_addr, uint3 * * @return Operation result. see @ref nrf_dfu_result_t. */ -nrf_dfu_result_t nrf_dfu_validation_post_external_app_execute(dfu_InitCommand const * p_init, bool is_trusted); +nrf_dfu_result_t nrf_dfu_validation_post_external_app_execute(dfu_init_command_t const * p_init, bool is_trusted); /** * @brief Function to check if there is a valid external app in Bank 1. diff --git a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c index eaf1df6533..f9e369d1e5 100644 --- a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c +++ b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.c @@ -78,7 +78,7 @@ static bool sd_req_check(uint32_t const * p_sd_req, uint8_t sd_req_cnt, bool acc } -static bool sd_req_ok(dfu_InitCommand const * p_init) +static bool sd_req_ok(dfu_init_command_t const * p_init) { ASSERT(p_init != NULL); bool result; @@ -100,9 +100,9 @@ static bool sd_req_ok(dfu_InitCommand const * p_init) { result = sd_req_check(p_init->sd_req, p_init->sd_req_count, - (p_init->type == dfu_FwType_EXTERNAL_APPLICATION)); + (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)); } - else if (p_init->type == dfu_FwType_APPLICATION) + else if (p_init->type == DFU_FW_TYPE_APPLICATION) { // The application wants to overwrite the SoftDevice. if (prevent_downgrade && (p_init->sd_req_count > 1) && (p_init->sd_req[0] == SD_REQ_APP_OVERWRITES_SD)) @@ -131,7 +131,7 @@ static bool sd_req_ok(dfu_InitCommand const * p_init) else { // Don't allow SoftDevice updates which assume no SD is present already. - result = !prevent_downgrade || (p_init->type != dfu_FwType_SOFTDEVICE); + result = !prevent_downgrade || (p_init->type != DFU_FW_TYPE_SOFTDEVICE); } } @@ -158,23 +158,23 @@ static bool sd_req_ok(dfu_InitCommand const * p_init) } -static bool fw_hash_type_ok(dfu_InitCommand const * p_init) +static bool fw_hash_type_ok(dfu_init_command_t const * p_init) { ASSERT(p_init != NULL); - return (p_init->hash.hash_type == dfu_HashType_SHA256); + return (p_init->hash.hash_type == DFU_HASH_TYPE_SHA256); } -static bool fw_version_required(dfu_FwType new_fw_type) +static bool fw_version_required(dfu_fw_type_t new_fw_type) { bool result = true; - if (new_fw_type == dfu_FwType_SOFTDEVICE) + if (new_fw_type == DFU_FW_TYPE_SOFTDEVICE) { result = false; // fw_version is optional in SoftDevice updates. If present, it will be checked against the app version. } - else if (new_fw_type == dfu_FwType_APPLICATION) + else if (new_fw_type == DFU_FW_TYPE_APPLICATION) { result = NRF_DFU_APP_DOWNGRADE_PREVENTION; // fw_version is configurable in app updates. } @@ -191,15 +191,15 @@ static bool fw_version_required(dfu_FwType new_fw_type) } -static bool fw_type_ok(dfu_InitCommand const * p_init) +static bool fw_type_ok(dfu_init_command_t const * p_init) { ASSERT(p_init != NULL); return ((p_init->has_type) - && ( (p_init->type == dfu_FwType_APPLICATION) - || (p_init->type == dfu_FwType_SOFTDEVICE) - || (p_init->type == dfu_FwType_BOOTLOADER) - || (p_init->type == dfu_FwType_SOFTDEVICE_BOOTLOADER) + && ( (p_init->type == DFU_FW_TYPE_APPLICATION) + || (p_init->type == DFU_FW_TYPE_SOFTDEVICE) + || (p_init->type == DFU_FW_TYPE_BOOTLOADER) + || (p_init->type == DFU_FW_TYPE_SOFTDEVICE_BOOTLOADER) #if NRF_DFU_SUPPORTS_EXTERNAL_APP || (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) #endif // NRF_DFU_SUPPORTS_EXTERNAL_APP @@ -214,13 +214,13 @@ static bool fw_type_ok(dfu_InitCommand const * p_init) // This function assumes p_init->has_fw_version. -static bool fw_version_ok(dfu_InitCommand const * p_init) +static bool fw_version_ok(dfu_init_command_t const * p_init) { ASSERT(p_init != NULL); ASSERT(p_init->has_fw_version); - if ((p_init->type == dfu_FwType_APPLICATION) || - (p_init->type == dfu_FwType_SOFTDEVICE)) + if ((p_init->type == DFU_FW_TYPE_APPLICATION) || + (p_init->type == DFU_FW_TYPE_SOFTDEVICE)) { if (!NRF_DFU_APP_DOWNGRADE_PREVENTION) { @@ -259,7 +259,7 @@ static bool fw_version_ok(dfu_InitCommand const * p_init) } -nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_InitCommand const * p_init) +nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_init_command_t const * p_init) { nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; if (!fw_type_ok(p_init)) diff --git a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.h b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.h index d17d5f02f6..3b9fbb04cf 100644 --- a/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.h +++ b/core/embed/sdk/nrf52/components/libraries/bootloader/dfu/nrf_dfu_ver_validation.h @@ -59,6 +59,6 @@ * * @return NRF_DFU_RES_CODE_SUCCESS if successful or error code otherwise */ -nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_InitCommand const * p_init); +nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_init_command_t const * p_init); #endif //__NRF_DFU_VER_VALIDATION_H diff --git a/core/embed/sdk/nrf52/modules/nrfx/mdk/gcc_startup_nrf52833.S b/core/embed/sdk/nrf52/modules/nrfx/mdk/gcc_startup_nrf52833.S index 14e1130962..16030a7eee 100644 --- a/core/embed/sdk/nrf52/modules/nrfx/mdk/gcc_startup_nrf52833.S +++ b/core/embed/sdk/nrf52/modules/nrfx/mdk/gcc_startup_nrf52833.S @@ -253,6 +253,7 @@ Reset_Handler: * * All addresses must be aligned to 4 bytes boundary. */ +#ifdef __STARTUP_CLEAR_BSS ldr r1, =__bss_start__ ldr r2, =__bss_end__ @@ -267,6 +268,7 @@ Reset_Handler: bgt .L_loop3 .L_loop3_done: +#endif /* __STARTUP_CLEAR_BSS */ /* Execute SystemInit function. */ bl SystemInit @@ -275,7 +277,7 @@ Reset_Handler: * If those libraries are not accessible, define __START as your entry point. */ #ifndef __START -#define __START main +#define __START _start #endif bl __START diff --git a/tools/style.c.exclude b/tools/style.c.exclude index 9b2c4a9fe0..1d04e7c0b1 100644 --- a/tools/style.c.exclude +++ b/tools/style.c.exclude @@ -12,5 +12,6 @@ ^\./crypto/sha3 ^\./legacy/vendor ^\./core/embed/segger -^\./core/embed/ble_bootloader/uecc +^\./core/embed/ble_bootloader/dfu +^\./core/embed/ble_firmware/uecc ^\./core/embed/sdk