1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #pragma once
16
17 #include <stdint.h>
18
19 #include <limits>
20 #include <optional>
21 #include <string_view>
22 #include <type_traits>
23
24 namespace android {
25 namespace snapshot {
26
27 struct CowOperationV3;
28 typedef CowOperationV3 CowOperation;
29
30 static constexpr uint64_t kCowMagicNumber = 0x436f77634f572121ULL;
31 static constexpr uint32_t kCowVersionMajor = 2;
32 static constexpr uint32_t kCowVersionMinor = 0;
33
34 static constexpr uint32_t kMinCowVersion = 1;
35 static constexpr uint32_t kMaxCowVersion = 3;
36
37 // This header appears as the first sequence of bytes in the COW. All fields
38 // in the layout are little-endian encoded. The on-disk layout is:
39 //
40 // +-----------------------+
41 // | Header (fixed) |
42 // +-----------------------+
43 // | Scratch space |
44 // +-----------------------+
45 // | Operation (variable) |
46 // | Data (variable) |
47 // +-----------------------+
48 // | Footer (fixed) |
49 // +-----------------------+
50 //
51 // After the header is a 2mb scratch space that is used to read ahead data during merge operations
52 //
53 // The operations begin immediately after the scratch space, and the "raw data"
54 // immediately follows the operation which refers to it. While streaming
55 // an OTA, we can immediately write the op and data, syncing after each pair,
56 // while storing operation metadata in memory. At the end, we compute data and
57 // hashes for the footer, which is placed at the tail end of the file.
58 //
59 // A missing or corrupt footer likely indicates that writing was cut off
60 // between writing the last operation/data pair, or the footer itself. In this
61 // case, the safest way to proceed is to assume the last operation is faulty.
62
63 struct CowHeaderPrefix {
64 uint64_t magic;
65 uint16_t major_version;
66 uint16_t minor_version;
67 uint16_t header_size; // size of CowHeader.
68 } __attribute__((packed));
69
70 struct CowHeader {
71 CowHeaderPrefix prefix;
72
73 // Size of footer struct
74 uint16_t footer_size;
75
76 // Size of op struct
77 uint16_t op_size;
78
79 // The size of block operations, in bytes.
80 uint32_t block_size;
81
82 // The number of ops to cluster together. 0 For no clustering. Cannot be 1.
83 uint32_t cluster_ops;
84
85 // Tracks merge operations completed
86 uint64_t num_merge_ops;
87
88 // Scratch space used during merge
89 uint32_t buffer_size;
90
91 } __attribute__((packed));
92
93 // Resume point structure used for resume buffer
94 struct ResumePoint {
95 // monotonically increasing value used by update_engine
96 uint64_t label;
97 // Index of last CowOperation guaranteed to be resumable
98 uint64_t op_index;
99 } __attribute__((packed));
100
101 static constexpr uint8_t kNumResumePoints = 4;
102
103 struct CowHeaderV3 : public CowHeader {
104 // Number of sequence data stored (each of which is a 32 bit integer)
105 uint64_t sequence_data_count;
106 // Number of currently written resume points &&
107 uint32_t resume_point_count;
108 // Number of max resume points that can be written
109 uint32_t resume_point_max;
110 // Number of CowOperationV3 structs in the operation buffer, currently and total
111 // region size.
112 uint64_t op_count;
113 uint64_t op_count_max;
114 // Compression Algorithm
115 uint32_t compression_algorithm;
116 // Max compression size supported
117 uint32_t max_compression_size;
118 } __attribute__((packed));
119
120 enum class CowOperationType : uint8_t {
121 kCowCopyOp = 1,
122 kCowReplaceOp = 2,
123 kCowZeroOp = 3,
124 kCowLabelOp = 4,
125 kCowClusterOp = 5,
126 kCowXorOp = 6,
127 kCowSequenceOp = 7,
128 kCowFooterOp = std::numeric_limits<uint8_t>::max(),
129 };
130
131 static constexpr CowOperationType kCowCopyOp = CowOperationType::kCowCopyOp;
132 static constexpr CowOperationType kCowReplaceOp = CowOperationType::kCowReplaceOp;
133 static constexpr CowOperationType kCowZeroOp = CowOperationType::kCowZeroOp;
134 static constexpr CowOperationType kCowLabelOp = CowOperationType::kCowLabelOp;
135 static constexpr CowOperationType kCowClusterOp = CowOperationType::kCowClusterOp;
136 static constexpr CowOperationType kCowXorOp = CowOperationType::kCowXorOp;
137 static constexpr CowOperationType kCowSequenceOp = CowOperationType::kCowSequenceOp;
138 static constexpr CowOperationType kCowFooterOp = CowOperationType::kCowFooterOp;
139
140 // This structure is the same size of a normal Operation, but is repurposed for the footer.
141 struct CowFooterOperation {
142 // The operation code (always kCowFooterOp).
143 CowOperationType type;
144
145 // If this operation reads from the data section of the COW, this contains
146 // the compression type of that data (see constants below).
147 uint8_t compression;
148
149 // Length of Footer Data. Currently 64.
150 uint16_t data_length;
151
152 // The amount of file space used by Cow operations
153 uint64_t ops_size;
154
155 // The number of cow operations in the file
156 uint64_t num_ops;
157 } __attribute__((packed));
158
159 // V2 version of COW. On disk format for older devices
160 struct CowOperationV2 {
161 // The operation code (see the constants and structures below).
162 CowOperationType type;
163
164 // If this operation reads from the data section of the COW, this contains
165 // the compression type of that data (see constants below).
166 uint8_t compression;
167
168 // If this operation reads from the data section of the COW, this contains
169 // the length.
170 uint16_t data_length;
171
172 // The block of data in the new image that this operation modifies.
173 uint64_t new_block;
174
175 // The value of |source| depends on the operation code.
176 //
177 // For copy operations, this is a block location in the source image.
178 //
179 // For replace operations, this is a byte offset within the COW's data
180 // sections (eg, not landing within the header or metadata). It is an
181 // absolute position within the image.
182 //
183 // For zero operations (replace with all zeroes), this is unused and must
184 // be zero.
185 //
186 // For Label operations, this is the value of the applied label.
187 //
188 // For Cluster operations, this is the length of the following data region
189 //
190 // For Xor operations, this is the byte location in the source image.
191 uint64_t source;
192 } __attribute__((packed));
193
194 static constexpr uint64_t kCowOpSourceInfoDataMask = (1ULL << 48) - 1;
195 static constexpr uint64_t kCowOpSourceInfoTypeBit = 60;
196 static constexpr uint64_t kCowOpSourceInfoTypeNumBits = 4;
197 static constexpr uint64_t kCowOpSourceInfoTypeMask = (1ULL << kCowOpSourceInfoTypeNumBits) - 1;
198
199 static constexpr uint64_t kCowOpSourceInfoCompressionBit = 57;
200 static constexpr uint64_t kCowOpSourceInfoCompressionNumBits = 3;
201 static constexpr uint64_t kCowOpSourceInfoCompressionMask =
202 ((1ULL << kCowOpSourceInfoCompressionNumBits) - 1);
203
204 // The on disk format of cow (currently == CowOperation)
205 struct CowOperationV3 {
206 // If this operation reads from the data section of the COW, this contains
207 // the length.
208 uint32_t data_length;
209
210 // The block of data in the new image that this operation modifies.
211 uint32_t new_block;
212
213 // source_info with have the following layout
214 // |--- 4 bits -- | --------- 3 bits ------ | --- 9 bits --- | --- 48 bits ---|
215 // |--- type --- | -- compression factor --| --- unused --- | --- source --- |
216 //
217 // The value of |source| depends on the operation code.
218 //
219 // CopyOp: a 32-bit block location in the source image.
220 // ReplaceOp: an absolute byte offset within the COW's data section.
221 // XorOp: an absolute byte offset in the source image.
222 // ZeroOp: unused
223 // LabelOp: a 64-bit opaque identifier.
224 //
225 // For ops other than Label:
226 // Bits 47-62 are reserved and must be zero.
227 // A block is compressed if it’s data is < block_sz
228 //
229 // Bits [57-59] represents the compression factor.
230 //
231 // Compression - factor
232 // ==========================
233 // 000 - 4k
234 // 001 - 8k
235 // 010 - 16k
236 // ...
237 // 110 - 256k
238 //
239 uint64_t source_info_;
sourceCowOperationV3240 constexpr uint64_t source() const { return source_info_ & kCowOpSourceInfoDataMask; }
set_sourceCowOperationV3241 constexpr void set_source(uint64_t source) {
242 // Clear the first 48 bit first
243 source_info_ &= ~kCowOpSourceInfoDataMask;
244 // Set the actual source field
245 source_info_ |= source & kCowOpSourceInfoDataMask;
246 }
typeCowOperationV3247 constexpr CowOperationType type() const {
248 // this is a mask to grab the first 4 bits of a 64 bit integer
249 const auto type = (source_info_ >> kCowOpSourceInfoTypeBit) & kCowOpSourceInfoTypeMask;
250 return static_cast<CowOperationType>(type);
251 }
set_typeCowOperationV3252 constexpr void set_type(CowOperationType type) {
253 // Clear the top 4 bits first
254 source_info_ &= ((1ULL << kCowOpSourceInfoTypeBit) - 1);
255 // set the actual type bits
256 source_info_ |= (static_cast<uint64_t>(type) & kCowOpSourceInfoTypeMask)
257 << kCowOpSourceInfoTypeBit;
258 }
set_compression_bitsCowOperationV3259 constexpr void set_compression_bits(uint8_t compression_factor) {
260 // Clear the 3 bits from bit 57 - [57-59]
261 source_info_ &= ~(kCowOpSourceInfoCompressionMask << kCowOpSourceInfoCompressionBit);
262 // Set the actual compression factor
263 source_info_ |=
264 (static_cast<uint64_t>(compression_factor) & kCowOpSourceInfoCompressionMask)
265 << kCowOpSourceInfoCompressionBit;
266 }
compression_bitsCowOperationV3267 constexpr uint8_t compression_bits() const {
268 // Grab the 3 bits from [57-59]
269 const auto compression_factor =
270 (source_info_ >> kCowOpSourceInfoCompressionBit) & kCowOpSourceInfoCompressionMask;
271 return static_cast<uint8_t>(compression_factor);
272 }
273 } __attribute__((packed));
274
275 // Ensure that getters/setters added to CowOperationV3 does not increases size
276 // of CowOperationV3 struct(no virtual method tables added).
277 static_assert(std::is_trivially_copyable_v<CowOperationV3>);
278 static_assert(std::is_standard_layout_v<CowOperationV3>);
279 static_assert(sizeof(CowOperationV2) == sizeof(CowFooterOperation));
280
281 enum CowCompressionAlgorithm : uint8_t {
282 kCowCompressNone = 0,
283 kCowCompressGz = 1,
284 kCowCompressBrotli = 2,
285 kCowCompressLz4 = 3,
286 kCowCompressZstd = 4,
287 };
288 struct CowCompression {
289 CowCompressionAlgorithm algorithm = kCowCompressNone;
290 int32_t compression_level = 0;
291 };
292
293 static constexpr uint8_t kCowReadAheadNotStarted = 0;
294 static constexpr uint8_t kCowReadAheadInProgress = 1;
295 static constexpr uint8_t kCowReadAheadDone = 2;
296
GetSequenceOffset(const CowHeaderV3 & header)297 static constexpr off_t GetSequenceOffset(const CowHeaderV3& header) {
298 return header.prefix.header_size + header.buffer_size;
299 }
300
GetResumeOffset(const CowHeaderV3 & header)301 static constexpr off_t GetResumeOffset(const CowHeaderV3& header) {
302 return GetSequenceOffset(header) + (header.sequence_data_count * sizeof(uint32_t));
303 }
304
GetOpOffset(uint32_t op_index,const CowHeaderV3 & header)305 static constexpr off_t GetOpOffset(uint32_t op_index, const CowHeaderV3& header) {
306 return GetResumeOffset(header) + (header.resume_point_max * sizeof(ResumePoint)) +
307 (op_index * sizeof(CowOperationV3));
308 }
309
GetDataOffset(const CowHeaderV3 & header)310 static constexpr off_t GetDataOffset(const CowHeaderV3& header) {
311 return GetOpOffset(header.op_count_max, header);
312 }
313
314 struct CowFooter {
315 CowFooterOperation op;
316 uint8_t unused[64];
317 } __attribute__((packed));
318
319 struct ScratchMetadata {
320 // Block of data in the image that operation modifies
321 // and read-ahead thread stores the modified data
322 // in the scratch space
323 uint64_t new_block;
324 // Offset within the file to read the data
325 uint64_t file_offset;
326 } __attribute__((packed));
327
328 struct BufferState {
329 uint8_t read_ahead_state;
330 } __attribute__((packed));
331
332 // 2MB Scratch space used for read-ahead
333 static constexpr uint64_t BUFFER_REGION_DEFAULT_SIZE = (1ULL << 21);
334
335 std::ostream& operator<<(std::ostream& os, CowOperationV2 const& arg);
336
337 std::ostream& operator<<(std::ostream& os, CowOperationV3 const& arg);
338
339 std::ostream& operator<<(std::ostream& os, ResumePoint const& arg);
340
341 std::ostream& operator<<(std::ostream& os, CowOperationType cow_type);
342
343 int64_t GetNextOpOffset(const CowOperationV2& op, uint32_t cluster_size);
344 int64_t GetNextDataOffset(const CowOperationV2& op, uint32_t cluster_size);
345
346 // Ops that are internal to the Cow Format and not OTA data
347 bool IsMetadataOp(const CowOperation& op);
348 // Ops that have dependencies on old blocks, and must take care in their merge order
349 bool IsOrderedOp(const CowOperation& op);
350
351 // Convert compression name to internal value.
352 std::optional<CowCompressionAlgorithm> CompressionAlgorithmFromString(std::string_view name);
353
354 // Return block size used for compression
355 size_t CowOpCompressionSize(const CowOperation* op, size_t block_size);
356
357 // Return the relative offset of the I/O block which the CowOperation
358 // multi-block compression
359 bool GetBlockOffset(const CowOperation* op, uint64_t io_block, size_t block_size, off_t* offset);
360 } // namespace snapshot
361 } // namespace android
362