1 /*!
2  * \file      NvmDataMgmt.c
3  *
4  * \brief     NVM context management implementation
5  *
6  * \copyright Revised BSD License, see section \ref LICENSE.
7  *
8  * \code
9  *                ______                              _
10  *               / _____)             _              | |
11  *              ( (____  _____ ____ _| |_ _____  ____| |__
12  *               \____ \| ___ |    (_   _) ___ |/ ___)  _ \
13  *               _____) ) ____| | | || |_| ____( (___| | | |
14  *              (______/|_____)_|_|_| \__)_____)\____)_| |_|
15  *              (C)2013-2017 Semtech
16  *
17  *               ___ _____ _   ___ _  _____ ___  ___  ___ ___
18  *              / __|_   _/_\ / __| |/ / __/ _ \| _ \/ __| __|
19  *              \__ \ | |/ _ \ (__| ' <| _| (_) |   / (__| _|
20  *              |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___|
21  *              embedded.connectivity.solutions===============
22  *
23  * \endcode
24  *
25  * \author    Miguel Luis ( Semtech )
26  *
27  * \author    Gregory Cristian ( Semtech )
28  *
29  * \author    Daniel Jaeckle ( STACKFORCE )
30  *
31  * \author    Johannes Bruder ( STACKFORCE )
32  */
33 
34 #include <stdio.h>
35 #include "utilities.h"
36 #include "nvmm.h"
37 #include "LoRaMac.h"
38 #include "NvmDataMgmt.h"
39 
40 /*!
41  * Enables/Disables the context storage management storage.
42  * Must be enabled for LoRaWAN 1.0.4 or later.
43  */
44 #ifndef CONTEXT_MANAGEMENT_ENABLED
45 #define CONTEXT_MANAGEMENT_ENABLED         1
46 #endif
47 
48 
49 static uint16_t NvmNotifyFlags = 0;
50 
NvmDataMgmtEvent(uint16_t notifyFlags)51 void NvmDataMgmtEvent( uint16_t notifyFlags )
52 {
53     NvmNotifyFlags = notifyFlags;
54 }
55 
NvmDataMgmtStore(void)56 uint16_t NvmDataMgmtStore( void )
57 {
58 #if( CONTEXT_MANAGEMENT_ENABLED == 1 )
59     uint16_t offset = 0;
60     uint16_t dataSize = 0;
61     MibRequestConfirm_t mibReq;
62     mibReq.Type = MIB_NVM_CTXS;
63     LoRaMacMibGetRequestConfirm( &mibReq );
64     LoRaMacNvmData_t* nvm = mibReq.Param.Contexts;
65 
66     // Input checks
67     if( NvmNotifyFlags == LORAMAC_NVM_NOTIFY_FLAG_NONE )
68     {
69         // There was no update.
70         return 0;
71     }
72     if( LoRaMacStop( ) != LORAMAC_STATUS_OK )
73     {
74         return 0;
75     }
76 
77     // Crypto
78     if( ( NvmNotifyFlags & LORAMAC_NVM_NOTIFY_FLAG_CRYPTO ) ==
79         LORAMAC_NVM_NOTIFY_FLAG_CRYPTO )
80     {
81         dataSize += NvmmWrite( ( uint8_t* ) &nvm->Crypto, sizeof( nvm->Crypto ),
82                                offset );
83     }
84     offset += sizeof( nvm->Crypto );
85 
86     // MacGroup1
87     if( ( NvmNotifyFlags & LORAMAC_NVM_NOTIFY_FLAG_MAC_GROUP1 ) ==
88         LORAMAC_NVM_NOTIFY_FLAG_MAC_GROUP1 )
89     {
90         dataSize += NvmmWrite( ( uint8_t* ) &nvm->MacGroup1,
91                                sizeof( nvm->MacGroup1 ), offset );
92     }
93     offset += sizeof( nvm->MacGroup1 );
94 
95     // MacGroup2
96     if( ( NvmNotifyFlags & LORAMAC_NVM_NOTIFY_FLAG_MAC_GROUP2 ) ==
97         LORAMAC_NVM_NOTIFY_FLAG_MAC_GROUP2 )
98     {
99         dataSize += NvmmWrite( ( uint8_t* ) &nvm->MacGroup2,
100                                sizeof( nvm->MacGroup2 ), offset );
101     }
102     offset += sizeof( nvm->MacGroup2 );
103 
104     // Secure element
105     if( ( NvmNotifyFlags & LORAMAC_NVM_NOTIFY_FLAG_SECURE_ELEMENT ) ==
106         LORAMAC_NVM_NOTIFY_FLAG_SECURE_ELEMENT )
107     {
108         dataSize += NvmmWrite( ( uint8_t* ) &nvm->SecureElement, sizeof( nvm->SecureElement ),
109                                offset );
110     }
111     offset += sizeof( nvm->SecureElement );
112 
113     // Region group 1
114     if( ( NvmNotifyFlags & LORAMAC_NVM_NOTIFY_FLAG_REGION_GROUP1 ) ==
115         LORAMAC_NVM_NOTIFY_FLAG_REGION_GROUP1 )
116     {
117         dataSize += NvmmWrite( ( uint8_t* ) &nvm->RegionGroup1,
118                                sizeof( nvm->RegionGroup1 ), offset );
119     }
120     offset += sizeof( nvm->RegionGroup1 );
121 
122     // Region group 2
123     if( ( NvmNotifyFlags & LORAMAC_NVM_NOTIFY_FLAG_REGION_GROUP2 ) ==
124         LORAMAC_NVM_NOTIFY_FLAG_REGION_GROUP2 )
125     {
126         dataSize += NvmmWrite( ( uint8_t* ) &nvm->RegionGroup2,
127                                sizeof( nvm->RegionGroup2 ), offset );
128     }
129     offset += sizeof( nvm->RegionGroup2 );
130 
131     // Class b
132     if( ( NvmNotifyFlags & LORAMAC_NVM_NOTIFY_FLAG_CLASS_B ) ==
133         LORAMAC_NVM_NOTIFY_FLAG_CLASS_B )
134     {
135         dataSize += NvmmWrite( ( uint8_t* ) &nvm->ClassB, sizeof( nvm->ClassB ),
136                                offset );
137     }
138     offset += sizeof( nvm->ClassB );
139 
140     // Reset notification flags
141     NvmNotifyFlags = LORAMAC_NVM_NOTIFY_FLAG_NONE;
142 
143     // Resume LoRaMac
144     LoRaMacStart( );
145     return dataSize;
146 #else
147     return 0;
148 #endif
149 }
150 
NvmDataMgmtRestore(void)151 uint16_t NvmDataMgmtRestore( void )
152 {
153 #if( CONTEXT_MANAGEMENT_ENABLED == 1 )
154     MibRequestConfirm_t mibReq;
155     mibReq.Type = MIB_NVM_CTXS;
156     LoRaMacMibGetRequestConfirm( &mibReq );
157     LoRaMacNvmData_t* nvm = mibReq.Param.Contexts;
158     uint16_t offset = 0;
159 
160     // Crypto
161     if( NvmmCrc32Check( sizeof( LoRaMacCryptoNvmData_t ), offset ) == false )
162     {
163         return 0;
164     }
165     offset += sizeof( LoRaMacCryptoNvmData_t );
166 
167     // Mac Group 1
168     if( NvmmCrc32Check( sizeof( LoRaMacNvmDataGroup1_t ), offset ) == false )
169     {
170         return 0;
171     }
172     offset += sizeof( LoRaMacNvmDataGroup1_t );
173 
174     // Mac Group 2
175     if( NvmmCrc32Check( sizeof( LoRaMacNvmDataGroup2_t ), offset ) == false )
176     {
177         return 0;
178     }
179     offset += sizeof( LoRaMacNvmDataGroup2_t );
180 
181     // Secure element
182     if( NvmmCrc32Check( sizeof( SecureElementNvmData_t ), offset ) == false )
183     {
184         return 0;
185     }
186     offset += sizeof( SecureElementNvmData_t );
187 
188     // Region group 1
189     if( sizeof( RegionNvmDataGroup1_t ) > sizeof( uint32_t ) )
190     {
191         if( NvmmCrc32Check( sizeof( RegionNvmDataGroup1_t ), offset ) == false )
192         {
193             return 0;
194         }
195     }
196     offset += sizeof( RegionNvmDataGroup1_t );
197 
198     // Region group 2
199     if( NvmmCrc32Check( sizeof( RegionNvmDataGroup2_t ), offset ) == false )
200     {
201         return 0;
202     }
203     offset += sizeof( RegionNvmDataGroup2_t );
204 
205     // Class b
206     if( NvmmCrc32Check( sizeof( LoRaMacClassBNvmData_t ), offset ) == false )
207     {
208         return 0;
209     }
210     offset += sizeof( LoRaMacClassBNvmData_t );
211 
212     if( NvmmRead( ( uint8_t* ) nvm, sizeof( LoRaMacNvmData_t ), 0 ) ==
213                   sizeof( LoRaMacNvmData_t ) )
214     {
215         return sizeof( LoRaMacNvmData_t );
216     }
217 #endif
218     return 0;
219 }
220 
NvmDataMgmtFactoryReset(void)221 bool NvmDataMgmtFactoryReset( void )
222 {
223     uint16_t offset = 0;
224 #if( CONTEXT_MANAGEMENT_ENABLED == 1 )
225     // Crypto
226     if( NvmmReset( sizeof( LoRaMacCryptoNvmData_t ), offset ) == false )
227     {
228         return false;
229     }
230     offset += sizeof( LoRaMacCryptoNvmData_t );
231 
232     // Mac Group 1
233     if( NvmmReset( sizeof( LoRaMacNvmDataGroup1_t ), offset ) == false )
234     {
235         return false;
236     }
237     offset += sizeof( LoRaMacNvmDataGroup1_t );
238 
239     // Mac Group 2
240     if( NvmmReset( sizeof( LoRaMacNvmDataGroup2_t ), offset ) == false )
241     {
242         return false;
243     }
244     offset += sizeof( LoRaMacNvmDataGroup2_t );
245 
246     // Secure element
247     if( NvmmReset( sizeof( SecureElementNvmData_t ), offset ) == false )
248     {
249         return false;
250     }
251     offset += sizeof( SecureElementNvmData_t );
252 
253     // Region group 1
254     if( NvmmReset( sizeof( RegionNvmDataGroup1_t ), offset ) == false )
255     {
256         return false;
257     }
258     offset += sizeof( RegionNvmDataGroup1_t );
259 
260     // Region group 2
261     if( NvmmReset( sizeof( RegionNvmDataGroup2_t ), offset ) == false )
262     {
263         return false;
264     }
265     offset += sizeof( RegionNvmDataGroup2_t );
266 
267     // Class b
268     if( NvmmReset( sizeof( LoRaMacClassBNvmData_t ), offset ) == false )
269     {
270         return false;
271     }
272     offset += sizeof( LoRaMacClassBNvmData_t );
273 #endif
274     return true;
275 }
276