1 /*
2  *  Copyright (c) 2019, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  *   This file implements OpenThread platform abstraction for storage of settings in RAM.
32  *
33  */
34 
35 #include "settings.h"
36 
37 #include <assert.h>
38 #include <stddef.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include <openthread/instance.h>
43 #include <openthread/platform/settings.h>
44 
45 #define SETTINGS_BUFFER_SIZE 1024
46 
47 #if OPENTHREAD_SETTINGS_RAM
48 
49 static uint8_t  sSettingsBuf[SETTINGS_BUFFER_SIZE];
50 static uint16_t sSettingsBufLength;
51 
52 OT_TOOL_PACKED_BEGIN
53 struct settingsBlock
54 {
55     uint16_t key;
56     uint16_t length;
57 } OT_TOOL_PACKED_END;
58 
59 // settings API
otPlatSettingsInit(otInstance * aInstance,const uint16_t * aSensitiveKeys,uint16_t aSensitiveKeysLength)60 void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
61 {
62     OT_UNUSED_VARIABLE(aInstance);
63     OT_UNUSED_VARIABLE(aSensitiveKeys);
64     OT_UNUSED_VARIABLE(aSensitiveKeysLength);
65 
66     sSettingsBufLength = 0;
67 }
68 
otPlatSettingsDeinit(otInstance * aInstance)69 void otPlatSettingsDeinit(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); }
70 
otPlatSettingsGet(otInstance * aInstance,uint16_t aKey,int aIndex,uint8_t * aValue,uint16_t * aValueLength)71 otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
72 {
73     OT_UNUSED_VARIABLE(aInstance);
74 
75     uint16_t                    i           = 0;
76     uint16_t                    valueLength = 0;
77     uint16_t                    readLength;
78     int                         currentIndex = 0;
79     const struct settingsBlock *currentBlock;
80     otError                     error = OT_ERROR_NOT_FOUND;
81 
82     while (i < sSettingsBufLength)
83     {
84         currentBlock = (struct settingsBlock *)&sSettingsBuf[i];
85 
86         if (aKey == currentBlock->key)
87         {
88             if (currentIndex == aIndex)
89             {
90                 readLength = currentBlock->length;
91 
92                 // Perform read only if an input buffer was passed in
93                 if (aValue != NULL && aValueLength != NULL)
94                 {
95                     // Adjust read length if input buffer size is smaller
96                     if (readLength > *aValueLength)
97                     {
98                         readLength = *aValueLength;
99                     }
100 
101                     memcpy(aValue, &sSettingsBuf[i + sizeof(struct settingsBlock)], readLength);
102                 }
103 
104                 valueLength = currentBlock->length;
105                 error       = OT_ERROR_NONE;
106                 break;
107             }
108 
109             currentIndex++;
110         }
111 
112         i += sizeof(struct settingsBlock) + currentBlock->length;
113     }
114 
115     if (aValueLength != NULL)
116     {
117         *aValueLength = valueLength;
118     }
119 
120     return error;
121 }
122 
otPlatSettingsSet(otInstance * aInstance,uint16_t aKey,const uint8_t * aValue,uint16_t aValueLength)123 otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
124 {
125     uint16_t                    i = 0;
126     uint16_t                    currentBlockLength;
127     uint16_t                    nextBlockStart;
128     const struct settingsBlock *currentBlock;
129 
130     // Delete all entries of aKey
131     while (i < sSettingsBufLength)
132     {
133         currentBlock       = (struct settingsBlock *)&sSettingsBuf[i];
134         currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length;
135 
136         if (aKey == currentBlock->key)
137         {
138             nextBlockStart = i + currentBlockLength;
139 
140             if (nextBlockStart < sSettingsBufLength)
141             {
142                 memmove(&sSettingsBuf[i], &sSettingsBuf[nextBlockStart], sSettingsBufLength - nextBlockStart);
143             }
144 
145             assert(sSettingsBufLength >= currentBlockLength);
146             sSettingsBufLength -= currentBlockLength;
147         }
148         else
149         {
150             i += currentBlockLength;
151         }
152     }
153 
154     return otPlatSettingsAdd(aInstance, aKey, aValue, aValueLength);
155 }
156 
otPlatSettingsAdd(otInstance * aInstance,uint16_t aKey,const uint8_t * aValue,uint16_t aValueLength)157 otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
158 {
159     OT_UNUSED_VARIABLE(aInstance);
160 
161     otError               error;
162     struct settingsBlock *currentBlock;
163     const uint16_t        newBlockLength = sizeof(struct settingsBlock) + aValueLength;
164 
165     if (sSettingsBufLength + newBlockLength <= sizeof(sSettingsBuf))
166     {
167         currentBlock         = (struct settingsBlock *)&sSettingsBuf[sSettingsBufLength];
168         currentBlock->key    = aKey;
169         currentBlock->length = aValueLength;
170 
171         memcpy(&sSettingsBuf[sSettingsBufLength + sizeof(struct settingsBlock)], aValue, aValueLength);
172         sSettingsBufLength += newBlockLength;
173 
174         error = OT_ERROR_NONE;
175     }
176     else
177     {
178         error = OT_ERROR_NO_BUFS;
179     }
180 
181     return error;
182 }
183 
otPlatSettingsDelete(otInstance * aInstance,uint16_t aKey,int aIndex)184 otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
185 {
186     OT_UNUSED_VARIABLE(aInstance);
187 
188     uint16_t                    i            = 0;
189     int                         currentIndex = 0;
190     uint16_t                    nextBlockStart;
191     uint16_t                    currentBlockLength;
192     const struct settingsBlock *currentBlock;
193     otError                     error = OT_ERROR_NOT_FOUND;
194 
195     while (i < sSettingsBufLength)
196     {
197         currentBlock       = (struct settingsBlock *)&sSettingsBuf[i];
198         currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length;
199 
200         if (aKey == currentBlock->key)
201         {
202             if (currentIndex == aIndex)
203             {
204                 nextBlockStart = i + currentBlockLength;
205 
206                 if (nextBlockStart < sSettingsBufLength)
207                 {
208                     memmove(&sSettingsBuf[i], &sSettingsBuf[nextBlockStart], sSettingsBufLength - nextBlockStart);
209                 }
210 
211                 assert(sSettingsBufLength >= currentBlockLength);
212                 sSettingsBufLength -= currentBlockLength;
213 
214                 error = OT_ERROR_NONE;
215                 break;
216             }
217             else
218             {
219                 currentIndex++;
220             }
221         }
222 
223         i += currentBlockLength;
224     }
225 
226     return error;
227 }
228 
otPlatSettingsWipe(otInstance * aInstance)229 void otPlatSettingsWipe(otInstance *aInstance) { otPlatSettingsInit(aInstance, NULL, 0); }
230 
231 #endif // OPENTHREAD_SETTINGS_RAM
232