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:
present() const28 bool present() const { return blob_.size() != 0; }
29
Load(Blob * blob) const30 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
Store(const Blob & blob)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
Delete()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.
FindSpaceSlot(uint32_t index)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
LoadHeader(Blob * blob)81 Status LoadHeader(Blob* blob) {
82 return g_header.Load(blob);
83 }
84
StoreHeader(const Blob & blob)85 Status StoreHeader(const Blob& blob) {
86 return g_header.Store(blob);
87 }
88
LoadSpace(uint32_t index,Blob * blob)89 Status LoadSpace(uint32_t index, Blob* blob) {
90 StorageSlot* slot = FindSpaceSlot(index);
91 return slot ? slot->Load(blob) : Status::kNotFound;
92 }
93
StoreSpace(uint32_t index,const Blob & blob)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
DeleteSpace(uint32_t index)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