1 // 2 // Copyright (C) 2018 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_DYNAMIC_PARTITION_CONTROL_ANDROID_H_ 18 #define UPDATE_ENGINE_DYNAMIC_PARTITION_CONTROL_ANDROID_H_ 19 20 #include <memory> 21 #include <set> 22 #include <string> 23 #include <vector> 24 25 #include <base/files/file_util.h> 26 #include <libsnapshot/auto_device.h> 27 #include <libsnapshot/snapshot.h> 28 29 #include "update_engine/common/dynamic_partition_control_interface.h" 30 31 namespace chromeos_update_engine { 32 33 class DynamicPartitionControlAndroid : public DynamicPartitionControlInterface { 34 public: 35 DynamicPartitionControlAndroid(); 36 ~DynamicPartitionControlAndroid(); 37 FeatureFlag GetDynamicPartitionsFeatureFlag() override; 38 FeatureFlag GetVirtualAbFeatureFlag() override; 39 bool OptimizeOperation(const std::string& partition_name, 40 const InstallOperation& operation, 41 InstallOperation* optimized) override; 42 void Cleanup() override; 43 44 bool PreparePartitionsForUpdate(uint32_t source_slot, 45 uint32_t target_slot, 46 const DeltaArchiveManifest& manifest, 47 bool update, 48 uint64_t* required_size) override; 49 bool FinishUpdate(bool powerwash_required) override; 50 std::unique_ptr<AbstractAction> GetCleanupPreviousUpdateAction( 51 BootControlInterface* boot_control, 52 PrefsInterface* prefs, 53 CleanupPreviousUpdateActionDelegateInterface* delegate) override; 54 55 bool ResetUpdate(PrefsInterface* prefs) override; 56 57 bool ListDynamicPartitionsForSlot( 58 uint32_t current_slot, std::vector<std::string>* partitions) override; 59 60 bool VerifyExtentsForUntouchedPartitions( 61 uint32_t source_slot, 62 uint32_t target_slot, 63 const std::vector<std::string>& partitions) override; 64 65 bool GetDeviceDir(std::string* path) override; 66 67 // Return the device for partition |partition_name| at slot |slot|. 68 // |current_slot| should be set to the current active slot. 69 // Note: this function is only used by BootControl*::GetPartitionDevice. 70 // Other callers should prefer BootControl*::GetPartitionDevice over 71 // BootControl*::GetDynamicPartitionControl()->GetPartitionDevice(). 72 bool GetPartitionDevice(const std::string& partition_name, 73 uint32_t slot, 74 uint32_t current_slot, 75 bool not_in_payload, 76 std::string* device, 77 bool* is_dynamic); 78 79 bool GetPartitionDevice(const std::string& partition_name, 80 uint32_t slot, 81 uint32_t current_slot, 82 std::string* device); 83 84 protected: 85 // These functions are exposed for testing. 86 87 // Unmap logical partition on device mapper. This is the reverse operation 88 // of MapPartitionOnDeviceMapper. 89 // Returns true if unmapped successfully. 90 virtual bool UnmapPartitionOnDeviceMapper( 91 const std::string& target_partition_name); 92 93 // Retrieves metadata from |super_device| at slot |slot|. 94 virtual std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder( 95 const std::string& super_device, uint32_t slot); 96 97 // Retrieves metadata from |super_device| at slot |source_slot|. And modifies 98 // the metadata so that during updates, the metadata can be written to 99 // |target_slot|. In particular, on retrofit devices, the returned metadata 100 // automatically includes block devices at |target_slot|. 101 virtual std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder( 102 const std::string& super_device, 103 uint32_t source_slot, 104 uint32_t target_slot); 105 106 // Write metadata |builder| to |super_device| at slot |target_slot|. 107 virtual bool StoreMetadata(const std::string& super_device, 108 android::fs_mgr::MetadataBuilder* builder, 109 uint32_t target_slot); 110 111 // Map logical partition on device-mapper. 112 // |super_device| is the device path of the physical partition ("super"). 113 // |target_partition_name| is the identifier used in metadata; for example, 114 // "vendor_a" 115 // |slot| is the selected slot to mount; for example, 0 for "_a". 116 // Returns true if mapped successfully; if so, |path| is set to the device 117 // path of the mapped logical partition. 118 virtual bool MapPartitionOnDeviceMapper( 119 const std::string& super_device, 120 const std::string& target_partition_name, 121 uint32_t slot, 122 bool force_writable, 123 std::string* path); 124 125 // Return true if a static partition exists at device path |path|. 126 virtual bool DeviceExists(const std::string& path); 127 128 // Returns the current state of the underlying device mapper device 129 // with given name. 130 // One of INVALID, SUSPENDED or ACTIVE. 131 virtual android::dm::DmDeviceState GetState(const std::string& name); 132 133 // Returns the path to the device mapper device node in '/dev' corresponding 134 // to 'name'. If the device does not exist, false is returned, and the path 135 // parameter is not set. 136 virtual bool GetDmDevicePathByName(const std::string& name, 137 std::string* path); 138 139 // Return the name of the super partition (which stores super partition 140 // metadata) for a given slot. 141 virtual std::string GetSuperPartitionName(uint32_t slot); 142 143 virtual void set_fake_mapped_devices(const std::set<std::string>& fake); 144 145 // Allow mock objects to override this to test recovery mode. 146 virtual bool IsRecovery(); 147 148 // Determine path for system_other partition. 149 // |source_slot| should be current slot. 150 // |target_slot| should be "other" slot. 151 // |partition_name_suffix| should be "system" + suffix(|target_slot|). 152 // Return true and set |path| if successful. 153 // Set |path| to empty if no need to erase system_other. 154 // Set |should_unmap| to true if path needs to be unmapped later. 155 // 156 // Note: system_other cannot use GetPartitionDevice or 157 // GetDynamicPartitionDevice because: 158 // - super partition metadata may be loaded from the source slot 159 // - UPDATED flag needs to be check to skip erasing if partition is not 160 // created by flashing tools 161 // - Snapshots from previous update attempts should not be used. 162 virtual bool GetSystemOtherPath(uint32_t source_slot, 163 uint32_t target_slot, 164 const std::string& partition_name_suffix, 165 std::string* path, 166 bool* should_unmap); 167 168 // Returns true if any entry in the fstab file in |path| has AVB enabled, 169 // false if not enabled, and nullopt for any error. 170 virtual std::optional<bool> IsAvbEnabledInFstab(const std::string& path); 171 172 // Returns true if system_other has AVB enabled, false if not enabled, and 173 // nullopt for any error. 174 virtual std::optional<bool> IsAvbEnabledOnSystemOther(); 175 176 // Erase system_other partition that may contain system_other.img. 177 // After the update, the content of system_other may be corrupted but with 178 // valid AVB footer. If the update is rolled back and factory data reset is 179 // triggered, system_b fails to be mapped with verity errors (see 180 // b/152444348). Erase the system_other so that mapping system_other is 181 // skipped. 182 virtual bool EraseSystemOtherAvbFooter(uint32_t source_slot, 183 uint32_t target_slot); 184 185 // Helper for PreparePartitionsForUpdate. Used for devices with dynamic 186 // partitions updating without snapshots. 187 // If |delete_source| is set, source partitions are deleted before resizing 188 // target partitions (using DeleteSourcePartitions). 189 virtual bool PrepareDynamicPartitionsForUpdate( 190 uint32_t source_slot, 191 uint32_t target_slot, 192 const DeltaArchiveManifest& manifest, 193 bool delete_source); 194 195 private: 196 friend class DynamicPartitionControlAndroidTest; 197 friend class SnapshotPartitionTestP; 198 199 void UnmapAllPartitions(); 200 bool MapPartitionInternal(const std::string& super_device, 201 const std::string& target_partition_name, 202 uint32_t slot, 203 bool force_writable, 204 std::string* path); 205 206 // Update |builder| according to |partition_metadata|, assuming the device 207 // does not have Virtual A/B. 208 bool UpdatePartitionMetadata(android::fs_mgr::MetadataBuilder* builder, 209 uint32_t target_slot, 210 const DeltaArchiveManifest& manifest); 211 212 // Helper for PreparePartitionsForUpdate. Used for snapshotted partitions for 213 // Virtual A/B update. 214 bool PrepareSnapshotPartitionsForUpdate(uint32_t source_slot, 215 uint32_t target_slot, 216 const DeltaArchiveManifest& manifest, 217 uint64_t* required_size); 218 219 enum class DynamicPartitionDeviceStatus { 220 SUCCESS, 221 ERROR, 222 TRY_STATIC, 223 }; 224 225 // Return SUCCESS and path in |device| if partition is dynamic. 226 // Return ERROR if any error. 227 // Return TRY_STATIC if caller should resolve the partition as a static 228 // partition instead. 229 DynamicPartitionDeviceStatus GetDynamicPartitionDevice( 230 const base::FilePath& device_dir, 231 const std::string& partition_name_suffix, 232 uint32_t slot, 233 uint32_t current_slot, 234 bool not_in_payload, 235 std::string* device); 236 237 // Return true if |partition_name_suffix| is a block device of 238 // super partition metadata slot |slot|. 239 bool IsSuperBlockDevice(const base::FilePath& device_dir, 240 uint32_t current_slot, 241 const std::string& partition_name_suffix); 242 243 // If sideloading a full OTA, delete source partitions from |builder|. 244 bool DeleteSourcePartitions(android::fs_mgr::MetadataBuilder* builder, 245 uint32_t source_slot, 246 const DeltaArchiveManifest& manifest); 247 248 // Returns true if metadata is expected to be mounted, false otherwise. 249 // Note that it returns false on non-Virtual A/B devices. 250 // 251 // Almost all functions of SnapshotManager depends on metadata being mounted. 252 // - In Android mode for Virtual A/B devices, assume it is mounted. If not, 253 // let caller fails when calling into SnapshotManager. 254 // - In recovery for Virtual A/B devices, it is possible that metadata is not 255 // formatted, hence it cannot be mounted. Caller should not call into 256 // SnapshotManager. 257 // - On non-Virtual A/B devices, updates do not depend on metadata partition. 258 // Caller should not call into SnapshotManager. 259 // 260 // This function does NOT mount metadata partition. Use EnsureMetadataMounted 261 // to mount metadata partition. 262 bool ExpectMetadataMounted(); 263 264 // Ensure /metadata is mounted. Returns true if successful, false otherwise. 265 // 266 // Note that this function returns true on non-Virtual A/B devices without 267 // doing anything. 268 bool EnsureMetadataMounted(); 269 270 std::set<std::string> mapped_devices_; 271 const FeatureFlag dynamic_partitions_; 272 const FeatureFlag virtual_ab_; 273 std::unique_ptr<android::snapshot::ISnapshotManager> snapshot_; 274 std::unique_ptr<android::snapshot::AutoDevice> metadata_device_; 275 bool target_supports_snapshot_ = false; 276 // Whether the target partitions should be loaded as dynamic partitions. Set 277 // by PreparePartitionsForUpdate() per each update. 278 bool is_target_dynamic_ = false; 279 uint32_t source_slot_ = UINT32_MAX; 280 uint32_t target_slot_ = UINT32_MAX; 281 282 DISALLOW_COPY_AND_ASSIGN(DynamicPartitionControlAndroid); 283 }; 284 285 } // namespace chromeos_update_engine 286 287 #endif // UPDATE_ENGINE_DYNAMIC_PARTITION_CONTROL_ANDROID_H_ 288