Home | History | Annotate | Download | only in hal
      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