STM32CubeWL/Middlewares/Third_Party/LoRaWAN/LmHandler/NvmCtxMgmt.c

401 lines
12 KiB
C

/*!
* \file NvmCtxMgmt.c
*
* \brief NVM context management implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
* ______ _
* / _____) _ | |
* ( (____ _____ ____ _| |_ _____ ____| |__
* \____ \| ___ | (_ _) ___ |/ ___) _ \
* _____) ) ____| | | || |_| ____( (___| | | |
* (______/|_____)_|_|_| \__)_____)\____)_| |_|
* (C)2013-2017 Semtech
*
* ___ _____ _ ___ _ _____ ___ ___ ___ ___
* / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __|
* \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _|
* |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
* embedded.connectivity.solutions===============
*
* \endcode
*
* \author Miguel Luis ( Semtech )
*
* \author Gregory Cristian ( Semtech )
*
* \author Daniel Jaeckle ( STACKFORCE )
*
* \author Johannes Bruder ( STACKFORCE )
*/
/**
******************************************************************************
*
* Portions COPYRIGHT 2020 STMicroelectronics
*
* @file NvmCtxMgmt.c
* @author MCD Application Team
* @brief NVM Context Management definition
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "NvmCtxMgmt.h"
/* Private typedef -----------------------------------------------------------*/
#if ( CONTEXT_MANAGEMENT_ENABLED == 1 )
/*!
* LoRaMAC Structure holding contexts changed status
* in case of a \ref MLME_NVM_CTXS_UPDATE indication.
*/
typedef union uLoRaMacCtxsUpdateInfo
{
/*!
* Byte-access to the bits
*/
uint8_t Value;
/*!
* The according context bit will be set to one
* if the context changed or 0 otherwise.
*/
struct sElements
{
/*!
* Mac core nvm context
*/
uint8_t Mac : 1;
/*!
* Region module nvm contexts
*/
uint8_t Region : 1;
/*!
* Crypto module context
*/
uint8_t Crypto : 1;
/*!
* Secure Element driver context
*/
uint8_t SecureElement : 1;
/*!
* MAC commands module context
*/
uint8_t Commands : 1;
/*!
* Class B module context
*/
uint8_t ClassB : 1;
/*!
* Confirm queue module context
*/
uint8_t ConfirmQueue : 1;
/*!
* FCnt Handler module context
*/
uint8_t FCntHandlerNvmCtx : 1;
} Elements;
} LoRaMacCtxUpdateStatus_t;
#endif /* CONTEXT_MANAGEMENT_ENABLED == 1 */
/* Private define ------------------------------------------------------------*/
/*!
* Enables/Disables the context storage management storage at all. Must be enabled for LoRaWAN 1.1.x.
* WARNING: Still under development and not tested yet.
*/
#define CONTEXT_MANAGEMENT_ENABLED 0
/*!
* Enables/Disables maximum persistent context storage management. All module contexts will be saved on a non-volatile memory.
* WARNING: Still under development and not tested yet.
*/
#define MAX_PERSISTENT_CTX_MGMT_ENABLED 0
#if ( MAX_PERSISTENT_CTX_MGMT_ENABLED == 1 )
#define NVM_CTX_STORAGE_MASK 0xFF
#else /* MAX_PERSISTENT_CTX_MGMT_ENABLED == 0 */
#define NVM_CTX_STORAGE_MASK 0x8C
#endif /* MAX_PERSISTENT_CTX_MGMT_ENABLED */
/* Private macro -------------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
#if ( CONTEXT_MANAGEMENT_ENABLED == 1 )
static LoRaMacCtxUpdateStatus_t CtxUpdateStatus = { .Value = 0 };
/*
* Nvmm handles
*/
static NvmmDataBlock_t SecureElementNvmCtxDataBlock;
static NvmmDataBlock_t CryptoNvmCtxDataBlock;
#if ( MAX_PERSISTENT_CTX_MGMT_ENABLED == 1 )
static NvmmDataBlock_t MacNvmCtxDataBlock;
static NvmmDataBlock_t RegionNvmCtxDataBlock;
static NvmmDataBlock_t CommandsNvmCtxDataBlock;
static NvmmDataBlock_t ConfirmQueueNvmCtxDataBlock;
static NvmmDataBlock_t ClassBNvmCtxDataBlock;
#endif /* MAX_PERSISTENT_CTX_MGMT_ENABLED == 1 */
#endif /* CONTEXT_MANAGEMENT_ENABLED == 1 */
/* Exported functions ---------------------------------------------------------*/
void NvmCtxMgmtEvent(LoRaMacNvmCtxModule_t module)
{
#if ( CONTEXT_MANAGEMENT_ENABLED == 1 )
switch (module)
{
case LORAMAC_NVMCTXMODULE_MAC:
{
CtxUpdateStatus.Elements.Mac = 1;
break;
}
case LORAMAC_NVMCTXMODULE_REGION:
{
CtxUpdateStatus.Elements.Region = 1;
break;
}
case LORAMAC_NVMCTXMODULE_CRYPTO:
{
CtxUpdateStatus.Elements.Crypto = 1;
break;
}
case LORAMAC_NVMCTXMODULE_SECURE_ELEMENT:
{
CtxUpdateStatus.Elements.SecureElement = 1;
break;
}
case LORAMAC_NVMCTXMODULE_COMMANDS:
{
CtxUpdateStatus.Elements.Commands = 1;
break;
}
case LORAMAC_NVMCTXMODULE_CLASS_B:
{
CtxUpdateStatus.Elements.ClassB = 1;
break;
}
case LORAMAC_NVMCTXMODULE_CONFIRM_QUEUE:
{
CtxUpdateStatus.Elements.ConfirmQueue = 1;
break;
}
default:
{
break;
}
}
#endif /* CONTEXT_MANAGEMENT_ENABLED == 1 */
}
NvmCtxMgmtStatus_t NvmCtxMgmtStore(void)
{
#if ( CONTEXT_MANAGEMENT_ENABLED == 1 )
/* Read out the contexts lengths and pointers */
MibRequestConfirm_t mibReq;
mibReq.Type = MIB_NVM_CTXS;
LoRaMacMibGetRequestConfirm(&mibReq);
LoRaMacCtxs_t *MacContexts = mibReq.Param.Contexts;
/* Input checks */
if ((CtxUpdateStatus.Value & NVM_CTX_STORAGE_MASK) == 0)
{
return NVMCTXMGMT_STATUS_FAIL;
}
if (LoRaMacStop() != LORAMAC_STATUS_OK)
{
return NVMCTXMGMT_STATUS_FAIL;
}
/* Write */
if (CtxUpdateStatus.Elements.Crypto == 1)
{
if (NvmmWrite(&CryptoNvmCtxDataBlock, MacContexts->CryptoNvmCtx, MacContexts->CryptoNvmCtxSize) != NVMM_SUCCESS)
{
return NVMCTXMGMT_STATUS_FAIL;
}
}
if (CtxUpdateStatus.Elements.SecureElement == 1)
{
if (NvmmWrite(&SecureElementNvmCtxDataBlock, MacContexts->SecureElementNvmCtx,
MacContexts->SecureElementNvmCtxSize) != NVMM_SUCCESS)
{
return NVMCTXMGMT_STATUS_FAIL;
}
}
#if ( MAX_PERSISTENT_CTX_MGMT_ENABLED == 1 )
if (CtxUpdateStatus.Elements.Mac == 1)
{
if (NvmmWrite(&MacNvmCtxDataBlock, MacContexts->MacNvmCtx, MacContexts->MacNvmCtxSize) != NVMM_SUCCESS)
{
return NVMCTXMGMT_STATUS_FAIL;
}
}
if (CtxUpdateStatus.Elements.Region == 1)
{
if (NvmmWrite(&RegionNvmCtxDataBlock, MacContexts->RegionNvmCtx, MacContexts->RegionNvmCtxSize) != NVMM_SUCCESS)
{
return NVMCTXMGMT_STATUS_FAIL;
}
}
if (CtxUpdateStatus.Elements.Commands == 1)
{
if (NvmmWrite(&CommandsNvmCtxDataBlock, MacContexts->CommandsNvmCtx, MacContexts->CommandsNvmCtxSize) != NVMM_SUCCESS)
{
return NVMCTXMGMT_STATUS_FAIL;
}
}
if (CtxUpdateStatus.Elements.ClassB == 1)
{
if (NvmmWrite(&ClassBNvmCtxDataBlock, MacContexts->ClassBNvmCtx, MacContexts->ClassBNvmCtxSize) != NVMM_SUCCESS)
{
return NVMCTXMGMT_STATUS_FAIL;
}
}
if (CtxUpdateStatus.Elements.ConfirmQueue == 1)
{
if (NvmmWrite(&ConfirmQueueNvmCtxDataBlock, MacContexts->ConfirmQueueNvmCtx,
MacContexts->ConfirmQueueNvmCtxSize) != NVMM_SUCCESS)
{
return NVMCTXMGMT_STATUS_FAIL;
}
}
#endif /* MAX_PERSISTENT_CTX_MGMT_ENABLED == 1 */
CtxUpdateStatus.Value = 0x00;
/* Resume LoRaMac */
LoRaMacStart();
return NVMCTXMGMT_STATUS_SUCCESS;
#else /* CONTEXT_MANAGEMENT_ENABLED == 0 */
return NVMCTXMGMT_STATUS_FAIL;
#endif /* CONTEXT_MANAGEMENT_ENABLED */
}
NvmCtxMgmtStatus_t NvmCtxMgmtRestore(void)
{
#if ( CONTEXT_MANAGEMENT_ENABLED == 1 )
MibRequestConfirm_t mibReq;
LoRaMacCtxs_t contexts = { 0 };
NvmCtxMgmtStatus_t status = NVMCTXMGMT_STATUS_SUCCESS;
/* Read out the contexts lengths */
mibReq.Type = MIB_NVM_CTXS;
LoRaMacMibGetRequestConfirm(&mibReq);
uint8_t NvmCryptoCtxRestore[mibReq.Param.Contexts->CryptoNvmCtxSize];
uint8_t NvmSecureElementCtxRestore[mibReq.Param.Contexts->SecureElementNvmCtxSize];
#if ( MAX_PERSISTENT_CTX_MGMT_ENABLED == 1 )
uint8_t NvmMacCtxRestore[mibReq.Param.Contexts->MacNvmCtxSize];
uint8_t NvmRegionCtxRestore[mibReq.Param.Contexts->RegionNvmCtxSize];
uint8_t NvmCommandsCtxRestore[mibReq.Param.Contexts->CommandsNvmCtxSize];
uint8_t NvmClassBCtxRestore[mibReq.Param.Contexts->ClassBNvmCtxSize];
uint8_t NvmConfirmQueueCtxRestore[mibReq.Param.Contexts->ConfirmQueueNvmCtxSize];
#endif /* MAX_PERSISTENT_CTX_MGMT_ENABLED == 1 */
if (NvmmDeclare(&CryptoNvmCtxDataBlock, mibReq.Param.Contexts->CryptoNvmCtxSize) == NVMM_SUCCESS)
{
NvmmRead(&CryptoNvmCtxDataBlock, NvmCryptoCtxRestore, mibReq.Param.Contexts->CryptoNvmCtxSize);
contexts.CryptoNvmCtx = &NvmCryptoCtxRestore;
contexts.CryptoNvmCtxSize = mibReq.Param.Contexts->CryptoNvmCtxSize;
}
else
{
status = NVMCTXMGMT_STATUS_FAIL;
}
if (NvmmDeclare(&SecureElementNvmCtxDataBlock, mibReq.Param.Contexts->SecureElementNvmCtxSize) == NVMM_SUCCESS)
{
NvmmRead(&SecureElementNvmCtxDataBlock, NvmSecureElementCtxRestore, mibReq.Param.Contexts->SecureElementNvmCtxSize);
contexts.SecureElementNvmCtx = &NvmSecureElementCtxRestore;
contexts.SecureElementNvmCtxSize = mibReq.Param.Contexts->SecureElementNvmCtxSize;
}
else
{
status = NVMCTXMGMT_STATUS_FAIL;
}
#if ( MAX_PERSISTENT_CTX_MGMT_ENABLED == 1 )
if (NvmmDeclare(&MacNvmCtxDataBlock, mibReq.Param.Contexts->MacNvmCtxSize) == NVMM_SUCCESS)
{
NvmmRead(&MacNvmCtxDataBlock, NvmMacCtxRestore, mibReq.Param.Contexts->MacNvmCtxSize);
contexts.MacNvmCtx = &NvmMacCtxRestore;
contexts.MacNvmCtxSize = mibReq.Param.Contexts->MacNvmCtxSize;
}
else
{
status = NVMCTXMGMT_STATUS_FAIL;
}
if (NvmmDeclare(&RegionNvmCtxDataBlock, mibReq.Param.Contexts->RegionNvmCtxSize) == NVMM_SUCCESS)
{
NvmmRead(&RegionNvmCtxDataBlock, NvmRegionCtxRestore, mibReq.Param.Contexts->RegionNvmCtxSize);
contexts.RegionNvmCtx = &NvmRegionCtxRestore;
contexts.RegionNvmCtxSize = mibReq.Param.Contexts->RegionNvmCtxSize;
}
else
{
status = NVMCTXMGMT_STATUS_FAIL;
}
if (NvmmDeclare(&CommandsNvmCtxDataBlock, mibReq.Param.Contexts->CommandsNvmCtxSize) == NVMM_SUCCESS)
{
NvmmRead(&CommandsNvmCtxDataBlock, NvmCommandsCtxRestore, mibReq.Param.Contexts->CommandsNvmCtxSize);
contexts.CommandsNvmCtx = &NvmCommandsCtxRestore;
contexts.CommandsNvmCtxSize = mibReq.Param.Contexts->CommandsNvmCtxSize;
}
else
{
status = NVMCTXMGMT_STATUS_FAIL;
}
if (NvmmDeclare(&ClassBNvmCtxDataBlock, mibReq.Param.Contexts->ClassBNvmCtxSize) == NVMM_SUCCESS)
{
NvmmRead(&ClassBNvmCtxDataBlock, NvmClassBCtxRestore, mibReq.Param.Contexts->ClassBNvmCtxSize);
contexts.ClassBNvmCtx = &NvmClassBCtxRestore;
contexts.ClassBNvmCtxSize = mibReq.Param.Contexts->ClassBNvmCtxSize;
}
else
{
status = NVMCTXMGMT_STATUS_FAIL;
}
if (NvmmDeclare(&ConfirmQueueNvmCtxDataBlock, mibReq.Param.Contexts->ConfirmQueueNvmCtxSize) == NVMM_SUCCESS)
{
NvmmRead(&ConfirmQueueNvmCtxDataBlock, NvmConfirmQueueCtxRestore, mibReq.Param.Contexts->ConfirmQueueNvmCtxSize);
contexts.ConfirmQueueNvmCtx = &NvmConfirmQueueCtxRestore;
contexts.ConfirmQueueNvmCtxSize = mibReq.Param.Contexts->ConfirmQueueNvmCtxSize;
}
else
{
status = NVMCTXMGMT_STATUS_FAIL;
}
#endif /* MAX_PERSISTENT_CTX_MGMT_ENABLED == 1 */
/* Enforce storing all contexts */
if (status == NVMCTXMGMT_STATUS_FAIL)
{
CtxUpdateStatus.Value = 0xFF;
NvmCtxMgmtStore();
}
else
{
/* If successful query the mac to restore contexts */
mibReq.Type = MIB_NVM_CTXS;
mibReq.Param.Contexts = &contexts;
LoRaMacMibSetRequestConfirm(&mibReq);
}
return status;
#else /* CONTEXT_MANAGEMENT_ENABLED == 0 */
return NVMCTXMGMT_STATUS_FAIL;
#endif /* CONTEXT_MANAGEMENT_ENABLED */
}
/* Private functions ---------------------------------------------------------*/