parent
e9509ae4d2
commit
dd797fa767
@ -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
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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 <pb.h>
|
||||
|
||||
#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
|
@ -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;
|
||||
}
|
@ -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; //<! Observer callback set by the user.
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function calls the user's observer (@ref m_observer) after it is done handling the event.
|
||||
*/
|
||||
static void dfu_observer(nrf_dfu_evt_type_t event)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case NRF_DFU_EVT_DFU_COMPLETED:
|
||||
case NRF_DFU_EVT_DFU_ABORTED:
|
||||
#ifndef NRF_DFU_NO_TRANSPORT
|
||||
UNUSED_RETURN_VALUE(nrf_dfu_transports_close(NULL));
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call user's observer if present. */
|
||||
if (m_user_observer)
|
||||
{
|
||||
m_user_observer(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t nrf_dfu_init(nrf_dfu_observer_t observer)
|
||||
{
|
||||
uint32_t ret_val;
|
||||
|
||||
m_user_observer = observer;
|
||||
|
||||
NRF_LOG_INFO("Entering DFU mode.");
|
||||
|
||||
dfu_observer(NRF_DFU_EVT_DFU_INITIALIZED);
|
||||
|
||||
// Initializing transports
|
||||
ret_val = nrf_dfu_transports_init(dfu_observer);
|
||||
if (ret_val != NRF_SUCCESS)
|
||||
{
|
||||
NRF_LOG_ERROR("Could not initalize DFU transport: 0x%08x", ret_val);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
ret_val = nrf_dfu_req_handler_init(dfu_observer);
|
||||
|
||||
return ret_val;
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 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 DFU modules
|
||||
* @{
|
||||
* @ingroup nrf_bootloader
|
||||
* @brief Modules providing Device Firmware Update (DFU) functionality.
|
||||
*
|
||||
* The DFU module, in combination with the @ref nrf_bootloader module,
|
||||
* can be used to implement a bootloader that supports Device Firmware Updates.
|
||||
*/
|
||||
|
||||
#ifndef NRF_DFU_H__
|
||||
#define NRF_DFU_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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__
|
||||
|
||||
/** @} */
|
@ -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;
|
||||
}
|
@ -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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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__
|
||||
/** @} */
|
@ -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;
|
||||
}
|
@ -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__
|
||||
|
||||
/** @} */
|
@ -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;
|
||||
}
|
@ -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 <stdint.h>
|
||||
|
||||
#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__
|
||||
|
||||
/** @} */
|
@ -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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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;
|
||||
}
|
@ -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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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__
|
||||
|
||||
/** @} */
|
@ -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 <stddef.h>
|
||||
#include <string.h>
|
||||
#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)) //<! Offset in the settings struct where the settings version is located.
|
||||
#define DFU_SETTINGS_INIT_COMMAND_OFFSET (offsetof(nrf_dfu_settings_t, init_command)) //<! Offset in the settings struct where the InitCommand is located.
|
||||
#define DFU_SETTINGS_BOOT_VALIDATION_OFFSET (offsetof(nrf_dfu_settings_t, boot_validation_crc)) //<! Offset in the settings struct where the boot validation info is located.
|
||||
#define DFU_SETTINGS_BOOT_VALIDATION_SIZE ((3 * sizeof(boot_validation_t)) + 4)
|
||||
#define DFU_SETTINGS_BOND_DATA_OFFSET_V1 (offsetof(nrf_dfu_settings_t, init_command) + INIT_COMMAND_MAX_SIZE_v1) //<! Offset in the settings struct where the bond data was located in settings version 1.
|
||||
#define DFU_SETTINGS_ADV_NAME_OFFSET_V1 (offsetof(nrf_dfu_settings_t, init_command) + INIT_COMMAND_MAX_SIZE_v1 + NRF_DFU_PEER_DATA_LEN) //<! Offset in the settings struct where the bond data was located in settings version 1.
|
||||
|
||||
#define NRF_LOG_MODULE_NAME nrf_dfu_settings
|
||||
#include "nrf_log.h"
|
||||
NRF_LOG_MODULE_REGISTER();
|
||||
|
||||
|
||||
/**@brief This variable reserves a page in flash for bootloader settings
|
||||
* to ensure the linker doesn't place any code or variables at this location.
|
||||
*/
|
||||
#if defined (__CC_ARM )
|
||||
|
||||
uint8_t m_dfu_settings_buffer[BOOTLOADER_SETTINGS_PAGE_SIZE]
|
||||
__attribute__((at(BOOTLOADER_SETTINGS_ADDRESS)))
|
||||
__attribute__((used));
|
||||
|
||||
#elif defined ( __GNUC__ ) || defined ( __SES_ARM )
|
||||
|
||||
uint8_t m_dfu_settings_buffer[BOOTLOADER_SETTINGS_PAGE_SIZE]
|
||||
__attribute__((section(".bootloader_settings_page")))
|
||||
__attribute__((used));
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
|
||||
__no_init __root uint8_t m_dfu_settings_buffer[BOOTLOADER_SETTINGS_PAGE_SIZE]
|
||||
@ BOOTLOADER_SETTINGS_ADDRESS;
|
||||
|
||||
#else
|
||||
|
||||
#error Not a valid compiler/linker for m_dfu_settings placement.
|
||||
|
||||
#endif // Compiler specific
|
||||
|
||||
#if defined(NRF52_SERIES)
|
||||
|
||||
/**@brief This variable reserves a page in flash for MBR parameters
|
||||
* to ensure the linker doesn't place any code or variables at this location.
|
||||
*/
|
||||
#if defined ( __CC_ARM )
|
||||
|
||||
uint8_t m_mbr_params_page[NRF_MBR_PARAMS_PAGE_SIZE]
|
||||
__attribute__((at(NRF_MBR_PARAMS_PAGE_ADDRESS)))
|
||||
__attribute__((used));
|
||||
|
||||
#elif defined ( __GNUC__ ) || defined ( __SES_ARM )
|
||||
|
||||
uint8_t m_mbr_params_page[NRF_MBR_PARAMS_PAGE_SIZE]
|
||||
__attribute__((section(".mbr_params_page")))
|
||||
__attribute__((used));
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
|
||||
__no_init uint8_t m_mbr_params_page[NRF_MBR_PARAMS_PAGE_SIZE]
|
||||
@ NRF_MBR_PARAMS_PAGE_ADDRESS;
|
||||
|
||||
#else
|
||||
|
||||
#error Not a valid compiler/linker for m_mbr_params_page placement.
|
||||
|
||||
#endif // Compiler specific
|
||||
|
||||
uint8_t * mp_dfu_settings_backup_buffer = &m_mbr_params_page[0];
|
||||
|
||||
|
||||
#ifndef NRF_DFU_IN_APP
|
||||
#define NRF_DFU_IN_APP 0
|
||||
#endif
|
||||
|
||||
|
||||
#define UICR_PARAM_PAGE_ADDR 0x10001018
|
||||
|
||||
#if !defined(BL_SETTINGS_ACCESS_ONLY) && !NRF_DFU_IN_APP
|
||||
/**@brief This variable has the linker write the MBR parameters page address to the
|
||||
* UICR register. This value will be written in the HEX file and thus to the
|
||||
* UICR when the bootloader is flashed into the chip.
|
||||
*/
|
||||
#if defined ( __CC_ARM )
|
||||
|
||||
uint32_t const m_uicr_mbr_params_page_address
|
||||
__attribute__((at(UICR_PARAM_PAGE_ADDR))) = NRF_MBR_PARAMS_PAGE_ADDRESS;
|
||||
|
||||
#elif defined ( __GNUC__ ) || defined ( __SES_ARM )
|
||||
|
||||
uint32_t const m_uicr_mbr_params_page_address
|
||||
__attribute__ ((section(".uicr_mbr_params_page")))
|
||||
__attribute__ ((used)) = NRF_MBR_PARAMS_PAGE_ADDRESS;
|
||||
|
||||
#elif defined ( __ICCARM__ )
|
||||
|
||||
__root uint32_t const m_uicr_mbr_params_page_address
|
||||
@ UICR_PARAM_PAGE_ADDR = NRF_MBR_PARAMS_PAGE_ADDRESS;
|
||||
|
||||
#else
|
||||
|
||||
#error Not a valid compiler/linker for m_mbr_params_page placement.
|
||||
|
||||
#endif // Compiler specific
|
||||
#endif // #ifndef BL_SETTINGS_ACCESS_ONLY
|
||||
#endif // #if defined( NRF52_SERIES )
|
||||
|
||||
nrf_dfu_settings_t s_dfu_settings;
|
||||
|
||||
static uint32_t settings_crc_get(nrf_dfu_settings_t const * p_settings)
|
||||
{
|
||||
ASSERT(offsetof(nrf_dfu_settings_t, crc) == 0);
|
||||
|
||||
// The crc is calculated from the s_dfu_settings struct, except the crc itself, the init command, bond data, and boot validation.
|
||||
return crc32_compute((uint8_t*)(p_settings) + 4, DFU_SETTINGS_INIT_COMMAND_OFFSET - 4, NULL);
|
||||
}
|
||||
|
||||
|
||||
static bool crc_ok(nrf_dfu_settings_t const * p_settings)
|
||||
{
|
||||
if (p_settings->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;
|
||||
}
|
@ -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 <stdint.h>
|
||||
#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__
|
||||
|
||||
/**@} */
|
@ -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 <stddef.h>
|
||||
#include <string.h>
|
||||
#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) //<! Offset in the settings struct where the additional peer data is located.
|
||||
#define DFU_SETTINGS_ADV_NAME_OFFSET offsetof(nrf_dfu_settings_t, adv_name) //<! Offset in the settings struct where the additional advertisement name is located.
|
||||
|
||||
extern nrf_dfu_settings_t s_dfu_settings;
|
||||
extern uint8_t m_dfu_settings_buffer[CODE_PAGE_SIZE];
|
||||
|
||||
#if defined(NRF_DFU_BLE_REQUIRES_BONDS) && (NRF_DFU_BLE_REQUIRES_BONDS == 1)
|
||||
|
||||
ret_code_t nrf_dfu_settings_peer_data_write(nrf_dfu_peer_data_t * p_data)
|
||||
{
|
||||
uint32_t ret_val;
|
||||
|
||||
uint32_t * p_peer_data_settings =
|
||||
(uint32_t*) &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET];
|
||||
|
||||
uint32_t crc = (uint32_t)*p_peer_data_settings;
|
||||
|
||||
VERIFY_PARAM_NOT_NULL(p_data);
|
||||
|
||||
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_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
|
||||
|
@ -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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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;
|
||||
}
|
||||
|
@ -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 <string.h>
|
||||
#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
|
@ -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;
|
||||
}
|
@ -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 <stdint.h>
|
||||
#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__
|
||||
|
||||
/** @} */
|
@ -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;
|
||||
}
|
@ -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
|
@ -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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#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__
|
||||
|
||||
/** @} */
|
@ -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;
|
||||
}
|
@ -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 <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#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__
|
||||
|
||||
/** @} */
|
@ -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
|
||||
|
||||
/** @} */
|
@ -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 <stdbool.h>
|
||||
#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;
|
||||
}
|
@ -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
|
@ -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) */
|
||||
|
@ -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 <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
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#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;
|
||||
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_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 {
|
||||
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;
|
||||
uint32_t fw_version;
|
||||
bool has_hw_version;
|
||||
uint32_t hw_version;
|
||||
uint32_t hw_version;
|
||||
pb_size_t sd_req_count;
|
||||
uint32_t sd_req[16];
|
||||
uint32_t sd_req[16];
|
||||
bool has_type;
|
||||
dfu_FwType type;
|
||||
dfu_fw_type_t type;
|
||||
bool has_sd_size;
|
||||
uint32_t sd_size;
|
||||
uint32_t sd_size;
|
||||
bool has_bl_size;
|
||||
uint32_t bl_size;
|
||||
uint32_t bl_size;
|
||||
bool has_app_size;
|
||||
uint32_t app_size;
|
||||
uint32_t app_size;
|
||||
bool has_hash;
|
||||
dfu_Hash hash;
|
||||
dfu_hash_t hash;
|
||||
bool has_is_debug;
|
||||
bool is_debug;
|
||||
bool is_debug;
|
||||
pb_size_t boot_validation_count;
|
||||
dfu_BootValidation boot_validation[3];
|
||||
} dfu_InitCommand;
|
||||
dfu_boot_validation_t boot_validation[3];
|
||||
/* @@protoc_insertion_point(struct:dfu_init_command_t) */
|
||||
} dfu_init_command_t;
|
||||
|
||||
/* Command type */
|
||||
typedef struct _dfu_Command {
|
||||
typedef struct {
|
||||
bool has_op_code;
|
||||
dfu_OpCode op_code;
|
||||
dfu_op_code_t 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 {
|
||||
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 command;
|
||||
dfu_command_t 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))
|
||||
dfu_signed_command_t signed_command;
|
||||
/* @@protoc_insertion_point(struct:dfu_packet_t) */
|
||||
} dfu_packet_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* 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
|
||||
|
Loading…
Reference in new issue