Implement setShouldSwitchSlotOnReboot and resetShouldSwitchSlotOnReboot
Test: Install OTA, call resetShouldSwitchSlotOnReboot, make sure slot is
set to _a, call setShouldSwitchSlot, make sure slot is set to _b
Bug: 187321613
Change-Id: I4d0a5ed9292bdbefda4b48e84dbcfb4751406b28
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 31fa90e..f067a82 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -624,10 +624,8 @@
}
bool DeltaPerformer::ParseManifestPartitions(ErrorCode* error) {
- partitions_.clear();
- for (const PartitionUpdate& partition : manifest_.partitions()) {
- partitions_.push_back(partition);
- }
+ partitions_.assign(manifest_.partitions().begin(),
+ manifest_.partitions().end());
// For VAB and partial updates, the partition preparation will copy the
// dynamic partitions metadata to the target metadata slot, and rename the
@@ -685,87 +683,11 @@
}
}
- // Fill in the InstallPlan::partitions based on the partitions from the
- // payload.
- for (const auto& partition : partitions_) {
- InstallPlan::Partition install_part;
- install_part.name = partition.partition_name();
- install_part.run_postinstall =
- partition.has_run_postinstall() && partition.run_postinstall();
- if (install_part.run_postinstall) {
- install_part.postinstall_path =
- (partition.has_postinstall_path() ? partition.postinstall_path()
- : kPostinstallDefaultScript);
- install_part.filesystem_type = partition.filesystem_type();
- install_part.postinstall_optional = partition.postinstall_optional();
- }
-
- if (partition.has_old_partition_info()) {
- const PartitionInfo& info = partition.old_partition_info();
- install_part.source_size = info.size();
- install_part.source_hash.assign(info.hash().begin(), info.hash().end());
- }
-
- if (!partition.has_new_partition_info()) {
- LOG(ERROR) << "Unable to get new partition hash info on partition "
- << install_part.name << ".";
- *error = ErrorCode::kDownloadNewPartitionInfoError;
- return false;
- }
- const PartitionInfo& info = partition.new_partition_info();
- install_part.target_size = info.size();
- install_part.target_hash.assign(info.hash().begin(), info.hash().end());
-
- install_part.block_size = block_size_;
- if (partition.has_hash_tree_extent()) {
- Extent extent = partition.hash_tree_data_extent();
- install_part.hash_tree_data_offset = extent.start_block() * block_size_;
- install_part.hash_tree_data_size = extent.num_blocks() * block_size_;
- extent = partition.hash_tree_extent();
- install_part.hash_tree_offset = extent.start_block() * block_size_;
- install_part.hash_tree_size = extent.num_blocks() * block_size_;
- uint64_t hash_tree_data_end =
- install_part.hash_tree_data_offset + install_part.hash_tree_data_size;
- if (install_part.hash_tree_offset < hash_tree_data_end) {
- LOG(ERROR) << "Invalid hash tree extents, hash tree data ends at "
- << hash_tree_data_end << ", but hash tree starts at "
- << install_part.hash_tree_offset;
- *error = ErrorCode::kDownloadNewPartitionInfoError;
- return false;
- }
- install_part.hash_tree_algorithm = partition.hash_tree_algorithm();
- install_part.hash_tree_salt.assign(partition.hash_tree_salt().begin(),
- partition.hash_tree_salt().end());
- }
- if (partition.has_fec_extent()) {
- Extent extent = partition.fec_data_extent();
- install_part.fec_data_offset = extent.start_block() * block_size_;
- install_part.fec_data_size = extent.num_blocks() * block_size_;
- extent = partition.fec_extent();
- install_part.fec_offset = extent.start_block() * block_size_;
- install_part.fec_size = extent.num_blocks() * block_size_;
- uint64_t fec_data_end =
- install_part.fec_data_offset + install_part.fec_data_size;
- if (install_part.fec_offset < fec_data_end) {
- LOG(ERROR) << "Invalid fec extents, fec data ends at " << fec_data_end
- << ", but fec starts at " << install_part.fec_offset;
- *error = ErrorCode::kDownloadNewPartitionInfoError;
- return false;
- }
- install_part.fec_roots = partition.fec_roots();
- }
-
- install_plan_->partitions.push_back(install_part);
- }
-
- // TODO(xunchang) only need to load the partitions for those in payload.
- // Because we have already loaded the other once when generating SOURCE_COPY
- // operations.
- if (!install_plan_->LoadPartitionsFromSlots(boot_control_)) {
- LOG(ERROR) << "Unable to determine all the partition devices.";
- *error = ErrorCode::kInstallDeviceOpenError;
+ if (!install_plan_->ParsePartitions(
+ partitions_, boot_control_, block_size_, error)) {
return false;
}
+
LogPartitionInfo(partitions_);
return true;
}
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index 06b7dd8..2bd81ae 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -26,6 +26,7 @@
#include <base/strings/stringprintf.h>
#include "update_engine/common/utils.h"
+#include "update_engine/update_metadata.pb.h"
#include "update_engine/payload_consumer/payload_constants.h"
using std::string;
@@ -186,4 +187,113 @@
postinstall_optional == that.postinstall_optional);
}
+template <typename PartitinoUpdateArray>
+bool InstallPlan::ParseManifestToInstallPlan(
+ const PartitinoUpdateArray& partitions,
+ BootControlInterface* boot_control,
+ size_t block_size,
+ InstallPlan* install_plan,
+ ErrorCode* error) {
+ // Fill in the InstallPlan::partitions based on the partitions from the
+ // payload.
+ for (const PartitionUpdate& partition : partitions) {
+ InstallPlan::Partition install_part;
+ install_part.name = partition.partition_name();
+ install_part.run_postinstall =
+ partition.has_run_postinstall() && partition.run_postinstall();
+ if (install_part.run_postinstall) {
+ install_part.postinstall_path =
+ (partition.has_postinstall_path() ? partition.postinstall_path()
+ : kPostinstallDefaultScript);
+ install_part.filesystem_type = partition.filesystem_type();
+ install_part.postinstall_optional = partition.postinstall_optional();
+ }
+
+ if (partition.has_old_partition_info()) {
+ const PartitionInfo& info = partition.old_partition_info();
+ install_part.source_size = info.size();
+ install_part.source_hash.assign(info.hash().begin(), info.hash().end());
+ }
+
+ if (!partition.has_new_partition_info()) {
+ LOG(ERROR) << "Unable to get new partition hash info on partition "
+ << install_part.name << ".";
+ *error = ErrorCode::kDownloadNewPartitionInfoError;
+ return false;
+ }
+ const PartitionInfo& info = partition.new_partition_info();
+ install_part.target_size = info.size();
+ install_part.target_hash.assign(info.hash().begin(), info.hash().end());
+
+ install_part.block_size = block_size;
+ if (partition.has_hash_tree_extent()) {
+ Extent extent = partition.hash_tree_data_extent();
+ install_part.hash_tree_data_offset = extent.start_block() * block_size;
+ install_part.hash_tree_data_size = extent.num_blocks() * block_size;
+ extent = partition.hash_tree_extent();
+ install_part.hash_tree_offset = extent.start_block() * block_size;
+ install_part.hash_tree_size = extent.num_blocks() * block_size;
+ uint64_t hash_tree_data_end =
+ install_part.hash_tree_data_offset + install_part.hash_tree_data_size;
+ if (install_part.hash_tree_offset < hash_tree_data_end) {
+ LOG(ERROR) << "Invalid hash tree extents, hash tree data ends at "
+ << hash_tree_data_end << ", but hash tree starts at "
+ << install_part.hash_tree_offset;
+ *error = ErrorCode::kDownloadNewPartitionInfoError;
+ return false;
+ }
+ install_part.hash_tree_algorithm = partition.hash_tree_algorithm();
+ install_part.hash_tree_salt.assign(partition.hash_tree_salt().begin(),
+ partition.hash_tree_salt().end());
+ }
+ if (partition.has_fec_extent()) {
+ Extent extent = partition.fec_data_extent();
+ install_part.fec_data_offset = extent.start_block() * block_size;
+ install_part.fec_data_size = extent.num_blocks() * block_size;
+ extent = partition.fec_extent();
+ install_part.fec_offset = extent.start_block() * block_size;
+ install_part.fec_size = extent.num_blocks() * block_size;
+ uint64_t fec_data_end =
+ install_part.fec_data_offset + install_part.fec_data_size;
+ if (install_part.fec_offset < fec_data_end) {
+ LOG(ERROR) << "Invalid fec extents, fec data ends at " << fec_data_end
+ << ", but fec starts at " << install_part.fec_offset;
+ *error = ErrorCode::kDownloadNewPartitionInfoError;
+ return false;
+ }
+ install_part.fec_roots = partition.fec_roots();
+ }
+
+ install_plan->partitions.push_back(install_part);
+ }
+
+ // TODO(xunchang) only need to load the partitions for those in payload.
+ // Because we have already loaded the other once when generating SOURCE_COPY
+ // operations.
+ if (!install_plan->LoadPartitionsFromSlots(boot_control)) {
+ LOG(ERROR) << "Unable to determine all the partition devices.";
+ *error = ErrorCode::kInstallDeviceOpenError;
+ return false;
+ }
+ return true;
+}
+
+bool InstallPlan::ParsePartitions(
+ const std::vector<PartitionUpdate>& partitions,
+ BootControlInterface* boot_control,
+ size_t block_size,
+ ErrorCode* error) {
+ return ParseManifestToInstallPlan(
+ partitions, boot_control, block_size, this, error);
+}
+
+bool InstallPlan::ParsePartitions(
+ const google::protobuf::RepeatedPtrField<PartitionUpdate>& partitions,
+ BootControlInterface* boot_control,
+ size_t block_size,
+ ErrorCode* error) {
+ return ParseManifestToInstallPlan(
+ partitions, boot_control, block_size, this, error);
+}
+
} // namespace chromeos_update_engine
diff --git a/payload_consumer/install_plan.h b/payload_consumer/install_plan.h
index 7c77789..0278ea5 100644
--- a/payload_consumer/install_plan.h
+++ b/payload_consumer/install_plan.h
@@ -47,10 +47,30 @@
void Dump() const;
std::string ToString() const;
+ private:
// Loads the |source_path| and |target_path| of all |partitions| based on the
// |source_slot| and |target_slot| if available. Returns whether it succeeded
// to load all the partitions for the valid slots.
bool LoadPartitionsFromSlots(BootControlInterface* boot_control);
+ template <typename PartitinoUpdateArray>
+ static bool ParseManifestToInstallPlan(const PartitinoUpdateArray& partitions,
+ BootControlInterface* boot_control,
+ size_t block_size,
+ InstallPlan* install_plan,
+ ErrorCode* error);
+
+ public:
+ // Load all partitions in |partitions| into this install plan, will also
+ // populate |source_path|, |target_pathh|, fec information, partition sizes.
+ bool ParsePartitions(const std::vector<PartitionUpdate>& partitions,
+ BootControlInterface* boot_control,
+ size_t block_size,
+ ErrorCode* error);
+ bool ParsePartitions(
+ const google::protobuf::RepeatedPtrField<PartitionUpdate>& partitions,
+ BootControlInterface* boot_control,
+ size_t block_size,
+ ErrorCode* error);
bool is_resume{false};
std::string download_url; // url to download from