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
24namespace nvram {
25namespace storage {
26
27namespace {
28
29class StorageSlot {
30 public:
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
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
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
64  void Clear() {
65    present_ = false;
66    read_error_ = false;
67    write_error_ = false;
68    NVRAM_CHECK(blob_.Resize(0));
69  }
70
71  bool present() const { return present_; }
72  void set_present(bool present) { present_ = present; }
73  void set_read_error(bool error) { read_error_ = 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.
84StorageSlot g_header;
85
86// Space blob storage.
87struct SpaceStorageSlot {
88  uint32_t index;
89  StorageSlot slot;
90};
91
92SpaceStorageSlot 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.
96StorageSlot* 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.
108StorageSlot* 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
127Status LoadHeader(Blob* blob) {
128  return g_header.Load(blob);
129}
130
131Status StoreHeader(const Blob& blob) {
132  return g_header.Store(blob);
133}
134
135void SetHeaderReadError(bool error) {
136  g_header.set_read_error(error);
137}
138
139void SetHeaderWriteError(bool error) {
140  g_header.set_write_error(error);
141}
142
143Status LoadSpace(uint32_t index, Blob* blob) {
144  StorageSlot* slot = FindSlotForIndex(index);
145  return slot ? slot->Load(blob) : Status::kNotFound;
146}
147
148Status StoreSpace(uint32_t index, const Blob& blob) {
149  StorageSlot* slot = FindOrCreateSlotForIndex(index);
150  return slot ? slot->Store(blob) : Status::kStorageError;
151}
152
153Status DeleteSpace(uint32_t index) {
154  StorageSlot* slot = FindSlotForIndex(index);
155  return slot ? slot->Delete() : Status::kNotFound;
156}
157
158void 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
165void SetSpaceReadError(uint32_t index, bool error) {
166  StorageSlot* slot = FindOrCreateSlotForIndex(index);
167  if (slot) {
168    slot->set_read_error(error);
169  }
170}
171
172void 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