18748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler/*
28748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * Copyright (C) 2016 The Android Open Source Project
38748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler *
48748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * Licensed under the Apache License, Version 2.0 (the "License");
58748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * you may not use this file except in compliance with the License.
68748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * You may obtain a copy of the License at
78748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler *
88748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler *      http://www.apache.org/licenses/LICENSE-2.0
98748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler *
108748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * Unless required by applicable law or agreed to in writing, software
118748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * distributed under the License is distributed on an "AS IS" BASIS,
128748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * See the License for the specific language governing permissions and
148748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler * limitations under the License.
158748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler */
168748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
178748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#ifndef NVRAM_CORE_PERSISTENCE_H_
188748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#define NVRAM_CORE_PERSISTENCE_H_
198748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
208748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerextern "C" {
218748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#include <stdint.h>
228748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler}  // extern "C"
238748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
248748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#include <nvram/messages/optional.h>
258748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#include <nvram/messages/struct.h>
268748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#include <nvram/messages/vector.h>
278748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
288748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#include <nvram/core/storage.h>
298748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
308748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslernamespace nvram {
318748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
328748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// The NVRAM header data structure, which holds global information used by the
338748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// NVRAM service, such as version and a list of defined spaces.
348748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstruct NvramHeader {
358748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // State flags affecting all spaces.
368748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  enum Flags {
378748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler    kFlagDisableCreate = 1 << 0,
388748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  };
398748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
408748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // Check whether a flag is present.
418748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  bool HasFlag(Flags flag) const {
428748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler    return (flags & flag) != 0;
438748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  }
448748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
458748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // Set a flag.
468748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  void SetFlag(Flags flag) {
478748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler    flags |= flag;
488748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  }
498748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
508748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // The current major header version. Bump this upon making
518748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // forward-incompatible changes to the storage format. Old versions will
528748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // reject the header on load and refuse to operate when they encounter a
538748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // version that is larger than the compile-time one.
548748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  static constexpr uint32_t kVersion = 1;
558748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
568748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // The header version, indicating the data format revision used when the
578748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // header was last written. On load, if the version is more recent then what
588748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // the code can handle, we bail out. This allows making forward-incompatible
598748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // changes to the data format with the guarantee that old code versions won't
608748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // clobber new data. This is a last resort kill switch for old code, in
618748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // general we should aim for maximum compatibility between versions.
628748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  uint32_t version = kVersion;
638748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
648748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // Current header flags. Bitwise OR of |NvramHeader::Flags| values.
658748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  uint32_t flags = 0;
668748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
678748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // A list of allocated indices, in no particular order.
688748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  Vector<uint32_t> allocated_indices;
698748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
708748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // An index that is in the process of being created or deleted. This field is
718748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // used as follows:
728748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //  * On space creation, we add the new space's index both to
738748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    |allocated_indices| and set it as the |provisional_index|. Then, the
748748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    header is written, followed by the space data. If we crash in between,
758748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    the next load will find |provisional_index| present and will check
768748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    whether that space is present on disk or not. If not, it'll clear the
778748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    index from |allocated_indices| and reset |provisional_index|, hence the
788748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    space is as good as never created.
798748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //  * On space deletion, the deleted space's index is removed from
808748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    |allocated_indices|, but stored in |provisional_index|. The, the header
818748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    gets written, followed by the space deletion. If we crash in between ,
828748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    the next load will find the provisional index set, but the space is
838748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    absent in |allocated_indices|. If this is the case, the initialization
848748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    code will make sure to delete the space data if it's still around and
858748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  //    clear |provisional_index| afterwards.
868748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  Optional<uint32_t> provisional_index;
878748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler};
888748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
898748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// All data corresponding to a single NVRAM space is held in an NvramSpace
908748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// structure. There is one structure per allocated index.
918748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstruct NvramSpace {
928748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // Flags indicating internal status in effect for a space.
938748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  enum Flags {
948748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler    kFlagWriteLocked = 1 << 0,
958748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  };
968748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
978748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // Check whether a given flag is set.
988748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  bool HasFlag(Flags flag) const {
998748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler    return (flags & flag) != 0;
1008748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  }
1018748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1028748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // Set a flag.
1038748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  void SetFlag(Flags flag) {
1048748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler    flags |= flag;
1058748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  }
1068748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1078748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // A helper to simplify checking control flags.
1088748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  bool HasControl(uint32_t control) const {
1098748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler    return (controls & (1 << control)) != 0;
1108748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  }
1118748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1128748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // Persistent space flags. Bitwise OR of |NvramSpace::Flags| values.
1138748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  uint32_t flags = 0;
1148748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1158748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // A bitmask of CONTROL_XYZ values in effect for the space. These are set at
1168748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // space creation time and generally not touched afterwards.
1178748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  uint32_t controls = 0;
1188748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1198748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // The authorization value for the space. This is a shared secret that must be
1208748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // provided to read and write the space as specified by the appropriate
1218748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // |controls| flags.
1228748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  Blob authorization_value;
1238748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1248748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  // The space payload data.
1258748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler  Blob contents;
1268748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler};
1278748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1288748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslernamespace persistence {
1298748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1308748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Load NVRAM header from storage.
1318748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status LoadHeader(NvramHeader* header);
1328748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1338748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Write the NVRAM header to storage.
1348748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status StoreHeader(const NvramHeader& header);
1358748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1368748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Load NVRAM space data for a given index from storage.
1378748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status LoadSpace(uint32_t index, NvramSpace* space);
1388748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1398748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Write the NVRAM space data for the given index to storage.
1408748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status StoreSpace(uint32_t index, const NvramSpace& space);
1418748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1428748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler// Delete the stored NVRAM space data for the given index.
1438748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nisslerstorage::Status DeleteSpace(uint32_t index);
1448748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1458748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler}  // namespace persistence
1468748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1478748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler}  // namespace nvram
1488748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler
1498748d72a31f800e83bcf48cf7ecf828ef9601fa9Mattias Nissler#endif  // NVRAM_CORE_PERSISTENCE_H_
150