| /* |
| * Copyright 2018 Google, Inc |
| * |
| * 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 _LIBDM_DMTARGET_H_ |
| #define _LIBDM_DMTARGET_H_ |
| |
| #include <linux/dm-ioctl.h> |
| #include <stdint.h> |
| |
| #include <string> |
| #include <vector> |
| |
| namespace android { |
| namespace dm { |
| |
| class DmTargetTypeInfo { |
| public: |
| DmTargetTypeInfo() : major_(0), minor_(0), patch_(0) {} |
| DmTargetTypeInfo(const struct dm_target_versions* info) |
| : name_(info->name), |
| major_(info->version[0]), |
| minor_(info->version[1]), |
| patch_(info->version[2]) {} |
| |
| const std::string& name() const { return name_; } |
| std::string version() const { |
| return std::to_string(major_) + "." + std::to_string(minor_) + "." + std::to_string(patch_); |
| } |
| |
| uint32_t major_version() const { return major_; } |
| uint32_t minor_version() const { return minor_; } |
| uint32_t patch_level() const { return patch_; } |
| |
| bool IsAtLeast(uint32_t major, uint32_t minor, uint32_t patch) const { |
| if (major_ > major) return true; |
| if (major_ < major) return false; |
| if (minor_ > minor) return true; |
| if (minor_ < minor) return false; |
| return patch_ >= patch; |
| } |
| |
| private: |
| std::string name_; |
| uint32_t major_; |
| uint32_t minor_; |
| uint32_t patch_; |
| }; |
| |
| class DmTarget { |
| public: |
| DmTarget(uint64_t start, uint64_t length) : start_(start), length_(length) {} |
| |
| virtual ~DmTarget() = default; |
| |
| // Returns name of the target. |
| virtual std::string name() const = 0; |
| |
| // Return the first logical sector represented by this target. |
| uint64_t start() const { return start_; } |
| |
| // Returns size in number of sectors when this target is part of |
| // a DmTable, return 0 otherwise. |
| uint64_t size() const { return length_; } |
| |
| // Function that converts this object to a string of arguments that can |
| // be passed to the kernel for adding this target in a table. Each target (e.g. verity, linear) |
| // must implement this, for it to be used on a device. |
| std::string Serialize() const; |
| |
| virtual bool Valid() const { return true; } |
| |
| protected: |
| // Get the parameter string that is passed to the end of the dm_target_spec |
| // for this target type. |
| virtual std::string GetParameterString() const = 0; |
| |
| private: |
| // logical sector number start and total length (in terms of 512-byte sectors) represented |
| // by this target within a DmTable. |
| uint64_t start_, length_; |
| }; |
| |
| class DmTargetZero final : public DmTarget { |
| public: |
| DmTargetZero(uint64_t start, uint64_t length) : DmTarget(start, length) {} |
| |
| std::string name() const override { return "zero"; } |
| std::string GetParameterString() const override; |
| }; |
| |
| class DmTargetLinear final : public DmTarget { |
| public: |
| DmTargetLinear(uint64_t start, uint64_t length, const std::string& block_device, |
| uint64_t physical_sector) |
| : DmTarget(start, length), block_device_(block_device), physical_sector_(physical_sector) {} |
| |
| std::string name() const override { return "linear"; } |
| std::string GetParameterString() const override; |
| const std::string& block_device() const { return block_device_; } |
| |
| private: |
| std::string block_device_; |
| uint64_t physical_sector_; |
| }; |
| |
| class DmTargetVerity final : public DmTarget { |
| public: |
| DmTargetVerity(uint64_t start, uint64_t length, uint32_t version, |
| const std::string& block_device, const std::string& hash_device, |
| uint32_t data_block_size, uint32_t hash_block_size, uint32_t num_data_blocks, |
| uint32_t hash_start_block, const std::string& hash_algorithm, |
| const std::string& root_digest, const std::string& salt); |
| |
| void UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks, uint32_t start); |
| void SetVerityMode(const std::string& mode); |
| void IgnoreZeroBlocks(); |
| |
| std::string name() const override { return "verity"; } |
| std::string GetParameterString() const override; |
| bool Valid() const override { return valid_; } |
| |
| private: |
| std::vector<std::string> base_args_; |
| std::vector<std::string> optional_args_; |
| bool valid_; |
| }; |
| |
| class DmTargetAndroidVerity final : public DmTarget { |
| public: |
| DmTargetAndroidVerity(uint64_t start, uint64_t length, const std::string& block_device, |
| const std::string& keyid) |
| : DmTarget(start, length), keyid_(keyid), block_device_(block_device) {} |
| |
| std::string name() const override { return "android-verity"; } |
| std::string GetParameterString() const override; |
| |
| private: |
| std::string keyid_; |
| std::string block_device_; |
| }; |
| |
| // This is the same as DmTargetVerity, but the table may be specified as a raw |
| // string. This code exists only for fs_mgr_verity and should be avoided. Use |
| // DmTargetVerity for new code instead. |
| class DmTargetVerityString final : public DmTarget { |
| public: |
| DmTargetVerityString(uint64_t start, uint64_t length, const std::string& target_string) |
| : DmTarget(start, length), target_string_(target_string) {} |
| |
| std::string name() const override { return "verity"; } |
| std::string GetParameterString() const override { return target_string_; } |
| bool Valid() const override { return true; } |
| |
| private: |
| std::string target_string_; |
| }; |
| |
| // dm-bow is the backup on write target that can provide checkpoint capability |
| // for file systems that do not support checkpoints natively |
| class DmTargetBow final : public DmTarget { |
| public: |
| DmTargetBow(uint64_t start, uint64_t length, const std::string& target_string) |
| : DmTarget(start, length), target_string_(target_string) {} |
| |
| std::string name() const override { return "bow"; } |
| std::string GetParameterString() const override { return target_string_; } |
| |
| private: |
| std::string target_string_; |
| }; |
| |
| enum class SnapshotStorageMode { |
| // The snapshot will be persisted to the COW device. |
| Persistent, |
| // The snapshot will be lost on reboot. |
| Transient, |
| // The snapshot will be merged from the COW device into the base device, |
| // in the background. |
| Merge |
| }; |
| |
| // Writes to a snapshot device will be written to the given COW device. Reads |
| // will read from the COW device or base device. The chunk size is specified |
| // in sectors. |
| class DmTargetSnapshot final : public DmTarget { |
| public: |
| DmTargetSnapshot(uint64_t start, uint64_t length, const std::string& base_device, |
| const std::string& cow_device, SnapshotStorageMode mode, uint64_t chunk_size) |
| : DmTarget(start, length), |
| base_device_(base_device), |
| cow_device_(cow_device), |
| mode_(mode), |
| chunk_size_(chunk_size) {} |
| |
| std::string name() const override; |
| std::string GetParameterString() const override; |
| bool Valid() const override { return true; } |
| |
| struct Status { |
| uint64_t sectors_allocated; |
| uint64_t total_sectors; |
| uint64_t metadata_sectors; |
| std::string error; |
| }; |
| |
| static double MergePercent(const Status& status, uint64_t sectors_initial = 0); |
| static bool ParseStatusText(const std::string& text, Status* status); |
| static bool ReportsOverflow(const std::string& target_type); |
| static bool GetDevicesFromParams(const std::string& params, std::string* base_device, |
| std::string* cow_device); |
| |
| private: |
| std::string base_device_; |
| std::string cow_device_; |
| SnapshotStorageMode mode_; |
| uint64_t chunk_size_; |
| }; |
| |
| // snapshot-origin will read/write directly to the backing device, updating any |
| // snapshot devices with a matching origin. |
| class DmTargetSnapshotOrigin final : public DmTarget { |
| public: |
| DmTargetSnapshotOrigin(uint64_t start, uint64_t length, const std::string& device) |
| : DmTarget(start, length), device_(device) {} |
| |
| std::string name() const override { return "snapshot-origin"; } |
| std::string GetParameterString() const override { return device_; } |
| bool Valid() const override { return true; } |
| |
| private: |
| std::string device_; |
| }; |
| |
| class DmTargetCrypt final : public DmTarget { |
| public: |
| DmTargetCrypt(uint64_t start, uint64_t length, const std::string& cipher, |
| const std::string& key, uint64_t iv_sector_offset, const std::string& device, |
| uint64_t device_sector) |
| : DmTarget(start, length), |
| cipher_(cipher), |
| key_(key), |
| iv_sector_offset_(iv_sector_offset), |
| device_(device), |
| device_sector_(device_sector) {} |
| |
| void AllowDiscards() { allow_discards_ = true; } |
| void AllowEncryptOverride() { allow_encrypt_override_ = true; } |
| void SetIvLargeSectors() { iv_large_sectors_ = true; } |
| void SetSectorSize(uint32_t sector_size) { sector_size_ = sector_size; } |
| |
| std::string name() const override { return "crypt"; } |
| bool Valid() const override { return true; } |
| std::string GetParameterString() const override; |
| |
| private: |
| std::string cipher_; |
| std::string key_; |
| uint64_t iv_sector_offset_; |
| std::string device_; |
| uint64_t device_sector_; |
| bool allow_discards_ = false; |
| bool allow_encrypt_override_ = false; |
| bool iv_large_sectors_ = false; |
| uint32_t sector_size_ = 0; |
| }; |
| |
| class DmTargetDefaultKey final : public DmTarget { |
| public: |
| DmTargetDefaultKey(uint64_t start, uint64_t length, const std::string& cipher, |
| const std::string& key, const std::string& blockdev, uint64_t start_sector) |
| : DmTarget(start, length), |
| cipher_(cipher), |
| key_(key), |
| blockdev_(blockdev), |
| start_sector_(start_sector) {} |
| |
| std::string name() const override { return "default-key"; } |
| bool Valid() const override { return true; } |
| std::string GetParameterString() const override; |
| |
| private: |
| std::string cipher_; |
| std::string key_; |
| std::string blockdev_; |
| uint64_t start_sector_; |
| }; |
| |
| } // namespace dm |
| } // namespace android |
| |
| #endif /* _LIBDM_DMTARGET_H_ */ |