1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "fake_storage.h" 18 19 #include <nvram/messages/blob.h> 20 #include <nvram/messages/compiler.h> 21 22 #define countof(a) (sizeof(a) / sizeof((a)[0])) 23 24 namespace nvram { 25 namespace storage { 26 27 namespace { 28 29 class StorageSlot { 30 public: 31 Status Load(Blob* blob) { 32 if (read_error_) { 33 return Status::kStorageError; 34 } 35 36 if (!present_) { 37 return Status::kNotFound; 38 } 39 40 NVRAM_CHECK(blob->Assign(blob_.data(), blob_.size())); 41 return Status::kSuccess; 42 } 43 44 Status Store(const Blob& blob) { 45 if (write_error_) { 46 return Status::kStorageError; 47 } 48 49 NVRAM_CHECK(blob_.Assign(blob.data(), blob.size())); 50 present_ = true; 51 return Status::kSuccess; 52 } 53 54 Status Delete() { 55 if (write_error_) { 56 return Status::kStorageError; 57 } 58 59 NVRAM_CHECK(blob_.Resize(0)); 60 present_ = false; 61 return Status::kSuccess; 62 } 63 64 void Clear() { 65 present_ = false; 66 read_error_ = false; 67 write_error_ = false; 68 NVRAM_CHECK(blob_.Resize(0)); 69 } 70 71 bool present() const { return present_; } 72 void set_present(bool present) { present_ = present; } 73 void set_read_error(bool error) { read_error_ = error; } 74 void set_write_error(bool error) { write_error_ = error; } 75 76 private: 77 bool present_ = false; 78 bool read_error_ = false; 79 bool write_error_ = false; 80 Blob blob_; 81 }; 82 83 // Header storage. 84 StorageSlot g_header; 85 86 // Space blob storage. 87 struct SpaceStorageSlot { 88 uint32_t index; 89 StorageSlot slot; 90 }; 91 92 SpaceStorageSlot g_spaces[256]; 93 94 // Find the position in |g_spaces| corresponding to a given space |index|. 95 // Returns the slot pointer or |nullptr| if not found. 96 StorageSlot* FindSlotForIndex(uint32_t index) { 97 for (size_t i = 0; i < countof(g_spaces); ++i) { 98 if (g_spaces[i].slot.present() && g_spaces[i].index == index) { 99 return &g_spaces[i].slot; 100 } 101 } 102 103 return nullptr; 104 } 105 106 // Finds or creates the slot for |index|. Returns the slot pointer or |nullptr| 107 // if not found. 108 StorageSlot* FindOrCreateSlotForIndex(uint32_t index) { 109 StorageSlot* slot = FindSlotForIndex(index); 110 if (slot) { 111 return slot; 112 } 113 114 115 for (size_t i = 0; i < countof(g_spaces); ++i) { 116 if (!g_spaces[i].slot.present()) { 117 g_spaces[i].index = index; 118 return &g_spaces[i].slot; 119 } 120 } 121 122 return nullptr; 123 } 124 125 } // namespace 126 127 Status LoadHeader(Blob* blob) { 128 return g_header.Load(blob); 129 } 130 131 Status StoreHeader(const Blob& blob) { 132 return g_header.Store(blob); 133 } 134 135 void SetHeaderReadError(bool error) { 136 g_header.set_read_error(error); 137 } 138 139 void SetHeaderWriteError(bool error) { 140 g_header.set_write_error(error); 141 } 142 143 Status LoadSpace(uint32_t index, Blob* blob) { 144 StorageSlot* slot = FindSlotForIndex(index); 145 return slot ? slot->Load(blob) : Status::kNotFound; 146 } 147 148 Status StoreSpace(uint32_t index, const Blob& blob) { 149 StorageSlot* slot = FindOrCreateSlotForIndex(index); 150 return slot ? slot->Store(blob) : Status::kStorageError; 151 } 152 153 Status DeleteSpace(uint32_t index) { 154 StorageSlot* slot = FindSlotForIndex(index); 155 return slot ? slot->Delete() : Status::kNotFound; 156 } 157 158 void Clear() { 159 g_header.Clear(); 160 for (size_t i = 0; i < countof(g_spaces); ++i) { 161 g_spaces[i].slot.Clear(); 162 } 163 } 164 165 void SetSpaceReadError(uint32_t index, bool error) { 166 StorageSlot* slot = FindOrCreateSlotForIndex(index); 167 if (slot) { 168 slot->set_read_error(error); 169 } 170 } 171 172 void SetSpaceWriteError(uint32_t index, bool error) { 173 StorageSlot* slot = FindOrCreateSlotForIndex(index); 174 if (slot) { 175 slot->set_write_error(error); 176 } 177 } 178 179 } // namespace storage 180 } // namespace nvram 181