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( NvmmCrc32Check( sizeof( RegionNvmDataGroup1_t ), offset ) == false )
190     {
191         return 0;
192     }
193     offset += sizeof( RegionNvmDataGroup1_t );
194 
195     // Region group 2
196     if( NvmmCrc32Check( sizeof( RegionNvmDataGroup2_t ), offset ) == false )
197     {
198         return 0;
199     }
200     offset += sizeof( RegionNvmDataGroup2_t );
201 
202     // Class b
203     if( NvmmCrc32Check( sizeof( LoRaMacClassBNvmData_t ), offset ) == false )
204     {
205         return 0;
206     }
207     offset += sizeof( LoRaMacClassBNvmData_t );
208 
209     if( NvmmRead( ( uint8_t* ) nvm, sizeof( LoRaMacNvmData_t ), 0 ) ==
210                   sizeof( LoRaMacNvmData_t ) )
211     {
212         return sizeof( LoRaMacNvmData_t );
213     }
214 #endif
215     return 0;
216 }
217 
NvmDataMgmtFactoryReset(void)218 bool NvmDataMgmtFactoryReset( void )
219 {
220     uint16_t offset = 0;
221 #if( CONTEXT_MANAGEMENT_ENABLED == 1 )
222     // Crypto
223     if( NvmmReset( sizeof( LoRaMacCryptoNvmData_t ), offset ) == false )
224     {
225         return false;
226     }
227     offset += sizeof( LoRaMacCryptoNvmData_t );
228 
229     // Mac Group 1
230     if( NvmmReset( sizeof( LoRaMacNvmDataGroup1_t ), offset ) == false )
231     {
232         return false;
233     }
234     offset += sizeof( LoRaMacNvmDataGroup1_t );
235 
236     // Mac Group 2
237     if( NvmmReset( sizeof( LoRaMacNvmDataGroup2_t ), offset ) == false )
238     {
239         return false;
240     }
241     offset += sizeof( LoRaMacNvmDataGroup2_t );
242 
243     // Secure element
244     if( NvmmReset( sizeof( SecureElementNvmData_t ), offset ) == false )
245     {
246         return false;
247     }
248     offset += sizeof( SecureElementNvmData_t );
249 
250     // Region group 1
251     if( NvmmReset( sizeof( RegionNvmDataGroup1_t ), offset ) == false )
252     {
253         return false;
254     }
255     offset += sizeof( RegionNvmDataGroup1_t );
256 
257     // Region group 2
258     if( NvmmReset( sizeof( RegionNvmDataGroup2_t ), offset ) == false )
259     {
260         return false;
261     }
262     offset += sizeof( RegionNvmDataGroup2_t );
263 
264     // Class b
265     if( NvmmReset( sizeof( LoRaMacClassBNvmData_t ), offset ) == false )
266     {
267         return false;
268     }
269     offset += sizeof( LoRaMacClassBNvmData_t );
270 #endif
271     return true;
272 }
273