blob: 90c1be35b056eabdbfff951ff4b31c9b1c82cfb0 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NVRAM_CORE_PERSISTENCE_H_
#define NVRAM_CORE_PERSISTENCE_H_
extern "C" {
#include <stdint.h>
} // extern "C"
#include <nvram/messages/optional.h>
#include <nvram/messages/struct.h>
#include <nvram/messages/vector.h>
#include <nvram/core/storage.h>
namespace nvram {
// The NVRAM header data structure, which holds global information used by the
// NVRAM service, such as version and a list of defined spaces.
struct NvramHeader {
// State flags affecting all spaces.
enum Flags {
kFlagDisableCreate = 1 << 0,
};
// Check whether a flag is present.
bool HasFlag(Flags flag) const {
return (flags & flag) != 0;
}
// Set a flag.
void SetFlag(Flags flag) {
flags |= flag;
}
// The current major header version. Bump this upon making
// forward-incompatible changes to the storage format. Old versions will
// reject the header on load and refuse to operate when they encounter a
// version that is larger than the compile-time one.
static constexpr uint32_t kVersion = 1;
// The header version, indicating the data format revision used when the
// header was last written. On load, if the version is more recent then what
// the code can handle, we bail out. This allows making forward-incompatible
// changes to the data format with the guarantee that old code versions won't
// clobber new data. This is a last resort kill switch for old code, in
// general we should aim for maximum compatibility between versions.
uint32_t version = kVersion;
// Current header flags. Bitwise OR of |NvramHeader::Flags| values.
uint32_t flags = 0;
// A list of allocated indices, in no particular order.
Vector<uint32_t> allocated_indices;
// An index that is in the process of being created or deleted. This field is
// used as follows:
// * On space creation, we add the new space's index both to
// |allocated_indices| and set it as the |provisional_index|. Then, the
// header is written, followed by the space data. If we crash in between,
// the next load will find |provisional_index| present and will check
// whether that space is present on disk or not. If not, it'll clear the
// index from |allocated_indices| and reset |provisional_index|, hence the
// space is as good as never created.
// * On space deletion, the deleted space's index is removed from
// |allocated_indices|, but stored in |provisional_index|. The, the header
// gets written, followed by the space deletion. If we crash in between ,
// the next load will find the provisional index set, but the space is
// absent in |allocated_indices|. If this is the case, the initialization
// code will make sure to delete the space data if it's still around and
// clear |provisional_index| afterwards.
Optional<uint32_t> provisional_index;
};
// All data corresponding to a single NVRAM space is held in an NvramSpace
// structure. There is one structure per allocated index.
struct NvramSpace {
// Flags indicating internal status in effect for a space.
enum Flags {
kFlagWriteLocked = 1 << 0,
};
// Check whether a given flag is set.
bool HasFlag(Flags flag) const {
return (flags & flag) != 0;
}
// Set a flag.
void SetFlag(Flags flag) {
flags |= flag;
}
// A helper to simplify checking control flags.
bool HasControl(uint32_t control) const {
return (controls & (1 << control)) != 0;
}
// Persistent space flags. Bitwise OR of |NvramSpace::Flags| values.
uint32_t flags = 0;
// A bitmask of CONTROL_XYZ values in effect for the space. These are set at
// space creation time and generally not touched afterwards.
uint32_t controls = 0;
// The authorization value for the space. This is a shared secret that must be
// provided to read and write the space as specified by the appropriate
// |controls| flags.
Blob authorization_value;
// The space payload data.
Blob contents;
};
namespace persistence {
// Load NVRAM header from storage.
storage::Status LoadHeader(NvramHeader* header);
// Write the NVRAM header to storage.
storage::Status StoreHeader(const NvramHeader& header);
// Load NVRAM space data for a given index from storage.
storage::Status LoadSpace(uint32_t index, NvramSpace* space);
// Write the NVRAM space data for the given index to storage.
storage::Status StoreSpace(uint32_t index, const NvramSpace& space);
// Delete the stored NVRAM space data for the given index.
storage::Status DeleteSpace(uint32_t index);
} // namespace persistence
} // namespace nvram
#endif // NVRAM_CORE_PERSISTENCE_H_