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:
Load(Blob * blob)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
Store(const Blob & blob)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
Delete()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
Clear()64 void Clear() {
65 present_ = false;
66 read_error_ = false;
67 write_error_ = false;
68 NVRAM_CHECK(blob_.Resize(0));
69 }
70
present() const71 bool present() const { return present_; }
set_present(bool present)72 void set_present(bool present) { present_ = present; }
set_read_error(bool error)73 void set_read_error(bool error) { read_error_ = error; }
set_write_error(bool 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.
FindSlotForIndex(uint32_t index)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.
FindOrCreateSlotForIndex(uint32_t index)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
LoadHeader(Blob * blob)127 Status LoadHeader(Blob* blob) {
128 return g_header.Load(blob);
129 }
130
StoreHeader(const Blob & blob)131 Status StoreHeader(const Blob& blob) {
132 return g_header.Store(blob);
133 }
134
SetHeaderReadError(bool error)135 void SetHeaderReadError(bool error) {
136 g_header.set_read_error(error);
137 }
138
SetHeaderWriteError(bool error)139 void SetHeaderWriteError(bool error) {
140 g_header.set_write_error(error);
141 }
142
LoadSpace(uint32_t index,Blob * blob)143 Status LoadSpace(uint32_t index, Blob* blob) {
144 StorageSlot* slot = FindSlotForIndex(index);
145 return slot ? slot->Load(blob) : Status::kNotFound;
146 }
147
StoreSpace(uint32_t index,const Blob & blob)148 Status StoreSpace(uint32_t index, const Blob& blob) {
149 StorageSlot* slot = FindOrCreateSlotForIndex(index);
150 return slot ? slot->Store(blob) : Status::kStorageError;
151 }
152
DeleteSpace(uint32_t index)153 Status DeleteSpace(uint32_t index) {
154 StorageSlot* slot = FindSlotForIndex(index);
155 return slot ? slot->Delete() : Status::kNotFound;
156 }
157
Clear()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
SetSpaceReadError(uint32_t index,bool error)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
SetSpaceWriteError(uint32_t index,bool error)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