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 <nvram/core/storage.h> 18 19namespace nvram { 20namespace storage { 21namespace { 22 23// Maximum number of space blobs supported. 24const int kMaxSpaces = 32; 25 26class StorageSlot { 27 public: 28 bool present() const { return blob_.size() != 0; } 29 30 Status Load(Blob* blob) const { 31 if (blob_.size() == 0) { 32 return Status::kNotFound; 33 } 34 35 if (!blob->Assign(blob_.data(), blob_.size())) { 36 return Status::kStorageError; 37 } 38 39 return Status::kSuccess; 40 } 41 42 Status Store(const Blob& blob) { 43 if (!blob_.Assign(blob.data(), blob.size())) { 44 return Status::kStorageError; 45 } 46 47 return Status::kSuccess; 48 } 49 50 Status Delete() { 51 return blob_.Resize(0) ? Status::kSuccess : Status::kStorageError; 52 } 53 54 private: 55 Blob blob_; 56}; 57 58// Stores the header blob. 59StorageSlot g_header; 60 61// Stores the space blobs. 62struct { 63 uint32_t index; 64 StorageSlot slot; 65} g_spaces[kMaxSpaces]; 66 67// Find the storage slot in |g_spaces| that corresponds to |index|. Returns 68// |nullptr| if no matching slot exists. 69StorageSlot* FindSpaceSlot(uint32_t index) { 70 for (size_t i = 0; i < kMaxSpaces; ++i) { 71 if (g_spaces[i].slot.present() && g_spaces[i].index == index) { 72 return &g_spaces[i].slot; 73 } 74 } 75 76 return nullptr; 77} 78 79} // namespace 80 81Status LoadHeader(Blob* blob) { 82 return g_header.Load(blob); 83} 84 85Status StoreHeader(const Blob& blob) { 86 return g_header.Store(blob); 87} 88 89Status LoadSpace(uint32_t index, Blob* blob) { 90 StorageSlot* slot = FindSpaceSlot(index); 91 return slot ? slot->Load(blob) : Status::kNotFound; 92} 93 94Status StoreSpace(uint32_t index, const Blob& blob) { 95 StorageSlot* slot = FindSpaceSlot(index); 96 if (slot) { 97 return slot->Store(blob); 98 } 99 100 // Allocate a new slot. 101 for (size_t i = 0; i < kMaxSpaces; ++i) { 102 if (!g_spaces[i].slot.present()) { 103 g_spaces[i].index = index; 104 return g_spaces[i].slot.Store(blob); 105 } 106 } 107 108 return Status::kStorageError; 109} 110 111Status DeleteSpace(uint32_t index) { 112 StorageSlot* slot = FindSpaceSlot(index); 113 if (slot) { 114 slot->Delete(); 115 } 116 117 return Status::kSuccess; 118} 119 120} // namespace storage 121} // namespace nvram 122