//
// 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_