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