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 #include "settings.h"
35
36 #include <assert.h>
37 #include <stddef.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include <openthread/instance.h>
42 #include <openthread/platform/settings.h>
43
44 #define SETTINGS_BUFFER_SIZE 1024
45
46 #if OPENTHREAD_SETTINGS_RAM
47
48 static uint8_t sSettingsBuf[SETTINGS_BUFFER_SIZE];
49 static uint16_t sSettingsBufLength;
50
51 OT_TOOL_PACKED_BEGIN
52 struct settingsBlock
53 {
54 uint16_t key;
55 uint16_t length;
56 } OT_TOOL_PACKED_END;
57
58 // settings API
otPlatSettingsInit(otInstance * aInstance,const uint16_t * aSensitiveKeys,uint16_t aSensitiveKeysLength)59 void otPlatSettingsInit(otInstance *aInstance, const uint16_t *aSensitiveKeys, uint16_t aSensitiveKeysLength)
60 {
61 OT_UNUSED_VARIABLE(aInstance);
62 OT_UNUSED_VARIABLE(aSensitiveKeys);
63 OT_UNUSED_VARIABLE(aSensitiveKeysLength);
64
65 sSettingsBufLength = 0;
66 }
67
otPlatSettingsDeinit(otInstance * aInstance)68 void otPlatSettingsDeinit(otInstance *aInstance) { OT_UNUSED_VARIABLE(aInstance); }
69
otPlatSettingsGet(otInstance * aInstance,uint16_t aKey,int aIndex,uint8_t * aValue,uint16_t * aValueLength)70 otError otPlatSettingsGet(otInstance *aInstance, uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength)
71 {
72 OT_UNUSED_VARIABLE(aInstance);
73
74 uint16_t i = 0;
75 uint16_t valueLength = 0;
76 uint16_t readLength;
77 int currentIndex = 0;
78 const struct settingsBlock *currentBlock;
79 otError error = OT_ERROR_NOT_FOUND;
80
81 while (i < sSettingsBufLength)
82 {
83 currentBlock = (struct settingsBlock *)&sSettingsBuf[i];
84
85 if (aKey == currentBlock->key)
86 {
87 if (currentIndex == aIndex)
88 {
89 readLength = currentBlock->length;
90
91 // Perform read only if an input buffer was passed in
92 if (aValue != NULL && aValueLength != NULL)
93 {
94 // Adjust read length if input buffer size is smaller
95 if (readLength > *aValueLength)
96 {
97 readLength = *aValueLength;
98 }
99
100 memcpy(aValue, &sSettingsBuf[i + sizeof(struct settingsBlock)], readLength);
101 }
102
103 valueLength = currentBlock->length;
104 error = OT_ERROR_NONE;
105 break;
106 }
107
108 currentIndex++;
109 }
110
111 i += sizeof(struct settingsBlock) + currentBlock->length;
112 }
113
114 if (aValueLength != NULL)
115 {
116 *aValueLength = valueLength;
117 }
118
119 return error;
120 }
121
otPlatSettingsSet(otInstance * aInstance,uint16_t aKey,const uint8_t * aValue,uint16_t aValueLength)122 otError otPlatSettingsSet(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
123 {
124 uint16_t i = 0;
125 uint16_t currentBlockLength;
126 uint16_t nextBlockStart;
127 const struct settingsBlock *currentBlock;
128
129 // Delete all entries of aKey
130 while (i < sSettingsBufLength)
131 {
132 currentBlock = (struct settingsBlock *)&sSettingsBuf[i];
133 currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length;
134
135 if (aKey == currentBlock->key)
136 {
137 nextBlockStart = i + currentBlockLength;
138
139 if (nextBlockStart < sSettingsBufLength)
140 {
141 memmove(&sSettingsBuf[i], &sSettingsBuf[nextBlockStart], sSettingsBufLength - nextBlockStart);
142 }
143
144 assert(sSettingsBufLength >= currentBlockLength);
145 sSettingsBufLength -= currentBlockLength;
146 }
147 else
148 {
149 i += currentBlockLength;
150 }
151 }
152
153 return otPlatSettingsAdd(aInstance, aKey, aValue, aValueLength);
154 }
155
otPlatSettingsAdd(otInstance * aInstance,uint16_t aKey,const uint8_t * aValue,uint16_t aValueLength)156 otError otPlatSettingsAdd(otInstance *aInstance, uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength)
157 {
158 OT_UNUSED_VARIABLE(aInstance);
159
160 otError error;
161 struct settingsBlock *currentBlock;
162 const uint16_t newBlockLength = sizeof(struct settingsBlock) + aValueLength;
163
164 if (sSettingsBufLength + newBlockLength <= sizeof(sSettingsBuf))
165 {
166 currentBlock = (struct settingsBlock *)&sSettingsBuf[sSettingsBufLength];
167 currentBlock->key = aKey;
168 currentBlock->length = aValueLength;
169
170 memcpy(&sSettingsBuf[sSettingsBufLength + sizeof(struct settingsBlock)], aValue, aValueLength);
171 sSettingsBufLength += newBlockLength;
172
173 error = OT_ERROR_NONE;
174 }
175 else
176 {
177 error = OT_ERROR_NO_BUFS;
178 }
179
180 return error;
181 }
182
otPlatSettingsDelete(otInstance * aInstance,uint16_t aKey,int aIndex)183 otError otPlatSettingsDelete(otInstance *aInstance, uint16_t aKey, int aIndex)
184 {
185 OT_UNUSED_VARIABLE(aInstance);
186
187 uint16_t i = 0;
188 int currentIndex = 0;
189 uint16_t nextBlockStart;
190 uint16_t currentBlockLength;
191 const struct settingsBlock *currentBlock;
192 otError error = OT_ERROR_NOT_FOUND;
193
194 while (i < sSettingsBufLength)
195 {
196 currentBlock = (struct settingsBlock *)&sSettingsBuf[i];
197 currentBlockLength = sizeof(struct settingsBlock) + currentBlock->length;
198
199 if (aKey == currentBlock->key)
200 {
201 if (currentIndex == aIndex)
202 {
203 nextBlockStart = i + currentBlockLength;
204
205 if (nextBlockStart < sSettingsBufLength)
206 {
207 memmove(&sSettingsBuf[i], &sSettingsBuf[nextBlockStart], sSettingsBufLength - nextBlockStart);
208 }
209
210 assert(sSettingsBufLength >= currentBlockLength);
211 sSettingsBufLength -= currentBlockLength;
212
213 error = OT_ERROR_NONE;
214 break;
215 }
216 else
217 {
218 currentIndex++;
219 }
220 }
221
222 i += currentBlockLength;
223 }
224
225 return error;
226 }
227
otPlatSettingsWipe(otInstance * aInstance)228 void otPlatSettingsWipe(otInstance *aInstance) { otPlatSettingsInit(aInstance, NULL, 0); }
229
230 #endif // OPENTHREAD_SETTINGS_RAM
231