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