1 //
2 // Copyright (C) 2015 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 UPDATE_ENGINE_PAYLOAD_GENERATOR_PAYLOAD_GENERATION_CONFIG_H_
18 #define UPDATE_ENGINE_PAYLOAD_GENERATOR_PAYLOAD_GENERATION_CONFIG_H_
19 
20 #include <cstddef>
21 
22 #include <memory>
23 #include <string>
24 #include <vector>
25 
26 #include <brillo/key_value_store.h>
27 
28 #include "update_engine/payload_consumer/payload_constants.h"
29 #include "update_engine/payload_generator/filesystem_interface.h"
30 #include "update_engine/update_metadata.pb.h"
31 
32 namespace chromeos_update_engine {
33 
34 struct PostInstallConfig {
35   // Whether the postinstall config is empty.
36   bool IsEmpty() const;
37 
38   // Whether this partition carries a filesystem with post-install program that
39   // must be run to finalize the update process.
40   bool run = false;
41 
42   // The path to the post-install program relative to the root of this
43   // filesystem.
44   std::string path;
45 
46   // The filesystem type used to mount the partition in order to run the
47   // post-install program.
48   std::string filesystem_type;
49 };
50 
51 struct PartitionConfig {
PartitionConfigPartitionConfig52   explicit PartitionConfig(std::string name) : name(name) {}
53 
54   // Returns whether the PartitionConfig is not an empty image and all the
55   // fields are set correctly to a valid image file.
56   bool ValidateExists() const;
57 
58   // Open then filesystem stored in this partition and stores it in
59   // |fs_interface|. Returns whether opening the filesystem worked.
60   bool OpenFilesystem();
61 
62   // The path to the partition file. This can be a regular file or a block
63   // device such as a loop device.
64   std::string path;
65 
66   // The size of the data in |path|. If rootfs verification is used (verity)
67   // this value should match the size of the verity device for the rootfs, and
68   // the size of the whole kernel. This value could be smaller than the
69   // partition and is the size of the data update_engine assumes verified for
70   // the source image, and the size of that data it should generate for the
71   // target image.
72   uint64_t size = 0;
73 
74   // The FilesystemInterface implementation used to access this partition's
75   // files.
76   std::unique_ptr<FilesystemInterface> fs_interface;
77 
78   std::string name;
79 
80   PostInstallConfig postinstall;
81 };
82 
83 // The ImageConfig struct describes a pair of binaries kernel and rootfs and the
84 // metadata associated with the image they are part of, like build number, size,
85 // etc.
86 struct ImageConfig {
87   // Returns whether the ImageConfig is an empty image.
88   bool ValidateIsEmpty() const;
89 
90   // Load |rootfs_size| and |kernel.size| from the respective image files. For
91   // the kernel, the whole |kernel.path| file is assumed. For the rootfs, the
92   // size is detected from the filesystem.
93   // Returns whether the image size was properly detected.
94   bool LoadImageSize();
95 
96   // Load postinstall config from a key value store.
97   bool LoadPostInstallConfig(const brillo::KeyValueStore& store);
98 
99   // Returns whether the |image_info| field is empty.
100   bool ImageInfoIsEmpty() const;
101 
102   // The ImageInfo message defined in the update_metadata.proto file describes
103   // the metadata of the image.
104   ImageInfo image_info;
105 
106   // The updated partitions.
107   std::vector<PartitionConfig> partitions;
108 };
109 
110 struct PayloadVersion {
PayloadVersionPayloadVersion111   PayloadVersion() : PayloadVersion(0, 0) {}
112   PayloadVersion(uint64_t major_version, uint32_t minor_version);
113 
114   // Returns whether the PayloadVersion is valid.
115   bool Validate() const;
116 
117   // Return whether the passed |operation| is allowed by this payload.
118   bool OperationAllowed(InstallOperation_Type operation) const;
119 
120   // Whether this payload version is a delta payload.
121   bool IsDelta() const;
122 
123   // Tells whether the update is done in-place, that is, whether the operations
124   // read and write from the same partition.
125   bool InplaceUpdate() const;
126 
127   // The major version of the payload.
128   uint64_t major;
129 
130   // The minor version of the payload.
131   uint32_t minor;
132 
133   // Wheter the IMGDIFF operation is allowed based on the available compressor
134   // in the delta_generator and the one supported by the target.
135   bool imgdiff_allowed = false;
136 };
137 
138 // The PayloadGenerationConfig struct encapsulates all the configuration to
139 // build the requested payload. This includes information about the old and new
140 // image as well as the restrictions applied to the payload (like minor-version
141 // and full/delta payload).
142 struct PayloadGenerationConfig {
143   // Returns whether the PayloadGenerationConfig is valid.
144   bool Validate() const;
145 
146   // Image information about the new image that's the target of this payload.
147   ImageConfig target;
148 
149   // Image information pertaining the old image, if any. This is only valid
150   // if is_full is false, so we are requested a delta payload.
151   ImageConfig source;
152 
153   // Wheter the requested payload is a delta payload.
154   bool is_delta = false;
155 
156   // The major/minor version of the payload.
157   PayloadVersion version;
158 
159   // The size of the rootfs partition, that not necessarily is the same as the
160   // filesystem in either source or target version, since there is some space
161   // after the partition used to store the verity hashes and or the bootcache.
162   uint64_t rootfs_partition_size = 0;
163 
164   // The |hard_chunk_size| is the maximum size that a single operation should
165   // write in the destination. Operations bigger than chunk_size should be
166   // split. A value of -1 means no hard chunk size limit. A very low limit
167   // means more operations, and less of a chance to reuse the data.
168   ssize_t hard_chunk_size = -1;
169 
170   // The |soft_chunk_size| is the preferred chunk size to use when there's no
171   // significant impact to the operations. For example, REPLACE, MOVE and
172   // SOURCE_COPY operations are not significantly impacted by the chunk size,
173   // except for a few bytes overhead in the manifest to describe extra
174   // operations. On the other hand, splitting BSDIFF operations impacts the
175   // payload size since it is not possible to use the redundancy *between*
176   // chunks.
177   size_t soft_chunk_size = 2 * 1024 * 1024;
178 
179   // TODO(deymo): Remove the block_size member and maybe replace it with a
180   // minimum alignment size for blocks (if needed). Algorithms should be able to
181   // pick the block_size they want, but for now only 4 KiB is supported.
182 
183   // The block size used for all the operations in the manifest.
184   size_t block_size = 4096;
185 };
186 
187 }  // namespace chromeos_update_engine
188 
189 #endif  // UPDATE_ENGINE_PAYLOAD_GENERATOR_PAYLOAD_GENERATION_CONFIG_H_
190