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