lin
2025-07-31 065ea569db06206874bbfa18eb25ff6121aec09b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
 
#ifndef UPDATE_ENGINE_PAYLOAD_GENERATOR_PAYLOAD_GENERATION_CONFIG_H_
#define UPDATE_ENGINE_PAYLOAD_GENERATOR_PAYLOAD_GENERATION_CONFIG_H_
 
#include <cstddef>
 
#include <memory>
#include <string>
#include <vector>
 
#include <brillo/key_value_store.h>
#include <brillo/secure_blob.h>
 
#include "update_engine/payload_consumer/payload_constants.h"
#include "update_engine/payload_generator/filesystem_interface.h"
#include "update_engine/update_metadata.pb.h"
 
namespace chromeos_update_engine {
 
struct PostInstallConfig {
  // Whether the postinstall config is empty.
  bool IsEmpty() const;
 
  // Whether this partition carries a filesystem with post-install program that
  // must be run to finalize the update process.
  bool run = false;
 
  // The path to the post-install program relative to the root of this
  // filesystem.
  std::string path;
 
  // The filesystem type used to mount the partition in order to run the
  // post-install program.
  std::string filesystem_type;
 
  // Whether this postinstall script should be ignored if it fails.
  bool optional = false;
};
 
// Data will be written to the payload and used for hash tree and FEC generation
// at device update time.
struct VerityConfig {
  // Whether the verity config is empty.
  bool IsEmpty() const;
 
  // The extent for data covered by verity hash tree.
  Extent hash_tree_data_extent;
 
  // The extent to store verity hash tree.
  Extent hash_tree_extent;
 
  // The hash algorithm used in verity hash tree.
  std::string hash_tree_algorithm;
 
  // The salt used for verity hash tree.
  brillo::Blob hash_tree_salt;
 
  // The extent for data covered by FEC.
  Extent fec_data_extent;
 
  // The extent to store FEC.
  Extent fec_extent;
 
  // The number of FEC roots.
  uint32_t fec_roots = 0;
};
 
struct PartitionConfig {
  explicit PartitionConfig(std::string name) : name(name) {}
 
  // Returns whether the PartitionConfig is not an empty image and all the
  // fields are set correctly to a valid image file.
  bool ValidateExists() const;
 
  // Open then filesystem stored in this partition and stores it in
  // |fs_interface|. Returns whether opening the filesystem worked.
  bool OpenFilesystem();
 
  // The path to the partition file. This can be a regular file or a block
  // device such as a loop device.
  std::string path;
 
  // The path to the .map file associated with |path| if any. The .map file is
  // generated by the Android filesystem generation tools when creating a
  // filesystem and describes the blocks used by each file.
  std::string mapfile_path;
 
  // The size of the data in |path|. If rootfs verification is used (verity)
  // this value should match the size of the verity device for the rootfs, and
  // the size of the whole kernel. This value could be smaller than the
  // partition and is the size of the data update_engine assumes verified for
  // the source image, and the size of that data it should generate for the
  // target image.
  uint64_t size = 0;
 
  // The FilesystemInterface implementation used to access this partition's
  // files.
  std::unique_ptr<FilesystemInterface> fs_interface;
 
  std::string name;
 
  PostInstallConfig postinstall;
  VerityConfig verity;
};
 
// The ImageConfig struct describes a pair of binaries kernel and rootfs and the
// metadata associated with the image they are part of, like build number, size,
// etc.
struct ImageConfig {
  // Returns whether the ImageConfig is an empty image.
  bool ValidateIsEmpty() const;
 
  // Load |rootfs_size| and |kernel.size| from the respective image files. For
  // the kernel, the whole |kernel.path| file is assumed. For the rootfs, the
  // size is detected from the filesystem.
  // Returns whether the image size was properly detected.
  bool LoadImageSize();
 
  // Load postinstall config from a key value store.
  bool LoadPostInstallConfig(const brillo::KeyValueStore& store);
 
  // Load verity config by parsing the partition images.
  bool LoadVerityConfig();
 
  // Load dynamic partition info from a key value store.
  bool LoadDynamicPartitionMetadata(const brillo::KeyValueStore& store);
 
  // Validate |dynamic_partition_metadata| against |partitions|.
  bool ValidateDynamicPartitionMetadata() const;
 
  // Returns whether the |image_info| field is empty.
  bool ImageInfoIsEmpty() const;
 
  // The ImageInfo message defined in the update_metadata.proto file describes
  // the metadata of the image.
  ImageInfo image_info;
 
  // The updated partitions.
  std::vector<PartitionConfig> partitions;
 
  // The super partition metadata.
  std::unique_ptr<DynamicPartitionMetadata> dynamic_partition_metadata;
};
 
struct PayloadVersion {
  PayloadVersion() : PayloadVersion(0, 0) {}
  PayloadVersion(uint64_t major_version, uint32_t minor_version);
 
  // Returns whether the PayloadVersion is valid.
  bool Validate() const;
 
  // Return whether the passed |operation| is allowed by this payload.
  bool OperationAllowed(InstallOperation::Type operation) const;
 
  // Whether this payload version is a delta payload.
  bool IsDelta() const;
 
  // Tells whether the update is done in-place, that is, whether the operations
  // read and write from the same partition.
  bool InplaceUpdate() const;
 
  // The major version of the payload.
  uint64_t major;
 
  // The minor version of the payload.
  uint32_t minor;
};
 
// The PayloadGenerationConfig struct encapsulates all the configuration to
// build the requested payload. This includes information about the old and new
// image as well as the restrictions applied to the payload (like minor-version
// and full/delta payload).
struct PayloadGenerationConfig {
  // Returns whether the PayloadGenerationConfig is valid.
  bool Validate() const;
 
  // Image information about the new image that's the target of this payload.
  ImageConfig target;
 
  // Image information pertaining the old image, if any. This is only valid
  // if is_full is false, so we are requested a delta payload.
  ImageConfig source;
 
  // Whether the requested payload is a delta payload.
  bool is_delta = false;
 
  // The major/minor version of the payload.
  PayloadVersion version;
 
  // The size of the rootfs partition, that not necessarily is the same as the
  // filesystem in either source or target version, since there is some space
  // after the partition used to store the verity hashes and or the bootcache.
  uint64_t rootfs_partition_size = 0;
 
  // The |hard_chunk_size| is the maximum size that a single operation should
  // write in the destination. Operations bigger than chunk_size should be
  // split. A value of -1 means no hard chunk size limit. A very low limit
  // means more operations, and less of a chance to reuse the data.
  ssize_t hard_chunk_size = -1;
 
  // The |soft_chunk_size| is the preferred chunk size to use when there's no
  // significant impact to the operations. For example, REPLACE, MOVE and
  // SOURCE_COPY operations are not significantly impacted by the chunk size,
  // except for a few bytes overhead in the manifest to describe extra
  // operations. On the other hand, splitting BSDIFF operations impacts the
  // payload size since it is not possible to use the redundancy *between*
  // chunks.
  size_t soft_chunk_size = 2 * 1024 * 1024;
 
  // TODO(deymo): Remove the block_size member and maybe replace it with a
  // minimum alignment size for blocks (if needed). Algorithms should be able to
  // pick the block_size they want, but for now only 4 KiB is supported.
 
  // The block size used for all the operations in the manifest.
  size_t block_size = 4096;
 
  // The maximum timestamp of the OS allowed to apply this payload.
  int64_t max_timestamp = 0;
};
 
}  // namespace chromeos_update_engine
 
#endif  // UPDATE_ENGINE_PAYLOAD_GENERATOR_PAYLOAD_GENERATION_CONFIG_H_