• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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