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