/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "fake_storage.h" #include #include #define countof(a) (sizeof(a) / sizeof((a)[0])) namespace nvram { namespace storage { namespace { class StorageSlot { public: Status Load(Blob* blob) { if (read_error_) { return Status::kStorageError; } if (!present_) { return Status::kNotFound; } NVRAM_CHECK(blob->Assign(blob_.data(), blob_.size())); return Status::kSuccess; } Status Store(const Blob& blob) { if (write_error_) { return Status::kStorageError; } NVRAM_CHECK(blob_.Assign(blob.data(), blob.size())); present_ = true; return Status::kSuccess; } Status Delete() { if (write_error_) { return Status::kStorageError; } NVRAM_CHECK(blob_.Resize(0)); present_ = false; return Status::kSuccess; } void Clear() { present_ = false; read_error_ = false; write_error_ = false; NVRAM_CHECK(blob_.Resize(0)); } bool present() const { return present_; } void set_present(bool present) { present_ = present; } void set_read_error(bool error) { read_error_ = error; } void set_write_error(bool error) { write_error_ = error; } private: bool present_ = false; bool read_error_ = false; bool write_error_ = false; Blob blob_; }; // Header storage. StorageSlot g_header; // Space blob storage. struct SpaceStorageSlot { uint32_t index; StorageSlot slot; }; SpaceStorageSlot g_spaces[256]; // Find the position in |g_spaces| corresponding to a given space |index|. // Returns the slot pointer or |nullptr| if not found. StorageSlot* FindSlotForIndex(uint32_t index) { for (size_t i = 0; i < countof(g_spaces); ++i) { if (g_spaces[i].slot.present() && g_spaces[i].index == index) { return &g_spaces[i].slot; } } return nullptr; } // Finds or creates the slot for |index|. Returns the slot pointer or |nullptr| // if not found. StorageSlot* FindOrCreateSlotForIndex(uint32_t index) { StorageSlot* slot = FindSlotForIndex(index); if (slot) { return slot; } for (size_t i = 0; i < countof(g_spaces); ++i) { if (!g_spaces[i].slot.present()) { g_spaces[i].index = index; return &g_spaces[i].slot; } } return nullptr; } } // namespace Status LoadHeader(Blob* blob) { return g_header.Load(blob); } Status StoreHeader(const Blob& blob) { return g_header.Store(blob); } void SetHeaderReadError(bool error) { g_header.set_read_error(error); } void SetHeaderWriteError(bool error) { g_header.set_write_error(error); } Status LoadSpace(uint32_t index, Blob* blob) { StorageSlot* slot = FindSlotForIndex(index); return slot ? slot->Load(blob) : Status::kNotFound; } Status StoreSpace(uint32_t index, const Blob& blob) { StorageSlot* slot = FindOrCreateSlotForIndex(index); return slot ? slot->Store(blob) : Status::kStorageError; } Status DeleteSpace(uint32_t index) { StorageSlot* slot = FindSlotForIndex(index); return slot ? slot->Delete() : Status::kNotFound; } void Clear() { g_header.Clear(); for (size_t i = 0; i < countof(g_spaces); ++i) { g_spaces[i].slot.Clear(); } } void SetSpaceReadError(uint32_t index, bool error) { StorageSlot* slot = FindOrCreateSlotForIndex(index); if (slot) { slot->set_read_error(error); } } void SetSpaceWriteError(uint32_t index, bool error) { StorageSlot* slot = FindOrCreateSlotForIndex(index); if (slot) { slot->set_write_error(error); } } } // namespace storage } // namespace nvram