• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2020, 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 #ifndef FLASH_HPP_
30 #define FLASH_HPP_
31 
32 #include "openthread-core-config.h"
33 
34 #if OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
35 
36 #include <stdint.h>
37 #include <string.h>
38 
39 #include <openthread/platform/toolchain.h>
40 
41 #include "common/debug.hpp"
42 #include "common/error.hpp"
43 #include "common/locator.hpp"
44 
45 namespace ot {
46 
47 /**
48  * Implements the flash storage driver.
49  */
50 class Flash : public InstanceLocator
51 {
52 public:
53     /**
54      * Constructor.
55      */
Flash(Instance & aInstance)56     explicit Flash(Instance &aInstance)
57         : InstanceLocator(aInstance)
58     {
59     }
60 
61     /**
62      * Initializes the flash storage driver.
63      */
64     void Init(void);
65 
66     /**
67      * Fetches the value identified by @p aKey.
68      *
69      * @param[in]      aKey          The key associated with the requested value.
70      * @param[in]      aIndex        The index of the specific item to get.
71      * @param[out]     aValue        A pointer to where the value of the setting should be written.
72      *                               May be `nullptr` if just testing for the presence or length of a key.
73      * @param[in,out]  aValueLength  A pointer to the length of the value.
74      *                               When called, this should point to an integer containing the maximum bytes that
75      *                               can be written to @p aValue.
76      *                               At return, the actual length of the setting is written.
77      *                               May be `nullptr` if performing a presence check.
78      *
79      * @retval kErrorNone       The value was fetched successfully.
80      * @retval kErrorNotFound   The key was not found.
81      */
82     Error Get(uint16_t aKey, int aIndex, uint8_t *aValue, uint16_t *aValueLength) const;
83 
84     /**
85      * Sets or replaces the value identified by @p aKey.
86      *
87      * If there was more than one value previously associated with @p aKey, then they are all deleted and replaced with
88      * this single entry.
89      *
90      * @param[in]  aKey          The key associated with the value.
91      * @param[in]  aValue        A pointer to where the new value of the setting should be read from.
92      *                           MUST NOT be `nullptr` if @p aValueLength is non-zero.
93      * @param[in]  aValueLength  The length of the data pointed to by @p aValue. May be zero.
94      *
95      * @retval kErrorNone     The value was changed.
96      * @retval kErrorNoBufs   Not enough space to store the value.
97      */
98     Error Set(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
99 
100     /**
101      * Adds a value to @p aKey.
102      *
103      * @param[in]  aKey          The key associated with the value.
104      * @param[in]  aValue        A pointer to where the new value of the setting should be read from.
105      *                           MUST NOT be `nullptr` if @p aValueLength is non-zero.
106      * @param[in]  aValueLength  The length of the data pointed to by @p aValue. May be zero.
107      *
108      * @retval kErrorNone    The value was added.
109      * @retval kErrorNoBufs  Not enough space to store the value.
110      */
111     Error Add(uint16_t aKey, const uint8_t *aValue, uint16_t aValueLength);
112 
113     /**
114      * Removes a value from @p aKey.
115      *
116      *
117      * @param[in] aKey    The key associated with the value.
118      * @param[in] aIndex  The index of the value to be removed.
119      *                    If set to -1, all values for @p aKey will be removed.
120      *
121      * @retval kErrorNone      The given key and index was found and removed successfully.
122      * @retval kErrorNotFound  The given key or index was not found.
123      */
124     Error Delete(uint16_t aKey, int aIndex);
125 
126     /**
127      * Removes all values.
128      */
129     void Wipe(void);
130 
131 private:
132     static constexpr uint32_t kSwapMarkerSize = 4; // in bytes
133 
134     static const uint32_t sSwapActive   = 0xbe5cc5ee;
135     static const uint32_t sSwapInactive = 0xbe5cc5ec;
136 
137     OT_TOOL_PACKED_BEGIN
138     class RecordHeader
139     {
140     public:
Init(uint16_t aKey,bool aFirst)141         void Init(uint16_t aKey, bool aFirst)
142         {
143             mKey   = aKey;
144             mFlags = kFlagsInit & ~kFlagAddBegin;
145 
146             if (aFirst)
147             {
148                 mFlags &= ~kFlagFirst;
149             }
150 
151             mLength   = 0;
152             mReserved = 0xffff;
153         }
154 
GetKey(void) const155         uint16_t GetKey(void) const { return mKey; }
SetKey(uint16_t aKey)156         void     SetKey(uint16_t aKey) { mKey = aKey; }
157 
GetLength(void) const158         uint16_t GetLength(void) const { return mLength; }
SetLength(uint16_t aLength)159         void     SetLength(uint16_t aLength) { mLength = aLength; }
160 
GetSize(void) const161         uint16_t GetSize(void) const { return sizeof(*this) + ((mLength + 3) & 0xfffc); }
162 
IsValid(void) const163         bool IsValid(void) const { return ((mFlags & (kFlagAddComplete | kFlagDelete)) == kFlagDelete); }
164 
IsAddBeginSet(void) const165         bool IsAddBeginSet(void) const { return (mFlags & kFlagAddBegin) == 0; }
SetAddBeginFlag(void)166         void SetAddBeginFlag(void) { mFlags &= ~kFlagAddBegin; }
167 
IsAddCompleteSet(void) const168         bool IsAddCompleteSet(void) const { return (mFlags & kFlagAddComplete) == 0; }
SetAddCompleteFlag(void)169         void SetAddCompleteFlag(void) { mFlags &= ~kFlagAddComplete; }
170 
IsDeleted(void) const171         bool IsDeleted(void) const { return (mFlags & kFlagDelete) == 0; }
SetDeleted(void)172         void SetDeleted(void) { mFlags &= ~kFlagDelete; }
173 
IsFirst(void) const174         bool IsFirst(void) const { return (mFlags & kFlagFirst) == 0; }
SetFirst(void)175         void SetFirst(void) { mFlags &= ~kFlagFirst; }
176 
177     private:
178         static constexpr uint16_t kFlagsInit       = 0xffff; // Flags initialize to all-ones.
179         static constexpr uint16_t kFlagAddBegin    = 1 << 0; // 0 indicates record write has started, 1 otherwise.
180         static constexpr uint16_t kFlagAddComplete = 1 << 1; // 0 indicates record write has completed, 1 otherwise.
181         static constexpr uint16_t kFlagDelete      = 1 << 2; // 0 indicates record was deleted, 1 otherwise.
182         static constexpr uint16_t kFlagFirst       = 1 << 3; // 0 indicates first record for key, 1 otherwise.
183 
184         uint16_t mKey;
185         uint16_t mFlags;
186         uint16_t mLength;
187         uint16_t mReserved;
188     } OT_TOOL_PACKED_END;
189 
190     OT_TOOL_PACKED_BEGIN
191     class Record : public RecordHeader
192     {
193     public:
GetData(void) const194         const uint8_t *GetData(void) const { return mData; }
SetData(const uint8_t * aData,uint16_t aDataLength)195         void           SetData(const uint8_t *aData, uint16_t aDataLength)
196         {
197             OT_ASSERT(aDataLength <= kMaxDataSize);
198             memcpy(mData, aData, aDataLength);
199             SetLength(aDataLength);
200         }
201 
202     private:
203 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE
204         static constexpr uint16_t kMaxDataSize = 1024;
205 #else
206         static constexpr uint16_t kMaxDataSize = 256;
207 #endif
208 
209         uint8_t mData[kMaxDataSize];
210     } OT_TOOL_PACKED_END;
211 
212     Error Add(uint16_t aKey, bool aFirst, const uint8_t *aValue, uint16_t aValueLength);
213     bool  DoesValidRecordExist(uint32_t aOffset, uint16_t aKey) const;
214     void  SanitizeFreeSpace(void);
215     void  Swap(void);
216 
217     uint32_t mSwapSize;
218     uint32_t mSwapUsed;
219     uint8_t  mSwapIndex;
220 };
221 
222 } // namespace ot
223 
224 #endif // OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE
225 
226 #endif // FLASH_HPP_
227