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 #ifndef NVRAM_CORE_PERSISTENCE_H_ 18 #define NVRAM_CORE_PERSISTENCE_H_ 19 20 extern "C" { 21 #include <stdint.h> 22 } // extern "C" 23 24 #include <nvram/messages/optional.h> 25 #include <nvram/messages/struct.h> 26 #include <nvram/messages/vector.h> 27 28 #include <nvram/core/storage.h> 29 30 namespace nvram { 31 32 // The NVRAM header data structure, which holds global information used by the 33 // NVRAM service, such as version and a list of defined spaces. 34 struct NvramHeader { 35 // State flags affecting all spaces. 36 enum Flags { 37 kFlagDisableCreate = 1 << 0, 38 }; 39 40 // Check whether a flag is present. HasFlagNvramHeader41 bool HasFlag(Flags flag) const { 42 return (flags & flag) != 0; 43 } 44 45 // Set a flag. SetFlagNvramHeader46 void SetFlag(Flags flag) { 47 flags |= flag; 48 } 49 50 // The current major header version. Bump this upon making 51 // forward-incompatible changes to the storage format. Old versions will 52 // reject the header on load and refuse to operate when they encounter a 53 // version that is larger than the compile-time one. 54 static constexpr uint32_t kVersion = 1; 55 56 // The header version, indicating the data format revision used when the 57 // header was last written. On load, if the version is more recent then what 58 // the code can handle, we bail out. This allows making forward-incompatible 59 // changes to the data format with the guarantee that old code versions won't 60 // clobber new data. This is a last resort kill switch for old code, in 61 // general we should aim for maximum compatibility between versions. 62 uint32_t version = kVersion; 63 64 // Current header flags. Bitwise OR of |NvramHeader::Flags| values. 65 uint32_t flags = 0; 66 67 // A list of allocated indices, in no particular order. 68 Vector<uint32_t> allocated_indices; 69 70 // An index that is in the process of being created or deleted. This field is 71 // used as follows: 72 // * On space creation, we add the new space's index both to 73 // |allocated_indices| and set it as the |provisional_index|. Then, the 74 // header is written, followed by the space data. If we crash in between, 75 // the next load will find |provisional_index| present and will check 76 // whether that space is present on disk or not. If not, it'll clear the 77 // index from |allocated_indices| and reset |provisional_index|, hence the 78 // space is as good as never created. 79 // * On space deletion, the deleted space's index is removed from 80 // |allocated_indices|, but stored in |provisional_index|. The, the header 81 // gets written, followed by the space deletion. If we crash in between , 82 // the next load will find the provisional index set, but the space is 83 // absent in |allocated_indices|. If this is the case, the initialization 84 // code will make sure to delete the space data if it's still around and 85 // clear |provisional_index| afterwards. 86 Optional<uint32_t> provisional_index; 87 }; 88 89 // All data corresponding to a single NVRAM space is held in an NvramSpace 90 // structure. There is one structure per allocated index. 91 struct NvramSpace { 92 // Flags indicating internal status in effect for a space. 93 enum Flags { 94 kFlagWriteLocked = 1 << 0, 95 }; 96 97 // Check whether a given flag is set. HasFlagNvramSpace98 bool HasFlag(Flags flag) const { 99 return (flags & flag) != 0; 100 } 101 102 // Set a flag. SetFlagNvramSpace103 void SetFlag(Flags flag) { 104 flags |= flag; 105 } 106 107 // A helper to simplify checking control flags. HasControlNvramSpace108 bool HasControl(uint32_t control) const { 109 return (controls & (1 << control)) != 0; 110 } 111 112 // Persistent space flags. Bitwise OR of |NvramSpace::Flags| values. 113 uint32_t flags = 0; 114 115 // A bitmask of CONTROL_XYZ values in effect for the space. These are set at 116 // space creation time and generally not touched afterwards. 117 uint32_t controls = 0; 118 119 // The authorization value for the space. This is a shared secret that must be 120 // provided to read and write the space as specified by the appropriate 121 // |controls| flags. 122 Blob authorization_value; 123 124 // The space payload data. 125 Blob contents; 126 }; 127 128 namespace persistence { 129 130 // Load NVRAM header from storage. 131 storage::Status LoadHeader(NvramHeader* header); 132 133 // Write the NVRAM header to storage. 134 storage::Status StoreHeader(const NvramHeader& header); 135 136 // Load NVRAM space data for a given index from storage. 137 storage::Status LoadSpace(uint32_t index, NvramSpace* space); 138 139 // Write the NVRAM space data for the given index to storage. 140 storage::Status StoreSpace(uint32_t index, const NvramSpace& space); 141 142 // Delete the stored NVRAM space data for the given index. 143 storage::Status DeleteSpace(uint32_t index); 144 145 } // namespace persistence 146 147 } // namespace nvram 148 149 #endif // NVRAM_CORE_PERSISTENCE_H_ 150