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