Imported more library files

Not compiling currently
This commit is contained in:
2025-04-12 23:37:19 +01:00
parent 264a3462e0
commit 9d06f983af
2518 changed files with 1021900 additions and 52 deletions

View File

@@ -0,0 +1,168 @@
/***************************************************************************//**
* @file
* @brief Representation of Application Properties
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#ifndef APPLICATION_PROPERTIES_H
#define APPLICATION_PROPERTIES_H
#include <stdint.h>
/***************************************************************************//**
* @addtogroup Interface
* @{
* @addtogroup ApplicationProperties Application Properties
* @brief Properties of the application that can be accessed by the bootloader
* @details
* Applications must contain an @ref ApplicationProperties_t struct declaring
* the application version and capabilities, and so on. The metadata contained
* in this struct will be extracted from the application by the Simplicity
* Commander tool and placed in the GBL upgrade file. If this struct is not
* in the application image, it will be added to the GBL file by the
* Simplicity Commander.
*
* The struct is also used to declare whether the application image is signed
* and what type of signature is used. If no @ref ApplicationProperties_t
* struct is present, the bootloader will assume that the application image
* is signed using @ref APPLICATION_SIGNATURE_ECDSA_P256.
*
* To ensure that the bootloader can easily locate the ApplicationProperties_t
* struct, if not already done by the linker, Simplicity Commander will modify
* word 13 of the application to insert a pointer to the
* ApplicationProperties_t struct.
* @{
******************************************************************************/
/// Magic value declaring the existence of an ApplicationProperties_t struct
#define APPLICATION_PROPERTIES_MAGIC { \
0x13, 0xb7, 0x79, 0xfa, \
0xc9, 0x25, 0xdd, 0xb7, \
0xad, 0xf3, 0xcf, 0xe0, \
0xf1, 0xb6, 0x14, 0xb8 \
}
/// Byte-reversed version of ::APPLICATION_PROPERTIES_MAGIC
#define APPLICATION_PROPERTIES_REVERSED { \
0xb8, 0x14, 0xb6, 0xf1, \
0xe0, 0xcf, 0xf3, 0xad, \
0xb7, 0xdd, 0x25, 0xc9, \
0xfa, 0x79, 0xb7, 0x13 \
}
/// Major version number of the AppliationProperties_t struct
#define APPLICATION_PROPERTIES_VERSION_MAJOR (1UL)
/// Minor version number of the AppliationProperties_t struct
#define APPLICATION_PROPERTIES_VERSION_MINOR (2UL)
/// Version number of the ApplicationCertificate_t struct
#define APPLICATION_CERTIFICATE_VERSION (1UL)
/// The application is not signed
#define APPLICATION_SIGNATURE_NONE (0UL)
/// @brief The SHA-256 digest of the application is signed using ECDSA with the
/// NIST P-256 curve.
#define APPLICATION_SIGNATURE_ECDSA_P256 (1UL << 0UL)
/// @brief The application is not signed, but has a CRC-32 checksum
#define APPLICATION_SIGNATURE_CRC32 (1UL << 1UL)
/// The application contains a Zigbee wireless stack
#define APPLICATION_TYPE_ZIGBEE (1UL << 0UL)
/// The application contains a Thread wireless stack
#define APPLICATION_TYPE_THREAD (1UL << 1UL)
/// The application contains a Flex wireless stack
#define APPLICATION_TYPE_FLEX (1UL << 2UL)
/// The application contains a Bluetooth wireless stack
#define APPLICATION_TYPE_BLUETOOTH (1UL << 3UL)
/// The application is an MCU application
#define APPLICATION_TYPE_MCU (1UL << 4UL)
/// The application contains a Bluetooth application
#define APPLICATION_TYPE_BLUETOOTH_APP (1UL << 5UL)
/// The application contains a bootloader
#define APPLICATION_TYPE_BOOTLOADER (1UL << 6UL)
/// The application contains a Zwave wireless stack
#define APPLICATION_TYPE_ZWAVE (1UL << 7UL)
/// Application Data
typedef struct ApplicationData {
/// @brief Bitfield representing type of application, e.g.,
/// @ref APPLICATION_TYPE_ZIGBEE
uint32_t type;
/// Version number for this application
uint32_t version;
/// Capabilities of this application
uint32_t capabilities;
/// Unique ID (UUID or GUID) for the product this application is built for
uint8_t productId[16];
} ApplicationData_t;
/// Application Certificate
typedef struct ApplicationCertificate {
/// Version of the certificate structure
uint8_t structVersion;
/// Reserved flags
uint8_t flags[3];
/// Public key
uint8_t key[64];
/// The version number of this certificate
uint32_t version;
/// Signature of the certificate
uint8_t signature[64];
} ApplicationCertificate_t;
/// Application Properties struct
typedef struct {
/// @brief Magic value indicating this is an ApplicationProperties_t struct.
/// Must equal @ref APPLICATION_PROPERTIES_MAGIC
uint8_t magic[16];
/// Version number of this struct
uint32_t structVersion;
/// Type of signature this application is signed with
uint32_t signatureType;
/// Location of the signature. Typically points to the end of the application
uint32_t signatureLocation;
/// Information about the application
ApplicationData_t app;
/// Pointer to information about the certificate
ApplicationCertificate_t *cert;
/// Pointer to Long Token Data Section
uint8_t *longTokenSectionAddress;
/// Parser Decryption Key
const uint8_t decryptKey[16];
} ApplicationProperties_t;
/** @} (end addtogroup ApplicationProperties) */
/** @} (end addtogroup Interface) */
/// Application Properties major version shift value
#define APPLICATION_PROPERTIES_VERSION_MAJOR_SHIFT (0U)
/// Application Properties minor version shift value
#define APPLICATION_PROPERTIES_VERSION_MINOR_SHIFT (8U)
/// Application Properties major version mask
#define APPLICATION_PROPERTIES_VERSION_MAJOR_MASK (0x000000FFU)
/// Application Properties minor version mask
#define APPLICATION_PROPERTIES_VERSION_MINOR_MASK (0xFFFFFF00U)
/// Version number of the AppliationProperties_t struct
#define APPLICATION_PROPERTIES_VERSION ((APPLICATION_PROPERTIES_VERSION_MINOR \
<< APPLICATION_PROPERTIES_VERSION_MINOR_SHIFT) \
| (APPLICATION_PROPERTIES_VERSION_MAJOR \
<< APPLICATION_PROPERTIES_VERSION_MAJOR_SHIFT))
#if (APPLICATION_PROPERTIES_VERSION_MAJOR \
> (APPLICATION_PROPERTIES_VERSION_MAJOR_MASK >> APPLICATION_PROPERTIES_VERSION_MAJOR_SHIFT))
|| (APPLICATION_PROPERTIES_VERSION_MINOR \
> (APPLICATION_PROPERTIES_VERSION_MINOR_MASK >> APPLICATION_PROPERTIES_VERSION_MINOR_SHIFT))
#error "Invalid application properties version"
#endif
#endif // APPLICATION_PROPERTIES_H

View File

@@ -0,0 +1,382 @@
/***************************************************************************//**
* @file
* @brief Error codes used and exposed by the bootloader.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#ifndef BTL_ERRORCODE_H
#define BTL_ERRORCODE_H
/**
* @addtogroup ErrorCodes Error Codes
* @brief Bootloader error codes
* @details
* @{
*/
/// No error, operation OK
#define BOOTLOADER_OK 0L
/**
* @addtogroup ErrorBases Error Code Base Values
* @brief Bootloader error code base values, per logical function
* @details
* @{
*/
/// Initialization errors
#define BOOTLOADER_ERROR_INIT_BASE 0x0100L
/// Image verification errors
#define BOOTLOADER_ERROR_PARSE_BASE 0x0200L
/// Storage errors
#define BOOTLOADER_ERROR_STORAGE_BASE 0x0400L
/// Bootload errors
#define BOOTLOADER_ERROR_BOOTLOAD_BASE 0x0500L
/// Security errors
#define BOOTLOADER_ERROR_SECURITY_BASE 0x0600L
/// Communication component errors
#define BOOTLOADER_ERROR_COMMUNICATION_BASE 0x0700L
/// XMODEM parser errors
#define BOOTLOADER_ERROR_XMODEM_BASE 0x0900L
/// Image file parser errors
#define BOOTLOADER_ERROR_PARSER_BASE 0x1000L
/// SPI Peripheral driver errors
#define BOOTLOADER_ERROR_SPI_PERIPHERAL_BASE 0x1100L
/// UART driver errors
#define BOOTLOADER_ERROR_UART_BASE 0x1200L
/// Compression errors
#define BOOTLOADER_ERROR_COMPRESSION_BASE 0x1300L
/** @} addtogroup ErrorBases */
/**
* @addtogroup InitError Initialization Error Codes
* @brief Bootloader error codes returned by initialization code.
* @details
* Offset from @ref BOOTLOADER_ERROR_INIT_BASE
* @{
*/
/// Storage initialization error
#define BOOTLOADER_ERROR_INIT_STORAGE \
(BOOTLOADER_ERROR_INIT_BASE | 0x01L)
/// Bootloader table invalid
#define BOOTLOADER_ERROR_INIT_TABLE \
(BOOTLOADER_ERROR_INIT_BASE | 0x02L)
/// Bootloader SFDP not supported
#define BOOTLOADER_ERROR_INIT_SFDP \
(BOOTLOADER_ERROR_INIT_BASE | 0x03L)
/** @} addtogroup InitError */
/**
* @addtogroup ParseErrpr Parse Error Codes
* @brief Bootloader error codes returned by image parsing.
* @details
* Offset from @ref BOOTLOADER_ERROR_PARSE_BASE
* @{
*/
/// Parse not complete, continue calling the
/// parsing function
#define BOOTLOADER_ERROR_PARSE_CONTINUE (BOOTLOADER_ERROR_PARSE_BASE | 0x01L)
/// Verification failed
#define BOOTLOADER_ERROR_PARSE_FAILED (BOOTLOADER_ERROR_PARSE_BASE | 0x02L)
/// Verification successfully completed. Image is valid.
#define BOOTLOADER_ERROR_PARSE_SUCCESS (BOOTLOADER_ERROR_PARSE_BASE | 0x03L)
/// Bootloader has no storage, and cannot parse images.
#define BOOTLOADER_ERROR_PARSE_STORAGE (BOOTLOADER_ERROR_PARSE_BASE | 0x04L)
/// Parse context incompatible with parse function
#define BOOTLOADER_ERROR_PARSE_CONTEXT (BOOTLOADER_ERROR_PARSE_BASE | 0x05L)
/** @} addtogroup VerificationError */
/**
* @addtogroup StorageError Storage Driver Error Codes
* @brief Bootloader error codes returned by a storage driver.
* @details
* Offset from @ref BOOTLOADER_ERROR_STORAGE_BASE
* @{
*/
/// Invalid slot
#define BOOTLOADER_ERROR_STORAGE_INVALID_SLOT \
(BOOTLOADER_ERROR_STORAGE_BASE | 0x01L)
/// Invalid address. Address not aligned/out of range
#define BOOTLOADER_ERROR_STORAGE_INVALID_ADDRESS \
(BOOTLOADER_ERROR_STORAGE_BASE | 0x02L)
/// The storage area needs to be erased before it can be used
#define BOOTLOADER_ERROR_STORAGE_NEEDS_ERASE \
(BOOTLOADER_ERROR_STORAGE_BASE | 0x03L)
/// The address or length needs to be aligned
#define BOOTLOADER_ERROR_STORAGE_NEEDS_ALIGN \
(BOOTLOADER_ERROR_STORAGE_BASE | 0x04L)
/// An error occured during bootload from storage
#define BOOTLOADER_ERROR_STORAGE_BOOTLOAD \
(BOOTLOADER_ERROR_STORAGE_BASE | 0x05L)
/// There is no image in this storage slot
#define BOOTLOADER_ERROR_STORAGE_NO_IMAGE \
(BOOTLOADER_ERROR_STORAGE_BASE | 0x06L)
/// Continue calling function
#define BOOTLOADER_ERROR_STORAGE_CONTINUE \
(BOOTLOADER_ERROR_STORAGE_BASE | 0x07L)
/// Generic storage error
#define BOOTLOADER_ERROR_STORAGE_GENERIC \
(BOOTLOADER_ERROR_STORAGE_BASE | 0x08L)
/** @} addtogroup StorageError */
/**
* @addtogroup BootloadError Bootloading Error Codes
* @brief Bootloader error codes returned by the bootloading process.
* @details
* Offset from @ref BOOTLOADER_ERROR_BOOTLOAD_BASE
* @{
*/
/// No images marked for bootload
#define BOOTLOADER_ERROR_BOOTLOAD_LIST_EMPTY \
(BOOTLOADER_ERROR_BOOTLOAD_BASE | 0x01L)
/// List of images marked for bootload is full
#define BOOTLOADER_ERROR_BOOTLOAD_LIST_FULL \
(BOOTLOADER_ERROR_BOOTLOAD_BASE | 0x02L)
/// Image already marked for bootload
#define BOOTLOADER_ERROR_BOOTLOAD_LIST_ENTRY_EXISTS \
(BOOTLOADER_ERROR_BOOTLOAD_BASE | 0x03L)
/// Bootload list overflowed, requested length too large
#define BOOTLOADER_ERROR_BOOTLOAD_LIST_OVERFLOW \
(BOOTLOADER_ERROR_BOOTLOAD_BASE | 0x04L)
/// No bootload list found at the base of storage
#define BOOTLOADER_ERROR_BOOTLOAD_LIST_NO_LIST \
(BOOTLOADER_ERROR_BOOTLOAD_BASE | 0x05L)
/// Bootload list found but with invalid CRC
#define BOOTLOADER_ERROR_BOOTLOAD_LIST_INVALID \
(BOOTLOADER_ERROR_BOOTLOAD_BASE | 0x06L)
/** @} addtogroup BootloadError */
/**
* @addtogroup SecurityError Security Error Codes
* @brief Bootloader error codes returned by security algorithms.
* @details
* Offset from @ref BOOTLOADER_ERROR_SECURITY_BASE
* @{
*/
/// Invalid input parameter to security algorithm
#define BOOTLOADER_ERROR_SECURITY_INVALID_PARAM \
(BOOTLOADER_ERROR_SECURITY_BASE | 0x01L)
/// Input parameter to security algorithm is out of range
#define BOOTLOADER_ERROR_SECURITY_PARAM_OUT_RANGE \
(BOOTLOADER_ERROR_SECURITY_BASE | 0x02L)
/// Invalid option for security algorithm
#define BOOTLOADER_ERROR_SECURITY_INVALID_OPTION \
(BOOTLOADER_ERROR_SECURITY_BASE | 0x03L)
/// Authentication did not check out
#define BOOTLOADER_ERROR_SECURITY_REJECTED \
(BOOTLOADER_ERROR_SECURITY_BASE | 0x04L)
/** @} addtogroup SecurityError */
/**
* @addtogroup CommunicationError Communication Component Error Codes
* @brief Bootloader error codes returned by communication components.
* @details
* Offset from @ref BOOTLOADER_ERROR_COMMUNICATION_BASE
* @{
*/
/// Invalid input parameter to security algorithm
/// Could not initialize hardware resources for communication protocol
#define BOOTLOADER_ERROR_COMMUNICATION_INIT \
(BOOTLOADER_ERROR_COMMUNICATION_BASE | 0x01L)
/// @brief Could not start communication with host (timeout, sync error,
/// version mismatch, ...)
#define BOOTLOADER_ERROR_COMMUNICATION_START \
(BOOTLOADER_ERROR_COMMUNICATION_BASE | 0x02L)
/// Host closed communication, no image received
#define BOOTLOADER_ERROR_COMMUNICATION_DONE \
(BOOTLOADER_ERROR_COMMUNICATION_BASE | 0x03L)
/// Unrecoverable error in host-bootloader communication
#define BOOTLOADER_ERROR_COMMUNICATION_ERROR \
(BOOTLOADER_ERROR_COMMUNICATION_BASE | 0x04L)
/// Host closed communication, no valid image received
#define BOOTLOADER_ERROR_COMMUNICATION_IMAGE_ERROR \
(BOOTLOADER_ERROR_COMMUNICATION_BASE | 0x05L)
/// Communication aborted, no response from host
#define BOOTLOADER_ERROR_COMMUNICATION_TIMEOUT \
(BOOTLOADER_ERROR_COMMUNICATION_BASE | 0x06L)
/** @} addtogroup CommunicationError */
/**
* @addtogroup XmodemError XMODEM Error Codes
* @brief Bootloader error codes returned by the XMODEM parser.
* @details
* Offset from @ref BOOTLOADER_ERROR_XMODEM_BASE
* @{
*/
/// Could not verify lower CRC byte
#define BOOTLOADER_ERROR_XMODEM_CRCL \
(BOOTLOADER_ERROR_XMODEM_BASE | 0x01L)
/// Could not verify upper CRC byte
#define BOOTLOADER_ERROR_XMODEM_CRCH \
(BOOTLOADER_ERROR_XMODEM_BASE | 0x02L)
/// No start of header found
#define BOOTLOADER_ERROR_XMODEM_NO_SOH \
(BOOTLOADER_ERROR_XMODEM_BASE | 0x03L)
/// Packet number doesn't match its inverse
#define BOOTLOADER_ERROR_XMODEM_PKTNUM \
(BOOTLOADER_ERROR_XMODEM_BASE | 0x04L)
/// Packet number error (unexpected sequence)
#define BOOTLOADER_ERROR_XMODEM_PKTSEQ \
(BOOTLOADER_ERROR_XMODEM_BASE | 0x05L)
/// Packet number error (duplicate)
#define BOOTLOADER_ERROR_XMODEM_PKTDUP \
(BOOTLOADER_ERROR_XMODEM_BASE | 0x06L)
/// Transfer is done (Technically not an error)
#define BOOTLOADER_ERROR_XMODEM_DONE \
(BOOTLOADER_ERROR_XMODEM_BASE | 0x07L)
/// Transfer is canceled
#define BOOTLOADER_ERROR_XMODEM_CANCEL \
(BOOTLOADER_ERROR_XMODEM_BASE | 0x08L)
/** @} addtogroup XmodemError */
/**
* @addtogroup ParserError Image Parser Error Codes
* @brief Bootloader error codes returned by the image file parser.
* @details
* Offset from @ref BOOTLOADER_ERROR_PARSER_BASE
* @{
*/
/// Encountered unexpected data/option
#define BOOTLOADER_ERROR_PARSER_UNEXPECTED \
(BOOTLOADER_ERROR_PARSER_BASE | 0x01L)
/// Ran out of internal buffer space.
/// Please increase internal buffer size to match biggest header
#define BOOTLOADER_ERROR_PARSER_BUFFER \
(BOOTLOADER_ERROR_PARSER_BASE | 0x02L)
/// Internal state: done parsing the current input buffer
#define BOOTLOADER_ERROR_PARSER_PARSED \
(BOOTLOADER_ERROR_PARSER_BASE | 0x03L)
/// Invalid encryption key or no key not present
#define BOOTLOADER_ERROR_PARSER_KEYERROR \
(BOOTLOADER_ERROR_PARSER_BASE | 0x04L)
/// Invalid checksum
#define BOOTLOADER_ERROR_PARSER_CRC \
(BOOTLOADER_ERROR_PARSER_BASE | 0x05L)
/// Invalid signature
#define BOOTLOADER_ERROR_PARSER_SIGNATURE \
(BOOTLOADER_ERROR_PARSER_BASE | 0x06L)
/// Image parsing is already done (or has previously errored out)
#define BOOTLOADER_ERROR_PARSER_EOF \
(BOOTLOADER_ERROR_PARSER_BASE | 0x07L)
/// Unknown data type in image file
#define BOOTLOADER_ERROR_PARSER_UNKNOWN_TAG \
(BOOTLOADER_ERROR_PARSER_BASE | 0x08L)
/// Image file version doesn't match with parser
#define BOOTLOADER_ERROR_PARSER_VERSION \
(BOOTLOADER_ERROR_PARSER_BASE | 0x09L)
/// Image file type doesn't match with parser
#define BOOTLOADER_ERROR_PARSER_FILETYPE \
(BOOTLOADER_ERROR_PARSER_BASE | 0x0AL)
/// Initialization failed
#define BOOTLOADER_ERROR_PARSER_INIT \
(BOOTLOADER_ERROR_PARSER_BASE | 0x0BL)
/// Upgrade file was rejected
#define BOOTLOADER_ERROR_PARSER_REJECTED \
(BOOTLOADER_ERROR_PARSER_BASE | 0x0CL)
/// Upgrade file overlaps with the upgrade location
#define BOOTLOADER_ERROR_PARSER_OVERLAP \
(BOOTLOADER_ERROR_PARSER_BASE | 0x0DL)
/// A GBL tag occurred in an order forbidden by the GBL format spec
#define BOOTLOADER_ERROR_PARSER_INVALID_TAG_ORDER \
(BOOTLOADER_ERROR_PARSER_BASE | 0x0EL)
/// OOB write in the storage slot while parsing the GBL file
#define BOOTLOADER_ERROR_PARSER_OOB_WRITE \
(BOOTLOADER_ERROR_PARSER_BASE | 0x0FL)
/** @} addtogroup ParserError */
/**
* @addtogroup SpiPeripheralError SPI Peripheral Driver Error Codes
* @brief Bootloader error codes returned by the SPI Peripheral driver.
* @details
* Offset from @ref BOOTLOADER_ERROR_SPI_PERIPHERAL_BASE
* @{
*/
/// Operation not allowed because hardware has not been initialized
#define BOOTLOADER_ERROR_SPI_PERIPHERAL_UNINIT \
(BOOTLOADER_ERROR_SPI_PERIPHERAL_BASE | 0x01)
/// Hardware fail during initialization
#define BOOTLOADER_ERROR_SPI_PERIPHERAL_INIT \
(BOOTLOADER_ERROR_SPI_PERIPHERAL_BASE | 0x02)
/// Invalid argument
#define BOOTLOADER_ERROR_SPI_PERIPHERAL_ARGUMENT \
(BOOTLOADER_ERROR_SPI_PERIPHERAL_BASE | 0x03)
/// Timeout
#define BOOTLOADER_ERROR_SPI_PERIPHERAL_TIMEOUT \
(BOOTLOADER_ERROR_SPI_PERIPHERAL_BASE | 0x04)
/// Buffer overflow condition
#define BOOTLOADER_ERROR_SPI_PERIPHERAL_OVERFLOW \
(BOOTLOADER_ERROR_SPI_PERIPHERAL_BASE | 0x05)
/// Busy condition
#define BOOTLOADER_ERROR_SPI_PERIPHERAL_BUSY \
(BOOTLOADER_ERROR_SPI_PERIPHERAL_BASE | 0x06)
/** @} addtogroup SpiPeripheralError */
/**
* @addtogroup UartError UART Driver Error Codes
* @brief Bootloader error codes returned by the UART driver.
* @details
* Offset from @ref BOOTLOADER_ERROR_UART_BASE
* @{
*/
/// Operation not allowed because hardware has not been initialized
#define BOOTLOADER_ERROR_UART_UNINIT (BOOTLOADER_ERROR_UART_BASE | 0x01)
/// Hardware fail during initialization
#define BOOTLOADER_ERROR_UART_INIT (BOOTLOADER_ERROR_UART_BASE | 0x02)
/// Invalid argument
#define BOOTLOADER_ERROR_UART_ARGUMENT (BOOTLOADER_ERROR_UART_BASE | 0x03)
/// Operation timed out
#define BOOTLOADER_ERROR_UART_TIMEOUT (BOOTLOADER_ERROR_UART_BASE | 0x04)
/// Buffer overflow condition
#define BOOTLOADER_ERROR_UART_OVERFLOW (BOOTLOADER_ERROR_UART_BASE | 0x05)
/// Busy condition
#define BOOTLOADER_ERROR_UART_BUSY (BOOTLOADER_ERROR_UART_BASE | 0x06)
/** @} addtogroup UartError */
/**
* @addtogroup CompressionError Compression Error Codes
* @brief Bootloader error codes returned by the decompressor
* @details
* Offset from @ref BOOTLOADER_ERROR_COMPRESSION_BASE
* @{
*/
/// Could not initialize decompressor
#define BOOTLOADER_ERROR_COMPRESSION_INIT \
(BOOTLOADER_ERROR_COMPRESSION_BASE | 0x01)
/// Invalid decompressor state -- possible invalid input
#define BOOTLOADER_ERROR_COMPRESSION_STATE \
(BOOTLOADER_ERROR_COMPRESSION_BASE | 0x02)
/// Data error
#define BOOTLOADER_ERROR_COMPRESSION_DATA \
(BOOTLOADER_ERROR_COMPRESSION_BASE | 0x03)
/// Data length error
#define BOOTLOADER_ERROR_COMPRESSION_DATALEN \
(BOOTLOADER_ERROR_COMPRESSION_BASE | 0x04)
/// Memory error
#define BOOTLOADER_ERROR_COMPRESSION_MEM \
(BOOTLOADER_ERROR_COMPRESSION_BASE | 0x05)
/** @} addtogroup CompressionError */
/** @} addtogroup ErrorCodes */
#endif // BTL_ERRORCODE_H

View File

@@ -0,0 +1,944 @@
/***************************************************************************//**
* @file
* @brief Application interface to the bootloader.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#include "btl_interface.h"
#include "em_core.h"
#include "btl_interface_cfg.h"
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
#if defined(SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#endif
#if defined(__GNUC__)
extern uint32_t __ResetReasonStart__;
#elif defined(__ICCARM__)
#pragma section = "BOOTLOADER_RESET_REASON"
#endif
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
// -----------------------------------------------------------------------------
// Configurations
#if ((!defined(BOOTLOADER_DISABLE_NVM3_FAULT_HANDLING) \
|| (defined(BOOTLOADER_DISABLE_NVM3_FAULT_HANDLING) \
&& (BOOTLOADER_DISABLE_NVM3_FAULT_HANDLING == 0))) && defined(SL_CATALOG_NVM3_PRESENT))
#define BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING
#endif // BOOTLOADER_DISABLE_NVM3_FAULT_HANDLING && SL_CATALOG_NVM3_PRESENT
#if !defined(BOOTLOADER_MANUAL_OVERRIDE_SECURITY_STATE) \
|| (defined(BOOTLOADER_MANUAL_OVERRIDE_SECURITY_STATE) \
&& (BOOTLOADER_MANUAL_OVERRIDE_SECURITY_STATE == 0))
#define BOOTLOADER_ENABLE_USART_AUTO_DETECTION
#endif // BOOTLOADER_MANUAL_OVERRIDE_SECURITY_STATE
#if (defined(BOOTLOADER_DISABLE_OLD_BOOTLOADER_MITIGATION) \
&& (BOOTLOADER_DISABLE_OLD_BOOTLOADER_MITIGATION == 1))
#define BOOTLOADER_DISABLE_MULTI_TIERED_FALLBACK
#undef BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING
#undef BOOTLOADER_ENABLE_USART_AUTO_DETECTION
#endif // BOOTLOADER_DISABLE_OLD_BOOTLOADER_MITIGATION
#if defined(SL_TRUSTZONE_SECURE)
#undef BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING
#endif // SL_TRUSTZONE_SECURE
// -----------------------------------------------------------------------------
// Configuration spesifics
#if defined(BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING)
// Allocated range of NVM3 IDs for bootloader usage */
#define BL_NVM3_RESERVED_ID (0x87100UL)
#include <string.h>
#include "nvm3_default.h"
static bool blPPUSATDnStateCacheSet = false;
static uint32_t blPPUSATDnStateCache[2] = { 0 };
#endif // BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING
#if defined(BOOTLOADER_ENABLE_USART_AUTO_DETECTION)
static void preConfigureUsartPPUSATD(void);
static void storeUsartInUse(void);
static int32_t usartNumberSpi = -1;
#endif // BOOTLOADER_ENABLE_USART_AUTO_DETECTION
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
// -----------------------------------------------------------------------------
// Static variables
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
#if !defined(BOOTLOADER_TEST_UNPRIVILEGED_ACCESS)
static CORE_DECLARE_IRQ_STATE;
#endif
static Bootloader_PPUSATDnCLKENnState_t blPPUSATDnCLKENnState = { 0 };
typedef enum {
IDLE, SAVE, TIERED
} ppusatdConfigurationState_t;
static ppusatdConfigurationState_t bootloader_ppusatdConfigstate = IDLE;
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
// -----------------------------------------------------------------------------
// Enums
typedef enum {
RESET, INITIALIZED, DEINITIALIZED
} initState_t;
static initState_t bootloader_InitState = RESET;
// -----------------------------------------------------------------------------
// Test helpers
#if defined(BOOTLOADER_TEST_UNPRIVILEGED_ACCESS)
extern bool enabled;
extern void enterUnprivilegedMode(bool);
extern void exitUnprivilegedMode(void);
#endif // BOOTLOADER_TEST_UNPRIVILEGED_ACCESS
// -----------------------------------------------------------------------------
// Functions
void bootloader_getInfo(BootloaderInformation_t *info)
{
#if defined(BOOTLOADER_HAS_FIRST_STAGE)
if (!bootloader_pointerToFirstStageValid(firstBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable)) {
// No bootloader is present (first stage or main stage invalid)
info->type = NO_BOOTLOADER;
info->capabilities = 0;
} else if ((firstBootloaderTable->header.type == BOOTLOADER_MAGIC_FIRST_STAGE)
&& (mainBootloaderTable->header.type == BOOTLOADER_MAGIC_MAIN)) {
info->type = SL_BOOTLOADER;
info->version = mainBootloaderTable->header.version;
info->capabilities = mainBootloaderTable->capabilities;
} else {
info->type = NO_BOOTLOADER;
info->capabilities = 0;
}
#else
if (!bootloader_pointerValid(mainBootloaderTable)) {
// No bootloader is present (first stage or main stage invalid)
info->type = NO_BOOTLOADER;
info->capabilities = 0;
} else if (mainBootloaderTable->header.type == BOOTLOADER_MAGIC_MAIN) {
info->type = SL_BOOTLOADER;
info->version = mainBootloaderTable->header.version;
info->capabilities = mainBootloaderTable->capabilities;
} else {
info->type = NO_BOOTLOADER;
info->capabilities = 0;
}
#endif
}
int32_t bootloader_init(void)
{
int32_t retVal;
if (!bootloader_pointerValid(mainBootloaderTable)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
if (mainBootloaderTable->header.type != BOOTLOADER_MAGIC_MAIN) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
if (bootloader_InitState == RESET || bootloader_InitState == DEINITIALIZED) {
#if defined(SL_TRUSTZONE_SECURE)
if (bootloader_InitState == RESET) {
// Enable SMU bus clock at the start-up of the TZ secure application
// to make it possible to configure the SMU peripheral. Since the CMU address
// is known. Otherwise, delegate the SMU bus clock enablement to the NS application.
#if defined(_CMU_CLKEN1_SMU_MASK)
CMU->CLKEN1_SET = CMU_CLKEN1_SMU;
#endif // _CMU_CLKEN1_SMU_MASK
}
#endif // SL_TRUSTZONE_SECURE
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif
#if defined(BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING)
NVIC_ClearPendingIRQ(SMU_SECURE_IRQn);
SMU->IF_CLR = SMU_IEN_PPUSEC;
NVIC_EnableIRQ(SMU_SECURE_IRQn);
SMU->IEN_SET = SMU_IEN_PPUSEC;
#endif
retVal = mainBootloaderTable->init();
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif
if (retVal == BOOTLOADER_OK) {
bootloader_InitState = INITIALIZED;
}
} else {
retVal = BOOTLOADER_OK;
}
return retVal;
}
int32_t bootloader_deinit(void)
{
int32_t retVal;
if (!bootloader_pointerValid(mainBootloaderTable)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
if (mainBootloaderTable->header.type != BOOTLOADER_MAGIC_MAIN) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
if (bootloader_InitState == INITIALIZED) {
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
#if defined(BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING)
SMU->IF_CLR = SMU_IEN_PPUSEC;
SMU->IEN_CLR = SMU_IEN_PPUSEC;
NVIC_ClearPendingIRQ(SMU_SECURE_IRQn);
NVIC_DisableIRQ(SMU_SECURE_IRQn);
#endif
retVal = mainBootloaderTable->deinit();
if (retVal == BOOTLOADER_OK) {
bootloader_InitState = DEINITIALIZED;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
} else {
retVal = BOOTLOADER_OK;
}
return retVal;
}
BootloaderResetCause_t bootloader_getResetReason(void)
{
#if defined(__GNUC__)
uint32_t resetReasonBase = (uint32_t)&__ResetReasonStart__;
#elif defined(__ICCARM__)
void *resetReasonBase = __section_begin("BOOTLOADER_RESET_REASON");
#endif
volatile BootloaderResetCause_t *resetCause = (BootloaderResetCause_t *)(resetReasonBase);
return *resetCause;
}
void bootloader_rebootAndInstall(void)
{
// Set reset reason to bootloader entry
#if defined(__GNUC__)
uint32_t resetReasonBase = (uint32_t)&__ResetReasonStart__;
#elif defined(__ICCARM__)
void *resetReasonBase = __section_begin("BOOTLOADER_RESET_REASON");
#endif
BootloaderResetCause_t *resetCause = (BootloaderResetCause_t *) (resetReasonBase);
resetCause->reason = BOOTLOADER_RESET_REASON_BOOTLOAD;
resetCause->signature = BOOTLOADER_RESET_SIGNATURE_VALID;
#if defined(RMU_PRESENT)
// Clear resetcause
RMU->CMD = RMU_CMD_RCCLR;
// Trigger a software system reset
RMU->CTRL = (RMU->CTRL & ~_RMU_CTRL_SYSRMODE_MASK) | RMU_CTRL_SYSRMODE_FULL;
#endif
NVIC_SystemReset();
}
int32_t bootloader_initParser(BootloaderParserContext_t *context,
size_t contextSize)
{
if (!bootloader_pointerValid(mainBootloaderTable)) {
return BOOTLOADER_ERROR_PARSE_FAILED;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
int32_t retVal = mainBootloaderTable->initParser(context, contextSize);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
int32_t bootloader_parseBuffer(BootloaderParserContext_t *context,
BootloaderParserCallbacks_t *callbacks,
uint8_t data[],
size_t numBytes)
{
if (!bootloader_pointerValid(mainBootloaderTable)) {
return BOOTLOADER_ERROR_PARSE_FAILED;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
int32_t retVal = mainBootloaderTable->parseBuffer(context, callbacks, data, numBytes);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
int32_t bootloader_parseImageInfo(BootloaderParserContext_t *context,
uint8_t data[],
size_t numBytes,
ApplicationData_t *appInfo,
uint32_t *bootloaderVersion)
{
if (!bootloader_pointerValid(mainBootloaderTable)) {
return BOOTLOADER_ERROR_PARSE_FAILED;
}
BootloaderInformation_t info = { .type = SL_BOOTLOADER, .version = 0U, .capabilities = 0U };
bootloader_getInfo(&info);
uint32_t blMajorVersion = ((info.version & BOOTLOADER_VERSION_MAJOR_MASK)
>> BOOTLOADER_VERSION_MAJOR_SHIFT);
uint32_t blMinorVersion = ((info.version & BOOTLOADER_VERSION_MINOR_MASK)
>> BOOTLOADER_VERSION_MINOR_SHIFT);
if ((blMajorVersion < 1UL) || (blMajorVersion == 1UL && blMinorVersion < 11UL)) {
return BOOTLOADER_ERROR_PARSE_FAILED;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
int32_t retVal = mainBootloaderTable->parseImageInfo(context, data, numBytes, appInfo, bootloaderVersion);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
uint32_t bootloader_parserContextSize(void)
{
if (!bootloader_pointerValid(mainBootloaderTable)) {
return 0UL;
}
BootloaderInformation_t info = { .type = SL_BOOTLOADER, .version = 0U, .capabilities = 0U };
bootloader_getInfo(&info);
uint32_t blMajorVersion = ((info.version & BOOTLOADER_VERSION_MAJOR_MASK)
>> BOOTLOADER_VERSION_MAJOR_SHIFT);
uint32_t blMinorVersion = ((info.version & BOOTLOADER_VERSION_MINOR_MASK)
>> BOOTLOADER_VERSION_MINOR_SHIFT);
if (blMajorVersion < 1UL) {
return 384UL;
}
if (blMajorVersion == 1UL && blMinorVersion < 11UL) {
#if defined(_SILICON_LABS_32B_SERIES_2)
if (blMinorVersion == 10UL) {
return 524UL;
} else {
return 384UL;
}
#else
return 384UL;
#endif
}
return (uint32_t)mainBootloaderTable->parserContextSize();
}
bool bootloader_verifyApplication(uint32_t startAddress)
{
if (!bootloader_pointerValid(mainBootloaderTable)) {
return false;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
bool retVal = mainBootloaderTable->verifyApplication(startAddress);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
bool bootloader_secureBootEnforced(void)
{
BootloaderInformation_t info = { .type = SL_BOOTLOADER, .version = 0U, .capabilities = 0U };
bootloader_getInfo(&info);
if (info.capabilities & BOOTLOADER_CAPABILITY_ENFORCE_SECURE_BOOT) {
return true;
}
return false;
}
bool bootloader_getUpgradeLocation(uint32_t *location)
{
if (!bootloader_pointerValid(mainBootloaderTable)) {
return false;
}
BootloaderInformation_t info = { .type = SL_BOOTLOADER, .version = 0U, .capabilities = 0U };
bootloader_getInfo(&info);
uint32_t blMajorVersion = ((info.version & BOOTLOADER_VERSION_MAJOR_MASK)
>> BOOTLOADER_VERSION_MAJOR_SHIFT);
uint32_t blMinorVersion = ((info.version & BOOTLOADER_VERSION_MINOR_MASK)
>> BOOTLOADER_VERSION_MINOR_SHIFT);
if (blMajorVersion > 2UL || (blMajorVersion == 2UL && blMinorVersion >= 1UL)) {
*location = mainBootloaderTable->getUpgradeLocation();
return true;
}
return false;
}
#if !defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
uint32_t bootloader_remainingApplicationUpgrades(void)
{
if (!bootloader_pointerValid(mainBootloaderTable)) {
return 0UL;
}
BootloaderInformation_t info = { .type = SL_BOOTLOADER, .version = 0U, .capabilities = 0U };
bootloader_getInfo(&info);
uint32_t blMajorVersion = ((info.version & BOOTLOADER_VERSION_MAJOR_MASK)
>> BOOTLOADER_VERSION_MAJOR_SHIFT);
uint32_t blMinorVersion = ((info.version & BOOTLOADER_VERSION_MINOR_MASK)
>> BOOTLOADER_VERSION_MINOR_SHIFT);
if ((blMajorVersion < 1UL) || (blMajorVersion == 1UL && blMinorVersion < 11UL)) {
return 0UL;
}
return (uint32_t)mainBootloaderTable->remainingApplicationUpgrades();
}
#endif
#if defined(_SILICON_LABS_32B_SERIES_2)
bool bootloader_getCertificateVersion(uint32_t *version)
{
// Access word 13 to read sl_app_properties of the bootloader.
ApplicationProperties_t *blProperties =
(ApplicationProperties_t *)(*(uint32_t *)(BTL_MAIN_STAGE_BASE + 52UL));
if (!bootloader_pointerValid(blProperties)) {
return false;
}
// Compatibility check of the application properties struct.
if (((blProperties->structVersion & APPLICATION_PROPERTIES_VERSION_MAJOR_MASK)
>> APPLICATION_PROPERTIES_VERSION_MAJOR_SHIFT) < 1UL) {
return false;
}
if (((blProperties->structVersion & APPLICATION_PROPERTIES_VERSION_MINOR_MASK)
>> APPLICATION_PROPERTIES_VERSION_MINOR_SHIFT) < 1UL) {
return false;
}
if (blProperties->cert == NULL) {
return false;
}
*version = blProperties->cert->version;
return true;
}
#endif // _SILICON_LABS_32B_SERIES_2
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
void bootloader_getPeripheralList(uint32_t *ppusatd0, uint32_t *ppusatd1, uint32_t *ppusatd2)
{
if (!bootloader_pointerValid(mainBootloaderTable)) {
return;
}
BootloaderInformation_t info = { .type = SL_BOOTLOADER, .version = 0U, .capabilities = 0U };
bootloader_getInfo(&info);
if (info.capabilities & BOOTLOADER_CAPABILITY_PERIPHERAL_LIST) {
mainBootloaderTable->getPeripheralList(ppusatd0, ppusatd1, ppusatd2);
}
}
#else
void bootloader_getPeripheralList(uint32_t *ppusatd0, uint32_t *ppusatd1)
{
if (!bootloader_pointerValid(mainBootloaderTable)) {
return;
}
BootloaderInformation_t info = { .type = SL_BOOTLOADER, .version = 0U, .capabilities = 0U };
bootloader_getInfo(&info);
if (info.capabilities & BOOTLOADER_CAPABILITY_PERIPHERAL_LIST) {
mainBootloaderTable->getPeripheralList(ppusatd0, ppusatd1);
}
}
#endif
void bootloader_ppusatdnSaveReconfigureState(Bootloader_PPUSATDnCLKENnState_t *ctx)
{
if (bootloader_ppusatdConfigstate != IDLE) {
// This function is called from a bootloader callback function
bootloader_ppusatdConfigstate = TIERED;
return;
}
uint32_t ppusatd0 = 0u;
uint32_t ppusatd1 = 0u;
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
uint32_t ppusatd2 = 0u;
#endif
if (ctx == NULL) {
return;
}
bootloader_ppusatdConfigstate = SAVE;
// Enter ATOMIC section. The ATOMIC section is exited when
// the restore function is called.
#if !defined(BOOTLOADER_TEST_UNPRIVILEGED_ACCESS)
CORE_ENTER_ATOMIC();
#endif
sli_bootloader_preHook();
#if defined(BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING)
// Read the stored PPUSATD state from NVM3
if (!blPPUSATDnStateCacheSet) {
Ecode_t status;
status = nvm3_initDefault();
if (status == ECODE_NVM3_OK) {
nvm3_ObjectKey_t object_id = BL_NVM3_RESERVED_ID;
status = nvm3_readData(nvm3_defaultHandle,
object_id,
blPPUSATDnStateCache,
sizeof(blPPUSATDnStateCache));
if (status == ECODE_NVM3_OK) {
blPPUSATDnStateCacheSet = true;
}
}
}
#endif // BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING
// Store the CLKENn states
#if defined(_CMU_CLKEN0_MASK)
ctx->CLKEN0 = CMU->CLKEN0;
ctx->CLKEN1 = CMU->CLKEN1;
#endif
#if defined(_CMU_CLKEN1_SMU_MASK)
CMU->CLKEN1_SET = CMU_CLKEN1_SMU;
#endif // _CMU_CLKEN1_SMU_MASK
ctx->SMU_STATUS = SMU->STATUS;
// Unlock SMU before re-configuration
SMU->LOCK = SMU_LOCK_SMULOCKKEY_UNLOCK;
// Store the PPUSATDn states
ctx->PPUSATD0 = SMU->PPUSATD0;
ctx->PPUSATD1 = SMU->PPUSATD1;
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
ctx->PPUSATD2 = SMU->PPUSATD2;
#endif
ctx->BMPUSATD0 = SMU->BMPUSATD0;
#if defined(SMU_NS_CFGNS_BASE)
// Store the PPUPATDn states
ctx->PPUPATD0 = SMU->PPUPATD0;
ctx->PPUPATD1 = SMU->PPUPATD1;
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
ctx->PPUPATD2 = SMU->PPUPATD2;
#endif
SMU->PPUPATD0 = SMU_NS_CFGNS->PPUNSPATD0;
SMU->PPUPATD1 = SMU_NS_CFGNS->PPUNSPATD1;
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
SMU->PPUPATD2 = SMU_NS_CFGNS->PPUNSPATD2;
#endif
#endif // SMU_NS_CFGNS_BASE
#if defined(CMU_CLKEN0_LDMA)
CMU->CLKEN0_SET = CMU_CLKEN0_LDMA;
#endif // CMU_CLKEN0_LDMA
#if defined(CRYPTOACC_PRESENT)
CMU->CLKEN1_SET = CMU_CLKEN1_CRYPTOACC;
#endif
// Wait for any active transition of other busmasters to finish
if (SMU->PPUSATD0 & SMU_PPUSATD0_LDMA) {
while (LDMA_S->STATUS & LDMA_STATUS_ANYBUSY) ;
} else {
while (LDMA_NS->STATUS & LDMA_STATUS_ANYBUSY) ;
}
#if defined(CRYPTOACC_PRESENT)
if (SMU->PPUSATD1 & SMU_PPUSATD1_CRYPTOACC) {
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_230)
while (CRYPTOACC_S->DMACTRL_STATUS & (CRYPTOACC_DMACTRL_STATUS_FETCH_BUSY | CRYPTOACC_DMACTRL_STATUS_PUSH_BUSY | CRYPTOACC_DMACTRL_STATUS_SOFT_RST_BUSY)) ;
#else
while (CRYPTOACC_S->STATUS & (CRYPTOACC_STATUS_FETCHERBSY | CRYPTOACC_STATUS_PUSHERBSY | CRYPTOACC_STATUS_SOFTRSTBSY)) ;
#endif
} else {
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_230)
while (CRYPTOACC_NS->DMACTRL_STATUS & (CRYPTOACC_DMACTRL_STATUS_FETCH_BUSY | CRYPTOACC_DMACTRL_STATUS_PUSH_BUSY | CRYPTOACC_DMACTRL_STATUS_SOFT_RST_BUSY)) ;
#else
while (CRYPTOACC_NS->STATUS & (CRYPTOACC_STATUS_FETCHERBSY | CRYPTOACC_STATUS_PUSHERBSY | CRYPTOACC_STATUS_SOFTRSTBSY)) ;
#endif
}
#endif // CRYPTOACC_PRESENT
// Configure the peripheral secure access state before calling into the bootloader.
#if !defined(BOOTLOADER_DISABLE_MULTI_TIERED_FALLBACK)
#if defined(BOOTLOADER_ENABLE_USART_AUTO_DETECTION)
// If we do not know which USART is used by the bootloader,
// and the bootloader is not initialized,
// Configure PPUSATDn bits for all the USART not in use.
preConfigureUsartPPUSATD();
#else
SMU->PPUSATD0_SET = BOOTLOADER_PPUSATD0_MASK;
SMU->PPUSATD1_SET = BOOTLOADER_PPUSATD1_MASK;
#endif // BOOTLOADER_ENABLE_USART_AUTO_DETECTION
SMU->PPUSATD0_SET = SMU_PPUSATD0_CMU;
SMU->PPUSATD0_SET = SMU_PPUSATD0_MSC;
if (bootloader_getAllocatedDMAChannel() != -1
&& bootloader_getAllocatedDMAChannel() != BOOTLOADER_ERROR_INIT_STORAGE) {
SMU->PPUSATD0_SET = SMU_PPUSATD0_LDMA;
SMU->PPUSATD0_SET = SMU_PPUSATD0_LDMAXBAR;
SMU->BMPUSATD0_SET = SMU_BMPUSATD0_LDMA;
}
SMU->PPUSATD0_SET = SMU_PPUSATD0_HFRCO0;
#if !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) && !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6) \
&& !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_8) && !defined(_SILICON_LABS_32B_SERIES_2_CONFIG_9)
SMU->PPUSATD0_SET = SMU_PPUSATD0_GPIO;
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
SMU->PPUSATD1_SET = SMU_PPUSATD1_GPCRC;
#else
SMU->PPUSATD0_SET = SMU_PPUSATD0_GPCRC;
#endif
#if defined(SMU_PPUSATD1_CRYPTOACC)
SMU->PPUSATD1_SET = SMU_PPUSATD1_CRYPTOACC;
#endif // SMU_PPUSATD1_CRYPTOACC
#if defined(SMU_PPUSATD1_SEMAILBOX)
SMU->PPUSATD1_SET = SMU_PPUSATD1_SEMAILBOX;
#elif defined(SMU_PPUSATD2_SEMAILBOX)
SMU->PPUSATD2_SET = SMU_PPUSATD2_SEMAILBOX;
#endif // SMU_PPUSATD1_SEMAILBOX
#elif defined(SL_TRUSTZONE_SECURE)
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5)
SMU->BMPUSATD0_SET = SMU_BMPUSATD0_LDMA0;
SMU->BMPUSATD0_SET = SMU_BMPUSATD0_LDMA1;
#else
SMU->BMPUSATD0_SET = SMU_BMPUSATD0_LDMA;
#endif
#endif // BOOTLOADER_DISABLE_MULTI_TIERED_FALLBACK
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
bootloader_getPeripheralList(&ppusatd0, &ppusatd1, &ppusatd2);
SMU->PPUSATD0_SET = ppusatd0;
SMU->PPUSATD1_SET = ppusatd1;
SMU->PPUSATD2_SET = ppusatd2;
#else
bootloader_getPeripheralList(&ppusatd0, &ppusatd1);
SMU->PPUSATD0_SET = ppusatd0;
SMU->PPUSATD1_SET = ppusatd1;
#endif
#if defined(BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING)
// Update the peripheral secure access state of
// the "unknown" peripheral that triggered a fault earlier
if (blPPUSATDnStateCacheSet == true) {
SMU->PPUSATD0_SET = blPPUSATDnStateCache[0];
SMU->PPUSATD1_SET = blPPUSATDnStateCache[1];
}
#endif // BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING
#if defined(BOOTLOADER_TEST_UNPRIVILEGED_ACCESS)
enterUnprivilegedMode(enabled);
#endif
}
void bootloader_ppusatdnRestoreState(Bootloader_PPUSATDnCLKENnState_t *ctx)
{
#if defined(BOOTLOADER_TEST_UNPRIVILEGED_ACCESS)
exitUnprivilegedMode();
#endif
if (bootloader_ppusatdConfigstate != SAVE) {
// This function is called from a bootloader callback function
bootloader_ppusatdConfigstate = SAVE;
return;
}
if (ctx == NULL) {
return;
}
// Wait for any active transition of other busmasters to finish
if (bootloader_getAllocatedDMAChannel() != -1
&& bootloader_getAllocatedDMAChannel() != BOOTLOADER_ERROR_INIT_STORAGE) {
#if defined(CMU_CLKEN0_LDMA)
CMU_S->CLKEN0_SET = CMU_CLKEN0_LDMA;
#endif // CMU_CLKEN0_LDMA
while (LDMA_S->STATUS & LDMA_STATUS_ANYBUSY) ;
}
#if defined(CRYPTOACC_PRESENT)
if (SMU->PPUSATD0 & SMU_PPUSATD0_CMU) {
CMU_S->CLKEN1_SET = CMU_CLKEN1_CRYPTOACC;
} else {
CMU_NS->CLKEN1_SET = CMU_CLKEN1_CRYPTOACC;
}
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_230)
while (CRYPTOACC_S->DMACTRL_STATUS & (CRYPTOACC_DMACTRL_STATUS_FETCH_BUSY | CRYPTOACC_DMACTRL_STATUS_PUSH_BUSY | CRYPTOACC_DMACTRL_STATUS_SOFT_RST_BUSY)) ;
#else
while (CRYPTOACC_S->STATUS & (CRYPTOACC_STATUS_FETCHERBSY | CRYPTOACC_STATUS_PUSHERBSY | CRYPTOACC_STATUS_SOFTRSTBSY)) ;
#endif
#endif // CRYPTOACC_PRESENT
SMU->PPUSATD0 = ctx->PPUSATD0;
SMU->PPUSATD1 = ctx->PPUSATD1;
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
SMU->PPUSATD2 = ctx->PPUSATD2;
#endif
SMU->BMPUSATD0 = ctx->BMPUSATD0;
#if defined(SMU_NS_CFGNS_BASE)
SMU->PPUPATD0 = ctx->PPUPATD0;
SMU->PPUPATD1 = ctx->PPUPATD1;
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
SMU->PPUPATD2 = ctx->PPUPATD2;
#endif
#endif // SMU_NS_CFGNS_BASE
if (ctx->SMU_STATUS & SMU_STATUS_SMULOCK) {
SMU->LOCK = 0u;
}
#if defined(BOOTLOADER_ENABLE_USART_AUTO_DETECTION)
storeUsartInUse();
#endif // BOOTLOADER_ENABLE_USART_AUTO_DETECTION
// Restore the CLKENn states
#if defined(_CMU_CLKEN0_MASK)
CMU->CLKEN0 = ctx->CLKEN0;
CMU->CLKEN1 = ctx->CLKEN1;
#endif
sli_bootloader_postHook();
#if !defined(BOOTLOADER_TEST_UNPRIVILEGED_ACCESS)
CORE_EXIT_ATOMIC();
#endif
// Update the state after the critical section has been
// exited to ensure that the SMU interrupt gets fired,
// before the state change happens.
bootloader_ppusatdConfigstate = IDLE;
}
__attribute__ ((weak)) void sli_bootloader_preHook(void)
{
}
__attribute__ ((weak)) void sli_bootloader_postHook(void)
{
}
#if defined(BOOTLOADER_ENABLE_USART_AUTO_DETECTION)
static void preConfigureUsartPPUSATD(void)
{
if (usartNumberSpi != -1) {
#if defined(SMU_PPUSATD1_USART0)
SMU->PPUSATD1_SET = (SMU_PPUSATD1_USART0 << usartNumberSpi);
#else
SMU->PPUSATD0_SET = (SMU_PPUSATD0_USART0 << usartNumberSpi);
#endif
return;
}
if (bootloader_InitState != RESET) {
// The USART taken by the bootloader
// is still unknown, do nothing.
return;
}
#if defined(USART0_BASE)
#if defined(CMU_CLKEN0_USART0)
CMU->CLKEN0_SET = CMU_CLKEN0_USART0;
#endif // CMU_CLKEN0_USART0
#if defined(SL_TRUSTZONE_SECURE)
if (USART0_NS->EN == _USART_EN_RESETVALUE) {
#else
if (USART0->EN == _USART_EN_RESETVALUE) {
#endif // SL_TRUSTZONE_SECURE
#if defined(SMU_PPUSATD1_USART0)
SMU->PPUSATD1_SET = SMU_PPUSATD1_USART0;
#else
SMU->PPUSATD0_SET = SMU_PPUSATD0_USART0;
#endif
}
#endif // USART0_BASE
#if defined(USART1_BASE)
#if defined(CMU_CLKEN0_USART1)
CMU->CLKEN0_SET = CMU_CLKEN0_USART1;
#elif defined(CMU_CLKEN2_USART1)
CMU->CLKEN2_SET = CMU_CLKEN2_USART1;
#endif
#if defined(SL_TRUSTZONE_SECURE)
if (USART1_NS->EN == _USART_EN_RESETVALUE) {
#else
if (USART1->EN == _USART_EN_RESETVALUE) {
#endif // SL_TRUSTZONE_SECURE
#if defined(SMU_PPUSATD1_USART1)
SMU->PPUSATD1_SET = SMU_PPUSATD1_USART1;
#else
SMU->PPUSATD0_SET = SMU_PPUSATD0_USART1;
#endif
}
#endif // USART1_BASE
#if defined(USART2_BASE)
#if defined(CMU_CLKEN0_USART2)
CMU->CLKEN0_SET = CMU_CLKEN0_USART2;
#elif defined(CMU_CLKEN2_USART2)
CMU->CLKEN2_SET = CMU_CLKEN2_USART2;
#endif
#if defined(SL_TRUSTZONE_SECURE)
if (USART2_NS->EN == _USART_EN_RESETVALUE) {
#else
if (USART2->EN == _USART_EN_RESETVALUE) {
#endif // SL_TRUSTZONE_SECURE
#if defined(SMU_PPUSATD1_USART2)
SMU->PPUSATD1_SET = SMU_PPUSATD1_USART2;
#else
SMU->PPUSATD0_SET = SMU_PPUSATD0_USART2;
#endif
}
#endif // USART2_BASE
}
static void storeUsartInUse(void)
{
if ((usartNumberSpi != -1) || (bootloader_InitState != RESET)) {
return;
}
#if defined(USART0_BASE)
#if defined(SL_TRUSTZONE_SECURE)
if (USART0_NS->EN & USART_EN_EN) {
#else
if (USART0->EN & USART_EN_EN) {
#endif // SL_TRUSTZONE_SECURE
usartNumberSpi = 0;
}
#endif // USART0_BASE
#if defined(USART1_BASE)
#if defined(SL_TRUSTZONE_SECURE)
if (USART1_NS->EN & USART_EN_EN) {
#else
if (USART1->EN & USART_EN_EN) {
#endif // SL_TRUSTZONE_SECURE
usartNumberSpi = 1;
}
#endif // USART1_BASE
#if defined(USART2_BASE)
#if defined(SL_TRUSTZONE_SECURE)
if (USART2_NS->EN & USART_EN_EN) {
#else
if (USART2->EN & USART_EN_EN) {
#endif // SL_TRUSTZONE_SECURE
usartNumberSpi = 2;
}
#endif // USART2_BASE
}
#endif // BOOTLOADER_ENABLE_USART_AUTO_DETECTION
#if defined(BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING)
void SMU_SECURE_IRQHandler(void)
{
#if !defined(BOOTLOADER_TEST_FAULT_HANDLING)
if (bootloader_ppusatdConfigstate == IDLE) {
// If none of the bootloader interface operations are active,
// the fault is not caused by the bootloader. Just park in the while loop.
while (true) ;
}
#endif // BOOTLOADER_TEST_FAULT_HANDLING
Ecode_t status;
uint32_t PPUSATDn_state[2] = { 0 };
nvm3_ObjectKey_t object_id = BL_NVM3_RESERVED_ID;
// First read the pre-existing configuration
status = nvm3_readData(nvm3_defaultHandle, object_id, PPUSATDn_state, sizeof(PPUSATDn_state));
if (status == ECODE_NVM3_OK) {
if (SMU->PPUFS > 31) {
PPUSATDn_state[1] |= 1 << (SMU->PPUFS - 32);
} else {
PPUSATDn_state[0] |= 1 << SMU->PPUFS;
}
// Nothing to do to recover if this fails, just continue and perform a reset.
(void)nvm3_writeData(nvm3_defaultHandle, object_id, PPUSATDn_state, sizeof(PPUSATDn_state));
} else if (status == ECODE_NVM3_ERR_KEY_NOT_FOUND) {
if (SMU->PPUFS > 31) {
PPUSATDn_state[1] = 1 << (SMU->PPUFS - 32);
} else {
PPUSATDn_state[0] = 1 << SMU->PPUFS;
}
(void)nvm3_writeData(nvm3_defaultHandle, object_id, PPUSATDn_state, sizeof(PPUSATDn_state));
} else {
// Do nothing. If NVM3 read fails for an unknown reason,
// perform a reset to recover from the failure state.
}
#if defined(__GNUC__)
uint32_t resetReasonBase = (uint32_t)&__ResetReasonStart__;
#elif defined(__ICCARM__)
void *resetReasonBase = __section_begin("BOOTLOADER_RESET_REASON");
#endif
BootloaderResetCause_t *resetCause = (BootloaderResetCause_t *) (resetReasonBase);
resetCause->reason = BOOTLOADER_RESET_REASON_FAULT;
resetCause->signature = BOOTLOADER_RESET_SIGNATURE_VALID;
NVIC_SystemReset();
}
#endif // BOOTLOADER_ENABLE_NVM3_FAULT_HANDLING
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif

View File

@@ -0,0 +1,773 @@
/***************************************************************************//**
* @file
* @brief Application interface to the bootloader.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#ifndef BTL_INTERFACE_H
#define BTL_INTERFACE_H
#include <stddef.h>
#include "btl_errorcode.h"
#include "btl_reset_info.h"
#include "application_properties.h"
// Include component-specific interfaces
#include "btl_interface_parser.h"
#include "btl_interface_storage.h"
// Get flash page size
#include "em_device.h"
#if defined(SL_TRUSTZONE_NONSECURE)
#include "sli_tz_ns_interface.h"
#endif
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
/***************************************************************************//**
* @addtogroup Interface Application Interface
* @brief Application interface to the bootloader
* @details
* The application interface consists of functions that can be included
* in the customer application that and will communicate with the
* bootloader through the @ref MainBootloaderTable_t. This table
* contains function pointers to the bootloader. The 10th word of the
* bootloader contains a pointer to this struct, allowing any application to
* easily locate it.
* To access the bootloader table, use wrapper functions. Avoid
* accessing the bootloader table directly.
*
* @{
* @addtogroup CommonInterface Common Application Interface
* @brief Generic application interface available on all versions of the
* bootloader, regardless of the available components.
* @note These Bootloader APIs are not reentrant and should be wrapped in critical section
* where needed.
* @details
* @{
******************************************************************************/
/// Bare boot table. Can be mapped on top of vector table to access contents.
typedef struct {
/// Pointer to top of stack
uint32_t *stackTop;
/// Pointer to reset vector
void (*resetVector)(void);
/// Reserved pointers to fault handlers
uint32_t reserved0[5];
/// Reserved pointers to RESERVED fields
uint32_t reserved1[3];
/// Pointer to bootloader table
void *table;
/// Reserved pointers to SVC and DebugMon interrupts
uint32_t reserved2[2];
/// Pointer to application signature
void *signature;
} BareBootTable_t;
// --------------------------------
// Bootloader defines
/// Bootloader version major version shift value
#define BOOTLOADER_VERSION_MAJOR_SHIFT (24U)
/// Bootloader version minor version shift value
#define BOOTLOADER_VERSION_MINOR_SHIFT (16U)
/// Bootloader version major version mask
#define BOOTLOADER_VERSION_MAJOR_MASK (0xFF000000U)
/// Bootloader version minor version mask
#define BOOTLOADER_VERSION_MINOR_MASK (0x00FF0000U)
/// Bootloader interface APIs are trust zone aware
#if defined(BOOTLOADER_SECURE)
#define BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
#elif defined(_SILICON_LABS_32B_SERIES_2) && !defined(BOOTLOADER_APPLOADER)
// The bootloader with AppLoader as the communication interface will not
// re-configure the SMU since it is using the NS peripherals by default.
#define BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
#endif
// --------------------------------
// Bootloader information typedefs
/// Type of bootloader
typedef enum {
/// No bootloader present.
NO_BOOTLOADER = 0,
/// Bootloader is a Silicon Labs bootloader.
SL_BOOTLOADER = 1
} BootloaderType_t;
/// Information about the current bootloader
typedef struct {
/// The type of bootloader.
BootloaderType_t type;
/// Version number of the bootloader
uint32_t version;
/// Capability mask for the bootloader.
uint32_t capabilities;
} BootloaderInformation_t;
/// Common header for bootloader tables
typedef struct {
/// Type of image
uint32_t type;
/// Version number of the bootloader/application table
uint32_t layout;
/// Version number of the image
uint32_t version;
} BootloaderHeader_t;
/// Address table for the First Stage Bootloader
typedef struct {
/// Header of the First Stage Bootloader table
BootloaderHeader_t header;
/// Start address of the Main Bootloader
BareBootTable_t *mainBootloader;
/// Location of the Main Bootloader upgrade image
BareBootTable_t *upgradeLocation;
} FirstBootloaderTable_t;
/// Address table for the Main Bootloader
typedef struct {
/// Header of the Main Bootloader table
BootloaderHeader_t header;
/// Size of the Main Bootloader
uint32_t size;
/// Start address of the application
BareBootTable_t *startOfAppSpace;
/// End address of the allocated application space
uint32_t *endOfAppSpace;
/// Capabilities of the bootloader
uint32_t capabilities;
// ------------------------------
/// Initialize bootloader for use from application
int32_t (*init)(void);
/// Deinitialize bootloader after use from application
int32_t (*deinit)(void);
// ------------------------------
/// Verify application
bool (*verifyApplication)(uint32_t startAddress);
// ------------------------------
/// Initialize parser
int32_t (*initParser)(BootloaderParserContext_t *context, size_t contextSize);
/// Parse a buffer
int32_t (*parseBuffer)(BootloaderParserContext_t *context,
const BootloaderParserCallbacks_t *callbacks,
uint8_t data[],
size_t numBytes);
// ------------------------------
/// Function table for storage component
const BootloaderStorageFunctions_t *storage;
// ------------------------------
/// Parse a buffer and get application and bootloader upgrade metadata from the buffer.
int32_t (*parseImageInfo)(BootloaderParserContext_t *context,
uint8_t data[],
size_t numBytes,
ApplicationData_t *appInfo,
uint32_t *bootloaderVersion);
// ------------------------------
/// Size of context buffer used by bootloader image parser to store parser state
uint32_t (*parserContextSize)(void);
// ------------------------------
/// Remaining number of application upgrades
uint32_t (*remainingApplicationUpgrades)(void);
// ------------------------------
/// Get the list of the peripheral that is used by the bootloader
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
void (*getPeripheralList)(uint32_t *ppusatd0, uint32_t *ppusatd1, uint32_t *ppusatd2);
#else
void (*getPeripheralList)(uint32_t *ppusatd0, uint32_t *ppusatd1);
#endif
// ------------------------------
/// Get base address of bootloader upgrade image
uint32_t (*getUpgradeLocation)(void);
} MainBootloaderTable_t;
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
/// Struct that represents the state of the PPUSATDn, PPUPATDn and CLKENn registers
typedef struct {
uint32_t PPUSATD0;
uint32_t PPUSATD1;
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
uint32_t PPUSATD2;
#endif
uint32_t BMPUSATD0;
#if defined(SMU_NS_CFGNS_BASE)
uint32_t PPUPATD0;
uint32_t PPUPATD1;
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
uint32_t PPUPATD2;
#endif
#endif
#if defined(_CMU_CLKEN0_MASK)
uint32_t CLKEN0;
uint32_t CLKEN1;
#endif
uint32_t SMU_STATUS;
} Bootloader_PPUSATDnCLKENnState_t;
/// Struct containing function arguments
typedef struct Bootloader_inOutVec {
void *base; /// the start address of the memory buffer
size_t len; /// the size in bytes
} Bootloader_inOutVec_t;
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
// --------------------------------
// Bootloader capabilities
/// Bootloader enforces signed application upgrade images
#define BOOTLOADER_CAPABILITY_ENFORCE_UPGRADE_SIGNATURE (1 << 0)
/// Bootloader enforces encrypted application upgrade images
#define BOOTLOADER_CAPABILITY_ENFORCE_UPGRADE_ENCRYPTION (1 << 1)
/// @brief Bootloader enforces signature verification of the application image
/// before every boot
#define BOOTLOADER_CAPABILITY_ENFORCE_SECURE_BOOT (1 << 2)
/// Bootloader has the capability of being upgraded
#define BOOTLOADER_CAPABILITY_BOOTLOADER_UPGRADE (1 << 4)
/// Bootloader has the capability of parsing GBL files
#define BOOTLOADER_CAPABILITY_GBL (1 << 5)
/// Bootloader has the capability of parsing signed GBL files
#define BOOTLOADER_CAPABILITY_GBL_SIGNATURE (1 << 6)
/// Bootloader has the capability of parsing encrypted GBL files
#define BOOTLOADER_CAPABILITY_GBL_ENCRYPTION (1 << 7)
/// @brief Bootloader enforces signature verification of the application image
/// before every boot using certificate
#define BOOTLOADER_CAPABILITY_ENFORCE_CERTIFICATE_SECURE_BOOT (1 << 8)
/// Bootloader has the capability of application rollback protection
#define BOOTLOADER_CAPABILITY_ROLLBACK_PROTECTION (1 << 9)
/// Bootloader has the capability to check the peripherals in use
#define BOOTLOADER_CAPABILITY_PERIPHERAL_LIST (1 << 10)
/// @brief Bootloader has the capability of storing data in an internal or
/// external storage medium
#define BOOTLOADER_CAPABILITY_STORAGE (1 << 16)
/// @brief Bootloader has the capability of communicating with host processors
/// using a communication interface
#define BOOTLOADER_CAPABILITY_COMMUNICATION (1 << 20)
// --------------------------------
// Magic constants for bootloader tables
/// Magic word indicating first stage bootloader table
#define BOOTLOADER_MAGIC_FIRST_STAGE (0xB00710ADUL)
/// Magic word indicating main bootloader table
#define BOOTLOADER_MAGIC_MAIN (0x5ECDB007UL)
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
#define BOOTLOADER_HEADER_VERSION_FIRST_STAGE (0x00000001UL)
#define BOOTLOADER_HEADER_VERSION_MAIN (0x00000002UL)
/// @endcond
// --------------------------------
// Bootloader table access
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
#if defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT) || defined(MAIN_BOOTLOADER_TEST)
// No first stage on devices with SE
#define BTL_FIRST_STAGE_SIZE (0UL)
#else
// First stage takes a single flash page
#define BTL_FIRST_STAGE_SIZE (FLASH_PAGE_SIZE)
#define BOOTLOADER_HAS_FIRST_STAGE
#endif
#if defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
// No writeable bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE 0x00000000UL
#define BTL_APPLICATION_BASE 0x00004000UL
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- BTL_FIRST_STAGE_SIZE)
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_84)
// Dedicated bootloader area of 38k
// Place the bootloader in the dedicated bootloader area of the
// information block
#define BTL_FIRST_STAGE_BASE 0x0FE10000UL
#define BTL_APPLICATION_BASE 0x00000000UL
#define BTL_MAIN_STAGE_MAX_SIZE (0x00009800UL - BTL_FIRST_STAGE_SIZE)
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_89)
#define BTL_FIRST_STAGE_BASE 0x0FE10000UL
#if defined(MAIN_BOOTLOADER_IN_MAIN_FLASH)
#define BTL_APPLICATION_BASE 0x00004800UL
#define BTL_MAIN_STAGE_MAX_SIZE BTL_APPLICATION_BASE
#else
// Dedicated bootloader area of 16k
// Place the bootloader in the dedicated bootloader area of the
// information block
#define BTL_APPLICATION_BASE 0x00000000UL
#define BTL_MAIN_STAGE_MAX_SIZE (0x00004000UL - BTL_FIRST_STAGE_SIZE)
#endif
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_95)
#define BTL_FIRST_STAGE_BASE 0x0FE10000UL
#if defined(MAIN_BOOTLOADER_IN_MAIN_FLASH)
#define BTL_APPLICATION_BASE 0x00004800UL
#define BTL_MAIN_STAGE_MAX_SIZE BTL_APPLICATION_BASE
#else
// Dedicated bootloader area of 18k
// Place the bootloader in the dedicated bootloader area of the
// information block
#define BTL_APPLICATION_BASE 0x00000000UL
#define BTL_MAIN_STAGE_MAX_SIZE (0x00004800UL - BTL_FIRST_STAGE_SIZE)
#endif
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_100) || defined(_SILICON_LABS_GECKO_INTERNAL_SDID_106)
// Dedicated bootloader area of 32k
// Place the bootloader in the dedicated bootloader area of the
// information block
#define BTL_FIRST_STAGE_BASE 0x0FE10000UL
#define BTL_APPLICATION_BASE 0x00000000UL
#define BTL_MAIN_STAGE_MAX_SIZE (0x00008000UL - BTL_FIRST_STAGE_SIZE)
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_103)
// Dedicated bootloader area of 18k
// Place the bootloader in the dedicated bootloader area of the
// information block
#define BTL_FIRST_STAGE_BASE 0x0FE10000UL
#define BTL_APPLICATION_BASE 0x00000000UL
#define BTL_MAIN_STAGE_MAX_SIZE (0x00004800UL - BTL_FIRST_STAGE_SIZE)
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_200)
// No bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE FLASH_BASE
#if defined(BOOTLOADER_APPLOADER)
#if defined(BOOTLOADER_SECURE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00014000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00012000UL)
#endif // BOOTLOADER_SECURE
#elif defined(BOOTLOADER_SECURE) && defined(BOOTLOADER_SUPPORT_COMMUNICATION)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00004000UL)
#endif // BOOTLOADER_APPLOADER
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- BTL_FIRST_STAGE_SIZE)
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_205)
// No bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE FLASH_BASE
#if defined(BOOTLOADER_APPLOADER)
#if defined(BOOTLOADER_SECURE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00014000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00012000UL)
#endif // BOOTLOADER_SECURE
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
#endif // BOOTLOADER_APPLOADER
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- BTL_FIRST_STAGE_SIZE)
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_210)
// No bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE FLASH_BASE
#if defined(BOOTLOADER_APPLOADER)
#if defined(BOOTLOADER_SECURE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00014000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00012000UL)
#endif // BOOTLOADER_SECURE
#elif defined(BOOTLOADER_CUSTOM_SIZE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00004000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
#endif // BOOTLOADER_APPLOADER
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- (BTL_FIRST_STAGE_BASE \
+ BTL_FIRST_STAGE_SIZE))
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_215)
// No bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE FLASH_BASE
#if defined(BOOTLOADER_APPLOADER)
#if defined(BOOTLOADER_SECURE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00014000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00012000UL)
#endif // BOOTLOADER_SECURE
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
#endif // BOOTLOADER_APPLOADER
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- (BTL_FIRST_STAGE_BASE \
+ BTL_FIRST_STAGE_SIZE))
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_220)
// No bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE FLASH_BASE
#if defined(BOOTLOADER_APPLOADER)
#if defined(BOOTLOADER_SECURE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00014000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00012000UL)
#endif // BOOTLOADER_SECURE
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
#endif // BOOTLOADER_APPLOADER
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- (BTL_FIRST_STAGE_BASE \
+ BTL_FIRST_STAGE_SIZE))
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_225)
// No bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE FLASH_BASE
#if defined(BOOTLOADER_APPLOADER)
#if defined(BOOTLOADER_SECURE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00014000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00012000UL)
#endif // BOOTLOADER_SECURE
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
#endif // BOOTLOADER_APPLOADER
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- (BTL_FIRST_STAGE_BASE \
+ BTL_FIRST_STAGE_SIZE))
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_230)
// No bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE FLASH_BASE
#if defined(BOOTLOADER_APPLOADER)
#if defined(BOOTLOADER_SECURE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00014000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00012000UL)
#endif // BOOTLOADER_SECURE
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
#endif // BOOTLOADER_APPLOADER
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- (BTL_FIRST_STAGE_BASE \
+ BTL_FIRST_STAGE_SIZE))
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_235)
// No bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE FLASH_BASE
#if defined(BOOTLOADER_APPLOADER)
#if defined(BOOTLOADER_SECURE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00014000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00012000UL)
#endif // BOOTLOADER_SECURE
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
#endif // BOOTLOADER_APPLOADER
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- (BTL_FIRST_STAGE_BASE \
+ BTL_FIRST_STAGE_SIZE))
#elif defined(_SILICON_LABS_GECKO_INTERNAL_SDID_240)
// No bootloader area: Place the bootloader in main flash
#define BTL_FIRST_STAGE_BASE FLASH_BASE
#if defined(BOOTLOADER_APPLOADER)
#if defined(BOOTLOADER_SECURE)
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00014000UL)
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00012000UL)
#endif // BOOTLOADER_SECURE
#else
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
#endif // BOOTLOADER_APPLOADER
#define BTL_MAIN_STAGE_MAX_SIZE (BTL_APPLICATION_BASE \
- (BTL_FIRST_STAGE_BASE \
+ BTL_FIRST_STAGE_SIZE))
#else
#error "This part is not supported in this bootloader version."
#endif
#if defined(MAIN_BOOTLOADER_TEST) || defined(MAIN_BOOTLOADER_IN_MAIN_FLASH)
#define BTL_MAIN_STAGE_BASE (FLASH_BASE)
#else
#define BTL_MAIN_STAGE_BASE (BTL_FIRST_STAGE_BASE \
+ BTL_FIRST_STAGE_SIZE)
#endif
#if defined(BOOTLOADER_HAS_FIRST_STAGE)
#define BTL_FIRST_BOOTLOADER_TABLE_BASE (BTL_FIRST_STAGE_BASE \
+ offsetof(BareBootTable_t, table))
#endif
#define BTL_MAIN_BOOTLOADER_TABLE_BASE (BTL_MAIN_STAGE_BASE \
+ offsetof(BareBootTable_t, table))
/// @endcond // DO_NOT_INCLUDE_WITH_DOXYGEN
#if defined(MAIN_BOOTLOADER_TEST)
#if defined(BOOTLOADER_HAS_FIRST_STAGE)
extern FirstBootloaderTable_t * firstBootloaderTable;
#endif
extern MainBootloaderTable_t *mainBootloaderTable;
#else
#if defined(BOOTLOADER_HAS_FIRST_STAGE)
/// Pointer to first stage bootloader table
#define firstBootloaderTable (*(FirstBootloaderTable_t **) \
(BTL_FIRST_BOOTLOADER_TABLE_BASE))
#endif // BOOTLOADER_HAS_FIRST_STAGE
/// Pointer to main bootloader table
#define mainBootloaderTable (*(MainBootloaderTable_t **) \
(BTL_MAIN_BOOTLOADER_TABLE_BASE))
#endif // MAIN_BOOTLOADER_TEST
// --------------------------------
// Functions
/***************************************************************************//**
* Get information about the bootloader on this device.
*
* The returned information is fetched from the main bootloader
* information table.
*
* @param[out] info Pointer to the bootloader information struct.
******************************************************************************/
void bootloader_getInfo(BootloaderInformation_t *info);
/***************************************************************************//**
* Initialize components of the bootloader
* so the app can use the interface. This typically includes initializing
* serial peripherals for communication with external SPI flashes, and so on.
*
* @return Error code. @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_INIT_BASE range.
******************************************************************************/
int32_t bootloader_init(void);
/***************************************************************************//**
* De-initialize components of the bootloader that were previously initialized.
* This typically includes powering down external SPI flashes and
* de-initializing the serial peripheral used for communication with the
* external flash.
*
* @return Error code. @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_INIT_BASE range.
******************************************************************************/
int32_t bootloader_deinit(void);
/***************************************************************************//**
* Reboot into the bootloader to perform an install.
*
* If there is a storage component and a slot is marked for bootload, install
* the image in that slot after verifying it.
*
* If a communication component is present, open the communication channel and
* receive an image to be installed.
******************************************************************************/
void bootloader_rebootAndInstall(void);
/***************************************************************************//**
* Verify the application image stored in the Flash memory starting at
* the address startAddress.
*
* If the secure boot is enforced, the function will only return true if the
* cryptographic signature of the application is valid. Otherwise, the
* application is verified according to the signature type defined in the
* ApplicationProperties_t structure embedded in the application. Silicon Labs
* wireless stacks include a declaration of this structure. However,
* applications not using a full wireless stack may need to instantiate
* the structure.
*
* Examples of results when the secure boot is not enforced:
* - App has no signature: Valid if initial stack pointer and program counter
* have reasonable values.
* - App has CRC checksum: Valid if checksum is valid.
* - App has ECDSA signature: Valid if ECDSA signature is valid.
*
* When secure boot is enforced, only ECDSA signed applications with
* a valid signature are considered valid.
*
*
* @param[in] startAddress Starting address of the application.
*
* @return True if the application is valid, else false.
******************************************************************************/
bool bootloader_verifyApplication(uint32_t startAddress);
/***************************************************************************//**
* Check whether signature verification on the application image in internal flash
* is enforced before every boot.
*
* @return True if signature verification is enforced, else false.
******************************************************************************/
bool bootloader_secureBootEnforced(void);
/***************************************************************************//**
* Get base address of the bootloader upgrade image.
*
* @param[out] location the base address of bootloader upgrade image.
*
* @return Returns true if the location was found.
******************************************************************************/
bool bootloader_getUpgradeLocation(uint32_t *location);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
/***************************************************************************//**
* Get the list of the peripheral that is used by the bootloader.
*
* @param[out] ppusatd0 Word containing all the peripherals used by the
* bootloader. Each bit represents a peripheral,
* which is ordered after the PPUSATD0 register bit
* fields.
*
* @param[out] ppusatd1 Word containing all the peripherals used by the
* bootloader. Each bit represents a peripheral,
* which is ordered after the PPUSATD1 register bit
* fields.
******************************************************************************/
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_6)
void bootloader_getPeripheralList(uint32_t *ppusatd0, uint32_t *ppusatd1, uint32_t *ppusatd2);
#else
void bootloader_getPeripheralList(uint32_t *ppusatd0, uint32_t *ppusatd1);
#endif
/***************************************************************************//**
* Save PPUSATDn state in RAM.
* Configure the peripheral attributes before calling into the bootloader.
*
* @note Enters ATOMIC section.
*
* @param[out] ctx Context struct to save register state into
*
* @return True if a valid certificate version is found.
******************************************************************************/
void bootloader_ppusatdnSaveReconfigureState(Bootloader_PPUSATDnCLKENnState_t *ctx);
/***************************************************************************//**
* Restore PPUSATDn state from RAM.
* Store the USART used by the bootloader if this is unknown.
*
* @note Exits ATOMIC section.
*
* @param[in] ctx Context struct to restore register state from
*
* @return True if a valid certificate version is found.
******************************************************************************/
void bootloader_ppusatdnRestoreState(Bootloader_PPUSATDnCLKENnState_t *ctx);
/***************************************************************************//**
* Called before the bootloader is initialized.
*
* This function implementation does not perform anything, but it is __weak
* so that it can be implemented by another application.
******************************************************************************/
void sli_bootloader_preHook(void);
/***************************************************************************//**
* Called after the bootloader is de-initialized.
*
* This function implementation does not perform anything, but it is __weak
* so that it can be implemented by another application.
******************************************************************************/
void sli_bootloader_postHook(void);
#endif
#if !defined(_SILICON_LABS_GECKO_INTERNAL_SDID_80)
/***************************************************************************//**
* Count the total remaining number of application upgrades.
*
* @return remaining number of application upgrades.
******************************************************************************/
uint32_t bootloader_remainingApplicationUpgrades(void);
#endif
#if defined(_SILICON_LABS_32B_SERIES_2)
/***************************************************************************//**
* Get bootloader certificate version.
*
* @param[out] version Bootloader certificate version
*
* @return True if a valid certificate version is found.
******************************************************************************/
bool bootloader_getCertificateVersion(uint32_t *version);
#endif // _SILICON_LABS_32B_SERIES_2
/***************************************************************************//**
* Get reset cause of the bootloader.
*
* @return Reset cause of the bootloader.
******************************************************************************/
BootloaderResetCause_t bootloader_getResetReason(void);
#if defined(BOOTLOADER_HAS_FIRST_STAGE)
/***************************************************************************//**
* Check if a pointer is valid and if it points to the bootloader first stage.
*
* This function checks pointers to bootloader
* jump tables.
*
*
* @param[in] ptr The pointer to check
*
* @return True if the pointer points to the bootloader first stage,
* false if not.
******************************************************************************/
__STATIC_INLINE bool bootloader_pointerToFirstStageValid(const void *ptr);
__STATIC_INLINE bool bootloader_pointerToFirstStageValid(const void *ptr)
{
#if defined(MAIN_BOOTLOADER_TEST)
// In main bootloader tests, no first stage is present
(void) ptr;
return false;
#elif BTL_FIRST_STAGE_BASE > 0U
if (((size_t)(ptr) >= BTL_FIRST_STAGE_BASE)
&& ((size_t)(ptr) < (BTL_FIRST_STAGE_BASE + BTL_FIRST_STAGE_SIZE))) {
return true;
} else {
return false;
}
#else
// First stage starts at address 0, don't need to check lower bound
if ((size_t)(ptr) < (BTL_FIRST_STAGE_BASE + BTL_FIRST_STAGE_SIZE)) {
return true;
} else {
return false;
}
#endif
}
#endif // BOOTLOADER_HAS_FIRST_STAGE
/***************************************************************************//**
* Check if a pointer is valid and if it points to the bootloader main stage.
*
* This function checks pointers to bootloader
* jump tables.
*
*
* @param[in] ptr The pointer to check
*
* @return True if the pointer points into the bootloader main stage,
* false if not.
******************************************************************************/
__STATIC_INLINE bool bootloader_pointerValid(const void *ptr);
__STATIC_INLINE bool bootloader_pointerValid(const void *ptr)
{
#if defined(MAIN_BOOTLOADER_TEST)
// In main bootloader tests, all of memory is considered part of the bootloader
(void) ptr;
return true;
#elif BTL_MAIN_STAGE_BASE > 0U
if (((size_t)ptr >= BTL_MAIN_STAGE_BASE)
&& ((size_t)ptr < (BTL_MAIN_STAGE_BASE + BTL_MAIN_STAGE_MAX_SIZE))) {
return true;
} else {
return false;
}
#else
if ((size_t)ptr < (BTL_MAIN_STAGE_BASE + BTL_MAIN_STAGE_MAX_SIZE)) {
return true;
} else {
return false;
}
#endif
}
/** @} (end addtogroup CommonInterface) */
/** @} (end addtogroup Interface) */
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#endif // BTL_INTERFACE_H

View File

@@ -0,0 +1,138 @@
/***************************************************************************//**
* @file
* @brief Application interface to the bootloader parser.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#ifndef BTL_INTERFACE_PARSER_H
#define BTL_INTERFACE_PARSER_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
/***************************************************************************//**
* @addtogroup Interface
* @{
* @addtogroup ParserInterface Application Parser Interface
* @brief Application interface for the bootloader image
* parser.
* @details The Parser Interface can be used to parse upgrade images from the
* context of the application.
* @{
******************************************************************************/
// -----------------------------------------------------------------------------
// Typedefs
/***************************************************************************//**
* Bootloader parser callback
*
* @param address Address of the data
* @param data Raw data
* @param length Size in bytes of raw data.
* @param context A context variable defined by the implementation that
* is implementing this callback.
******************************************************************************/
typedef void (*BootloaderParserCallback_t)(uint32_t address,
uint8_t *data,
size_t length,
void *context);
/// Context for the bootloader image parser routine.
typedef struct BootloaderParserContext BootloaderParserContext_t;
/// Function pointers to parser callbacks
typedef struct {
/// Opaque pointer passed to the callback functions
void *context;
/// Callback function pointer for application image data
BootloaderParserCallback_t applicationCallback;
/// Callback function pointer for image metadata
BootloaderParserCallback_t metadataCallback;
/// Callback function pointer for bootloader upgrade image data
BootloaderParserCallback_t bootloaderCallback;
} BootloaderParserCallbacks_t;
/***************************************************************************//**
* Initialize the image parser.
*
* @param[in] context Pointer to the parser context struct.
* @param[in] contextSize Size of the context struct.
*
* @return BOOTLOADER_OK if success, BOOTLOADER_ERROR_PARSE_CONTEXT if context
* struct is too small.
******************************************************************************/
int32_t bootloader_initParser(BootloaderParserContext_t *context,
size_t contextSize);
#if !defined(SL_TRUSTZONE_NONSECURE)
/***************************************************************************//**
* Parse a buffer.
* @param[in] context Pointer to the parser context struct.
* @param[in] callbacks Callbacks to be called by the parser.
* @param[in] data Data to be parsed.
* @param[in] numBytes Size of the data buffer.
*
* @return BOOTLOADER_ERROR_PARSE_CONTINUE if the chunk was parsed correctly,
* and a new chunk is expected. BOOTLOADER_ERROR_PARSE_ERROR if
* something went wrong while parsing. BOOTLOADER_ERROR_PARSE_SUCCESS
* if the entire file was successfully parsed.
******************************************************************************/
int32_t bootloader_parseBuffer(BootloaderParserContext_t *context,
BootloaderParserCallbacks_t *callbacks,
uint8_t data[],
size_t numBytes);
#endif // SL_TRUSTZONE_NONSECURE
/***************************************************************************//**
* Parse a buffer and get application and bootloader upgrade metadata
* from the buffer.
*
* @note \p appInfo and \p bootloaderVersion will default to zeros.
*
* @param[in] context Pointer to the parser context struct.
* @param[in] data Data to be parsed.
* @param[in] numBytes Size of the data buffer.
* @param[out] appInfo Pointer to @ref ApplicationData_t struct.
* @param[out] bootloaderVersion Pointer to an integer representing bootloader
* version.
*
* @return @ref BOOTLOADER_OK if metadata was filled successfully.
******************************************************************************/
#if !defined(SL_TRUSTZONE_NONSECURE)
int32_t bootloader_parseImageInfo(BootloaderParserContext_t *context,
uint8_t data[],
size_t numBytes,
ApplicationData_t *appInfo,
uint32_t *bootloaderVersion);
#else
int32_t bootloader_parseImageInfo(uint8_t data[],
size_t numBytes,
ApplicationData_t *appInfo,
uint32_t *bootloaderVersion);
#endif // SL_TRUSTZONE_NONSECURE
/***************************************************************************//**
* Find the size of the context struct BootloaderParserContext used by the bootloader
* image parser to store parser state.
*
* @return size of BootloaderParserContext, returns 0 if something went wrong.
******************************************************************************/
uint32_t bootloader_parserContextSize(void);
/** @} (end addtogroup ParserInterface) */
/** @} (end addtogroup Interface) */
#endif // BTL_INTERFACE_PARSER_H

View File

@@ -0,0 +1,769 @@
/***************************************************************************//**
* @file
* @brief Application interface to the storage component of the bootloader.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#include "btl_interface.h"
#include "btl_internal_flash.h"
#include <string.h>
// -----------------------------------------------------------------------------
// Defines
// Make assert no-op if not configured
#ifndef BTL_ASSERT
#define BTL_ASSERT(x)
#endif
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
// -----------------------------------------------------------------------------
// Static variables
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
static Bootloader_PPUSATDnCLKENnState_t blPPUSATDnCLKENnState = { 0 };
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
// -----------------------------------------------------------------------------
// Functions
static bool verifyAddressRange(uint32_t address,
uint32_t length)
{
// Flash starts at FLASH_BASE, and is FLASH_SIZE large
if ((length > FLASH_SIZE)
#if (FLASH_BASE > 0x0UL)
|| (address < FLASH_BASE)
#endif
|| (address > FLASH_BASE + FLASH_SIZE)) {
return false;
}
if ((address + length) <= FLASH_BASE + FLASH_SIZE) {
return true;
} else {
return false;
}
}
static bool verifyErased(uint32_t address,
uint32_t length)
{
for (uint32_t i = 0; i < length; i += 4) {
if (*(uint32_t *)(address + i) != 0xFFFFFFFF) {
return false;
}
}
return true;
}
void bootloader_getStorageInfo(BootloaderStorageInformation_t *info)
{
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
mainBootloaderTable->storage->getInfo(info);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
}
int32_t bootloader_getStorageSlotInfo(uint32_t slotId,
BootloaderStorageSlot_t *slot)
{
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
return mainBootloaderTable->storage->getSlotInfo(slotId, slot);
}
int32_t bootloader_readStorage(uint32_t slotId,
uint32_t offset,
uint8_t *buffer,
size_t length)
{
int32_t retVal;
BootloaderStorageInformation_t storageInfo;
BootloaderStorageSlot_t storageSlot;
//Check for the storageType of the device
bootloader_getStorageInfo(&storageInfo);
if (storageInfo.storageType == INTERNAL_FLASH) {
// Ensure slot is valid
if (slotId >= storageInfo.numStorageSlots) {
return BOOTLOADER_ERROR_STORAGE_INVALID_SLOT;
}
retVal = bootloader_getStorageSlotInfo(slotId, &storageSlot);
if (retVal != BOOTLOADER_OK) {
return retVal;
}
// Ensure address is within slot
if ((offset + length > storageSlot.length) \
|| (offset > storageSlot.length) \
|| (length > storageSlot.length)) {
return BOOTLOADER_ERROR_STORAGE_INVALID_ADDRESS;
}
// Address range is valid; read data
retVal = bootloader_readRawStorage(storageSlot.address + offset,
buffer,
length);
}
//END OF INTERNAL_FLASH
else {
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
retVal = mainBootloaderTable->storage->read(slotId, offset, buffer, length);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif
}
return retVal;
}
int32_t bootloader_writeStorage(uint32_t slotId,
uint32_t offset,
uint8_t *buffer,
size_t length)
{
int32_t retVal;
BootloaderStorageInformation_t storageInfo;
BootloaderStorageSlot_t storageSlot;
//Check for the storageType of the device
bootloader_getStorageInfo(&storageInfo);
if (storageInfo.storageType == INTERNAL_FLASH) {
// Ensure slot is valid
if (slotId >= storageInfo.numStorageSlots) {
return BOOTLOADER_ERROR_STORAGE_INVALID_SLOT;
}
retVal = bootloader_getStorageSlotInfo(slotId, &storageSlot);
if (retVal != BOOTLOADER_OK) {
return retVal;
}
// Ensure address is within slot
if ((offset + length > storageSlot.length) \
|| (offset > storageSlot.length) \
|| (length > storageSlot.length)) {
return BOOTLOADER_ERROR_STORAGE_INVALID_ADDRESS;
}
retVal = bootloader_writeRawStorage(storageSlot.address + offset,
buffer,
length);
} else {
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
retVal = mainBootloaderTable->storage->write(slotId, offset, buffer, length);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
}
return retVal;
}
int32_t bootloader_eraseWriteStorage(uint32_t slotId,
uint32_t offset,
uint8_t *buffer,
size_t length)
{
int32_t retVal;
uint16_t flashPageSize;
uint32_t storageStartAddr;
uint32_t eraseOffset;
uint32_t eraseLength;
BootloaderStorageSlot_t storageSlot;
BootloaderStorageInformation_t storageInfo;
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
bootloader_getStorageInfo(&storageInfo);
flashPageSize = storageInfo.info->pageSize;
if (flashPageSize == 0) {
return BOOTLOADER_ERROR_STORAGE_INVALID_SLOT;
}
retVal = bootloader_getStorageSlotInfo(slotId, &storageSlot);
if (retVal != BOOTLOADER_OK) {
return retVal;
}
storageStartAddr = storageSlot.address;
if (offset + length > storageSlot.length) {
return BOOTLOADER_ERROR_STORAGE_INVALID_ADDRESS;
}
if (offset % flashPageSize) {
// Erase from next page:
eraseOffset = (offset & ~(flashPageSize - 1)) + flashPageSize;
if ((offset + length) % flashPageSize) {
// Example case for this if/else section:
// 0 1 2 3
// |----|----|----|
// ^ ^
// O L
eraseLength = ((offset + length) & ~(flashPageSize - 1)) + flashPageSize - eraseOffset;
} else {
// Example case for this if/else section:
// 0 1 2 3
// |----|----|----|
// ^ ^
// O L
eraseLength = length - (flashPageSize - (offset % flashPageSize));
}
eraseOffset = storageStartAddr + eraseOffset;
} else {
eraseOffset = storageStartAddr + offset;
if (length % flashPageSize) {
// Example case for this if/else section:
// 0 1 2 3
// |----|----|----|
// ^ ^
// O L
eraseLength = (length & ~(flashPageSize - 1)) + flashPageSize;
} else {
// Example case for this if/else section:
// 0 1 2 3
// |----|----|----|
// ^ ^
// O L
eraseLength = length;
}
}
if (eraseLength != 0) {
retVal = bootloader_eraseRawStorage(eraseOffset, eraseLength);
if (retVal != BOOTLOADER_OK) {
return retVal;
}
}
retVal = bootloader_writeRawStorage(storageStartAddr + offset, buffer, length);
if (retVal != BOOTLOADER_OK) {
return retVal;
}
return BOOTLOADER_OK;
}
int32_t bootloader_eraseStorageSlot(uint32_t slotId)
{
int32_t retVal;
BootloaderStorageInformation_t storageInfo;
BootloaderStorageSlot_t storageSlot;
//Check for the storageType of the device
bootloader_getStorageInfo(&storageInfo);
if (storageInfo.storageType == INTERNAL_FLASH) {
// Ensure slot is valid
if (slotId >= storageInfo.numStorageSlots) {
return BOOTLOADER_ERROR_STORAGE_INVALID_SLOT;
}
retVal = bootloader_getStorageSlotInfo(slotId, &storageSlot);
if (retVal != BOOTLOADER_OK) {
return retVal;
}
retVal = bootloader_eraseRawStorage(storageSlot.address, storageSlot.length);
} else {
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
retVal = mainBootloaderTable->storage->erase(slotId);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
}
return retVal;
}
int32_t bootloader_initChunkedEraseStorageSlot(uint32_t slotId,
BootloaderEraseStatus_t *eraseStat)
{
int32_t retVal;
BootloaderStorageInformation_t storageInfo;
bootloader_getStorageInfo(&storageInfo);
retVal = bootloader_getStorageSlotInfo(slotId, &eraseStat->storageSlotInfo);
if (retVal != BOOTLOADER_OK) {
return retVal;
}
eraseStat->currentPageAddr = eraseStat->storageSlotInfo.address;
eraseStat->pageSize = storageInfo.info->pageSize;
return BOOTLOADER_OK;
}
int32_t bootloader_chunkedEraseStorageSlot(BootloaderEraseStatus_t *eraseStat)
{
int32_t retVal;
if (eraseStat->currentPageAddr
== (eraseStat->storageSlotInfo.address + eraseStat->storageSlotInfo.length)) {
return BOOTLOADER_OK;
}
retVal = bootloader_eraseRawStorage(eraseStat->currentPageAddr, eraseStat->pageSize);
if (retVal != BOOTLOADER_OK) {
return retVal;
}
eraseStat->currentPageAddr += eraseStat->pageSize;
if (eraseStat->currentPageAddr
== (eraseStat->storageSlotInfo.address + eraseStat->storageSlotInfo.length)) {
return BOOTLOADER_OK;
}
return BOOTLOADER_ERROR_STORAGE_CONTINUE;
}
int32_t bootloader_setImageToBootload(int32_t slotId)
{
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
int32_t retVal = mainBootloaderTable->storage->setImagesToBootload(&slotId, 1);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
int32_t bootloader_setImagesToBootload(int32_t *slotIds, size_t length)
{
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
int32_t retVal = mainBootloaderTable->storage->setImagesToBootload(slotIds, length);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
int32_t bootloader_getImagesToBootload(int32_t *slotIds, size_t length)
{
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
int32_t retVal = mainBootloaderTable->storage->getImagesToBootload(slotIds, length);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
int32_t bootloader_appendImageToBootloadList(int32_t slotId)
{
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_TABLE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
int32_t retVal = mainBootloaderTable->storage->appendImageToBootloadList(slotId);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
int32_t bootloader_initVerifyImage(uint32_t slotId,
void *context,
size_t contextSize)
{
int32_t retVal;
if (!bootloader_pointerValid(mainBootloaderTable)) {
return BOOTLOADER_ERROR_PARSE_STORAGE;
}
// Check that the bootloader has image verification capability
if (mainBootloaderTable->storage == NULL) {
return BOOTLOADER_ERROR_PARSE_STORAGE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
retVal = mainBootloaderTable->storage->initParseImage(
slotId,
(BootloaderParserContext_t*)context,
contextSize);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
int32_t bootloader_continueVerifyImage(void *context,
BootloaderParserCallback_t metadataCallback)
{
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_PARSE_STORAGE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
int32_t retVal = mainBootloaderTable->storage->verifyImage(
(BootloaderParserContext_t *)context,
metadataCallback);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retVal;
}
int32_t bootloader_verifyImage(uint32_t slotId,
BootloaderParserCallback_t metadataCallback)
{
int32_t retval;
uint8_t context[BOOTLOADER_STORAGE_VERIFICATION_CONTEXT_SIZE];
if (!bootloader_pointerValid(mainBootloaderTable)) {
return BOOTLOADER_ERROR_PARSE_STORAGE;
}
retval = bootloader_initVerifyImage(slotId,
context,
BOOTLOADER_STORAGE_VERIFICATION_CONTEXT_SIZE);
if (retval != BOOTLOADER_OK) {
return retval;
}
do {
retval = bootloader_continueVerifyImage(context, metadataCallback);
} while (retval == BOOTLOADER_ERROR_PARSE_CONTINUE);
if (retval == BOOTLOADER_ERROR_PARSE_SUCCESS) {
return BOOTLOADER_OK;
} else {
return retval;
}
}
int32_t bootloader_getImageInfo(uint32_t slotId,
ApplicationData_t *appInfo,
uint32_t *bootloaderVersion)
{
int32_t retval;
uint8_t context[BOOTLOADER_STORAGE_VERIFICATION_CONTEXT_SIZE];
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_PARSE_STORAGE;
}
// Check that the bootloader has image verification capability
BTL_ASSERT(mainBootloaderTable->storage != NULL);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
retval = mainBootloaderTable->storage->initParseImage(
slotId,
(BootloaderParserContext_t *)context,
BOOTLOADER_STORAGE_VERIFICATION_CONTEXT_SIZE);
if (retval != BOOTLOADER_OK) {
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retval;
}
retval = mainBootloaderTable->storage->getImageInfo(
(BootloaderParserContext_t *)context,
appInfo,
bootloaderVersion);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return retval;
}
bool bootloader_storageIsBusy(void)
{
bool isBusy = false;
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return true;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
isBusy = mainBootloaderTable->storage->isBusy();
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
return isBusy;
}
int32_t bootloader_readRawStorage(uint32_t address,
uint8_t *buffer,
size_t length)
{
int32_t retVal;
BootloaderStorageInformation_t storageInfo;
//Check for the storageType of the device
bootloader_getStorageInfo(&storageInfo);
if (storageInfo.storageType == INTERNAL_FLASH) {
// Ensure address is is within flash
if (!verifyAddressRange(address, length)) {
return BOOTLOADER_ERROR_STORAGE_INVALID_ADDRESS;
}
memcpy(buffer, (void *)address, length);
retVal = BOOTLOADER_OK;
} else {
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_STORAGE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
retVal = mainBootloaderTable->storage->readRaw(address, buffer, length);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
}
return retVal;
}
int32_t bootloader_writeRawStorage(uint32_t address,
uint8_t *buffer,
size_t length)
{
int32_t retVal;
BootloaderStorageInformation_t storageInfo;
//Check for the storageType of the device
bootloader_getStorageInfo(&storageInfo);
if (storageInfo.storageType == INTERNAL_FLASH) {
// Ensure address is is within chip
if (!verifyAddressRange(address, length)) {
return BOOTLOADER_ERROR_STORAGE_INVALID_ADDRESS;
}
// Ensure space is empty
if (!verifyErased(address, length)) {
return BOOTLOADER_ERROR_STORAGE_NEEDS_ERASE;
}
if (flash_writeBuffer(address, buffer, length)) {
retVal = BOOTLOADER_OK;
} else {
retVal = BOOTLOADER_ERROR_STORAGE_INVALID_ADDRESS;
}
//END OF INTERNAL FLASH
} else {
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_STORAGE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
retVal = mainBootloaderTable->storage->writeRaw(address, buffer, length);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
}
return retVal;
}
int32_t bootloader_getAllocatedDMAChannel(void)
{
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_STORAGE;
}
BootloaderInformation_t info = { .type = SL_BOOTLOADER, .version = 0U, .capabilities = 0U };
bootloader_getInfo(&info);
if ((info.capabilities & BOOTLOADER_CAPABILITY_STORAGE) == 0u) {
return BOOTLOADER_ERROR_INIT_STORAGE;
}
uint32_t blMajorVersion = ((info.version & BOOTLOADER_VERSION_MAJOR_MASK)
>> BOOTLOADER_VERSION_MAJOR_SHIFT);
uint32_t blMinorVersion = ((info.version & BOOTLOADER_VERSION_MINOR_MASK)
>> BOOTLOADER_VERSION_MINOR_SHIFT);
if ((blMajorVersion < 1UL) || (blMajorVersion == 1UL && blMinorVersion < 11UL)) {
return BOOTLOADER_ERROR_INIT_STORAGE;
}
return mainBootloaderTable->storage->getDMAchannel();
}
int32_t bootloader_eraseRawStorage(uint32_t address,
size_t length)
{
int32_t retVal;
BootloaderStorageInformation_t storageInfo;
//Check for the storageType of the device
bootloader_getStorageInfo(&storageInfo);
if (storageInfo.storageType == INTERNAL_FLASH) {
// Ensure erase covers an integer number of pages
if (length % FLASH_PAGE_SIZE) {
return BOOTLOADER_ERROR_STORAGE_NEEDS_ALIGN;
}
// Ensure erase is page aligned
if (address % FLASH_PAGE_SIZE) {
return BOOTLOADER_ERROR_STORAGE_NEEDS_ALIGN;
}
// Ensure address is is within flash
if (!verifyAddressRange(address, length)) {
return BOOTLOADER_ERROR_STORAGE_INVALID_ADDRESS;
}
bool ret = false;
do {
ret = flash_erasePage(address);
address += FLASH_PAGE_SIZE;
length -= FLASH_PAGE_SIZE;
} while (length > 0 && ret);
if (ret) {
retVal = BOOTLOADER_OK;
} else {
retVal = BOOTLOADER_ERROR_STORAGE_INVALID_ADDRESS;
}
} else {
if (!bootloader_pointerValid(mainBootloaderTable)
|| !bootloader_pointerValid(mainBootloaderTable->storage)) {
return BOOTLOADER_ERROR_INIT_STORAGE;
}
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnSaveReconfigureState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
retVal = mainBootloaderTable->storage->eraseRaw(address, length);
#if defined(BOOTLOADER_INTERFACE_TRUSTZONE_AWARE)
bootloader_ppusatdnRestoreState(&blPPUSATDnCLKENnState);
#endif // BOOTLOADER_INTERFACE_TRUSTZONE_AWARE
}
return retVal;
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif

View File

@@ -0,0 +1,653 @@
/***************************************************************************//**
* @file
* @brief Application interface to the storage component of the bootloader.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#ifndef BTL_INTERFACE_STORAGE_H
#define BTL_INTERFACE_STORAGE_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
// Get part series version.
#include "em_device.h"
/***************************************************************************//**
* @addtogroup Interface
* @{
* @addtogroup StorageInterface Application Storage Interface
* @brief Application interface for interfacing with the bootloader storage.
* @note These Bootloader APIs are not reentrant and should be wrapped in critical section
* where needed.
* @details The Storage Interface is only available on bootloaders that declare
* they support @ref BOOTLOADER_CAPABILITY_STORAGE.
*
* @li @ref bootloader_interface_example
*
* @n @section bootloader_interface_example Example
*
* @brief Snippet for the OTA use case:
* @verbatim
* OTA Example
* Assuming the user has an upgrade image downloaded which will be used to upgrade the application
*
* Initialize the bootloader interface
* bootloader_init();
*
* Erase the storage slot in internal/SPI flash memory
* bootloader_eraseStorageSlot(0);
*
* Write the upgrade image (GBL file data) to the slot. blinkGbl  uint8 array holding the GBL data in memory
* bootloader_writeStorage(0, 0, blinkGbl, sizeof(blinkGbl));
*
* Reboot into the bootloader to install the new image
* bootloader_rebootAndInstall();
*
* The general flow for bootloader interface APIs from the application is:
*
* General flow
*
* Initialize the bootloader interface
* bootloader_init();
*
* Interface API accesses
* ……………
* ……………
* ……………
*
* De-initialize the bootloader interface
* bootloader_deinit();
* @endverbatim
* @{
******************************************************************************/
// -----------------------------------------------------------------------------
// Typedefs
/// Possible storage types
typedef enum {
/// Storage backend is a SPI flash
SPIFLASH,
/// Storage backend is internal flash
INTERNAL_FLASH,
/// Storage backend is custom
CUSTOM_STORAGE
} BootloaderStorageType_t;
/// Information about a storage slot
typedef struct {
/// Address of the slot.
uint32_t address;
/// Size of the slot.
uint32_t length;
} BootloaderStorageSlot_t;
/// Information about the bootloader storage implementation
/// <b>Note:</b> From Gecko Bootloader version >= 2.1,
/// the pointer <b>partType</b> will only contain a zero value.
/// The <b>partType</b> variable can be used to find information
/// about the attached storage.
typedef struct {
/// The version of this data structure
uint16_t version;
/// A bitmask describing the capabilities of this particular storage
uint16_t capabilitiesMask;
/// Maximum time it takes to erase a page. (in milliseconds)
uint32_t pageEraseMs;
/// Maximum time it takes to erase the entire part. (in milliseconds)
uint32_t partEraseMs;
/// The size of a single erasable page in bytes
uint32_t pageSize;
/// The total size of the storage in bytes
uint32_t partSize;
/// Pointer to a string describing the attached storage
char *partDescription;
/// The number of bytes in a word for the storage
uint8_t wordSizeBytes;
/// Value representing the attached storage
uint32_t partType;
} BootloaderStorageImplementationInformation_t;
/// Information about the bootloader storage \n
/// <b>Note:</b> The <b>flashInfo</b> variable is only usable with
/// Gecko Bootloader version >= 2.0. All previous versions of the
/// Gecko Bootloader do not support the <b>flashInfo</b> data field.
typedef struct {
/// The version of this data structure
uint32_t version;
/// The capabilities of the storage component
uint32_t capabilities;
/// Type of storage
BootloaderStorageType_t storageType;
/// Number of storage slots
uint32_t numStorageSlots;
/// A pointer to detailed information about the attached storage
BootloaderStorageImplementationInformation_t *info;
/// Detailed information about the attached storage(<b>available for use only with Gecko Bootloader version >= 2.0</b>)
BootloaderStorageImplementationInformation_t flashInfo;
} BootloaderStorageInformation_t;
/// Erase status struct
typedef struct {
/// Address of the current page to be erased
uint32_t currentPageAddr;
/// The size of a single erasable page in bytes
uint32_t pageSize;
/// Information about a storage slot
BootloaderStorageSlot_t storageSlotInfo;
} BootloaderEraseStatus_t;
/// Storage API accessible from the application
typedef struct BootloaderStorageFunctions {
/// Version of this struct
uint32_t version;
/// Get information about the storage -- capabilities, layout, configuration
void (*getInfo)(BootloaderStorageInformation_t *info);
/// Get information about storage slot -- size, location
int32_t (*getSlotInfo)(uint32_t slotId, BootloaderStorageSlot_t *slot);
/// Read bytes from slot into buffer
int32_t (*read)(uint32_t slotId,
uint32_t offset,
uint8_t *buffer,
size_t length);
/// Write bytes from buffer into slot
int32_t (*write)(uint32_t slotId,
uint32_t offset,
uint8_t *buffer,
size_t length);
/// Erase an entire slot
int32_t (*erase)(uint32_t slotId);
// ------------------------------
/// Mark a list of slots for bootload
int32_t (*setImagesToBootload)(int32_t *slotIds, size_t length);
/// Mark a list of slots for bootload
int32_t (*getImagesToBootload)(int32_t *slotIds, size_t length);
/// Append a slot to bootload list
int32_t (*appendImageToBootloadList)(int32_t slotId);
// ------------------------------
/// Start image parsing
int32_t (*initParseImage)(uint32_t slotId,
BootloaderParserContext_t *context,
size_t contextSize);
/// Continue image verification
int32_t (*verifyImage)(BootloaderParserContext_t *context,
BootloaderParserCallback_t metadataCallback);
/// Get app and bootloader upgrade information from storage slot
int32_t (*getImageInfo)(BootloaderParserContext_t *context,
ApplicationData_t *appInfo,
uint32_t *bootloaderVersion);
/// Check whether the bootloader storage is busy
bool (*isBusy)(void);
/// Read raw bytes from storage
int32_t (*readRaw)(uint32_t address, uint8_t *buffer, size_t length);
/// Write bytes to raw storage
int32_t (*writeRaw)(uint32_t address, uint8_t *buffer, size_t length);
/// Erase storage
int32_t (*eraseRaw)(uint32_t address, size_t length);
/// Get configured DMA channel
int32_t (*getDMAchannel)(void);
} BootloaderStorageFunctions_t;
// -----------------------------------------------------------------------------
// Defines
/// Context size for bootloader verification context
#if defined(_SILICON_LABS_32B_SERIES_2)
#if defined(SEMAILBOX_PRESENT)
/// Context size(701) includes counter(16) plus stream_block(16 (block size) * 8 (Maximum blocks))
#define BOOTLOADER_STORAGE_VERIFICATION_CONTEXT_SIZE (705)
#else
#define BOOTLOADER_STORAGE_VERIFICATION_CONTEXT_SIZE (593)
#endif
#else
#define BOOTLOADER_STORAGE_VERIFICATION_CONTEXT_SIZE (384)
#endif
/// Current version of the BootloaderStorageInformation_t struct
#define BOOTLOADER_STORAGE_INFO_VERSION (0x30000U)
/// Current version of the BootloaderStorageImplementationInformation_t struct
#define BOOTLOADER_STORAGE_IMPL_INFO_VERSION (0x0210U)
/// Major version of the BootloaderStorageImplementationInformation_t struct
#define BOOTLOADER_STORAGE_IMPL_INFO_VERSION_MAJOR (0x0200U)
/// Major version mask for @ref BOOTLOADER_STORAGE_IMPL_INFO_VERSION
#define BOOTLOADER_STORAGE_IMPL_INFO_VERSION_MAJOR_MASK (0xFF00U)
/// Spiflash capability indicating that it supports erase
#define BOOTLOADER_STORAGE_IMPL_CAPABILITY_ERASE_SUPPORTED (1 << 0)
/// @brief Spiflash capability indicating it requires full page erases before
/// new data can be written
#define BOOTLOADER_STORAGE_IMPL_CAPABILITY_PAGE_ERASE_REQUIRED (1 << 1)
/// Spiflash capability indicating that the write function is blocking
#define BOOTLOADER_STORAGE_IMPL_CAPABILITY_BLOCKING_WRITE (1 << 2)
/// Spiflash capability indicating that the erase function is blocking
#define BOOTLOADER_STORAGE_IMPL_CAPABILITY_BLOCKING_ERASE (1 << 3)
/// ISSI IS25LQ040B SPI Flash
#define BOOTLOADER_STORAGE_ISSI_IS25LQ040B (1U << 0)
/// ISSI IS25LQ020B SPI Flash
#define BOOTLOADER_STORAGE_ISSI_IS25LQ020B (1U << 1)
/// ISSI IS25LQ010B SPI Flash
#define BOOTLOADER_STORAGE_ISSI_IS25LQ010B (1U << 2)
/// ISSI IS25LQ512B SPI Flash
#define BOOTLOADER_STORAGE_ISSI_IS25LQ512B (1U << 3)
/// ISSI IS25LQ025B SPI Flash
#define BOOTLOADER_STORAGE_ISSI_IS25LQ025B (1U << 4)
/// Numonyx M25P16 SPI Flash
#define BOOTLOADER_STORAGE_NUMONYX_M25P16 (1U << 5)
/// Numonyx M25P80 SPI Flash
#define BOOTLOADER_STORAGE_NUMONYX_M25P80 (1U << 6)
/// Numonyx M25P40 SPI Flash
#define BOOTLOADER_STORAGE_NUMONYX_M25P40 (1U << 7)
/// Numonyx M25P20 SPI Flash
#define BOOTLOADER_STORAGE_NUMONYX_M25P20 (1U << 8)
/// Adesto AT25SF041 SPI Flash
#define BOOTLOADER_STORAGE_ADESTO_AT25SF041 (1U << 9)
/// Atmel AT25DF081A SPI Flash
#define BOOTLOADER_STORAGE_ATMEL_AT25DF081A (1U << 10)
/// Atmel AT25DF041A SPI Flash
#define BOOTLOADER_STORAGE_ATMEL_AT25DF041A (1U << 11)
/// Macronix MX25R6435F SPI Flash
#define BOOTLOADER_STORAGE_MACRONIX_MX25R6435F (1U << 12)
/// Macronix MX25R6435F SPI Flash
#define BOOTLOADER_STORAGE_MACRONIX_MX25R3235F (1U << 13)
/// Macronix MX25U1635E SPI Flash
#define BOOTLOADER_STORAGE_MACRONIX_MX25U1635E (1U << 14)
/// Macronix MX25L1606E SPI Flash
#define BOOTLOADER_STORAGE_MACRONIX_MX25L1606E (1U << 15)
/// Macronix MX25R8035F SPI Flash
#define BOOTLOADER_STORAGE_MACRONIX_MX25R8035F (1U << 16)
/// Macronix MX25L8006E SPI Flash
#define BOOTLOADER_STORAGE_MACRONIX_MX25L8006E (1U << 17)
/// Macronix MX25L4006E SPI Flash
#define BOOTLOADER_STORAGE_MACRONIX_MX25L4006E (1U << 18)
/// Macronix MX25L2006E SPI Flash
#define BOOTLOADER_STORAGE_MACRONIX_MX25L2006E (1U << 19)
/// Winbond W25Q80BV SPI Flash
#define BOOTLOADER_STORAGE_WINBOND_W25Q80BV (1U << 20)
/// Winbond W25X20BV SPI Flash
#define BOOTLOADER_STORAGE_WINBOND_W25X20BV (1U << 21)
/// Spansion S25L208K SPI Flash
#define BOOTLOADER_STORAGE_SPANSION_S25FL208K (1U << 22)
/// Internal storage
#define BOOTLOADER_STORAGE_INTERNAL_STORAGE (1U << 30)
/// JEDEC Supported SPI Flash
#define BOOTLOADER_STORAGE_JEDEC (1U << 31)
// -----------------------------------------------------------------------------
// Functions
/***************************************************************************//**
* Get information about the storage component.
*
* @param[out] info Information about the storage component.
******************************************************************************/
void bootloader_getStorageInfo(BootloaderStorageInformation_t *info);
/***************************************************************************//**
* Get information about a storage slot.
*
* @param[in] slotId ID of the slot to get information about
* @param[out] slot Information about the storage slot
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_getStorageSlotInfo(uint32_t slotId,
BootloaderStorageSlot_t *slot);
/***************************************************************************//**
* Read data from a storage slot.
*
* @param[in] slotId ID of the slot
* @param[in] offset Offset into the slot to start reading from
* @param[out] buffer Buffer to store the data
* @param[in] length Amount of data to read
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_readStorage(uint32_t slotId,
uint32_t offset,
uint8_t *buffer,
size_t length);
/***************************************************************************//**
* Write data to a storage slot.
*
* @note
* If DMA-based MSC write is enabled on the bootloader, writing data from
* flash to flash is not supported on Series-1 devices. DMA-based MSC write is
* enabled, both offset and buffer should be word aligned. In case the buffer
* is not aligned, the normal write procedure is used instead of DMA.
*
* @param[in] slotId ID of the slot
* @param[in] offset Offset into the slot to start writing to
* @param[in] buffer Buffer to read data to write from
* @param[in] length Amount of data to write. Must be a multiple of 4.
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_writeStorage(uint32_t slotId,
uint32_t offset,
uint8_t *buffer,
size_t length);
/***************************************************************************//**
* Erase and write data to a storage slot.
*
* @note This function automatically erases the following Flash page whenever
* the written data crosses a page boundary. In other words, the function
* can't be used to perform multiple sequential writes to the same
* address range unless the range starts at a page boundary.
* For a sequential write, the first call to this function should have
* a start address at a page boundary. Otherwise, the corresponding page
* of the starting address needs to be erased explicitly. If DMA-based
* MSC write is enabled on the bootloader, writing data from flash to
* flash is not supported on Series-1 devices.
*
* @param[in] slotId ID of the slot
* @param[in] offset Offset into the slot to start writing to
* @param[in] buffer Buffer to read data to write from
* @param[in] length Amount of data to write. Must be a multiple of 4.
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_eraseWriteStorage(uint32_t slotId,
uint32_t offset,
uint8_t *buffer,
size_t length);
/***************************************************************************//**
* Erase all contents of a storage slot.
*
* @param[in] slotId ID of the slot
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_eraseStorageSlot(uint32_t slotId);
/***************************************************************************//**
* Initialize chunked erase of a storage slot.
*
* @note This function must be called before calling
* @ref bootloader_chunkedEraseStorageSlot in a loop.
*
* @param[in] slotId ID of the slot
* @param[in] eraseStat Erase status struct
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_initChunkedEraseStorageSlot(uint32_t slotId,
BootloaderEraseStatus_t *eraseStat);
/***************************************************************************//**
* Erase one page from a storage slot according to
* the struct BootloaderEraseStatus_t.
*
* @note @ref bootloader_initChunkedEraseStorageSlot must be called
* before calling this function, in order to prepare
* BootloaderEraseStatus_t.
*
* @note This can be called sequentially to, for example, erase all contents
* of a storage slot.
*
* @param[in] eraseStat Erase status struct
*
* @return @ref BOOTLOADER_ERROR_STORAGE_CONTINUE if erasing a page was
* successful. Erase can be continued by calling this function again.
* @ref BOOTLOADER_OK if the entire slot has been erased,
* else error code in @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_chunkedEraseStorageSlot(BootloaderEraseStatus_t *eraseStat);
/***************************************************************************//**
* Set a prioritized list of images to attempt to bootload. The last call to
* this function determines which slot will be installed when
* @ref bootloader_rebootAndInstall is called.
*
* @param[in] slotIds Prioritized list of slot IDs to attempt to bootload. The
* first image to pass verification will be bootloaded.
* @param[in] length Length of the slotIds array
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_BOOTLOAD_BASE range
******************************************************************************/
int32_t bootloader_setImagesToBootload(int32_t *slotIds, size_t length);
/***************************************************************************//**
* Get the prioritized list of images the bootloader will attempt to bootload.
*
* @param[out] slotIds Prioritized list of slot IDs to attempt to bootload. The
* first image to pass verification will be bootloaded.
* @param[in] length Length of the slotIds array
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_BOOTLOAD_BASE range
******************************************************************************/
int32_t bootloader_getImagesToBootload(int32_t *slotIds, size_t length);
/***************************************************************************//**
* Append a single image to the list of images to attempt to bootload.
*
* @param[in] slotId ID of the slot to append
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_BOOTLOAD_BASE range
******************************************************************************/
int32_t bootloader_appendImageToBootloadList(int32_t slotId);
/***************************************************************************//**
* Set a single image to attempt to bootload.
*
* @param[in] slotId ID of the slot
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_BOOTLOAD_BASE range
******************************************************************************/
int32_t bootloader_setImageToBootload(int32_t slotId);
/***************************************************************************//**
* Initialize image verification.
*
* Initialize verification of an upgrade image stored in a bootloader storage
* slot.
*
* @note This function must be called before calling
* @ref bootloader_continueVerifyImage in a loop.
*
* @note The context pointer must point to memory allocated by the caller.
* The caller must ensure that the context pointer is 32 bit aligned.
* The required size of this context may depend on the version
* of the bootloader. The required size for the bootloader associated with
* this version of the application interface is given by the define
* @ref BOOTLOADER_STORAGE_VERIFICATION_CONTEXT_SIZE.
*
* @note Instead of calling @ref bootloader_initVerifyImage followed by
* @ref bootloader_continueVerifyImage, call
* @ref bootloader_verifyImage if no
* time-critical tasks are needed and sufficient stack space is
* available for the automatically allocated context. The purpose of the
* init-and-continue functions is to allow the caller to service system
* needs during verification.
*
*
* @param[in] slotId ID of the slot to check.
* @param context Pointer to memory used to hold the parser context.
* @param[in] contextSize Size of the context. An error is returned if the
* supplied context is too small.
*
* @return @ref BOOTLOADER_OK if the image parser was initialized, else error
* code.
******************************************************************************/
#if !defined(SL_TRUSTZONE_NONSECURE)
int32_t bootloader_initVerifyImage(uint32_t slotId,
void *context,
size_t contextSize);
#else
int32_t bootloader_initVerifyImage(uint32_t slotId);
#endif // SL_TRUSTZONE_NONSECURE
/***************************************************************************//**
* Continue image verification.
*
* Continue verification of an upgrade image stored in a bootloader storage
* slot.
*
* @note This function must be called in a loop until anything other than
* @ref BOOTLOADER_ERROR_PARSE_CONTINUE is returned.
*
* @note @ref bootloader_initVerifyImage must be called before calling this
* function to reset the parser.
*
* @note Instead of calling @ref bootloader_initVerifyImage followed by
* @ref bootloader_continueVerifyImage, call
* @ref bootloader_verifyImage if no
* time-critical tasks are needed. The purpose of the
* init-and-continue functions is to allow the caller to service system
* needs during verification.
*
*
* @param context Pointer to a context structure that has
* been initialized by calling
* @ref bootloader_initVerifyImage()
* @param[in] metadataCallback Function pointer, which is called when
* the binary metadata in the image is currently
* verified. Set to NULL if not required.
*
* @return @ref BOOTLOADER_ERROR_PARSE_CONTINUE if parsing was successful, and
* the parser expects more data. @ref BOOTLOADER_ERROR_PARSE_SUCCESS if
* the parser has successfully parsed the image and it passes
* verification. Else error code.
******************************************************************************/
#if !defined(SL_TRUSTZONE_NONSECURE)
int32_t bootloader_continueVerifyImage(void *context,
BootloaderParserCallback_t metadataCallback);
#else
int32_t bootloader_continueVerifyImage(void);
#endif // SL_TRUSTZONE_NONSECURE
/***************************************************************************//**
* Verify that the image in the given storage slot is valid.
*
* @param[in] slotId ID of the slot to check
* @param[in] metadataCallback Function pointer, which is called when
* binary metadata is present in the storage slot.
* Set to NULL if not required.
*
* @note This function allocates a context structure of the size given by
* @ref BOOTLOADER_STORAGE_VERIFICATION_CONTEXT_SIZE on the caller's
* stack. To manage memory and allocate the
* context elsewhere (on the heap, as a global variable, and so on), use
* @ref bootloader_initVerifyImage and @ref bootloader_continueVerifyImage
* functions instead.
*
* @return @ref BOOTLOADER_OK if the image is valid, else error code.
******************************************************************************/
#if !defined(SL_TRUSTZONE_NONSECURE)
int32_t bootloader_verifyImage(uint32_t slotId,
BootloaderParserCallback_t metadataCallback);
#else
int32_t bootloader_verifyImage(uint32_t slotId);
#endif // SL_TRUSTZONE_NONSECURE
/***************************************************************************//**
* Get application and bootloader upgrade metadata from the storage slot.
*
* @param[in] slotId ID of the slot to check
* @param[out] appInfo Pointer to @ref ApplicationData_t struct
* @param[out] bootloaderVersion Pointer to an integer representing bootloader
* version
*
* @return @ref BOOTLOADER_OK if metadata was filled successfully
******************************************************************************/
int32_t bootloader_getImageInfo(uint32_t slotId,
ApplicationData_t *appInfo,
uint32_t *bootloaderVersion);
/***************************************************************************//**
* Check whether the bootloader storage is busy.
*
* @return True if the storage is busy
******************************************************************************/
bool bootloader_storageIsBusy(void);
#if !defined(SL_TRUSTZONE_NONSECURE)
/***************************************************************************//**
* Read raw data from storage.
*
* @param[in] address Address to start reading from
* @param[out] buffer Buffer to store the data
* @param[in] length Amount of data to read
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_readRawStorage(uint32_t address,
uint8_t *buffer,
size_t length);
/***************************************************************************//**
* Write data to storage.
*
* @note
* If DMA-based MSC write is enabled on the bootloader, writing data from
* flash to flash is not supported on Series-1 devices.
*
* @param[in] address Address to start writing to
* @param[in] buffer Buffer to read data to write from
* @param[in] length Amount of data to write. Must be a multiple of 4.
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_writeRawStorage(uint32_t address,
uint8_t *buffer,
size_t length);
/***************************************************************************//**
* Erase data from storage.
*
* @note Erasing storage must adhere to the limitations of the underlying
* storage medium, such as requiring full page erases. Use
* @ref bootloader_getStorageInfo to learn about the limitations of the
* configured storage medium.
*
* @param[in] address Address to start erasing from
* @param[in] length Length of data to erase
*
* @return @ref BOOTLOADER_OK on success, else error code in
* @ref BOOTLOADER_ERROR_STORAGE_BASE range
******************************************************************************/
int32_t bootloader_eraseRawStorage(uint32_t address, size_t length);
#endif // !SL_TRUSTZONE_NONSECURE
/***************************************************************************//**
* Get allocated DMA channel for MSC write.
*
* @return A positive number channel. -1 if DMA-based MSC write
* is not enabled. Otherwise, the error code
* BOOTLOADER_ERROR_INIT_STORAGE.
******************************************************************************/
int32_t bootloader_getAllocatedDMAChannel(void);
/** @} (end addtogroup StorageInterface) */
/** @} (end addtogroup Interface) */
#endif // BTL_INTERFACE_STORAGE_H

View File

@@ -0,0 +1,104 @@
/***************************************************************************//**
* @file
* @brief Reset information for the Silicon Labs Gecko bootloader
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#ifndef BTL_RESET_INFO_H
#define BTL_RESET_INFO_H
#include <stdint.h>
/***************************************************************************//**
* @addtogroup Interface
* @{
* @addtogroup CommonInterface
* @{
* @addtogroup ResetInterface Reset Information
* @brief Passing information when resetting into and out of the bootloader
* @details
* To signal the bootloader to run, the
* application needs to write the @ref BootloaderResetCause_t structure
* to the first address of RAM, setting @ref BootloaderResetCause_t.reason
* to @ref BOOTLOADER_RESET_REASON_BOOTLOAD.
*
* The reset cause is only valid if @ref BootloaderResetCause_t.signature
* is set to @ref BOOTLOADER_RESET_SIGNATURE_VALID.
* @code BootloaderResetCause_t resetCause = {
* .reason = BOOTLOADER_RESET_REASON_BOOTLOAD,
* .signature = BOOTLOADER_RESET_SIGNATURE_VALID
* } @endcode
*
* When the bootloader reboots back into the app, it sets the reset
* reason to @ref BOOTLOADER_RESET_REASON_GO if the bootload succeeded,
* or @ref BOOTLOADER_RESET_REASON_BADIMAGE if the bootload failed due
* to errors when parsing the upgrade image.
*
* @note
* The reset information is automatically filled out before reset if the
* @ref bootloader_rebootAndInstall function is called.
* @{
******************************************************************************/
/// Reset cause of the bootloader
typedef struct {
/// Reset reason as defined in the [reset information](@ref ResetInterface)
uint16_t reason;
/// Signature indicating whether the reset reason is valid
uint16_t signature;
} BootloaderResetCause_t;
/// Unknown bootloader cause (should never occur)
#define BOOTLOADER_RESET_REASON_UNKNOWN 0x0200u
/// Bootloader caused reset telling app to run
#define BOOTLOADER_RESET_REASON_GO 0x0201u
/// Application requested that bootloader runs
#define BOOTLOADER_RESET_REASON_BOOTLOAD 0x0202u
/// Bootloader detected bad external upgrade image
#define BOOTLOADER_RESET_REASON_BADIMAGE 0x0203u
/// Fatal Error or assert in bootloader
#define BOOTLOADER_RESET_REASON_FATAL 0x0204u
/// Forced bootloader activation
#define BOOTLOADER_RESET_REASON_FORCE 0x0205u
/// OTA Bootloader mode activation
#define BOOTLOADER_RESET_REASON_OTAVALID 0x0206u
/// Bootloader initiated deep sleep
#define BOOTLOADER_RESET_REASON_DEEPSLEEP 0x0207u
/// Application verification failed
#define BOOTLOADER_RESET_REASON_BADAPP 0x0208u
/// Bootloader requested that first stage upgrades main bootloader
#define BOOTLOADER_RESET_REASON_UPGRADE 0x0209u
/// Bootloader timed out waiting for upgrade image
#define BOOTLOADER_RESET_REASON_TIMEOUT 0x020Au
/// Soft-reset was forced to handle a fault
#define BOOTLOADER_RESET_REASON_FAULT 0x020Bu
/// Soft-reset was forced to handle a security fault
#define BOOTLOADER_RESET_REASON_TZ_FAULT 0x020Cu
/// Insufficient slot space to re-create a new firmware
#define BOOTLOADER_RESET_REASON_NO_SLOT_SPACE 0x020Du
/// CRC mismatch of the newly re-constructed firmware
#define BOOTLOADER_RESET_REASON_BADCRC 0x020Eu
/// Re-creation of the new application using the DDFU library failed
#define BOOTLOADER_RESET_REASON_DDFU_FAIL 0x020Fu
/// Reset signature is valid
#define BOOTLOADER_RESET_SIGNATURE_VALID 0xF00Fu
/// Reset signature is invalid
#define BOOTLOADER_RESET_SIGNATURE_INVALID 0xC33Cu
/** @} (end addtogroup ResetInterface) */
/** @} (end addtogroup CommonInterface) */
/** @} (end addtogroup Interface) */
#endif // BTL_RESET_INFO_H

View File

@@ -0,0 +1,49 @@
/***************************************************************************//**
* @file
* @brief Application Properties Source File
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifdef APP_PROPERTIES_CONFIG_FILE
#include APP_PROPERTIES_CONFIG_FILE
#else
#include "app_properties_config.h"
#endif
const ApplicationProperties_t sl_app_properties = {
.magic = APPLICATION_PROPERTIES_MAGIC,
.structVersion = APPLICATION_PROPERTIES_VERSION,
.signatureType = SL_APPLICATION_SIGNATURE,
.signatureLocation = SL_APPLICATION_SIGNATURE_LOCATION,
.app = {
.type = SL_APPLICATION_TYPE,
.version = SL_APPLICATION_VERSION,
.capabilities = SL_APPLICATION_CAPABILITIES,
.productId = SL_APPLICATION_PRODUCT_ID
},
.cert = 0,
.longTokenSectionAddress = 0
};

View File

@@ -0,0 +1,210 @@
#ifndef BTL_UTIL_H
#define BTL_UTIL_H
#define BTL_STR_HELPER(x) #x
#define QUOTE(x) BTL_STR_HELPER(x)
#if defined(__CSTAT__)
#define MISRAC_DISABLE _Pragma( \
"cstat_disable= \
\"MISRAC2012-Dir-4.3\",\"MISRAC2012-Dir-4.4\",\"MISRAC2012-Dir-4.5\", \
\"MISRAC2012-Dir-4.6_a\",\"MISRAC2012-Dir-4.6_b\",\"MISRAC2012-Dir-4.7_a\", \
\"MISRAC2012-Dir-4.7_b\",\"MISRAC2012-Dir-4.7_c\",\"MISRAC2012-Dir-4.8\", \
\"MISRAC2012-Dir-4.9\",\"MISRAC2012-Dir-4.10\",\"MISRAC2012-Dir-4.11_a\", \
\"MISRAC2012-Dir-4.11_b\",\"MISRAC2012-Dir-4.11_c\",\"MISRAC2012-Dir-4.11_d\", \
\"MISRAC2012-Dir-4.11_e\",\"MISRAC2012-Dir-4.11_f\",\"MISRAC2012-Dir-4.11_g\", \
\"MISRAC2012-Dir-4.11_h\",\"MISRAC2012-Dir-4.11_i\",\"MISRAC2012-Dir-4.12\", \
\"MISRAC2012-Dir-4.13_b\",\"MISRAC2012-Dir-4.13_c\",\"MISRAC2012-Dir-4.13_d\", \
\"MISRAC2012-Dir-4.13_e\",\"MISRAC2012-Dir-4.13_f\",\"MISRAC2012-Dir-4.13_g\", \
\"MISRAC2012-Dir-4.13_h\",\"MISRAC2012-Rule-1.3_a\",\"MISRAC2012-Rule-1.3_b\", \
\"MISRAC2012-Rule-1.3_c\",\"MISRAC2012-Rule-1.3_d\",\"MISRAC2012-Rule-1.3_e\", \
\"MISRAC2012-Rule-1.3_f\",\"MISRAC2012-Rule-1.3_g\",\"MISRAC2012-Rule-1.3_h\", \
\"MISRAC2012-Rule-1.3_i\",\"MISRAC2012-Rule-1.3_j\",\"MISRAC2012-Rule-1.3_k\", \
\"MISRAC2012-Rule-1.3_m\",\"MISRAC2012-Rule-1.3_n\",\"MISRAC2012-Rule-1.3_o\", \
\"MISRAC2012-Rule-1.3_p\",\"MISRAC2012-Rule-1.3_q\",\"MISRAC2012-Rule-1.3_r\", \
\"MISRAC2012-Rule-1.3_s\",\"MISRAC2012-Rule-1.3_t\",\"MISRAC2012-Rule-1.3_u\", \
\"MISRAC2012-Rule-1.3_v\",\"MISRAC2012-Rule-1.3_w\",\"MISRAC2012-Rule-2.1_a\", \
\"MISRAC2012-Rule-2.1_b\",\"MISRAC2012-Rule-2.2_a\",\"MISRAC2012-Rule-2.2_b\", \
\"MISRAC2012-Rule-2.2_c\",\"MISRAC2012-Rule-2.3\",\"MISRAC2012-Rule-2.4\", \
\"MISRAC2012-Rule-2.5\",\"MISRAC2012-Rule-2.6\",\"MISRAC2012-Rule-2.7\", \
\"MISRAC2012-Rule-3.1\",\"MISRAC2012-Rule-3.2\",\"MISRAC2012-Rule-5.1\", \
\"MISRAC2012-Rule-5.2_c89\",\"MISRAC2012-Rule-5.2_c99\", \
\"MISRAC2012-Rule-5.3_c89\",\"MISRAC2012-Rule-5.3_c99\", \
\"MISRAC2012-Rule-5.4_c89\",\"MISRAC2012-Rule-5.4_c99\", \
\"MISRAC2012-Rule-5.5_c89\",\"MISRAC2012-Rule-5.5_c99\", \
\"MISRAC2012-Rule-5.6\",\"MISRAC2012-Rule-5.7\",\"MISRAC2012-Rule-5.8\", \
\"MISRAC2012-Rule-5.9\",\"MISRAC2012-Rule-6.1\",\"MISRAC2012-Rule-6.2\", \
\"MISRAC2012-Rule-7.1\",\"MISRAC2012-Rule-7.2\",\"MISRAC2012-Rule-7.3\", \
\"MISRAC2012-Rule-7.4_a\",\"MISRAC2012-Rule-7.4_b\",\"MISRAC2012-Rule-8.1\", \
\"MISRAC2012-Rule-8.2_a\",\"MISRAC2012-Rule-8.2_b\",\"MISRAC2012-Rule-8.3_b\", \
\"MISRAC2012-Rule-8.4\",\"MISRAC2012-Rule-8.5_a\",\"MISRAC2012-Rule-8.5_b\", \
\"MISRAC2012-Rule-8.6\",\"MISRAC2012-Rule-8.7\",\"MISRAC2012-Rule-8.9_a\", \
\"MISRAC2012-Rule-8.9_b\",\"MISRAC2012-Rule-8.10\",\"MISRAC2012-Rule-8.11\", \
\"MISRAC2012-Rule-8.12\",\"MISRAC2012-Rule-8.13\",\"MISRAC2012-Rule-8.14\", \
\"MISRAC2012-Rule-9.1_a\",\"MISRAC2012-Rule-9.1_b\",\"MISRAC2012-Rule-9.1_c\", \
\"MISRAC2012-Rule-9.1_d\",\"MISRAC2012-Rule-9.1_e\",\"MISRAC2012-Rule-9.1_f\", \
\"MISRAC2012-Rule-9.2\",\"MISRAC2012-Rule-9.3\",\"MISRAC2012-Rule-9.4\", \
\"MISRAC2012-Rule-9.5_a\",\"MISRAC2012-Rule-9.5_b\",\"MISRAC2012-Rule-10.1_R2\", \
\"MISRAC2012-Rule-10.1_R3\",\"MISRAC2012-Rule-10.1_R4\", \
\"MISRAC2012-Rule-10.1_R5\",\"MISRAC2012-Rule-10.1_R6\", \
\"MISRAC2012-Rule-10.1_R7\",\"MISRAC2012-Rule-10.1_R8\", \
\"MISRAC2012-Rule-10.2\",\"MISRAC2012-Rule-10.3\",\"MISRAC2012-Rule-10.4_a\", \
\"MISRAC2012-Rule-10.4_b\",\"MISRAC2012-Rule-10.5\",\"MISRAC2012-Rule-10.6\", \
\"MISRAC2012-Rule-10.7\",\"MISRAC2012-Rule-10.8\",\"MISRAC2012-Rule-11.1\", \
\"MISRAC2012-Rule-11.2\",\"MISRAC2012-Rule-11.3\",\"MISRAC2012-Rule-11.4\", \
\"MISRAC2012-Rule-11.5\",\"MISRAC2012-Rule-11.6\",\"MISRAC2012-Rule-11.7\", \
\"MISRAC2012-Rule-11.8\",\"MISRAC2012-Rule-11.9\",\"MISRAC2012-Rule-12.1\", \
\"MISRAC2012-Rule-12.2\",\"MISRAC2012-Rule-12.3\",\"MISRAC2012-Rule-13.1\", \
\"MISRAC2012-Rule-13.2_a\",\"MISRAC2012-Rule-13.2_b\",\"MISRAC2012-Rule-13.2_c\", \
\"MISRAC2012-Rule-13.3\",\"MISRAC2012-Rule-13.4_a\",\"MISRAC2012-Rule-13.4_b\", \
\"MISRAC2012-Rule-13.5\",\"MISRAC2012-Rule-13.6\",\"MISRAC2012-Rule-14.1_a\", \
\"MISRAC2012-Rule-14.1_b\",\"MISRAC2012-Rule-14.2\",\"MISRAC2012-Rule-14.3_a\", \
\"MISRAC2012-Rule-14.3_b\",\"MISRAC2012-Rule-14.4_a\",\"MISRAC2012-Rule-14.4_b\", \
\"MISRAC2012-Rule-14.4_c\",\"MISRAC2012-Rule-14.4_d\",\"MISRAC2012-Rule-15.1\", \
\"MISRAC2012-Rule-15.2\",\"MISRAC2012-Rule-15.3\",\"MISRAC2012-Rule-15.4\", \
\"MISRAC2012-Rule-15.5\",\"MISRAC2012-Rule-15.6_a\",\"MISRAC2012-Rule-15.6_b\", \
\"MISRAC2012-Rule-15.6_c\",\"MISRAC2012-Rule-15.6_d\",\"MISRAC2012-Rule-15.6_e\", \
\"MISRAC2012-Rule-15.7\",\"MISRAC2012-Rule-16.1\",\"MISRAC2012-Rule-16.2\", \
\"MISRAC2012-Rule-16.3\",\"MISRAC2012-Rule-16.4\",\"MISRAC2012-Rule-16.5\", \
\"MISRAC2012-Rule-16.6\",\"MISRAC2012-Rule-16.7\",\"MISRAC2012-Rule-17.1\", \
\"MISRAC2012-Rule-17.2_a\",\"MISRAC2012-Rule-17.2_b\",\"MISRAC2012-Rule-17.3\", \
\"MISRAC2012-Rule-17.4\",\"MISRAC2012-Rule-17.5\",\"MISRAC2012-Rule-17.6\", \
\"MISRAC2012-Rule-17.7\",\"MISRAC2012-Rule-17.8\",\"MISRAC2012-Rule-18.1_a\", \
\"MISRAC2012-Rule-18.1_b\",\"MISRAC2012-Rule-18.1_c\",\"MISRAC2012-Rule-18.1_d\", \
\"MISRAC2012-Rule-18.2\",\"MISRAC2012-Rule-18.3\",\"MISRAC2012-Rule-18.4\", \
\"MISRAC2012-Rule-18.5\",\"MISRAC2012-Rule-18.6_a\",\"MISRAC2012-Rule-18.6_b\", \
\"MISRAC2012-Rule-18.6_c\",\"MISRAC2012-Rule-18.6_d\",\"MISRAC2012-Rule-18.7\", \
\"MISRAC2012-Rule-18.8\",\"MISRAC2012-Rule-19.1\",\"MISRAC2012-Rule-19.2\", \
\"MISRAC2012-Rule-20.1\",\"MISRAC2012-Rule-20.2\",\"MISRAC2012-Rule-20.4_c89\", \
\"MISRAC2012-Rule-20.4_c99\",\"MISRAC2012-Rule-20.5\",\"MISRAC2012-Rule-20.7\", \
\"MISRAC2012-Rule-20.10\",\"MISRAC2012-Rule-21.1\",\"MISRAC2012-Rule-21.2\", \
\"MISRAC2012-Rule-21.3\",\"MISRAC2012-Rule-21.4\",\"MISRAC2012-Rule-21.5\", \
\"MISRAC2012-Rule-21.6\",\"MISRAC2012-Rule-21.7\",\"MISRAC2012-Rule-21.8\", \
\"MISRAC2012-Rule-21.9\",\"MISRAC2012-Rule-21.10\",\"MISRAC2012-Rule-21.11\", \
\"MISRAC2012-Rule-21.12_a\",\"MISRAC2012-Rule-21.12_b\",\"MISRAC2012-Rule-22.1_a\", \
\"MISRAC2012-Rule-22.1_b\",\"MISRAC2012-Rule-22.2_a\",\"MISRAC2012-Rule-22.2_b\", \
\"MISRAC2012-Rule-22.2_c\",\"MISRAC2012-Rule-22.3\",\"MISRAC2012-Rule-22.4\", \
\"MISRAC2012-Rule-22.5_a\",\"MISRAC2012-Rule-22.5_b\",\"MISRAC2012-Rule-22.6\"")
#define MISRAC_ENABLE _Pragma( \
"cstat_restore= \
\"MISRAC2012-Dir-4.3\",\"MISRAC2012-Dir-4.4\",\"MISRAC2012-Dir-4.5\", \
\"MISRAC2012-Dir-4.6_a\",\"MISRAC2012-Dir-4.6_b\",\"MISRAC2012-Dir-4.7_a\", \
\"MISRAC2012-Dir-4.7_b\",\"MISRAC2012-Dir-4.7_c\",\"MISRAC2012-Dir-4.8\", \
\"MISRAC2012-Dir-4.9\",\"MISRAC2012-Dir-4.10\",\"MISRAC2012-Dir-4.11_a\", \
\"MISRAC2012-Dir-4.11_b\",\"MISRAC2012-Dir-4.11_c\",\"MISRAC2012-Dir-4.11_d\", \
\"MISRAC2012-Dir-4.11_e\",\"MISRAC2012-Dir-4.11_f\",\"MISRAC2012-Dir-4.11_g\", \
\"MISRAC2012-Dir-4.11_h\",\"MISRAC2012-Dir-4.11_i\",\"MISRAC2012-Dir-4.12\", \
\"MISRAC2012-Dir-4.13_b\",\"MISRAC2012-Dir-4.13_c\",\"MISRAC2012-Dir-4.13_d\", \
\"MISRAC2012-Dir-4.13_e\",\"MISRAC2012-Dir-4.13_f\",\"MISRAC2012-Dir-4.13_g\", \
\"MISRAC2012-Dir-4.13_h\",\"MISRAC2012-Rule-1.3_a\",\"MISRAC2012-Rule-1.3_b\", \
\"MISRAC2012-Rule-1.3_c\",\"MISRAC2012-Rule-1.3_d\",\"MISRAC2012-Rule-1.3_e\", \
\"MISRAC2012-Rule-1.3_f\",\"MISRAC2012-Rule-1.3_g\",\"MISRAC2012-Rule-1.3_h\", \
\"MISRAC2012-Rule-1.3_i\",\"MISRAC2012-Rule-1.3_j\",\"MISRAC2012-Rule-1.3_k\", \
\"MISRAC2012-Rule-1.3_m\",\"MISRAC2012-Rule-1.3_n\",\"MISRAC2012-Rule-1.3_o\", \
\"MISRAC2012-Rule-1.3_p\",\"MISRAC2012-Rule-1.3_q\",\"MISRAC2012-Rule-1.3_r\", \
\"MISRAC2012-Rule-1.3_s\",\"MISRAC2012-Rule-1.3_t\",\"MISRAC2012-Rule-1.3_u\", \
\"MISRAC2012-Rule-1.3_v\",\"MISRAC2012-Rule-1.3_w\",\"MISRAC2012-Rule-2.1_a\", \
\"MISRAC2012-Rule-2.1_b\",\"MISRAC2012-Rule-2.2_a\",\"MISRAC2012-Rule-2.2_b\", \
\"MISRAC2012-Rule-2.2_c\",\"MISRAC2012-Rule-2.3\",\"MISRAC2012-Rule-2.4\", \
\"MISRAC2012-Rule-2.5\",\"MISRAC2012-Rule-2.6\",\"MISRAC2012-Rule-2.7\", \
\"MISRAC2012-Rule-3.1\",\"MISRAC2012-Rule-3.2\",\"MISRAC2012-Rule-5.1\", \
\"MISRAC2012-Rule-5.2_c89\",\"MISRAC2012-Rule-5.2_c99\", \
\"MISRAC2012-Rule-5.3_c89\",\"MISRAC2012-Rule-5.3_c99\", \
\"MISRAC2012-Rule-5.4_c89\",\"MISRAC2012-Rule-5.4_c99\", \
\"MISRAC2012-Rule-5.5_c89\",\"MISRAC2012-Rule-5.5_c99\", \
\"MISRAC2012-Rule-5.6\",\"MISRAC2012-Rule-5.7\",\"MISRAC2012-Rule-5.8\", \
\"MISRAC2012-Rule-5.9\",\"MISRAC2012-Rule-6.1\",\"MISRAC2012-Rule-6.2\", \
\"MISRAC2012-Rule-7.1\",\"MISRAC2012-Rule-7.2\",\"MISRAC2012-Rule-7.3\", \
\"MISRAC2012-Rule-7.4_a\",\"MISRAC2012-Rule-7.4_b\",\"MISRAC2012-Rule-8.1\", \
\"MISRAC2012-Rule-8.2_a\",\"MISRAC2012-Rule-8.2_b\",\"MISRAC2012-Rule-8.3_b\", \
\"MISRAC2012-Rule-8.4\",\"MISRAC2012-Rule-8.5_a\",\"MISRAC2012-Rule-8.5_b\", \
\"MISRAC2012-Rule-8.6\",\"MISRAC2012-Rule-8.7\",\"MISRAC2012-Rule-8.9_a\", \
\"MISRAC2012-Rule-8.9_b\",\"MISRAC2012-Rule-8.10\",\"MISRAC2012-Rule-8.11\", \
\"MISRAC2012-Rule-8.12\",\"MISRAC2012-Rule-8.13\",\"MISRAC2012-Rule-8.14\", \
\"MISRAC2012-Rule-9.1_a\",\"MISRAC2012-Rule-9.1_b\",\"MISRAC2012-Rule-9.1_c\", \
\"MISRAC2012-Rule-9.1_d\",\"MISRAC2012-Rule-9.1_e\",\"MISRAC2012-Rule-9.1_f\", \
\"MISRAC2012-Rule-9.2\",\"MISRAC2012-Rule-9.3\",\"MISRAC2012-Rule-9.4\", \
\"MISRAC2012-Rule-9.5_a\",\"MISRAC2012-Rule-9.5_b\",\"MISRAC2012-Rule-10.1_R2\", \
\"MISRAC2012-Rule-10.1_R3\",\"MISRAC2012-Rule-10.1_R4\", \
\"MISRAC2012-Rule-10.1_R5\",\"MISRAC2012-Rule-10.1_R6\", \
\"MISRAC2012-Rule-10.1_R7\",\"MISRAC2012-Rule-10.1_R8\", \
\"MISRAC2012-Rule-10.2\",\"MISRAC2012-Rule-10.3\",\"MISRAC2012-Rule-10.4_a\", \
\"MISRAC2012-Rule-10.4_b\",\"MISRAC2012-Rule-10.5\",\"MISRAC2012-Rule-10.6\", \
\"MISRAC2012-Rule-10.7\",\"MISRAC2012-Rule-10.8\",\"MISRAC2012-Rule-11.1\", \
\"MISRAC2012-Rule-11.2\",\"MISRAC2012-Rule-11.3\",\"MISRAC2012-Rule-11.4\", \
\"MISRAC2012-Rule-11.5\",\"MISRAC2012-Rule-11.6\",\"MISRAC2012-Rule-11.7\", \
\"MISRAC2012-Rule-11.8\",\"MISRAC2012-Rule-11.9\",\"MISRAC2012-Rule-12.1\", \
\"MISRAC2012-Rule-12.2\",\"MISRAC2012-Rule-12.3\",\"MISRAC2012-Rule-13.1\", \
\"MISRAC2012-Rule-13.2_a\",\"MISRAC2012-Rule-13.2_b\",\"MISRAC2012-Rule-13.2_c\", \
\"MISRAC2012-Rule-13.3\",\"MISRAC2012-Rule-13.4_a\",\"MISRAC2012-Rule-13.4_b\", \
\"MISRAC2012-Rule-13.5\",\"MISRAC2012-Rule-13.6\",\"MISRAC2012-Rule-14.1_a\", \
\"MISRAC2012-Rule-14.1_b\",\"MISRAC2012-Rule-14.2\",\"MISRAC2012-Rule-14.3_a\", \
\"MISRAC2012-Rule-14.3_b\",\"MISRAC2012-Rule-14.4_a\",\"MISRAC2012-Rule-14.4_b\", \
\"MISRAC2012-Rule-14.4_c\",\"MISRAC2012-Rule-14.4_d\",\"MISRAC2012-Rule-15.1\", \
\"MISRAC2012-Rule-15.2\",\"MISRAC2012-Rule-15.3\",\"MISRAC2012-Rule-15.4\", \
\"MISRAC2012-Rule-15.5\",\"MISRAC2012-Rule-15.6_a\",\"MISRAC2012-Rule-15.6_b\", \
\"MISRAC2012-Rule-15.6_c\",\"MISRAC2012-Rule-15.6_d\",\"MISRAC2012-Rule-15.6_e\", \
\"MISRAC2012-Rule-15.7\",\"MISRAC2012-Rule-16.1\",\"MISRAC2012-Rule-16.2\", \
\"MISRAC2012-Rule-16.3\",\"MISRAC2012-Rule-16.4\",\"MISRAC2012-Rule-16.5\", \
\"MISRAC2012-Rule-16.6\",\"MISRAC2012-Rule-16.7\",\"MISRAC2012-Rule-17.1\", \
\"MISRAC2012-Rule-17.2_a\",\"MISRAC2012-Rule-17.2_b\",\"MISRAC2012-Rule-17.3\", \
\"MISRAC2012-Rule-17.4\",\"MISRAC2012-Rule-17.5\",\"MISRAC2012-Rule-17.6\", \
\"MISRAC2012-Rule-17.7\",\"MISRAC2012-Rule-17.8\",\"MISRAC2012-Rule-18.1_a\", \
\"MISRAC2012-Rule-18.1_b\",\"MISRAC2012-Rule-18.1_c\",\"MISRAC2012-Rule-18.1_d\", \
\"MISRAC2012-Rule-18.2\",\"MISRAC2012-Rule-18.3\",\"MISRAC2012-Rule-18.4\", \
\"MISRAC2012-Rule-18.5\",\"MISRAC2012-Rule-18.6_a\",\"MISRAC2012-Rule-18.6_b\", \
\"MISRAC2012-Rule-18.6_c\",\"MISRAC2012-Rule-18.6_d\",\"MISRAC2012-Rule-18.7\", \
\"MISRAC2012-Rule-18.8\",\"MISRAC2012-Rule-19.1\",\"MISRAC2012-Rule-19.2\", \
\"MISRAC2012-Rule-20.1\",\"MISRAC2012-Rule-20.2\",\"MISRAC2012-Rule-20.4_c89\", \
\"MISRAC2012-Rule-20.4_c99\",\"MISRAC2012-Rule-20.5\",\"MISRAC2012-Rule-20.7\", \
\"MISRAC2012-Rule-20.10\",\"MISRAC2012-Rule-21.1\",\"MISRAC2012-Rule-21.2\", \
\"MISRAC2012-Rule-21.3\",\"MISRAC2012-Rule-21.4\",\"MISRAC2012-Rule-21.5\", \
\"MISRAC2012-Rule-21.6\",\"MISRAC2012-Rule-21.7\",\"MISRAC2012-Rule-21.8\", \
\"MISRAC2012-Rule-21.9\",\"MISRAC2012-Rule-21.10\",\"MISRAC2012-Rule-21.11\", \
\"MISRAC2012-Rule-21.12_a\",\"MISRAC2012-Rule-21.12_b\",\"MISRAC2012-Rule-22.1_a\", \
\"MISRAC2012-Rule-22.1_b\",\"MISRAC2012-Rule-22.2_a\",\"MISRAC2012-Rule-22.2_b\", \
\"MISRAC2012-Rule-22.2_c\",\"MISRAC2012-Rule-22.3\",\"MISRAC2012-Rule-22.4\", \
\"MISRAC2012-Rule-22.5_a\",\"MISRAC2012-Rule-22.5_b\",\"MISRAC2012-Rule-22.6\"")
#elif defined(__ICCARM__)
#define MISRAC_DISABLE _Pragma( \
"diag_suppress= \
Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
Pm155")
#define MISRAC_ENABLE _Pragma( \
"diag_default= \
Pm001,Pm002,Pm003,Pm004,Pm005,Pm006,Pm007,Pm008,Pm009,Pm010,Pm011,\
Pm012,Pm013,Pm014,Pm015,Pm016,Pm017,Pm018,Pm019,Pm020,Pm021,Pm022,\
Pm023,Pm024,Pm025,Pm026,Pm027,Pm028,Pm029,Pm030,Pm031,Pm032,Pm033,\
Pm034,Pm035,Pm036,Pm037,Pm038,Pm039,Pm040,Pm041,Pm042,Pm043,Pm044,\
Pm045,Pm046,Pm047,Pm048,Pm049,Pm050,Pm051,Pm052,Pm053,Pm054,Pm055,\
Pm056,Pm057,Pm058,Pm059,Pm060,Pm061,Pm062,Pm063,Pm064,Pm065,Pm066,\
Pm067,Pm068,Pm069,Pm070,Pm071,Pm072,Pm073,Pm074,Pm075,Pm076,Pm077,\
Pm078,Pm079,Pm080,Pm081,Pm082,Pm083,Pm084,Pm085,Pm086,Pm087,Pm088,\
Pm089,Pm090,Pm091,Pm092,Pm093,Pm094,Pm095,Pm096,Pm097,Pm098,Pm099,\
Pm100,Pm101,Pm102,Pm103,Pm104,Pm105,Pm106,Pm107,Pm108,Pm109,Pm110,\
Pm111,Pm112,Pm113,Pm114,Pm115,Pm116,Pm117,Pm118,Pm119,Pm120,Pm121,\
Pm122,Pm123,Pm124,Pm125,Pm126,Pm127,Pm128,Pm129,Pm130,Pm131,Pm132,\
Pm133,Pm134,Pm135,Pm136,Pm137,Pm138,Pm139,Pm140,Pm141,Pm142,Pm143,\
Pm144,Pm145,Pm146,Pm147,Pm148,Pm149,Pm150,Pm151,Pm152,Pm153,Pm154,\
Pm155")
#else
#define MISRAC_DISABLE
#define MISRAC_ENABLE
#endif
#endif

View File

@@ -0,0 +1,233 @@
/***************************************************************************//**
* @file
* @brief Abstraction of internal flash read and write routines.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#include "core/flash/btl_internal_flash.h"
#include "core/btl_util.h"
MISRAC_DISABLE
#include "em_cmu.h"
#include "em_msc.h"
MISRAC_ENABLE
#if !defined(_SILICON_LABS_32B_SERIES_2)
static MSC_Status_TypeDef writeHalfword(uint32_t address,
uint16_t data);
static MSC_Status_TypeDef writeHalfwordDMA(uint32_t address,
uint16_t data,
int ch);
static MSC_Status_TypeDef writeHalfword(uint32_t address,
uint16_t data)
{
uint32_t address32, data32;
MSC_Status_TypeDef retval;
address32 = address & ~3UL;
if (address & 2UL) {
data32 = 0x0000FFFFUL | ((uint32_t)data << 16UL);
} else {
data32 = 0xFFFF0000UL | (uint32_t)data;
}
retval = MSC_WriteWord((uint32_t *)address32, &data32, 4U);
return retval;
}
static MSC_Status_TypeDef writeHalfwordDMA(uint32_t address,
uint16_t data,
int ch)
{
uint32_t address32, data32;
MSC_Status_TypeDef retval;
address32 = address & ~3UL;
if (address & 2UL) {
data32 = 0x0000FFFFUL | ((uint32_t)data << 16UL);
} else {
data32 = 0xFFFF0000UL | (uint32_t)data;
}
// ch is verified by flash_writeBuffer_dma, which calls this function.
retval = MSC_WriteWordDma(ch, (uint32_t *)address32, &data32, 4U);
return retval;
}
#endif // !defined(_SILICON_LABS_32B_SERIES_2)
bool flash_erasePage(uint32_t address)
{
#if defined(_CMU_CLKEN1_MASK)
CMU->CLKEN1_SET = CMU_CLKEN1_MSC;
#endif
MSC_Status_TypeDef retval = MSC_ErasePage((uint32_t *)address);
if (retval == mscReturnOk) {
return true;
} else {
return false;
}
}
bool flash_writeBuffer_dma(uint32_t address,
const void *data,
size_t length,
int ch)
{
MSC_Status_TypeDef retval = mscReturnOk;
if ((ch < 0) || (ch >= (int)DMA_CHAN_COUNT)) {
return false;
}
MISRAC_DISABLE
CMU_ClockEnable(cmuClock_LDMA, true);
#if defined(CMU_CLKEN0_LDMAXBAR)
CMU_ClockEnable(cmuClock_LDMAXBAR, true);
#endif
MISRAC_ENABLE
if (length == 0UL) {
// Attempt to write zero-length array, return immediately
return true;
}
#if defined(_SILICON_LABS_32B_SERIES_2)
if ((address & 3UL) || (length & 3UL)) {
// Unaligned write, return early
return false;
}
#if defined(_CMU_CLKEN1_MASK)
CMU->CLKEN1_SET = CMU_CLKEN1_MSC;
#endif
retval = MSC_WriteWordDma(ch, (uint32_t *)address, data, length);
#else
uint16_t * data16 = (uint16_t *)data;
if ((address & 1UL) || (length & 1UL)) {
// Unaligned write, return early
return false;
}
// Flash unaligned data at start
if (address & 2UL) {
if ((writeHalfwordDMA(address, *data16, ch)) != mscReturnOk) {
return false;
}
address += 2UL;
length -= 2UL;
data16++;
}
// Flash word-aligned data
if (length >= 4UL) {
uint32_t length16 = (length & ~3UL);
retval = MSC_WriteWordDma(ch, (uint32_t *)address, data16, length16);
data16 += length16 / sizeof(uint16_t);
address += length16;
length -= length16;
}
if (retval != mscReturnOk) {
return false;
}
// Flash unaligned data at end
if (length > 0UL) {
retval = writeHalfwordDMA(address, *data16, ch);
address += 2UL;
length -= 2UL;
}
#endif // #if defined(_SILICON_LABS_32B_SERIES_2)
if (retval == mscReturnOk) {
return true;
} else {
return false;
}
}
bool flash_writeBuffer(uint32_t address,
const void *data,
size_t length)
{
MSC_Status_TypeDef retval = mscReturnOk;
if (length == 0UL) {
// Attempt to write zero-length array, return immediately
return true;
}
#if defined(_SILICON_LABS_32B_SERIES_2)
if ((address & 3UL) || (length & 3UL)) {
// Unaligned write, return early
return false;
}
#if defined(_CMU_CLKEN1_MASK)
CMU->CLKEN1_SET = CMU_CLKEN1_MSC;
#endif
retval = MSC_WriteWord((uint32_t *)address, data, length);
#else
uint16_t * data16 = (uint16_t *)data;
if ((address & 1UL) || (length & 1UL)) {
// Unaligned write, return early
return false;
}
// Flash unaligned data at start
if (address & 2UL) {
if ((writeHalfword(address, *data16)) != mscReturnOk) {
return false;
}
address += 2UL;
length -= 2UL;
data16++;
}
// Flash word-aligned data
if (length >= 4UL) {
uint32_t length16 = (length & ~3UL);
retval = MSC_WriteWord((uint32_t *)address, data16, length16);
data16 += length16 / sizeof(uint16_t);
address += length16;
length -= length16;
}
if (retval != mscReturnOk) {
return false;
}
// Flash unaligned data at end
if (length > 0UL) {
retval = writeHalfword(address, *data16);
address += 2UL;
length -= 2UL;
}
#endif // #if defined(_SILICON_LABS_32B_SERIES_2)
if (retval == mscReturnOk) {
return true;
} else {
return false;
}
}

View File

@@ -0,0 +1,84 @@
/***************************************************************************//**
* @file
* @brief Abstraction of internal flash read and write routines.
*******************************************************************************
* # License
* <b>Copyright 2021 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* The licensor of this software is Silicon Laboratories Inc. Your use of this
* software is governed by the terms of Silicon Labs Master Software License
* Agreement (MSLA) available at
* www.silabs.com/about-us/legal/master-software-license-agreement. This
* software is distributed to you in Source Code format and is governed by the
* sections of the MSLA applicable to Source Code.
*
******************************************************************************/
#ifndef BTL_INTERNAL_FLASH_H
#define BTL_INTERNAL_FLASH_H
#include "core/btl_util.h"
MISRAC_DISABLE
#include "em_device.h"
MISRAC_ENABLE
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
/***************************************************************************//**
* @addtogroup Core Bootloader Core
* @{
* @addtogroup Flash
* @brief Interface to internal flash
* @details Used for writing application images to the main flash.
* @{
******************************************************************************/
// -----------------------------------------------------------------------------
// Defines
/// DMA Channel for MSC write
#define SL_GBL_MSC_LDMA_CHANNEL 2
// -----------------------------------------------------------------------------
// Prototypes
/**
* Erase a flash page.
*
* @param[in] address Start address of the flash page to erase.
* @return True if operation was successful
*/
bool flash_erasePage(uint32_t address);
/**
* Write buffer to internal flash.
*
* @param address Starting address to write data to. Must be half-word aligned.
* @param data Data buffer to write to internal flash
* @param length Amount of bytes in the data buffer to write
* @param ch DMA channel to use
* @return True if operation was successful
*/
bool flash_writeBuffer_dma(uint32_t address,
const void *data,
size_t length,
int ch);
/**
* Write buffer to internal flash.
*
* @param address Starting address to write data to. Must be half-word aligned.
* @param data Data buffer to write to internal flash
* @param length Amount of bytes in the data buffer to write
* @return True if operation was successful
*/
bool flash_writeBuffer(uint32_t address,
const void *data,
size_t length);
/** @} addtogroup internal_flash */
/** @} addtogroup core */
#endif // BTL_INTERNAL_FLASH_H