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 19 namespace nvram { 20 namespace storage { 21 namespace { 22 23 // Maximum number of space blobs supported. 24 const int kMaxSpaces = 32; 25 26 class 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. 59 StorageSlot g_header; 60 61 // Stores the space blobs. 62 struct { 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. 69 StorageSlot* 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 81 Status LoadHeader(Blob* blob) { 82 return g_header.Load(blob); 83 } 84 85 Status StoreHeader(const Blob& blob) { 86 return g_header.Store(blob); 87 } 88 89 Status LoadSpace(uint32_t index, Blob* blob) { 90 StorageSlot* slot = FindSpaceSlot(index); 91 return slot ? slot->Load(blob) : Status::kNotFound; 92 } 93 94 Status 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 111 Status 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