Snap for 6439596 from 92f188b249cd0a99e50a04c6f70df207d66defc1 to qt-aml-tzdata-release
Change-Id: Ife2ff0109b56469285ec6aec6c08fdfb0f78d3ce
diff --git a/.clang-format b/.clang-format
index 3b6a627..c1244fe 100644
--- a/.clang-format
+++ b/.clang-format
@@ -34,6 +34,5 @@
BinPackParameters: false
CommentPragmas: NOLINT:.*
DerivePointerAlignment: false
-IncludeBlocks: Preserve
PointerAlignment: Left
TabWidth: 2
diff --git a/Android.bp b/Android.bp
index d6f1090..284845d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -128,7 +128,6 @@
"libverity_tree",
],
shared_libs: [
- "libziparchive",
"libbase",
"libcrypto",
"libfec",
@@ -165,7 +164,6 @@
"common/utils.cc",
"payload_consumer/bzip_extent_writer.cc",
"payload_consumer/cached_file_descriptor.cc",
- "payload_consumer/certificate_parser_android.cc",
"payload_consumer/delta_performer.cc",
"payload_consumer/download_action.cc",
"payload_consumer/extent_reader.cc",
@@ -193,25 +191,16 @@
name: "libupdate_engine_boot_control_exports",
defaults: ["update_metadata-protos_exports"],
- static_libs: [
- "libsnapshot",
- "update_metadata-protos",
- ],
+ static_libs: ["update_metadata-protos"],
shared_libs: [
"libbootloader_message",
"libfs_mgr",
+ "libhwbinder",
"libhidlbase",
"liblp",
"libutils",
"android.hardware.boot@1.0",
- "android.hardware.boot@1.1",
],
- target: {
- recovery: {
- static_libs: ["libsnapshot_nobinder"],
- exclude_static_libs: ["libsnapshot"],
- },
- },
}
cc_library_static {
@@ -225,7 +214,6 @@
srcs: [
"boot_control_android.cc",
"dynamic_partition_control_android.cc",
- "dynamic_partition_utils.cc",
],
}
@@ -305,10 +293,7 @@
],
static_libs: ["libupdate_engine_android"],
- required: [
- "cacerts_google",
- "otacerts",
- ],
+ required: ["cacerts_google"],
srcs: ["main.cc"],
init_rc: ["update_engine.rc"],
@@ -339,7 +324,6 @@
"metrics_reporter_stub.cc",
"metrics_utils.cc",
"network_selector_stub.cc",
- "sideload_logging_android.cc",
"sideload_main.cc",
"update_attempter_android.cc",
"update_boot_flags_action.cc",
@@ -374,6 +358,7 @@
recovery: {
exclude_shared_libs: [
"libprotobuf-cpp-lite",
+ "libhwbinder",
"libbrillo-stream",
"libbrillo",
"libchrome",
@@ -381,9 +366,7 @@
},
},
- required: [
- "otacerts.recovery",
- ],
+ required: ["android.hardware.boot@1.0-impl-wrapper.recovery"],
}
// libupdate_engine_client (type: shared_library)
@@ -417,7 +400,8 @@
],
srcs: [
- ":libupdate_engine_client_aidl",
+ "binder_bindings/android/brillo/IUpdateEngine.aidl",
+ "binder_bindings/android/brillo/IUpdateEngineStatusCallback.aidl",
"client_library/client.cc",
"client_library/client_binder.cc",
"parcelable_update_engine_status.cc",
@@ -425,15 +409,6 @@
],
}
-filegroup {
- name: "libupdate_engine_client_aidl",
- srcs: [
- "binder_bindings/android/brillo/IUpdateEngine.aidl",
- "binder_bindings/android/brillo/IUpdateEngineStatusCallback.aidl",
- ],
- path: "binder_bindings",
-}
-
// update_engine_client (type: executable)
// ========================================================
// update_engine console client.
@@ -569,6 +544,8 @@
gtest: false,
stem: "delta_generator",
+ relative_install_path: "update_engine_unittests",
+ no_named_install_directory: true,
}
// test_http_server (type: executable)
@@ -583,6 +560,8 @@
],
gtest: false,
+ relative_install_path: "update_engine_unittests",
+ no_named_install_directory: true,
}
// test_subprocess (type: executable)
@@ -594,6 +573,8 @@
srcs: ["test_subprocess.cc"],
gtest: false,
+ relative_install_path: "update_engine_unittests",
+ no_named_install_directory: true,
}
// Public keys for unittests.
@@ -602,19 +583,16 @@
name: "ue_unittest_keys",
cmd: "openssl rsa -in $(location unittest_key.pem) -pubout -out $(location unittest_key.pub.pem) &&" +
"openssl rsa -in $(location unittest_key2.pem) -pubout -out $(location unittest_key2.pub.pem) &&" +
- "openssl rsa -in $(location unittest_key_RSA4096.pem) -pubout -out $(location unittest_key_RSA4096.pub.pem) &&" +
- "openssl pkey -in $(location unittest_key_EC.pem) -pubout -out $(location unittest_key_EC.pub.pem)",
+ "openssl rsa -in $(location unittest_key_RSA4096.pem) -pubout -out $(location unittest_key_RSA4096.pub.pem)",
srcs: [
"unittest_key.pem",
"unittest_key2.pem",
"unittest_key_RSA4096.pem",
- "unittest_key_EC.pem",
],
out: [
"unittest_key.pub.pem",
"unittest_key2.pub.pem",
"unittest_key_RSA4096.pub.pem",
- "unittest_key_EC.pub.pem",
],
}
@@ -644,6 +622,11 @@
"libpayload_generator_exports",
"libupdate_engine_android_exports",
],
+ required: [
+ "test_http_server",
+ "test_subprocess",
+ "ue_unittest_delta_generator",
+ ],
static_libs: [
"libpayload_generator",
@@ -652,30 +635,19 @@
"libchrome_test_helpers",
"libupdate_engine_android",
],
-
- header_libs: [
- "libstorage_literals_headers",
+ shared_libs: [
+ "libhidltransport",
],
data: [
- ":test_http_server",
- ":test_subprocess",
- ":ue_unittest_delta_generator",
":ue_unittest_disk_imgs",
":ue_unittest_keys",
- "otacerts.zip",
"unittest_key.pem",
"unittest_key2.pem",
"unittest_key_RSA4096.pem",
- "unittest_key_EC.pem",
"update_engine.conf",
],
- // We cannot use the default generated AndroidTest.xml because of the use of helper modules
- // (i.e. test_http_server, test_subprocess, ue_unittest_delta_generator).
- test_config: "test_config.xml",
- test_suites: ["device-tests"],
-
srcs: [
"boot_control_android_unittest.cc",
"certificate_checker_unittest.cc",
@@ -695,10 +667,8 @@
"common/terminator_unittest.cc",
"common/test_utils.cc",
"common/utils_unittest.cc",
- "dynamic_partition_control_android_unittest.cc",
"payload_consumer/bzip_extent_writer_unittest.cc",
"payload_consumer/cached_file_descriptor_unittest.cc",
- "payload_consumer/certificate_parser_android_unittest.cc",
"payload_consumer/delta_performer_integration_test.cc",
"payload_consumer/delta_performer_unittest.cc",
"payload_consumer/extent_reader_unittest.cc",
diff --git a/binder_bindings/android/os/IUpdateEngine.aidl b/binder_bindings/android/os/IUpdateEngine.aidl
index 1305079..c0e29f5 100644
--- a/binder_bindings/android/os/IUpdateEngine.aidl
+++ b/binder_bindings/android/os/IUpdateEngine.aidl
@@ -17,7 +17,6 @@
package android.os;
import android.os.IUpdateEngineCallback;
-import android.os.ParcelFileDescriptor;
/** @hide */
interface IUpdateEngine {
@@ -27,11 +26,6 @@
in long payload_size,
in String[] headerKeyValuePairs);
/** @hide */
- void applyPayloadFd(in ParcelFileDescriptor pfd,
- in long payload_offset,
- in long payload_size,
- in String[] headerKeyValuePairs);
- /** @hide */
boolean bind(IUpdateEngineCallback callback);
/** @hide */
boolean unbind(IUpdateEngineCallback callback);
diff --git a/binder_bindings/android/os/IUpdateEngineCallback.aidl b/binder_bindings/android/os/IUpdateEngineCallback.aidl
index 4bacf9a..ee15c8b 100644
--- a/binder_bindings/android/os/IUpdateEngineCallback.aidl
+++ b/binder_bindings/android/os/IUpdateEngineCallback.aidl
@@ -19,7 +19,6 @@
/** @hide */
oneway interface IUpdateEngineCallback {
/** @hide */
- @UnsupportedAppUsage
void onStatusUpdate(int status_code, float percentage);
/** @hide */
void onPayloadApplicationComplete(int error_code);
diff --git a/binder_service_android.cc b/binder_service_android.cc
index 88bc1f2..137694a 100644
--- a/binder_service_android.cc
+++ b/binder_service_android.cc
@@ -24,9 +24,6 @@
using android::binder::Status;
using android::os::IUpdateEngineCallback;
-using android::os::ParcelFileDescriptor;
-using std::string;
-using std::vector;
using update_engine::UpdateEngineStatus;
namespace {
@@ -97,9 +94,9 @@
const android::String16& url,
int64_t payload_offset,
int64_t payload_size,
- const vector<android::String16>& header_kv_pairs) {
- const string payload_url{android::String8{url}.string()};
- vector<string> str_headers;
+ const std::vector<android::String16>& header_kv_pairs) {
+ const std::string payload_url{android::String8{url}.string()};
+ std::vector<std::string> str_headers;
str_headers.reserve(header_kv_pairs.size());
for (const auto& header : header_kv_pairs) {
str_headers.emplace_back(android::String8{header}.string());
@@ -113,25 +110,6 @@
return Status::ok();
}
-Status BinderUpdateEngineAndroidService::applyPayloadFd(
- const ParcelFileDescriptor& pfd,
- int64_t payload_offset,
- int64_t payload_size,
- const vector<android::String16>& header_kv_pairs) {
- vector<string> str_headers;
- str_headers.reserve(header_kv_pairs.size());
- for (const auto& header : header_kv_pairs) {
- str_headers.emplace_back(android::String8{header}.string());
- }
-
- brillo::ErrorPtr error;
- if (!service_delegate_->ApplyPayload(
- pfd.get(), payload_offset, payload_size, str_headers, &error)) {
- return ErrorPtrToStatus(error);
- }
- return Status::ok();
-}
-
Status BinderUpdateEngineAndroidService::suspend() {
brillo::ErrorPtr error;
if (!service_delegate_->SuspendUpdate(&error))
diff --git a/binder_service_android.h b/binder_service_android.h
index 0dda93b..d8c4e9c 100644
--- a/binder_service_android.h
+++ b/binder_service_android.h
@@ -53,11 +53,6 @@
int64_t payload_offset,
int64_t payload_size,
const std::vector<android::String16>& header_kv_pairs) override;
- android::binder::Status applyPayloadFd(
- const ::android::os::ParcelFileDescriptor& pfd,
- int64_t payload_offset,
- int64_t payload_size,
- const std::vector<android::String16>& header_kv_pairs) override;
android::binder::Status bind(
const android::sp<android::os::IUpdateEngineCallback>& callback,
bool* return_value) override;
diff --git a/boot_control_android.cc b/boot_control_android.cc
index b1d775e..1fab85f 100644
--- a/boot_control_android.cc
+++ b/boot_control_android.cc
@@ -22,10 +22,11 @@
#include <base/bind.h>
#include <base/logging.h>
+#include <base/strings/string_util.h>
#include <bootloader_message/bootloader_message.h>
#include <brillo/message_loops/message_loop.h>
+#include <fs_mgr.h>
#include <fs_mgr_overlayfs.h>
-#include <libdm/dm.h>
#include "update_engine/common/utils.h"
#include "update_engine/dynamic_partition_control_android.h"
@@ -33,12 +34,15 @@
using std::string;
using android::dm::DmDeviceState;
+using android::fs_mgr::Partition;
using android::hardware::hidl_string;
using android::hardware::Return;
using android::hardware::boot::V1_0::BoolResult;
using android::hardware::boot::V1_0::CommandResult;
using android::hardware::boot::V1_0::IBootControl;
using Slot = chromeos_update_engine::BootControlInterface::Slot;
+using PartitionMetadata =
+ chromeos_update_engine::BootControlInterface::PartitionMetadata;
namespace {
@@ -107,9 +111,9 @@
Slot slot,
const string& partition_name_suffix) const {
string source_device =
- device_dir.Append(dynamic_control_->GetSuperPartitionName(slot)).value();
- auto source_metadata =
- dynamic_control_->LoadMetadataBuilder(source_device, slot);
+ device_dir.Append(fs_mgr_get_super_partition_name(slot)).value();
+ auto source_metadata = dynamic_control_->LoadMetadataBuilder(
+ source_device, slot, BootControlInterface::kInvalidSlot);
return source_metadata->HasBlockDevice(partition_name_suffix);
}
@@ -120,9 +124,10 @@
Slot slot,
string* device) const {
string super_device =
- device_dir.Append(dynamic_control_->GetSuperPartitionName(slot)).value();
+ device_dir.Append(fs_mgr_get_super_partition_name(slot)).value();
- auto builder = dynamic_control_->LoadMetadataBuilder(super_device, slot);
+ auto builder = dynamic_control_->LoadMetadataBuilder(
+ super_device, slot, BootControlInterface::kInvalidSlot);
if (builder == nullptr) {
LOG(ERROR) << "No metadata in slot "
@@ -138,8 +143,8 @@
if (IsSuperBlockDevice(device_dir, current_slot, partition_name_suffix)) {
LOG(ERROR) << "The static partition " << partition_name_suffix
<< " is a block device for current metadata ("
- << dynamic_control_->GetSuperPartitionName(current_slot)
- << ", slot " << BootControlInterface::SlotName(current_slot)
+ << fs_mgr_get_super_partition_name(current_slot) << ", slot "
+ << BootControlInterface::SlotName(current_slot)
<< "). It cannot be used as a logical partition.";
return DynamicPartitionDeviceStatus::ERROR;
}
@@ -191,7 +196,7 @@
// current payload doesn't encode them as dynamic partitions. This may happen
// when applying a retrofit update on top of a dynamic-partitions-enabled
// build.
- if (dynamic_control_->GetDynamicPartitionsFeatureFlag().IsEnabled() &&
+ if (dynamic_control_->IsDynamicPartitionsEnabled() &&
(slot == GetCurrentSlot() || is_target_dynamic_)) {
switch (GetDynamicPartitionDevice(
device_dir, partition_name_suffix, slot, device)) {
@@ -245,10 +250,6 @@
}
bool BootControlAndroid::SetActiveBootSlot(Slot slot) {
- if (slot != GetCurrentSlot() && !dynamic_control_->FinishUpdate()) {
- return false;
- }
-
CommandResult result;
auto ret = module_->setActiveBootSlot(slot, StoreResultCallback(&result));
if (!ret.isOk()) {
@@ -279,9 +280,113 @@
brillo::MessageLoop::kTaskIdNull;
}
-bool BootControlAndroid::PreparePartitionsForUpdate(
+namespace {
+
+bool UpdatePartitionMetadata(DynamicPartitionControlInterface* dynamic_control,
+ Slot source_slot,
+ Slot target_slot,
+ const string& target_suffix,
+ const PartitionMetadata& partition_metadata) {
+ string device_dir_str;
+ if (!dynamic_control->GetDeviceDir(&device_dir_str)) {
+ return false;
+ }
+ base::FilePath device_dir(device_dir_str);
+ auto source_device =
+ device_dir.Append(fs_mgr_get_super_partition_name(source_slot)).value();
+
+ auto builder = dynamic_control->LoadMetadataBuilder(
+ source_device, source_slot, target_slot);
+ if (builder == nullptr) {
+ // TODO(elsk): allow reconstructing metadata from partition_metadata
+ // in recovery sideload.
+ LOG(ERROR) << "No metadata at "
+ << BootControlInterface::SlotName(source_slot);
+ return false;
+ }
+
+ std::vector<string> groups = builder->ListGroups();
+ for (const auto& group_name : groups) {
+ if (base::EndsWith(
+ group_name, target_suffix, base::CompareCase::SENSITIVE)) {
+ LOG(INFO) << "Removing group " << group_name;
+ builder->RemoveGroupAndPartitions(group_name);
+ }
+ }
+
+ uint64_t total_size = 0;
+ for (const auto& group : partition_metadata.groups) {
+ total_size += group.size;
+ }
+
+ string expr;
+ uint64_t allocatable_space = builder->AllocatableSpace();
+ if (!dynamic_control->IsDynamicPartitionsRetrofit()) {
+ allocatable_space /= 2;
+ expr = "half of ";
+ }
+ if (total_size > allocatable_space) {
+ LOG(ERROR) << "The maximum size of all groups with suffix " << target_suffix
+ << " (" << total_size << ") has exceeded " << expr
+ << " allocatable space for dynamic partitions "
+ << allocatable_space << ".";
+ return false;
+ }
+
+ for (const auto& group : partition_metadata.groups) {
+ auto group_name_suffix = group.name + target_suffix;
+ if (!builder->AddGroup(group_name_suffix, group.size)) {
+ LOG(ERROR) << "Cannot add group " << group_name_suffix << " with size "
+ << group.size;
+ return false;
+ }
+ LOG(INFO) << "Added group " << group_name_suffix << " with size "
+ << group.size;
+
+ for (const auto& partition : group.partitions) {
+ auto partition_name_suffix = partition.name + target_suffix;
+ Partition* p = builder->AddPartition(
+ partition_name_suffix, group_name_suffix, LP_PARTITION_ATTR_READONLY);
+ if (!p) {
+ LOG(ERROR) << "Cannot add partition " << partition_name_suffix
+ << " to group " << group_name_suffix;
+ return false;
+ }
+ if (!builder->ResizePartition(p, partition.size)) {
+ LOG(ERROR) << "Cannot resize partition " << partition_name_suffix
+ << " to size " << partition.size << ". Not enough space?";
+ return false;
+ }
+ LOG(INFO) << "Added partition " << partition_name_suffix << " to group "
+ << group_name_suffix << " with size " << partition.size;
+ }
+ }
+
+ auto target_device =
+ device_dir.Append(fs_mgr_get_super_partition_name(target_slot)).value();
+ return dynamic_control->StoreMetadata(
+ target_device, builder.get(), target_slot);
+}
+
+bool UnmapTargetPartitions(DynamicPartitionControlInterface* dynamic_control,
+ const string& target_suffix,
+ const PartitionMetadata& partition_metadata) {
+ for (const auto& group : partition_metadata.groups) {
+ for (const auto& partition : group.partitions) {
+ if (!dynamic_control->UnmapPartitionOnDeviceMapper(
+ partition.name + target_suffix, true /* wait */)) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+} // namespace
+
+bool BootControlAndroid::InitPartitionMetadata(
Slot target_slot,
- const DeltaArchiveManifest& manifest,
+ const PartitionMetadata& partition_metadata,
bool update_metadata) {
if (fs_mgr_overlayfs_is_setup()) {
// Non DAP devices can use overlayfs as well.
@@ -290,26 +395,45 @@
"resources.\n"
<< "run adb enable-verity to deactivate if required and try again.";
}
- if (!dynamic_control_->GetDynamicPartitionsFeatureFlag().IsEnabled()) {
+ if (!dynamic_control_->IsDynamicPartitionsEnabled()) {
return true;
}
auto source_slot = GetCurrentSlot();
if (target_slot == source_slot) {
- LOG(ERROR) << "Cannot call PreparePartitionsForUpdate on current slot.";
+ LOG(ERROR) << "Cannot call InitPartitionMetadata on current slot.";
return false;
}
// Although the current build supports dynamic partitions, the given payload
// doesn't use it for target partitions. This could happen when applying a
// retrofit update. Skip updating the partition metadata for the target slot.
- is_target_dynamic_ = !manifest.dynamic_partition_metadata().groups().empty();
+ is_target_dynamic_ = !partition_metadata.groups.empty();
if (!is_target_dynamic_) {
return true;
}
- return dynamic_control_->PreparePartitionsForUpdate(
- source_slot, target_slot, manifest, update_metadata);
+ if (!update_metadata) {
+ return true;
+ }
+
+ string target_suffix;
+ if (!GetSuffix(target_slot, &target_suffix)) {
+ return false;
+ }
+
+ // Unmap all the target dynamic partitions because they would become
+ // inconsistent with the new metadata.
+ if (!UnmapTargetPartitions(
+ dynamic_control_.get(), target_suffix, partition_metadata)) {
+ return false;
+ }
+
+ return UpdatePartitionMetadata(dynamic_control_.get(),
+ source_slot,
+ target_slot,
+ target_suffix,
+ partition_metadata);
}
} // namespace chromeos_update_engine
diff --git a/boot_control_android.h b/boot_control_android.h
index 65543ca..a6f33be 100644
--- a/boot_control_android.h
+++ b/boot_control_android.h
@@ -51,9 +51,9 @@
bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
- bool PreparePartitionsForUpdate(Slot slot,
- const DeltaArchiveManifest& manifest,
- bool update_metadata) override;
+ bool InitPartitionMetadata(Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) override;
void Cleanup() override;
private:
@@ -84,7 +84,7 @@
const std::string& partition_name_suffix) const;
// Whether the target partitions should be loaded as dynamic partitions. Set
- // by PreparePartitionsForUpdate() per each update.
+ // by InitPartitionMetadata() per each update.
bool is_target_dynamic_{false};
DISALLOW_COPY_AND_ASSIGN(BootControlAndroid);
diff --git a/boot_control_android_unittest.cc b/boot_control_android_unittest.cc
index e44af15..b2885a3 100644
--- a/boot_control_android_unittest.cc
+++ b/boot_control_android_unittest.cc
@@ -26,22 +26,236 @@
#include <gtest/gtest.h>
#include <libdm/dm.h>
-#include "update_engine/dynamic_partition_test_utils.h"
#include "update_engine/mock_boot_control_hal.h"
#include "update_engine/mock_dynamic_partition_control.h"
using android::dm::DmDeviceState;
+using android::fs_mgr::MetadataBuilder;
using android::hardware::Void;
using std::string;
using testing::_;
using testing::AnyNumber;
+using testing::Contains;
+using testing::Eq;
using testing::Invoke;
+using testing::Key;
+using testing::MakeMatcher;
+using testing::Matcher;
+using testing::MatcherInterface;
+using testing::MatchResultListener;
using testing::NiceMock;
using testing::Not;
using testing::Return;
namespace chromeos_update_engine {
+constexpr const uint32_t kMaxNumSlots = 2;
+constexpr const char* kSlotSuffixes[kMaxNumSlots] = {"_a", "_b"};
+constexpr const char* kFakeDevicePath = "/fake/dev/path/";
+constexpr const char* kFakeDmDevicePath = "/fake/dm/dev/path/";
+constexpr const uint32_t kFakeMetadataSize = 65536;
+constexpr const char* kDefaultGroup = "foo";
+
+// A map describing the size of each partition.
+// "{name, size}"
+using PartitionSizes = std::map<string, uint64_t>;
+
+// "{name_a, size}"
+using PartitionSuffixSizes = std::map<string, uint64_t>;
+
+using PartitionMetadata = BootControlInterface::PartitionMetadata;
+
+// C++ standards do not allow uint64_t (aka unsigned long) to be the parameter
+// of user-defined literal operators.
+constexpr unsigned long long operator"" _MiB(unsigned long long x) { // NOLINT
+ return x << 20;
+}
+constexpr unsigned long long operator"" _GiB(unsigned long long x) { // NOLINT
+ return x << 30;
+}
+
+constexpr uint64_t kDefaultGroupSize = 5_GiB;
+// Super device size. 1 MiB for metadata.
+constexpr uint64_t kDefaultSuperSize = kDefaultGroupSize * 2 + 1_MiB;
+
+template <typename U, typename V>
+std::ostream& operator<<(std::ostream& os, const std::map<U, V>& param) {
+ os << "{";
+ bool first = true;
+ for (const auto& pair : param) {
+ if (!first)
+ os << ", ";
+ os << pair.first << ":" << pair.second;
+ first = false;
+ }
+ return os << "}";
+}
+
+template <typename T>
+std::ostream& operator<<(std::ostream& os, const std::vector<T>& param) {
+ os << "[";
+ bool first = true;
+ for (const auto& e : param) {
+ if (!first)
+ os << ", ";
+ os << e;
+ first = false;
+ }
+ return os << "]";
+}
+
+std::ostream& operator<<(std::ostream& os,
+ const PartitionMetadata::Partition& p) {
+ return os << "{" << p.name << ", " << p.size << "}";
+}
+
+std::ostream& operator<<(std::ostream& os, const PartitionMetadata::Group& g) {
+ return os << "{" << g.name << ", " << g.size << ", " << g.partitions << "}";
+}
+
+std::ostream& operator<<(std::ostream& os, const PartitionMetadata& m) {
+ return os << m.groups;
+}
+
+inline string GetDevice(const string& name) {
+ return kFakeDevicePath + name;
+}
+
+inline string GetDmDevice(const string& name) {
+ return kFakeDmDevicePath + name;
+}
+
+// TODO(elsk): fs_mgr_get_super_partition_name should be mocked.
+inline string GetSuperDevice(uint32_t slot) {
+ return GetDevice(fs_mgr_get_super_partition_name(slot));
+}
+
+struct TestParam {
+ uint32_t source;
+ uint32_t target;
+};
+std::ostream& operator<<(std::ostream& os, const TestParam& param) {
+ return os << "{source: " << param.source << ", target:" << param.target
+ << "}";
+}
+
+// To support legacy tests, auto-convert {name_a: size} map to
+// PartitionMetadata.
+PartitionMetadata partitionSuffixSizesToMetadata(
+ const PartitionSuffixSizes& partition_sizes) {
+ PartitionMetadata metadata;
+ for (const char* suffix : kSlotSuffixes) {
+ metadata.groups.push_back(
+ {string(kDefaultGroup) + suffix, kDefaultGroupSize, {}});
+ }
+ for (const auto& pair : partition_sizes) {
+ for (size_t suffix_idx = 0; suffix_idx < kMaxNumSlots; ++suffix_idx) {
+ if (base::EndsWith(pair.first,
+ kSlotSuffixes[suffix_idx],
+ base::CompareCase::SENSITIVE)) {
+ metadata.groups[suffix_idx].partitions.push_back(
+ {pair.first, pair.second});
+ }
+ }
+ }
+ return metadata;
+}
+
+// To support legacy tests, auto-convert {name: size} map to PartitionMetadata.
+PartitionMetadata partitionSizesToMetadata(
+ const PartitionSizes& partition_sizes) {
+ PartitionMetadata metadata;
+ metadata.groups.push_back({string{kDefaultGroup}, kDefaultGroupSize, {}});
+ for (const auto& pair : partition_sizes) {
+ metadata.groups[0].partitions.push_back({pair.first, pair.second});
+ }
+ return metadata;
+}
+
+std::unique_ptr<MetadataBuilder> NewFakeMetadata(
+ const PartitionMetadata& metadata) {
+ auto builder =
+ MetadataBuilder::New(kDefaultSuperSize, kFakeMetadataSize, kMaxNumSlots);
+ EXPECT_GE(builder->AllocatableSpace(), kDefaultGroupSize * 2);
+ EXPECT_NE(nullptr, builder);
+ if (builder == nullptr)
+ return nullptr;
+ for (const auto& group : metadata.groups) {
+ EXPECT_TRUE(builder->AddGroup(group.name, group.size));
+ for (const auto& partition : group.partitions) {
+ auto p = builder->AddPartition(partition.name, group.name, 0 /* attr */);
+ EXPECT_TRUE(p && builder->ResizePartition(p, partition.size));
+ }
+ }
+ return builder;
+}
+
+class MetadataMatcher : public MatcherInterface<MetadataBuilder*> {
+ public:
+ explicit MetadataMatcher(const PartitionSuffixSizes& partition_sizes)
+ : partition_metadata_(partitionSuffixSizesToMetadata(partition_sizes)) {}
+ explicit MetadataMatcher(const PartitionMetadata& partition_metadata)
+ : partition_metadata_(partition_metadata) {}
+
+ bool MatchAndExplain(MetadataBuilder* metadata,
+ MatchResultListener* listener) const override {
+ bool success = true;
+ for (const auto& group : partition_metadata_.groups) {
+ for (const auto& partition : group.partitions) {
+ auto p = metadata->FindPartition(partition.name);
+ if (p == nullptr) {
+ if (!success)
+ *listener << "; ";
+ *listener << "No partition " << partition.name;
+ success = false;
+ continue;
+ }
+ if (p->size() != partition.size) {
+ if (!success)
+ *listener << "; ";
+ *listener << "Partition " << partition.name << " has size "
+ << p->size() << ", expected " << partition.size;
+ success = false;
+ }
+ if (p->group_name() != group.name) {
+ if (!success)
+ *listener << "; ";
+ *listener << "Partition " << partition.name << " has group "
+ << p->group_name() << ", expected " << group.name;
+ success = false;
+ }
+ }
+ }
+ return success;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "expect: " << partition_metadata_;
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "expect not: " << partition_metadata_;
+ }
+
+ private:
+ PartitionMetadata partition_metadata_;
+};
+
+inline Matcher<MetadataBuilder*> MetadataMatches(
+ const PartitionSuffixSizes& partition_sizes) {
+ return MakeMatcher(new MetadataMatcher(partition_sizes));
+}
+
+inline Matcher<MetadataBuilder*> MetadataMatches(
+ const PartitionMetadata& partition_metadata) {
+ return MakeMatcher(new MetadataMatcher(partition_metadata));
+}
+
+MATCHER_P(HasGroup, group, " has group " + group) {
+ auto groups = arg->ListGroups();
+ return std::find(groups.begin(), groups.end(), group) != groups.end();
+}
+
class BootControlAndroidTest : public ::testing::Test {
protected:
void SetUp() override {
@@ -60,10 +274,10 @@
return Void();
}));
- ON_CALL(dynamicControl(), GetDynamicPartitionsFeatureFlag())
- .WillByDefault(Return(FeatureFlag(FeatureFlag::Value::LAUNCH)));
- ON_CALL(dynamicControl(), GetVirtualAbFeatureFlag())
- .WillByDefault(Return(FeatureFlag(FeatureFlag::Value::NONE)));
+ ON_CALL(dynamicControl(), IsDynamicPartitionsEnabled())
+ .WillByDefault(Return(true));
+ ON_CALL(dynamicControl(), IsDynamicPartitionsRetrofit())
+ .WillByDefault(Return(false));
ON_CALL(dynamicControl(), DeviceExists(_)).WillByDefault(Return(true));
ON_CALL(dynamicControl(), GetDeviceDir(_))
.WillByDefault(Invoke([](auto path) {
@@ -75,13 +289,6 @@
*device = GetDmDevice(partition_name_suffix);
return true;
}));
-
- ON_CALL(dynamicControl(), GetSuperPartitionName(_))
- .WillByDefault(Return(kFakeSuper));
- }
-
- std::string GetSuperDevice(uint32_t slot) {
- return GetDevice(dynamicControl().GetSuperPartitionName(slot));
}
// Return the mocked HAL module.
@@ -98,14 +305,53 @@
// Set the fake metadata to return when LoadMetadataBuilder is called on
// |slot|.
void SetMetadata(uint32_t slot, const PartitionSuffixSizes& sizes) {
+ SetMetadata(slot, partitionSuffixSizesToMetadata(sizes));
+ }
+
+ void SetMetadata(uint32_t slot, const PartitionMetadata& metadata) {
EXPECT_CALL(dynamicControl(),
- LoadMetadataBuilder(GetSuperDevice(slot), slot))
+ LoadMetadataBuilder(GetSuperDevice(slot), slot, _))
.Times(AnyNumber())
- .WillRepeatedly(Invoke([sizes](auto, auto) {
- return NewFakeMetadata(PartitionSuffixSizesToManifest(sizes));
+ .WillRepeatedly(Invoke([metadata](auto, auto, auto) {
+ return NewFakeMetadata(metadata);
}));
}
+ // Expect that UnmapPartitionOnDeviceMapper is called on target() metadata
+ // slot with each partition in |partitions|.
+ void ExpectUnmap(const std::set<string>& partitions) {
+ // Error when UnmapPartitionOnDeviceMapper is called on unknown arguments.
+ ON_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(_, _))
+ .WillByDefault(Return(false));
+
+ for (const auto& partition : partitions) {
+ EXPECT_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(partition, _))
+ .WillOnce(Invoke([this](auto partition, auto) {
+ mapped_devices_.erase(partition);
+ return true;
+ }));
+ }
+ }
+
+ void ExpectDevicesAreMapped(const std::set<string>& partitions) {
+ ASSERT_EQ(partitions.size(), mapped_devices_.size());
+ for (const auto& partition : partitions) {
+ EXPECT_THAT(mapped_devices_, Contains(Key(Eq(partition))))
+ << "Expect that " << partition << " is mapped, but it is not.";
+ }
+ }
+
+ void ExpectStoreMetadata(const PartitionSuffixSizes& partition_sizes) {
+ ExpectStoreMetadataMatch(MetadataMatches(partition_sizes));
+ }
+
+ virtual void ExpectStoreMetadataMatch(
+ const Matcher<MetadataBuilder*>& matcher) {
+ EXPECT_CALL(dynamicControl(),
+ StoreMetadata(GetSuperDevice(target()), matcher, target()))
+ .WillOnce(Return(true));
+ }
+
uint32_t source() { return slots_.source; }
uint32_t target() { return slots_.target; }
@@ -123,17 +369,28 @@
ON_CALL(module(), getCurrentSlot()).WillByDefault(Invoke([this] {
return source();
}));
+ // Should not store metadata to source slot.
+ EXPECT_CALL(dynamicControl(),
+ StoreMetadata(GetSuperDevice(source()), _, source()))
+ .Times(0);
+ // Should not load metadata from target slot.
+ EXPECT_CALL(dynamicControl(),
+ LoadMetadataBuilder(GetSuperDevice(target()), target(), _))
+ .Times(0);
}
- bool PreparePartitionsForUpdate(uint32_t slot,
- PartitionSizes partition_sizes,
- bool update_metadata = true) {
- auto m = PartitionSizesToManifest(partition_sizes);
- return bootctl_.PreparePartitionsForUpdate(slot, m, update_metadata);
+ bool InitPartitionMetadata(uint32_t slot,
+ PartitionSizes partition_sizes,
+ bool update_metadata = true) {
+ auto m = partitionSizesToMetadata(partition_sizes);
+ LOG(INFO) << m;
+ return bootctl_.InitPartitionMetadata(slot, m, update_metadata);
}
BootControlAndroid bootctl_; // BootControlAndroid under test.
TestParam slots_;
+ // mapped devices through MapPartitionOnDeviceMapper.
+ std::map<string, string> mapped_devices_;
};
class BootControlAndroidTestP
@@ -146,6 +403,125 @@
}
};
+// Test resize case. Grow if target metadata contains a partition with a size
+// less than expected.
+TEST_P(BootControlAndroidTestP, NeedGrowIfSizeNotMatchWhenResizing) {
+ SetMetadata(source(),
+ {{S("system"), 2_GiB},
+ {S("vendor"), 1_GiB},
+ {T("system"), 2_GiB},
+ {T("vendor"), 1_GiB}});
+ ExpectStoreMetadata({{S("system"), 2_GiB},
+ {S("vendor"), 1_GiB},
+ {T("system"), 3_GiB},
+ {T("vendor"), 1_GiB}});
+ ExpectUnmap({T("system"), T("vendor")});
+
+ EXPECT_TRUE(
+ InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 1_GiB}}));
+}
+
+// Test resize case. Shrink if target metadata contains a partition with a size
+// greater than expected.
+TEST_P(BootControlAndroidTestP, NeedShrinkIfSizeNotMatchWhenResizing) {
+ SetMetadata(source(),
+ {{S("system"), 2_GiB},
+ {S("vendor"), 1_GiB},
+ {T("system"), 2_GiB},
+ {T("vendor"), 1_GiB}});
+ ExpectStoreMetadata({{S("system"), 2_GiB},
+ {S("vendor"), 1_GiB},
+ {T("system"), 2_GiB},
+ {T("vendor"), 150_MiB}});
+ ExpectUnmap({T("system"), T("vendor")});
+
+ EXPECT_TRUE(InitPartitionMetadata(target(),
+ {{"system", 2_GiB}, {"vendor", 150_MiB}}));
+}
+
+// Test adding partitions on the first run.
+TEST_P(BootControlAndroidTestP, AddPartitionToEmptyMetadata) {
+ SetMetadata(source(), PartitionSuffixSizes{});
+ ExpectStoreMetadata({{T("system"), 2_GiB}, {T("vendor"), 1_GiB}});
+ ExpectUnmap({T("system"), T("vendor")});
+
+ EXPECT_TRUE(
+ InitPartitionMetadata(target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}));
+}
+
+// Test subsequent add case.
+TEST_P(BootControlAndroidTestP, AddAdditionalPartition) {
+ SetMetadata(source(), {{S("system"), 2_GiB}, {T("system"), 2_GiB}});
+ ExpectStoreMetadata(
+ {{S("system"), 2_GiB}, {T("system"), 2_GiB}, {T("vendor"), 1_GiB}});
+ ExpectUnmap({T("system"), T("vendor")});
+
+ EXPECT_TRUE(
+ InitPartitionMetadata(target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}));
+}
+
+// Test delete one partition.
+TEST_P(BootControlAndroidTestP, DeletePartition) {
+ SetMetadata(source(),
+ {{S("system"), 2_GiB},
+ {S("vendor"), 1_GiB},
+ {T("system"), 2_GiB},
+ {T("vendor"), 1_GiB}});
+ // No T("vendor")
+ ExpectStoreMetadata(
+ {{S("system"), 2_GiB}, {S("vendor"), 1_GiB}, {T("system"), 2_GiB}});
+ ExpectUnmap({T("system")});
+
+ EXPECT_TRUE(InitPartitionMetadata(target(), {{"system", 2_GiB}}));
+}
+
+// Test delete all partitions.
+TEST_P(BootControlAndroidTestP, DeleteAll) {
+ SetMetadata(source(),
+ {{S("system"), 2_GiB},
+ {S("vendor"), 1_GiB},
+ {T("system"), 2_GiB},
+ {T("vendor"), 1_GiB}});
+ ExpectStoreMetadata({{S("system"), 2_GiB}, {S("vendor"), 1_GiB}});
+
+ EXPECT_TRUE(InitPartitionMetadata(target(), {}));
+}
+
+// Test corrupt source metadata case.
+TEST_P(BootControlAndroidTestP, CorruptedSourceMetadata) {
+ EXPECT_CALL(dynamicControl(),
+ LoadMetadataBuilder(GetSuperDevice(source()), source(), _))
+ .WillOnce(Invoke([](auto, auto, auto) { return nullptr; }));
+ ExpectUnmap({T("system")});
+
+ EXPECT_FALSE(InitPartitionMetadata(target(), {{"system", 1_GiB}}))
+ << "Should not be able to continue with corrupt source metadata";
+}
+
+// Test that InitPartitionMetadata fail if there is not enough space on the
+// device.
+TEST_P(BootControlAndroidTestP, NotEnoughSpace) {
+ SetMetadata(source(),
+ {{S("system"), 3_GiB},
+ {S("vendor"), 2_GiB},
+ {T("system"), 0},
+ {T("vendor"), 0}});
+ EXPECT_FALSE(
+ InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 3_GiB}}))
+ << "Should not be able to fit 11GiB data into 10GiB space";
+}
+
+TEST_P(BootControlAndroidTestP, NotEnoughSpaceForSlot) {
+ SetMetadata(source(),
+ {{S("system"), 1_GiB},
+ {S("vendor"), 1_GiB},
+ {T("system"), 0},
+ {T("vendor"), 0}});
+ EXPECT_FALSE(
+ InitPartitionMetadata(target(), {{"system", 3_GiB}, {"vendor", 3_GiB}}))
+ << "Should not be able to grow over size of super / 2";
+}
+
// Test applying retrofit update on a build with dynamic partitions enabled.
TEST_P(BootControlAndroidTestP,
ApplyRetrofitUpdateOnDynamicPartitionsEnabledBuild) {
@@ -154,10 +530,16 @@
{S("vendor"), 1_GiB},
{T("system"), 2_GiB},
{T("vendor"), 1_GiB}});
+ // Should not try to unmap any target partition.
+ EXPECT_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(_, _)).Times(0);
+ // Should not store metadata to target slot.
+ EXPECT_CALL(dynamicControl(),
+ StoreMetadata(GetSuperDevice(target()), _, target()))
+ .Times(0);
- // Not calling through BootControlAndroidTest::PreparePartitionsForUpdate(),
- // since we don't want any default group in the PartitionMetadata.
- EXPECT_TRUE(bootctl_.PreparePartitionsForUpdate(target(), {}, true));
+ // Not calling through BootControlAndroidTest::InitPartitionMetadata(), since
+ // we don't want any default group in the PartitionMetadata.
+ EXPECT_TRUE(bootctl_.InitPartitionMetadata(target(), {}, true));
// Should use dynamic source partitions.
EXPECT_CALL(dynamicControl(), GetState(S("system")))
@@ -196,11 +578,10 @@
{S("vendor"), 1_GiB},
{T("system"), 2_GiB},
{T("vendor"), 1_GiB}});
-
- EXPECT_CALL(dynamicControl(), PreparePartitionsForUpdate(_, _, _, false))
- .WillOnce(Return(true));
-
- EXPECT_TRUE(PreparePartitionsForUpdate(
+ EXPECT_CALL(dynamicControl(),
+ StoreMetadata(GetSuperDevice(target()), _, target()))
+ .Times(0);
+ EXPECT_TRUE(InitPartitionMetadata(
target(), {{"system", 2_GiB}, {"vendor", 1_GiB}}, false));
// Dynamic partition "system".
@@ -241,10 +622,241 @@
BootControlAndroidTestP,
testing::Values(TestParam{0, 1}, TestParam{1, 0}));
+const PartitionSuffixSizes update_sizes_0() {
+ // Initial state is 0 for "other" slot.
+ return {
+ {"grown_a", 2_GiB},
+ {"shrunk_a", 1_GiB},
+ {"same_a", 100_MiB},
+ {"deleted_a", 150_MiB},
+ // no added_a
+ {"grown_b", 200_MiB},
+ // simulate system_other
+ {"shrunk_b", 0},
+ {"same_b", 0},
+ {"deleted_b", 0},
+ // no added_b
+ };
+}
+
+const PartitionSuffixSizes update_sizes_1() {
+ return {
+ {"grown_a", 2_GiB},
+ {"shrunk_a", 1_GiB},
+ {"same_a", 100_MiB},
+ {"deleted_a", 150_MiB},
+ // no added_a
+ {"grown_b", 3_GiB},
+ {"shrunk_b", 150_MiB},
+ {"same_b", 100_MiB},
+ {"added_b", 150_MiB},
+ // no deleted_b
+ };
+}
+
+const PartitionSuffixSizes update_sizes_2() {
+ return {
+ {"grown_a", 4_GiB},
+ {"shrunk_a", 100_MiB},
+ {"same_a", 100_MiB},
+ {"deleted_a", 64_MiB},
+ // no added_a
+ {"grown_b", 3_GiB},
+ {"shrunk_b", 150_MiB},
+ {"same_b", 100_MiB},
+ {"added_b", 150_MiB},
+ // no deleted_b
+ };
+}
+
+// Test case for first update after the device is manufactured, in which
+// case the "other" slot is likely of size "0" (except system, which is
+// non-zero because of system_other partition)
+TEST_F(BootControlAndroidTest, SimulatedFirstUpdate) {
+ SetSlots({0, 1});
+
+ SetMetadata(source(), update_sizes_0());
+ SetMetadata(target(), update_sizes_0());
+ ExpectStoreMetadata(update_sizes_1());
+ ExpectUnmap({"grown_b", "shrunk_b", "same_b", "added_b"});
+
+ EXPECT_TRUE(InitPartitionMetadata(target(),
+ {{"grown", 3_GiB},
+ {"shrunk", 150_MiB},
+ {"same", 100_MiB},
+ {"added", 150_MiB}}));
+}
+
+// After first update, test for the second update. In the second update, the
+// "added" partition is deleted and "deleted" partition is re-added.
+TEST_F(BootControlAndroidTest, SimulatedSecondUpdate) {
+ SetSlots({1, 0});
+
+ SetMetadata(source(), update_sizes_1());
+ SetMetadata(target(), update_sizes_0());
+
+ ExpectStoreMetadata(update_sizes_2());
+ ExpectUnmap({"grown_a", "shrunk_a", "same_a", "deleted_a"});
+
+ EXPECT_TRUE(InitPartitionMetadata(target(),
+ {{"grown", 4_GiB},
+ {"shrunk", 100_MiB},
+ {"same", 100_MiB},
+ {"deleted", 64_MiB}}));
+}
+
TEST_F(BootControlAndroidTest, ApplyingToCurrentSlot) {
SetSlots({1, 1});
- EXPECT_FALSE(PreparePartitionsForUpdate(target(), {}))
+ EXPECT_FALSE(InitPartitionMetadata(target(), {}))
<< "Should not be able to apply to current slot.";
}
+class BootControlAndroidGroupTestP : public BootControlAndroidTestP {
+ public:
+ void SetUp() override {
+ BootControlAndroidTestP::SetUp();
+ SetMetadata(
+ source(),
+ {.groups = {SimpleGroup(S("android"), 3_GiB, S("system"), 2_GiB),
+ SimpleGroup(S("oem"), 2_GiB, S("vendor"), 1_GiB),
+ SimpleGroup(T("android"), 3_GiB, T("system"), 0),
+ SimpleGroup(T("oem"), 2_GiB, T("vendor"), 0)}});
+ }
+
+ // Return a simple group with only one partition.
+ PartitionMetadata::Group SimpleGroup(const string& group,
+ uint64_t group_size,
+ const string& partition,
+ uint64_t partition_size) {
+ return {.name = group,
+ .size = group_size,
+ .partitions = {{.name = partition, .size = partition_size}}};
+ }
+
+ void ExpectStoreMetadata(const PartitionMetadata& partition_metadata) {
+ ExpectStoreMetadataMatch(MetadataMatches(partition_metadata));
+ }
+
+ // Expect that target slot is stored with target groups.
+ void ExpectStoreMetadataMatch(
+ const Matcher<MetadataBuilder*>& matcher) override {
+ BootControlAndroidTestP::ExpectStoreMetadataMatch(AllOf(
+ MetadataMatches(PartitionMetadata{
+ .groups = {SimpleGroup(S("android"), 3_GiB, S("system"), 2_GiB),
+ SimpleGroup(S("oem"), 2_GiB, S("vendor"), 1_GiB)}}),
+ matcher));
+ }
+};
+
+// Allow to resize within group.
+TEST_P(BootControlAndroidGroupTestP, ResizeWithinGroup) {
+ ExpectStoreMetadata(PartitionMetadata{
+ .groups = {SimpleGroup(T("android"), 3_GiB, T("system"), 3_GiB),
+ SimpleGroup(T("oem"), 2_GiB, T("vendor"), 2_GiB)}});
+ ExpectUnmap({T("system"), T("vendor")});
+
+ EXPECT_TRUE(bootctl_.InitPartitionMetadata(
+ target(),
+ PartitionMetadata{
+ .groups = {SimpleGroup("android", 3_GiB, "system", 3_GiB),
+ SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
+ true));
+}
+
+TEST_P(BootControlAndroidGroupTestP, NotEnoughSpaceForGroup) {
+ EXPECT_FALSE(bootctl_.InitPartitionMetadata(
+ target(),
+ PartitionMetadata{
+ .groups = {SimpleGroup("android", 3_GiB, "system", 1_GiB),
+ SimpleGroup("oem", 2_GiB, "vendor", 3_GiB)}},
+ true))
+ << "Should not be able to grow over maximum size of group";
+}
+
+TEST_P(BootControlAndroidGroupTestP, GroupTooBig) {
+ EXPECT_FALSE(bootctl_.InitPartitionMetadata(
+ target(),
+ PartitionMetadata{.groups = {{.name = "android", .size = 3_GiB},
+ {.name = "oem", .size = 3_GiB}}},
+ true))
+ << "Should not be able to grow over size of super / 2";
+}
+
+TEST_P(BootControlAndroidGroupTestP, AddPartitionToGroup) {
+ ExpectStoreMetadata(PartitionMetadata{
+ .groups = {
+ {.name = T("android"),
+ .size = 3_GiB,
+ .partitions = {{.name = T("system"), .size = 2_GiB},
+ {.name = T("product_services"), .size = 1_GiB}}}}});
+ ExpectUnmap({T("system"), T("vendor"), T("product_services")});
+
+ EXPECT_TRUE(bootctl_.InitPartitionMetadata(
+ target(),
+ PartitionMetadata{
+ .groups = {{.name = "android",
+ .size = 3_GiB,
+ .partitions = {{.name = "system", .size = 2_GiB},
+ {.name = "product_services",
+ .size = 1_GiB}}},
+ SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
+ true));
+}
+
+TEST_P(BootControlAndroidGroupTestP, RemovePartitionFromGroup) {
+ ExpectStoreMetadata(PartitionMetadata{
+ .groups = {{.name = T("android"), .size = 3_GiB, .partitions = {}}}});
+ ExpectUnmap({T("vendor")});
+
+ EXPECT_TRUE(bootctl_.InitPartitionMetadata(
+ target(),
+ PartitionMetadata{
+ .groups = {{.name = "android", .size = 3_GiB, .partitions = {}},
+ SimpleGroup("oem", 2_GiB, "vendor", 2_GiB)}},
+ true));
+}
+
+TEST_P(BootControlAndroidGroupTestP, AddGroup) {
+ ExpectStoreMetadata(PartitionMetadata{
+ .groups = {
+ SimpleGroup(T("new_group"), 2_GiB, T("new_partition"), 2_GiB)}});
+ ExpectUnmap({T("system"), T("vendor"), T("new_partition")});
+
+ EXPECT_TRUE(bootctl_.InitPartitionMetadata(
+ target(),
+ PartitionMetadata{
+ .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
+ SimpleGroup("oem", 1_GiB, "vendor", 1_GiB),
+ SimpleGroup("new_group", 2_GiB, "new_partition", 2_GiB)}},
+ true));
+}
+
+TEST_P(BootControlAndroidGroupTestP, RemoveGroup) {
+ ExpectStoreMetadataMatch(Not(HasGroup(T("oem"))));
+ ExpectUnmap({T("system")});
+ EXPECT_TRUE(bootctl_.InitPartitionMetadata(
+ target(),
+ PartitionMetadata{
+ .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB)}},
+ true));
+}
+
+TEST_P(BootControlAndroidGroupTestP, ResizeGroup) {
+ ExpectStoreMetadata(PartitionMetadata{
+ .groups = {SimpleGroup(T("android"), 2_GiB, T("system"), 2_GiB),
+ SimpleGroup(T("oem"), 3_GiB, T("vendor"), 3_GiB)}});
+ ExpectUnmap({T("system"), T("vendor")});
+
+ EXPECT_TRUE(bootctl_.InitPartitionMetadata(
+ target(),
+ PartitionMetadata{
+ .groups = {SimpleGroup("android", 2_GiB, "system", 2_GiB),
+ SimpleGroup("oem", 3_GiB, "vendor", 3_GiB)}},
+ true));
+}
+
+INSTANTIATE_TEST_CASE_P(BootControlAndroidTest,
+ BootControlAndroidGroupTestP,
+ testing::Values(TestParam{0, 1}, TestParam{1, 0}));
+
} // namespace chromeos_update_engine
diff --git a/boot_control_chromeos.cc b/boot_control_chromeos.cc
index 7e748d5..ccba316 100644
--- a/boot_control_chromeos.cc
+++ b/boot_control_chromeos.cc
@@ -326,8 +326,10 @@
return -1;
}
-bool BootControlChromeOS::PreparePartitionsForUpdate(
- Slot slot, const DeltaArchiveManifest& manifest, bool update_metadata) {
+bool BootControlChromeOS::InitPartitionMetadata(
+ Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) {
return true;
}
diff --git a/boot_control_chromeos.h b/boot_control_chromeos.h
index 29841c9..f3682e9 100644
--- a/boot_control_chromeos.h
+++ b/boot_control_chromeos.h
@@ -50,9 +50,9 @@
bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
- bool PreparePartitionsForUpdate(Slot slot,
- const DeltaArchiveManifest& manifest,
- bool update_metadata) override;
+ bool InitPartitionMetadata(Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) override;
void Cleanup() override;
private:
diff --git a/common/boot_control_interface.h b/common/boot_control_interface.h
index 9bf639a..392d785 100644
--- a/common/boot_control_interface.h
+++ b/common/boot_control_interface.h
@@ -25,8 +25,6 @@
#include <base/callback.h>
#include <base/macros.h>
-#include "update_engine/update_metadata.pb.h"
-
namespace chromeos_update_engine {
// The abstract boot control interface defines the interaction with the
@@ -37,6 +35,19 @@
public:
using Slot = unsigned int;
+ struct PartitionMetadata {
+ struct Partition {
+ std::string name;
+ uint64_t size;
+ };
+ struct Group {
+ std::string name;
+ uint64_t size;
+ std::vector<Partition> partitions;
+ };
+ std::vector<Group> groups;
+ };
+
static const Slot kInvalidSlot = UINT_MAX;
virtual ~BootControlInterface() = default;
@@ -56,9 +67,9 @@
// The |slot| number must be between 0 and GetNumSlots() - 1 and the
// |partition_name| is a platform-specific name that identifies a partition on
// every slot. In order to access the dynamic partitions in the target slot,
- // PreparePartitionsForUpdate() must be called (once per payload) prior to
- // calling this function. On success, returns true and stores the block device
- // in |device|.
+ // InitPartitionMetadata() must be called (once per payload) prior to calling
+ // this function. On success, returns true and stores the block device in
+ // |device|.
virtual bool GetPartitionDevice(const std::string& partition_name,
Slot slot,
std::string* device) const = 0;
@@ -85,11 +96,12 @@
// Initializes the metadata of the underlying partitions for a given |slot|
// and sets up the states for accessing dynamic partitions.
- // Metadata will be written to the specified |slot| if
+ // |partition_metadata| will be written to the specified |slot| if
// |update_metadata| is set.
- virtual bool PreparePartitionsForUpdate(Slot slot,
- const DeltaArchiveManifest& manifest,
- bool update_metadata) = 0;
+ virtual bool InitPartitionMetadata(
+ Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) = 0;
// Do necessary clean-up operations after the whole update.
virtual void Cleanup() = 0;
diff --git a/common/boot_control_stub.cc b/common/boot_control_stub.cc
index b10e82f..0fe8a98 100644
--- a/common/boot_control_stub.cc
+++ b/common/boot_control_stub.cc
@@ -59,8 +59,10 @@
return false;
}
-bool BootControlStub::PreparePartitionsForUpdate(
- Slot slot, const DeltaArchiveManifest& manifest, bool update_metadata) {
+bool BootControlStub::InitPartitionMetadata(
+ Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
diff --git a/common/boot_control_stub.h b/common/boot_control_stub.h
index f2973a2..8dfaffc 100644
--- a/common/boot_control_stub.h
+++ b/common/boot_control_stub.h
@@ -45,9 +45,9 @@
bool MarkSlotUnbootable(BootControlInterface::Slot slot) override;
bool SetActiveBootSlot(BootControlInterface::Slot slot) override;
bool MarkBootSuccessfulAsync(base::Callback<void(bool)> callback) override;
- bool PreparePartitionsForUpdate(Slot slot,
- const DeltaArchiveManifest& manifest,
- bool update_metadata) override;
+ bool InitPartitionMetadata(Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) override;
void Cleanup() override;
private:
diff --git a/common/fake_boot_control.h b/common/fake_boot_control.h
index 11810d1..3d65075 100644
--- a/common/fake_boot_control.h
+++ b/common/fake_boot_control.h
@@ -74,9 +74,9 @@
return true;
}
- bool PreparePartitionsForUpdate(Slot slot,
- const DeltaArchiveManifest& manifest,
- bool update_metadata) override {
+ bool InitPartitionMetadata(Slot slot,
+ const PartitionMetadata& partition_metadata,
+ bool update_metadata) override {
return true;
}
diff --git a/common/fake_hardware.h b/common/fake_hardware.h
index 8da5326..3e5a66e 100644
--- a/common/fake_hardware.h
+++ b/common/fake_hardware.h
@@ -128,8 +128,6 @@
int64_t GetBuildTimestamp() const override { return build_timestamp_; }
- bool AllowDowngrade() const override { return false; }
-
bool GetFirstActiveOmahaPingSent() const override {
return first_active_omaha_ping_sent_;
}
diff --git a/common/file_fetcher.cc b/common/file_fetcher.cc
index 7134fd6..3836e54 100644
--- a/common/file_fetcher.cc
+++ b/common/file_fetcher.cc
@@ -43,9 +43,8 @@
// static
bool FileFetcher::SupportedUrl(const string& url) {
// Note that we require the file path to start with a "/".
- return (
- base::StartsWith(url, "file:///", base::CompareCase::INSENSITIVE_ASCII) ||
- base::StartsWith(url, "fd://", base::CompareCase::INSENSITIVE_ASCII));
+ return base::StartsWith(
+ url, "file:///", base::CompareCase::INSENSITIVE_ASCII);
}
FileFetcher::~FileFetcher() {
@@ -68,20 +67,12 @@
return;
}
- string file_path;
-
- if (base::StartsWith(url, "fd://", base::CompareCase::INSENSITIVE_ASCII)) {
- int fd = std::stoi(url.substr(strlen("fd://")));
- file_path = url;
- stream_ = brillo::FileStream::FromFileDescriptor(fd, false, nullptr);
- } else {
- file_path = url.substr(strlen("file://"));
- stream_ =
- brillo::FileStream::Open(base::FilePath(file_path),
- brillo::Stream::AccessMode::READ,
- brillo::FileStream::Disposition::OPEN_EXISTING,
- nullptr);
- }
+ string file_path = url.substr(strlen("file://"));
+ stream_ =
+ brillo::FileStream::Open(base::FilePath(file_path),
+ brillo::Stream::AccessMode::READ,
+ brillo::FileStream::Disposition::OPEN_EXISTING,
+ nullptr);
if (!stream_) {
LOG(ERROR) << "Couldn't open " << file_path;
@@ -192,4 +183,5 @@
transfer_in_progress_ = false;
transfer_paused_ = false;
}
+
} // namespace chromeos_update_engine
diff --git a/common/hardware_interface.h b/common/hardware_interface.h
index 4a64c3e..0140588 100644
--- a/common/hardware_interface.h
+++ b/common/hardware_interface.h
@@ -122,10 +122,6 @@
// Returns the timestamp of the current OS build.
virtual int64_t GetBuildTimestamp() const = 0;
- // Returns true if the current OS build allows installing the payload with an
- // older timestamp.
- virtual bool AllowDowngrade() const = 0;
-
// Returns whether the first active ping was sent to Omaha at some point, and
// that the value is persisted across recovery (and powerwash) once set with
// |SetFirstActiveOmahaPingSent()|.
diff --git a/common/platform_constants.h b/common/platform_constants.h
index 243af69..6eaa940 100644
--- a/common/platform_constants.h
+++ b/common/platform_constants.h
@@ -38,10 +38,6 @@
// whole payload.
extern const char kUpdatePayloadPublicKeyPath[];
-// Path to the location of the zip archive file that contains PEM encoded X509
-// certificates. e.g. 'system/etc/security/otacerts.zip'.
-extern const char kUpdateCertificatesPath[];
-
// Path to the directory containing all the SSL certificates accepted by
// update_engine when sending requests to Omaha and the download server (if
// HTTPS is used for that as well).
diff --git a/common/platform_constants_android.cc b/common/platform_constants_android.cc
index f468c3b..9d8d30e 100644
--- a/common/platform_constants_android.cc
+++ b/common/platform_constants_android.cc
@@ -25,8 +25,8 @@
"https://clients2.google.com/service/update2/brillo";
const char kOmahaUpdaterID[] = "Brillo";
const char kOmahaPlatformName[] = "Brillo";
-const char kUpdatePayloadPublicKeyPath[] = "";
-const char kUpdateCertificatesPath[] = "/system/etc/security/otacerts.zip";
+const char kUpdatePayloadPublicKeyPath[] =
+ "/etc/update_engine/update-payload-key.pub.pem";
const char kCACertificatesPath[] = "/system/etc/security/cacerts_google";
// No deadline file API support on Android.
const char kOmahaResponseDeadlineFile[] = "";
diff --git a/common/platform_constants_chromeos.cc b/common/platform_constants_chromeos.cc
index fe94a45..f1ac490 100644
--- a/common/platform_constants_chromeos.cc
+++ b/common/platform_constants_chromeos.cc
@@ -27,7 +27,6 @@
const char kOmahaPlatformName[] = "Chrome OS";
const char kUpdatePayloadPublicKeyPath[] =
"/usr/share/update_engine/update-payload-key.pub.pem";
-const char kUpdateCertificatesPath[] = "";
const char kCACertificatesPath[] = "/usr/share/chromeos-ca-certificates";
const char kOmahaResponseDeadlineFile[] = "/tmp/update-check-response-deadline";
// This directory is wiped during powerwash.
diff --git a/common/utils.cc b/common/utils.cc
index e7b6975..34d97a2 100644
--- a/common/utils.cc
+++ b/common/utils.cc
@@ -1064,16 +1064,6 @@
}
}
-string GetFilePath(int fd) {
- base::FilePath proc("/proc/self/fd/" + std::to_string(fd));
- base::FilePath file_name;
-
- if (!base::ReadSymbolicLink(proc, &file_name)) {
- return "not found";
- }
- return file_name.value();
-}
-
} // namespace utils
} // namespace chromeos_update_engine
diff --git a/common/utils.h b/common/utils.h
index 9dca9e8..9160d9f 100644
--- a/common/utils.h
+++ b/common/utils.h
@@ -304,9 +304,6 @@
// reboot. Returns whether it succeeded getting the boot_id.
bool GetBootId(std::string* boot_id);
-// This function gets the file path of the file pointed to by FileDiscriptor.
-std::string GetFilePath(int fd);
-
// Divide |x| by |y| and round up to the nearest integer.
constexpr uint64_t DivRoundUp(uint64_t x, uint64_t y) {
return (x + y - 1) / y;
diff --git a/common/utils_unittest.cc b/common/utils_unittest.cc
index b4ac2f5..7d1c59e 100644
--- a/common/utils_unittest.cc
+++ b/common/utils_unittest.cc
@@ -507,13 +507,4 @@
ExpectInvalidParseRollbackKeyVersion("1.99999");
}
-TEST(UtilsTest, GetFilePathTest) {
- test_utils::ScopedTempFile file;
- int fd = HANDLE_EINTR(open(file.path().c_str(), O_RDONLY));
- EXPECT_GE(fd, 0);
- EXPECT_EQ(file.path(), utils::GetFilePath(fd));
- EXPECT_EQ("not found", utils::GetFilePath(-1));
- IGNORE_EINTR(close(fd));
-}
-
} // namespace chromeos_update_engine
diff --git a/dynamic_partition_control_android.cc b/dynamic_partition_control_android.cc
index c641a6b..40c2663 100644
--- a/dynamic_partition_control_android.cc
+++ b/dynamic_partition_control_android.cc
@@ -16,90 +16,46 @@
#include "update_engine/dynamic_partition_control_android.h"
-#include <chrono> // NOLINT(build/c++11) - using libsnapshot / liblp API
-#include <map>
#include <memory>
#include <set>
#include <string>
-#include <vector>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <base/files/file_util.h>
#include <base/logging.h>
-#include <base/strings/string_util.h>
#include <bootloader_message/bootloader_message.h>
-#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
-#include <libsnapshot/snapshot.h>
#include "update_engine/common/boot_control_interface.h"
#include "update_engine/common/utils.h"
-#include "update_engine/dynamic_partition_utils.h"
using android::base::GetBoolProperty;
using android::base::Join;
using android::dm::DeviceMapper;
using android::dm::DmDeviceState;
using android::fs_mgr::CreateLogicalPartition;
-using android::fs_mgr::CreateLogicalPartitionParams;
using android::fs_mgr::DestroyLogicalPartition;
using android::fs_mgr::MetadataBuilder;
-using android::fs_mgr::Partition;
using android::fs_mgr::PartitionOpener;
-using android::fs_mgr::SlotSuffixForSlotNumber;
namespace chromeos_update_engine {
constexpr char kUseDynamicPartitions[] = "ro.boot.dynamic_partitions";
constexpr char kRetrfoitDynamicPartitions[] =
"ro.boot.dynamic_partitions_retrofit";
-constexpr char kVirtualAbEnabled[] = "ro.virtual_ab.enabled";
-constexpr char kVirtualAbRetrofit[] = "ro.virtual_ab.retrofit";
-// Map timeout for dynamic partitions.
-constexpr std::chrono::milliseconds kMapTimeout{1000};
-// Map timeout for dynamic partitions with snapshots. Since several devices
-// needs to be mapped, this timeout is longer than |kMapTimeout|.
-constexpr std::chrono::milliseconds kMapSnapshotTimeout{5000};
+constexpr uint64_t kMapTimeoutMillis = 1000;
DynamicPartitionControlAndroid::~DynamicPartitionControlAndroid() {
- CleanupInternal();
+ CleanupInternal(false /* wait */);
}
-static FeatureFlag GetFeatureFlag(const char* enable_prop,
- const char* retrofit_prop) {
- bool retrofit = GetBoolProperty(retrofit_prop, false);
- bool enabled = GetBoolProperty(enable_prop, false);
- if (retrofit && !enabled) {
- LOG(ERROR) << retrofit_prop << " is true but " << enable_prop
- << " is not. These sysprops are inconsistent. Assume that "
- << enable_prop << " is true from now on.";
- }
- if (retrofit) {
- return FeatureFlag(FeatureFlag::Value::RETROFIT);
- }
- if (enabled) {
- return FeatureFlag(FeatureFlag::Value::LAUNCH);
- }
- return FeatureFlag(FeatureFlag::Value::NONE);
+bool DynamicPartitionControlAndroid::IsDynamicPartitionsEnabled() {
+ return GetBoolProperty(kUseDynamicPartitions, false);
}
-DynamicPartitionControlAndroid::DynamicPartitionControlAndroid()
- : dynamic_partitions_(
- GetFeatureFlag(kUseDynamicPartitions, kRetrfoitDynamicPartitions)),
- virtual_ab_(GetFeatureFlag(kVirtualAbEnabled, kVirtualAbRetrofit)) {
- if (GetVirtualAbFeatureFlag().IsEnabled()) {
- snapshot_ = android::snapshot::SnapshotManager::New();
- CHECK(snapshot_ != nullptr) << "Cannot initialize SnapshotManager.";
- }
-}
-
-FeatureFlag DynamicPartitionControlAndroid::GetDynamicPartitionsFeatureFlag() {
- return dynamic_partitions_;
-}
-
-FeatureFlag DynamicPartitionControlAndroid::GetVirtualAbFeatureFlag() {
- return virtual_ab_;
+bool DynamicPartitionControlAndroid::IsDynamicPartitionsRetrofit() {
+ return GetBoolProperty(kRetrfoitDynamicPartitions, false);
}
bool DynamicPartitionControlAndroid::MapPartitionInternal(
@@ -108,26 +64,12 @@
uint32_t slot,
bool force_writable,
std::string* path) {
- CreateLogicalPartitionParams params = {
- .block_device = super_device,
- .metadata_slot = slot,
- .partition_name = target_partition_name,
- .force_writable = force_writable,
- };
- bool success = false;
- if (GetVirtualAbFeatureFlag().IsEnabled() && target_supports_snapshot_ &&
- force_writable) {
- // Only target partitions are mapped with force_writable. On Virtual
- // A/B devices, target partitions may overlap with source partitions, so
- // they must be mapped with snapshot.
- params.timeout_ms = kMapSnapshotTimeout;
- success = snapshot_->MapUpdateSnapshot(params, path);
- } else {
- params.timeout_ms = kMapTimeout;
- success = CreateLogicalPartition(params, path);
- }
-
- if (!success) {
+ if (!CreateLogicalPartition(super_device.c_str(),
+ slot,
+ target_partition_name,
+ force_writable,
+ std::chrono::milliseconds(kMapTimeoutMillis),
+ path)) {
LOG(ERROR) << "Cannot map " << target_partition_name << " in "
<< super_device << " on device mapper.";
return false;
@@ -161,7 +103,7 @@
// Note that for source partitions, if GetState() == ACTIVE, callers (e.g.
// BootControlAndroid) should not call MapPartitionOnDeviceMapper, but
// should directly call GetDmDevicePathByName.
- if (!UnmapPartitionOnDeviceMapper(target_partition_name)) {
+ if (!UnmapPartitionOnDeviceMapper(target_partition_name, true /* wait */)) {
LOG(ERROR) << target_partition_name
<< " is mapped before the update, and it cannot be unmapped.";
return false;
@@ -185,22 +127,12 @@
}
bool DynamicPartitionControlAndroid::UnmapPartitionOnDeviceMapper(
- const std::string& target_partition_name) {
+ const std::string& target_partition_name, bool wait) {
if (DeviceMapper::Instance().GetState(target_partition_name) !=
DmDeviceState::INVALID) {
- // Partitions at target slot on non-Virtual A/B devices are mapped as
- // dm-linear. Also, on Virtual A/B devices, system_other may be mapped for
- // preopt apps as dm-linear.
- // Call DestroyLogicalPartition to handle these cases.
- bool success = DestroyLogicalPartition(target_partition_name);
-
- // On a Virtual A/B device, |target_partition_name| may be a leftover from
- // a paused update. Clean up any underlying devices.
- if (GetVirtualAbFeatureFlag().IsEnabled()) {
- success &= snapshot_->UnmapUpdateSnapshot(target_partition_name);
- }
-
- if (!success) {
+ if (!DestroyLogicalPartition(
+ target_partition_name,
+ std::chrono::milliseconds(wait ? kMapTimeoutMillis : 0))) {
LOG(ERROR) << "Cannot unmap " << target_partition_name
<< " from device mapper.";
return false;
@@ -212,22 +144,18 @@
return true;
}
-void DynamicPartitionControlAndroid::CleanupInternal() {
- metadata_device_.reset();
- if (mapped_devices_.empty()) {
- return;
- }
+void DynamicPartitionControlAndroid::CleanupInternal(bool wait) {
// UnmapPartitionOnDeviceMapper removes objects from mapped_devices_, hence
// a copy is needed for the loop.
std::set<std::string> mapped = mapped_devices_;
LOG(INFO) << "Destroying [" << Join(mapped, ", ") << "] from device mapper";
for (const auto& partition_name : mapped) {
- ignore_result(UnmapPartitionOnDeviceMapper(partition_name));
+ ignore_result(UnmapPartitionOnDeviceMapper(partition_name, wait));
}
}
void DynamicPartitionControlAndroid::Cleanup() {
- CleanupInternal();
+ CleanupInternal(true /* wait */);
}
bool DynamicPartitionControlAndroid::DeviceExists(const std::string& path) {
@@ -246,27 +174,18 @@
std::unique_ptr<MetadataBuilder>
DynamicPartitionControlAndroid::LoadMetadataBuilder(
- const std::string& super_device, uint32_t source_slot) {
- return LoadMetadataBuilder(
- super_device, source_slot, BootControlInterface::kInvalidSlot);
-}
-
-std::unique_ptr<MetadataBuilder>
-DynamicPartitionControlAndroid::LoadMetadataBuilder(
const std::string& super_device,
uint32_t source_slot,
uint32_t target_slot) {
std::unique_ptr<MetadataBuilder> builder;
- if (target_slot == BootControlInterface::kInvalidSlot) {
+
+ if (target_slot != BootControlInterface::kInvalidSlot &&
+ IsDynamicPartitionsRetrofit()) {
+ builder = MetadataBuilder::NewForUpdate(
+ PartitionOpener(), super_device, source_slot, target_slot);
+ } else {
builder =
MetadataBuilder::New(PartitionOpener(), super_device, source_slot);
- } else {
- bool always_keep_source_slot = !target_supports_snapshot_;
- builder = MetadataBuilder::NewForUpdate(PartitionOpener(),
- super_device,
- source_slot,
- target_slot,
- always_keep_source_slot);
}
if (builder == nullptr) {
@@ -293,7 +212,7 @@
return false;
}
- if (GetDynamicPartitionsFeatureFlag().IsRetrofit()) {
+ if (IsDynamicPartitionsRetrofit()) {
if (!FlashPartitionTable(super_device, *metadata)) {
LOG(ERROR) << "Cannot write metadata to " << super_device;
return false;
@@ -348,188 +267,4 @@
*out = base::FilePath(misc_device).DirName().value();
return true;
}
-
-bool DynamicPartitionControlAndroid::PreparePartitionsForUpdate(
- uint32_t source_slot,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest,
- bool update) {
- target_supports_snapshot_ =
- manifest.dynamic_partition_metadata().snapshot_enabled();
-
- if (GetVirtualAbFeatureFlag().IsEnabled()) {
- metadata_device_ = snapshot_->EnsureMetadataMounted();
- TEST_AND_RETURN_FALSE(metadata_device_ != nullptr);
- }
-
- if (!update)
- return true;
-
- if (GetVirtualAbFeatureFlag().IsEnabled()) {
- // On Virtual A/B device, either CancelUpdate() or BeginUpdate() must be
- // called before calling UnmapUpdateSnapshot.
- // - If target_supports_snapshot_, PrepareSnapshotPartitionsForUpdate()
- // calls BeginUpdate() which resets update state
- // - If !target_supports_snapshot_, explicitly CancelUpdate().
- if (target_supports_snapshot_) {
- return PrepareSnapshotPartitionsForUpdate(
- source_slot, target_slot, manifest);
- }
- if (!snapshot_->CancelUpdate()) {
- LOG(ERROR) << "Cannot cancel previous update.";
- return false;
- }
- }
- return PrepareDynamicPartitionsForUpdate(source_slot, target_slot, manifest);
-}
-
-bool DynamicPartitionControlAndroid::PrepareDynamicPartitionsForUpdate(
- uint32_t source_slot,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest) {
- const std::string target_suffix = SlotSuffixForSlotNumber(target_slot);
-
- // Unmap all the target dynamic partitions because they would become
- // inconsistent with the new metadata.
- for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
- for (const auto& partition_name : group.partition_names()) {
- if (!UnmapPartitionOnDeviceMapper(partition_name + target_suffix)) {
- return false;
- }
- }
- }
-
- std::string device_dir_str;
- if (!GetDeviceDir(&device_dir_str)) {
- return false;
- }
- base::FilePath device_dir(device_dir_str);
- auto source_device =
- device_dir.Append(GetSuperPartitionName(source_slot)).value();
-
- auto builder = LoadMetadataBuilder(source_device, source_slot, target_slot);
- if (builder == nullptr) {
- LOG(ERROR) << "No metadata at "
- << BootControlInterface::SlotName(source_slot);
- return false;
- }
-
- if (!UpdatePartitionMetadata(builder.get(), target_slot, manifest)) {
- return false;
- }
-
- auto target_device =
- device_dir.Append(GetSuperPartitionName(target_slot)).value();
- return StoreMetadata(target_device, builder.get(), target_slot);
-}
-
-bool DynamicPartitionControlAndroid::PrepareSnapshotPartitionsForUpdate(
- uint32_t source_slot,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest) {
- if (!snapshot_->BeginUpdate()) {
- LOG(ERROR) << "Cannot begin new update.";
- return false;
- }
- if (!snapshot_->CreateUpdateSnapshots(manifest)) {
- LOG(ERROR) << "Cannot create update snapshots.";
- return false;
- }
- return true;
-}
-
-std::string DynamicPartitionControlAndroid::GetSuperPartitionName(
- uint32_t slot) {
- return fs_mgr_get_super_partition_name(slot);
-}
-
-bool DynamicPartitionControlAndroid::UpdatePartitionMetadata(
- MetadataBuilder* builder,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest) {
- // If applying downgrade from Virtual A/B to non-Virtual A/B, the left-over
- // COW group needs to be deleted to ensure there are enough space to create
- // target partitions.
- builder->RemoveGroupAndPartitions(android::snapshot::kCowGroupName);
-
- const std::string target_suffix = SlotSuffixForSlotNumber(target_slot);
- DeleteGroupsWithSuffix(builder, target_suffix);
-
- uint64_t total_size = 0;
- for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
- total_size += group.size();
- }
-
- std::string expr;
- uint64_t allocatable_space = builder->AllocatableSpace();
- if (!GetDynamicPartitionsFeatureFlag().IsRetrofit()) {
- allocatable_space /= 2;
- expr = "half of ";
- }
- if (total_size > allocatable_space) {
- LOG(ERROR) << "The maximum size of all groups with suffix " << target_suffix
- << " (" << total_size << ") has exceeded " << expr
- << "allocatable space for dynamic partitions "
- << allocatable_space << ".";
- return false;
- }
-
- // name of partition(e.g. "system") -> size in bytes
- std::map<std::string, uint64_t> partition_sizes;
- for (const auto& partition : manifest.partitions()) {
- partition_sizes.emplace(partition.partition_name(),
- partition.new_partition_info().size());
- }
-
- for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
- auto group_name_suffix = group.name() + target_suffix;
- if (!builder->AddGroup(group_name_suffix, group.size())) {
- LOG(ERROR) << "Cannot add group " << group_name_suffix << " with size "
- << group.size();
- return false;
- }
- LOG(INFO) << "Added group " << group_name_suffix << " with size "
- << group.size();
-
- for (const auto& partition_name : group.partition_names()) {
- auto partition_sizes_it = partition_sizes.find(partition_name);
- if (partition_sizes_it == partition_sizes.end()) {
- // TODO(tbao): Support auto-filling partition info for framework-only
- // OTA.
- LOG(ERROR) << "dynamic_partition_metadata contains partition "
- << partition_name << " but it is not part of the manifest. "
- << "This is not supported.";
- return false;
- }
- uint64_t partition_size = partition_sizes_it->second;
-
- auto partition_name_suffix = partition_name + target_suffix;
- Partition* p = builder->AddPartition(
- partition_name_suffix, group_name_suffix, LP_PARTITION_ATTR_READONLY);
- if (!p) {
- LOG(ERROR) << "Cannot add partition " << partition_name_suffix
- << " to group " << group_name_suffix;
- return false;
- }
- if (!builder->ResizePartition(p, partition_size)) {
- LOG(ERROR) << "Cannot resize partition " << partition_name_suffix
- << " to size " << partition_size << ". Not enough space?";
- return false;
- }
- LOG(INFO) << "Added partition " << partition_name_suffix << " to group "
- << group_name_suffix << " with size " << partition_size;
- }
- }
-
- return true;
-}
-
-bool DynamicPartitionControlAndroid::FinishUpdate() {
- if (GetVirtualAbFeatureFlag().IsEnabled() && target_supports_snapshot_) {
- LOG(INFO) << "Snapshot writes are done.";
- return snapshot_->FinishedSnapshotWrites();
- }
- return true;
-}
-
} // namespace chromeos_update_engine
diff --git a/dynamic_partition_control_android.h b/dynamic_partition_control_android.h
index 07ce281..1233b64 100644
--- a/dynamic_partition_control_android.h
+++ b/dynamic_partition_control_android.h
@@ -23,102 +23,45 @@
#include <set>
#include <string>
-#include <libsnapshot/auto_device.h>
-#include <libsnapshot/snapshot.h>
-
namespace chromeos_update_engine {
class DynamicPartitionControlAndroid : public DynamicPartitionControlInterface {
public:
- DynamicPartitionControlAndroid();
+ DynamicPartitionControlAndroid() = default;
~DynamicPartitionControlAndroid();
- FeatureFlag GetDynamicPartitionsFeatureFlag() override;
- FeatureFlag GetVirtualAbFeatureFlag() override;
+ bool IsDynamicPartitionsEnabled() override;
+ bool IsDynamicPartitionsRetrofit() override;
bool MapPartitionOnDeviceMapper(const std::string& super_device,
const std::string& target_partition_name,
uint32_t slot,
bool force_writable,
std::string* path) override;
+ bool UnmapPartitionOnDeviceMapper(const std::string& target_partition_name,
+ bool wait) override;
void Cleanup() override;
bool DeviceExists(const std::string& path) override;
android::dm::DmDeviceState GetState(const std::string& name) override;
bool GetDmDevicePathByName(const std::string& name,
std::string* path) override;
std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder(
- const std::string& super_device, uint32_t source_slot) override;
-
- bool PreparePartitionsForUpdate(uint32_t source_slot,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest,
- bool update) override;
- bool GetDeviceDir(std::string* path) override;
- std::string GetSuperPartitionName(uint32_t slot) override;
- bool FinishUpdate() override;
-
- protected:
- // These functions are exposed for testing.
-
- // Unmap logical partition on device mapper. This is the reverse operation
- // of MapPartitionOnDeviceMapper.
- // Returns true if unmapped successfully.
- virtual bool UnmapPartitionOnDeviceMapper(
- const std::string& target_partition_name);
-
- // Retrieve metadata from |super_device| at slot |source_slot|.
- //
- // If |target_slot| != kInvalidSlot, before returning the metadata, this
- // function modifies the metadata so that during updates, the metadata can be
- // written to |target_slot|. In particular, on retrofit devices, the returned
- // metadata automatically includes block devices at |target_slot|.
- //
- // If |target_slot| == kInvalidSlot, this function returns metadata at
- // |source_slot| without modifying it. This is the same as
- // LoadMetadataBuilder(const std::string&, uint32_t).
- virtual std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder(
const std::string& super_device,
uint32_t source_slot,
- uint32_t target_slot);
-
- // Write metadata |builder| to |super_device| at slot |target_slot|.
- virtual bool StoreMetadata(const std::string& super_device,
- android::fs_mgr::MetadataBuilder* builder,
- uint32_t target_slot);
+ uint32_t target_slot) override;
+ bool StoreMetadata(const std::string& super_device,
+ android::fs_mgr::MetadataBuilder* builder,
+ uint32_t target_slot) override;
+ bool GetDeviceDir(std::string* path) override;
private:
- friend class DynamicPartitionControlAndroidTest;
+ std::set<std::string> mapped_devices_;
- void CleanupInternal();
+ void CleanupInternal(bool wait);
bool MapPartitionInternal(const std::string& super_device,
const std::string& target_partition_name,
uint32_t slot,
bool force_writable,
std::string* path);
- // Update |builder| according to |partition_metadata|, assuming the device
- // does not have Virtual A/B.
- bool UpdatePartitionMetadata(android::fs_mgr::MetadataBuilder* builder,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest);
-
- // Helper for PreparePartitionsForUpdate. Used for dynamic partitions without
- // Virtual A/B update.
- bool PrepareDynamicPartitionsForUpdate(uint32_t source_slot,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest);
-
- // Helper for PreparePartitionsForUpdate. Used for snapshotted partitions for
- // Virtual A/B update.
- bool PrepareSnapshotPartitionsForUpdate(uint32_t source_slot,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest);
-
- std::set<std::string> mapped_devices_;
- const FeatureFlag dynamic_partitions_;
- const FeatureFlag virtual_ab_;
- std::unique_ptr<android::snapshot::SnapshotManager> snapshot_;
- std::unique_ptr<android::snapshot::AutoDevice> metadata_device_;
- bool target_supports_snapshot_ = false;
-
DISALLOW_COPY_AND_ASSIGN(DynamicPartitionControlAndroid);
};
diff --git a/dynamic_partition_control_android_unittest.cc b/dynamic_partition_control_android_unittest.cc
deleted file mode 100644
index e8ef1f9..0000000
--- a/dynamic_partition_control_android_unittest.cc
+++ /dev/null
@@ -1,489 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-#include "update_engine/dynamic_partition_control_android.h"
-
-#include <set>
-#include <vector>
-
-#include <base/logging.h>
-#include <base/strings/string_util.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "update_engine/dynamic_partition_test_utils.h"
-#include "update_engine/mock_dynamic_partition_control.h"
-
-using std::string;
-using testing::_;
-using testing::AnyNumber;
-using testing::Invoke;
-using testing::NiceMock;
-using testing::Not;
-using testing::Return;
-
-namespace chromeos_update_engine {
-
-class DynamicPartitionControlAndroidTest : public ::testing::Test {
- public:
- void SetUp() override {
- module_ = std::make_unique<NiceMock<MockDynamicPartitionControlAndroid>>();
-
- ON_CALL(dynamicControl(), GetDynamicPartitionsFeatureFlag())
- .WillByDefault(Return(FeatureFlag(FeatureFlag::Value::LAUNCH)));
- ON_CALL(dynamicControl(), GetVirtualAbFeatureFlag())
- .WillByDefault(Return(FeatureFlag(FeatureFlag::Value::NONE)));
-
- ON_CALL(dynamicControl(), GetDeviceDir(_))
- .WillByDefault(Invoke([](auto path) {
- *path = kFakeDevicePath;
- return true;
- }));
-
- ON_CALL(dynamicControl(), GetSuperPartitionName(_))
- .WillByDefault(Return(kFakeSuper));
- }
-
- // Return the mocked DynamicPartitionControlInterface.
- NiceMock<MockDynamicPartitionControlAndroid>& dynamicControl() {
- return static_cast<NiceMock<MockDynamicPartitionControlAndroid>&>(*module_);
- }
-
- std::string GetSuperDevice(uint32_t slot) {
- return GetDevice(dynamicControl().GetSuperPartitionName(slot));
- }
-
- uint32_t source() { return slots_.source; }
- uint32_t target() { return slots_.target; }
-
- // Return partition names with suffix of source().
- std::string S(const std::string& name) {
- return name + kSlotSuffixes[source()];
- }
-
- // Return partition names with suffix of target().
- std::string T(const std::string& name) {
- return name + kSlotSuffixes[target()];
- }
-
- // Set the fake metadata to return when LoadMetadataBuilder is called on
- // |slot|.
- void SetMetadata(uint32_t slot, const PartitionSuffixSizes& sizes) {
- EXPECT_CALL(dynamicControl(),
- LoadMetadataBuilder(GetSuperDevice(slot), slot, _))
- .Times(AnyNumber())
- .WillRepeatedly(Invoke([sizes](auto, auto, auto) {
- return NewFakeMetadata(PartitionSuffixSizesToManifest(sizes));
- }));
- }
-
- void ExpectStoreMetadata(const PartitionSuffixSizes& partition_sizes) {
- EXPECT_CALL(dynamicControl(),
- StoreMetadata(GetSuperDevice(target()),
- MetadataMatches(partition_sizes),
- target()))
- .WillOnce(Return(true));
- }
-
- // Expect that UnmapPartitionOnDeviceMapper is called on target() metadata
- // slot with each partition in |partitions|.
- void ExpectUnmap(const std::set<std::string>& partitions) {
- // Error when UnmapPartitionOnDeviceMapper is called on unknown arguments.
- ON_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(_))
- .WillByDefault(Return(false));
-
- for (const auto& partition : partitions) {
- EXPECT_CALL(dynamicControl(), UnmapPartitionOnDeviceMapper(partition))
- .WillOnce(Return(true));
- }
- }
- bool PreparePartitionsForUpdate(const PartitionSizes& partition_sizes) {
- return dynamicControl().PreparePartitionsForUpdate(
- source(), target(), PartitionSizesToManifest(partition_sizes), true);
- }
- void SetSlots(const TestParam& slots) { slots_ = slots; }
-
- struct Listener : public ::testing::MatchResultListener {
- explicit Listener(std::ostream* os) : MatchResultListener(os) {}
- };
-
- testing::AssertionResult UpdatePartitionMetadata(
- const PartitionSuffixSizes& source_metadata,
- const PartitionSizes& update_metadata,
- const PartitionSuffixSizes& expected) {
- return UpdatePartitionMetadata(
- PartitionSuffixSizesToManifest(source_metadata),
- PartitionSizesToManifest(update_metadata),
- PartitionSuffixSizesToManifest(expected));
- }
- testing::AssertionResult UpdatePartitionMetadata(
- const DeltaArchiveManifest& source_manifest,
- const DeltaArchiveManifest& update_manifest,
- const DeltaArchiveManifest& expected) {
- return UpdatePartitionMetadata(
- source_manifest, update_manifest, MetadataMatches(expected));
- }
- testing::AssertionResult UpdatePartitionMetadata(
- const DeltaArchiveManifest& source_manifest,
- const DeltaArchiveManifest& update_manifest,
- const Matcher<MetadataBuilder*>& matcher) {
- auto super_metadata = NewFakeMetadata(source_manifest);
- if (!module_->UpdatePartitionMetadata(
- super_metadata.get(), target(), update_manifest)) {
- return testing::AssertionFailure()
- << "UpdatePartitionMetadataInternal failed";
- }
- std::stringstream ss;
- Listener listener(&ss);
- if (matcher.MatchAndExplain(super_metadata.get(), &listener)) {
- return testing::AssertionSuccess() << ss.str();
- } else {
- return testing::AssertionFailure() << ss.str();
- }
- }
-
- std::unique_ptr<DynamicPartitionControlAndroid> module_;
- TestParam slots_;
-};
-
-class DynamicPartitionControlAndroidTestP
- : public DynamicPartitionControlAndroidTest,
- public ::testing::WithParamInterface<TestParam> {
- public:
- void SetUp() override {
- DynamicPartitionControlAndroidTest::SetUp();
- SetSlots(GetParam());
- }
-};
-
-// Test resize case. Grow if target metadata contains a partition with a size
-// less than expected.
-TEST_P(DynamicPartitionControlAndroidTestP,
- NeedGrowIfSizeNotMatchWhenResizing) {
- PartitionSuffixSizes source_metadata{{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}};
- PartitionSuffixSizes expected{{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 3_GiB},
- {T("vendor"), 1_GiB}};
- PartitionSizes update_metadata{{"system", 3_GiB}, {"vendor", 1_GiB}};
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_metadata, update_metadata, expected));
-}
-
-// Test resize case. Shrink if target metadata contains a partition with a size
-// greater than expected.
-TEST_P(DynamicPartitionControlAndroidTestP,
- NeedShrinkIfSizeNotMatchWhenResizing) {
- PartitionSuffixSizes source_metadata{{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}};
- PartitionSuffixSizes expected{{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 150_MiB}};
- PartitionSizes update_metadata{{"system", 2_GiB}, {"vendor", 150_MiB}};
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_metadata, update_metadata, expected));
-}
-
-// Test adding partitions on the first run.
-TEST_P(DynamicPartitionControlAndroidTestP, AddPartitionToEmptyMetadata) {
- PartitionSuffixSizes source_metadata{};
- PartitionSuffixSizes expected{{T("system"), 2_GiB}, {T("vendor"), 1_GiB}};
- PartitionSizes update_metadata{{"system", 2_GiB}, {"vendor", 1_GiB}};
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_metadata, update_metadata, expected));
-}
-
-// Test subsequent add case.
-TEST_P(DynamicPartitionControlAndroidTestP, AddAdditionalPartition) {
- PartitionSuffixSizes source_metadata{{S("system"), 2_GiB},
- {T("system"), 2_GiB}};
- PartitionSuffixSizes expected{
- {S("system"), 2_GiB}, {T("system"), 2_GiB}, {T("vendor"), 1_GiB}};
- PartitionSizes update_metadata{{"system", 2_GiB}, {"vendor", 1_GiB}};
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_metadata, update_metadata, expected));
-}
-
-// Test delete one partition.
-TEST_P(DynamicPartitionControlAndroidTestP, DeletePartition) {
- PartitionSuffixSizes source_metadata{{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}};
- // No T("vendor")
- PartitionSuffixSizes expected{
- {S("system"), 2_GiB}, {S("vendor"), 1_GiB}, {T("system"), 2_GiB}};
- PartitionSizes update_metadata{{"system", 2_GiB}};
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_metadata, update_metadata, expected));
-}
-
-// Test delete all partitions.
-TEST_P(DynamicPartitionControlAndroidTestP, DeleteAll) {
- PartitionSuffixSizes source_metadata{{S("system"), 2_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 2_GiB},
- {T("vendor"), 1_GiB}};
- PartitionSuffixSizes expected{{S("system"), 2_GiB}, {S("vendor"), 1_GiB}};
- PartitionSizes update_metadata{};
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_metadata, update_metadata, expected));
-}
-
-// Test corrupt source metadata case.
-TEST_P(DynamicPartitionControlAndroidTestP, CorruptedSourceMetadata) {
- EXPECT_CALL(dynamicControl(),
- LoadMetadataBuilder(GetSuperDevice(source()), source(), _))
- .WillOnce(Invoke([](auto, auto, auto) { return nullptr; }));
- ExpectUnmap({T("system")});
-
- EXPECT_FALSE(PreparePartitionsForUpdate({{"system", 1_GiB}}))
- << "Should not be able to continue with corrupt source metadata";
-}
-
-// Test that UpdatePartitionMetadata fails if there is not enough space on the
-// device.
-TEST_P(DynamicPartitionControlAndroidTestP, NotEnoughSpace) {
- PartitionSuffixSizes source_metadata{{S("system"), 3_GiB},
- {S("vendor"), 2_GiB},
- {T("system"), 0},
- {T("vendor"), 0}};
- PartitionSizes update_metadata{{"system", 3_GiB}, {"vendor", 3_GiB}};
-
- EXPECT_FALSE(UpdatePartitionMetadata(source_metadata, update_metadata, {}))
- << "Should not be able to fit 11GiB data into 10GiB space";
-}
-
-TEST_P(DynamicPartitionControlAndroidTestP, NotEnoughSpaceForSlot) {
- PartitionSuffixSizes source_metadata{{S("system"), 1_GiB},
- {S("vendor"), 1_GiB},
- {T("system"), 0},
- {T("vendor"), 0}};
- PartitionSizes update_metadata{{"system", 3_GiB}, {"vendor", 3_GiB}};
- EXPECT_FALSE(UpdatePartitionMetadata(source_metadata, update_metadata, {}))
- << "Should not be able to grow over size of super / 2";
-}
-
-INSTANTIATE_TEST_CASE_P(DynamicPartitionControlAndroidTest,
- DynamicPartitionControlAndroidTestP,
- testing::Values(TestParam{0, 1}, TestParam{1, 0}));
-
-class DynamicPartitionControlAndroidGroupTestP
- : public DynamicPartitionControlAndroidTestP {
- public:
- DeltaArchiveManifest source_manifest;
- void SetUp() override {
- DynamicPartitionControlAndroidTestP::SetUp();
- AddGroupAndPartition(
- &source_manifest, S("android"), 3_GiB, S("system"), 2_GiB);
- AddGroupAndPartition(&source_manifest, S("oem"), 2_GiB, S("vendor"), 1_GiB);
- AddGroupAndPartition(&source_manifest, T("android"), 3_GiB, T("system"), 0);
- AddGroupAndPartition(&source_manifest, T("oem"), 2_GiB, T("vendor"), 0);
- }
-
- void AddGroupAndPartition(DeltaArchiveManifest* manifest,
- const string& group,
- uint64_t group_size,
- const string& partition,
- uint64_t partition_size) {
- auto* g = AddGroup(manifest, group, group_size);
- AddPartition(manifest, g, partition, partition_size);
- }
-};
-
-// Allow to resize within group.
-TEST_P(DynamicPartitionControlAndroidGroupTestP, ResizeWithinGroup) {
- DeltaArchiveManifest expected;
- AddGroupAndPartition(&expected, T("android"), 3_GiB, T("system"), 3_GiB);
- AddGroupAndPartition(&expected, T("oem"), 2_GiB, T("vendor"), 2_GiB);
-
- DeltaArchiveManifest update_manifest;
- AddGroupAndPartition(&update_manifest, "android", 3_GiB, "system", 3_GiB);
- AddGroupAndPartition(&update_manifest, "oem", 2_GiB, "vendor", 2_GiB);
-
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_manifest, update_manifest, expected));
-}
-
-TEST_P(DynamicPartitionControlAndroidGroupTestP, NotEnoughSpaceForGroup) {
- DeltaArchiveManifest update_manifest;
- AddGroupAndPartition(&update_manifest, "android", 3_GiB, "system", 1_GiB),
- AddGroupAndPartition(&update_manifest, "oem", 2_GiB, "vendor", 3_GiB);
- EXPECT_FALSE(UpdatePartitionMetadata(source_manifest, update_manifest, {}))
- << "Should not be able to grow over maximum size of group";
-}
-
-TEST_P(DynamicPartitionControlAndroidGroupTestP, GroupTooBig) {
- DeltaArchiveManifest update_manifest;
- AddGroup(&update_manifest, "android", 3_GiB);
- AddGroup(&update_manifest, "oem", 3_GiB);
- EXPECT_FALSE(UpdatePartitionMetadata(source_manifest, update_manifest, {}))
- << "Should not be able to grow over size of super / 2";
-}
-
-TEST_P(DynamicPartitionControlAndroidGroupTestP, AddPartitionToGroup) {
- DeltaArchiveManifest expected;
- auto* g = AddGroup(&expected, T("android"), 3_GiB);
- AddPartition(&expected, g, T("system"), 2_GiB);
- AddPartition(&expected, g, T("system_ext"), 1_GiB);
-
- DeltaArchiveManifest update_manifest;
- g = AddGroup(&update_manifest, "android", 3_GiB);
- AddPartition(&update_manifest, g, "system", 2_GiB);
- AddPartition(&update_manifest, g, "system_ext", 1_GiB);
- AddGroupAndPartition(&update_manifest, "oem", 2_GiB, "vendor", 2_GiB);
-
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_manifest, update_manifest, expected));
-}
-
-TEST_P(DynamicPartitionControlAndroidGroupTestP, RemovePartitionFromGroup) {
- DeltaArchiveManifest expected;
- AddGroup(&expected, T("android"), 3_GiB);
-
- DeltaArchiveManifest update_manifest;
- AddGroup(&update_manifest, "android", 3_GiB);
- AddGroupAndPartition(&update_manifest, "oem", 2_GiB, "vendor", 2_GiB);
-
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_manifest, update_manifest, expected));
-}
-
-TEST_P(DynamicPartitionControlAndroidGroupTestP, AddGroup) {
- DeltaArchiveManifest expected;
- AddGroupAndPartition(
- &expected, T("new_group"), 2_GiB, T("new_partition"), 2_GiB);
-
- DeltaArchiveManifest update_manifest;
- AddGroupAndPartition(&update_manifest, "android", 2_GiB, "system", 2_GiB);
- AddGroupAndPartition(&update_manifest, "oem", 1_GiB, "vendor", 1_GiB);
- AddGroupAndPartition(
- &update_manifest, "new_group", 2_GiB, "new_partition", 2_GiB);
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_manifest, update_manifest, expected));
-}
-
-TEST_P(DynamicPartitionControlAndroidGroupTestP, RemoveGroup) {
- DeltaArchiveManifest update_manifest;
- AddGroupAndPartition(&update_manifest, "android", 2_GiB, "system", 2_GiB);
-
- EXPECT_TRUE(UpdatePartitionMetadata(
- source_manifest, update_manifest, Not(HasGroup(T("oem")))));
-}
-
-TEST_P(DynamicPartitionControlAndroidGroupTestP, ResizeGroup) {
- DeltaArchiveManifest expected;
- AddGroupAndPartition(&expected, T("android"), 2_GiB, T("system"), 2_GiB);
- AddGroupAndPartition(&expected, T("oem"), 3_GiB, T("vendor"), 3_GiB);
- DeltaArchiveManifest update_manifest;
- AddGroupAndPartition(&update_manifest, "android", 2_GiB, "system", 2_GiB),
- AddGroupAndPartition(&update_manifest, "oem", 3_GiB, "vendor", 3_GiB);
- EXPECT_TRUE(
- UpdatePartitionMetadata(source_manifest, update_manifest, expected));
-}
-
-INSTANTIATE_TEST_CASE_P(DynamicPartitionControlAndroidTest,
- DynamicPartitionControlAndroidGroupTestP,
- testing::Values(TestParam{0, 1}, TestParam{1, 0}));
-
-const PartitionSuffixSizes update_sizes_0() {
- // Initial state is 0 for "other" slot.
- return {
- {"grown_a", 2_GiB},
- {"shrunk_a", 1_GiB},
- {"same_a", 100_MiB},
- {"deleted_a", 150_MiB},
- // no added_a
- {"grown_b", 200_MiB},
- // simulate system_other
- {"shrunk_b", 0},
- {"same_b", 0},
- {"deleted_b", 0},
- // no added_b
- };
-}
-
-const PartitionSuffixSizes update_sizes_1() {
- return {
- {"grown_a", 2_GiB},
- {"shrunk_a", 1_GiB},
- {"same_a", 100_MiB},
- {"deleted_a", 150_MiB},
- // no added_a
- {"grown_b", 3_GiB},
- {"shrunk_b", 150_MiB},
- {"same_b", 100_MiB},
- {"added_b", 150_MiB},
- // no deleted_b
- };
-}
-
-const PartitionSuffixSizes update_sizes_2() {
- return {
- {"grown_a", 4_GiB},
- {"shrunk_a", 100_MiB},
- {"same_a", 100_MiB},
- {"deleted_a", 64_MiB},
- // no added_a
- {"grown_b", 3_GiB},
- {"shrunk_b", 150_MiB},
- {"same_b", 100_MiB},
- {"added_b", 150_MiB},
- // no deleted_b
- };
-}
-
-// Test case for first update after the device is manufactured, in which
-// case the "other" slot is likely of size "0" (except system, which is
-// non-zero because of system_other partition)
-TEST_F(DynamicPartitionControlAndroidTest, SimulatedFirstUpdate) {
- SetSlots({0, 1});
-
- SetMetadata(source(), update_sizes_0());
- SetMetadata(target(), update_sizes_0());
- ExpectStoreMetadata(update_sizes_1());
- ExpectUnmap({"grown_b", "shrunk_b", "same_b", "added_b"});
-
- EXPECT_TRUE(PreparePartitionsForUpdate({{"grown", 3_GiB},
- {"shrunk", 150_MiB},
- {"same", 100_MiB},
- {"added", 150_MiB}}));
-}
-
-// After first update, test for the second update. In the second update, the
-// "added" partition is deleted and "deleted" partition is re-added.
-TEST_F(DynamicPartitionControlAndroidTest, SimulatedSecondUpdate) {
- SetSlots({1, 0});
-
- SetMetadata(source(), update_sizes_1());
- SetMetadata(target(), update_sizes_0());
-
- ExpectStoreMetadata(update_sizes_2());
- ExpectUnmap({"grown_a", "shrunk_a", "same_a", "deleted_a"});
-
- EXPECT_TRUE(PreparePartitionsForUpdate({{"grown", 4_GiB},
- {"shrunk", 100_MiB},
- {"same", 100_MiB},
- {"deleted", 64_MiB}}));
-}
-
-} // namespace chromeos_update_engine
diff --git a/dynamic_partition_control_interface.h b/dynamic_partition_control_interface.h
index 9c18973..86a0730 100644
--- a/dynamic_partition_control_interface.h
+++ b/dynamic_partition_control_interface.h
@@ -26,34 +26,17 @@
#include <libdm/dm.h>
#include <liblp/builder.h>
-#include "update_engine/common/boot_control_interface.h"
-#include "update_engine/update_metadata.pb.h"
-
namespace chromeos_update_engine {
-struct FeatureFlag {
- enum class Value { NONE = 0, RETROFIT, LAUNCH };
- constexpr explicit FeatureFlag(Value value) : value_(value) {}
- constexpr bool IsEnabled() const { return value_ != Value::NONE; }
- constexpr bool IsRetrofit() const { return value_ == Value::RETROFIT; }
- constexpr bool IsLaunch() const { return value_ == Value::LAUNCH; }
-
- private:
- Value value_;
-};
-
class DynamicPartitionControlInterface {
public:
virtual ~DynamicPartitionControlInterface() = default;
- // Return the feature flags of dynamic partitions on this device.
- // Return RETROFIT iff dynamic partitions is retrofitted on this device,
- // LAUNCH iff this device is launched with dynamic partitions,
- // NONE iff dynamic partitions is disabled on this device.
- virtual FeatureFlag GetDynamicPartitionsFeatureFlag() = 0;
+ // Return true iff dynamic partitions is enabled on this device.
+ virtual bool IsDynamicPartitionsEnabled() = 0;
- // Return the feature flags of Virtual A/B on this device.
- virtual FeatureFlag GetVirtualAbFeatureFlag() = 0;
+ // Return true iff dynamic partitions is retrofitted on this device.
+ virtual bool IsDynamicPartitionsRetrofit() = 0;
// Map logical partition on device-mapper.
// |super_device| is the device path of the physical partition ("super").
@@ -69,6 +52,13 @@
bool force_writable,
std::string* path) = 0;
+ // Unmap logical partition on device mapper. This is the reverse operation
+ // of MapPartitionOnDeviceMapper.
+ // If |wait| is set, wait until the device is unmapped.
+ // Returns true if unmapped successfully.
+ virtual bool UnmapPartitionOnDeviceMapper(
+ const std::string& target_partition_name, bool wait) = 0;
+
// Do necessary cleanups before destroying the object.
virtual void Cleanup() = 0;
@@ -87,26 +77,20 @@
std::string* path) = 0;
// Retrieve metadata from |super_device| at slot |source_slot|.
+ // On retrofit devices, if |target_slot| != kInvalidSlot, the returned
+ // metadata automatically includes block devices at |target_slot|.
virtual std::unique_ptr<android::fs_mgr::MetadataBuilder> LoadMetadataBuilder(
- const std::string& super_device, uint32_t source_slot) = 0;
+ const std::string& super_device,
+ uint32_t source_slot,
+ uint32_t target_slot) = 0;
- // Prepare all partitions for an update specified in |manifest|.
- // This is needed before calling MapPartitionOnDeviceMapper(), otherwise the
- // device would be mapped in an inconsistent way.
- // If |update| is set, create snapshots and writes super partition metadata.
- virtual bool PreparePartitionsForUpdate(uint32_t source_slot,
- uint32_t target_slot,
- const DeltaArchiveManifest& manifest,
- bool update) = 0;
+ // Write metadata |builder| to |super_device| at slot |target_slot|.
+ virtual bool StoreMetadata(const std::string& super_device,
+ android::fs_mgr::MetadataBuilder* builder,
+ uint32_t target_slot) = 0;
// Return a possible location for devices listed by name.
virtual bool GetDeviceDir(std::string* path) = 0;
-
- // Return the name of the super partition (which stores super partition
- // metadata) for a given slot.
- virtual std::string GetSuperPartitionName(uint32_t slot) = 0;
-
- virtual bool FinishUpdate() = 0;
};
} // namespace chromeos_update_engine
diff --git a/dynamic_partition_test_utils.h b/dynamic_partition_test_utils.h
deleted file mode 100644
index 346998f..0000000
--- a/dynamic_partition_test_utils.h
+++ /dev/null
@@ -1,286 +0,0 @@
-//
-// Copyright (C) 2019 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_DYNAMIC_PARTITION_TEST_UTILS_H_
-#define UPDATE_ENGINE_DYNAMIC_PARTITION_TEST_UTILS_H_
-
-#include <stdint.h>
-
-#include <iostream>
-#include <map>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/strings/string_util.h>
-#include <fs_mgr.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <liblp/builder.h>
-#include <storage_literals/storage_literals.h>
-
-#include "update_engine/common/boot_control_interface.h"
-#include "update_engine/update_metadata.pb.h"
-
-namespace chromeos_update_engine {
-
-using android::fs_mgr::MetadataBuilder;
-using testing::_;
-using testing::MakeMatcher;
-using testing::Matcher;
-using testing::MatcherInterface;
-using testing::MatchResultListener;
-using namespace android::storage_literals; // NOLINT(build/namespaces)
-
-constexpr const uint32_t kMaxNumSlots = 2;
-constexpr const char* kSlotSuffixes[kMaxNumSlots] = {"_a", "_b"};
-constexpr const char* kFakeDevicePath = "/fake/dev/path/";
-constexpr const char* kFakeDmDevicePath = "/fake/dm/dev/path/";
-constexpr const uint32_t kFakeMetadataSize = 65536;
-constexpr const char* kDefaultGroup = "foo";
-constexpr const char* kFakeSuper = "fake_super";
-
-// A map describing the size of each partition.
-// "{name, size}"
-using PartitionSizes = std::map<std::string, uint64_t>;
-
-// "{name_a, size}"
-using PartitionSuffixSizes = std::map<std::string, uint64_t>;
-
-constexpr uint64_t kDefaultGroupSize = 5_GiB;
-// Super device size. 1 MiB for metadata.
-constexpr uint64_t kDefaultSuperSize = kDefaultGroupSize * 2 + 1_MiB;
-
-template <typename U, typename V>
-inline std::ostream& operator<<(std::ostream& os, const std::map<U, V>& param) {
- os << "{";
- bool first = true;
- for (const auto& pair : param) {
- if (!first)
- os << ", ";
- os << pair.first << ":" << pair.second;
- first = false;
- }
- return os << "}";
-}
-
-template <typename V>
-inline void VectorToStream(std::ostream& os, const V& param) {
- os << "[";
- bool first = true;
- for (const auto& e : param) {
- if (!first)
- os << ", ";
- os << e;
- first = false;
- }
- os << "]";
-}
-
-inline std::ostream& operator<<(std::ostream& os, const PartitionUpdate& p) {
- return os << "{" << p.partition_name() << ", "
- << p.new_partition_info().size() << "}";
-}
-
-inline std::ostream& operator<<(std::ostream& os,
- const DynamicPartitionGroup& g) {
- os << "{" << g.name() << ", " << g.size() << ", ";
- VectorToStream(os, g.partition_names());
- return os << "}";
-}
-
-inline std::ostream& operator<<(std::ostream& os,
- const DeltaArchiveManifest& m) {
- os << "{.groups = ";
- VectorToStream(os, m.dynamic_partition_metadata().groups());
- os << ", .partitions = ";
- VectorToStream(os, m.partitions());
- return os;
-}
-
-inline std::string GetDevice(const std::string& name) {
- return kFakeDevicePath + name;
-}
-
-inline std::string GetDmDevice(const std::string& name) {
- return kFakeDmDevicePath + name;
-}
-
-inline DynamicPartitionGroup* AddGroup(DeltaArchiveManifest* manifest,
- const std::string& group,
- uint64_t group_size) {
- auto* g = manifest->mutable_dynamic_partition_metadata()->add_groups();
- g->set_name(group);
- g->set_size(group_size);
- return g;
-}
-
-inline void AddPartition(DeltaArchiveManifest* manifest,
- DynamicPartitionGroup* group,
- const std::string& partition,
- uint64_t partition_size) {
- group->add_partition_names(partition);
- auto* p = manifest->add_partitions();
- p->set_partition_name(partition);
- p->mutable_new_partition_info()->set_size(partition_size);
-}
-
-// To support legacy tests, auto-convert {name_a: size} map to
-// DeltaArchiveManifest.
-inline DeltaArchiveManifest PartitionSuffixSizesToManifest(
- const PartitionSuffixSizes& partition_sizes) {
- DeltaArchiveManifest manifest;
- for (const char* suffix : kSlotSuffixes) {
- AddGroup(&manifest, std::string(kDefaultGroup) + suffix, kDefaultGroupSize);
- }
- for (const auto& pair : partition_sizes) {
- for (size_t suffix_idx = 0; suffix_idx < kMaxNumSlots; ++suffix_idx) {
- if (base::EndsWith(pair.first,
- kSlotSuffixes[suffix_idx],
- base::CompareCase::SENSITIVE)) {
- AddPartition(
- &manifest,
- manifest.mutable_dynamic_partition_metadata()->mutable_groups(
- suffix_idx),
- pair.first,
- pair.second);
- }
- }
- }
- return manifest;
-}
-
-// To support legacy tests, auto-convert {name: size} map to PartitionMetadata.
-inline DeltaArchiveManifest PartitionSizesToManifest(
- const PartitionSizes& partition_sizes) {
- DeltaArchiveManifest manifest;
- auto* g = AddGroup(&manifest, std::string(kDefaultGroup), kDefaultGroupSize);
- for (const auto& pair : partition_sizes) {
- AddPartition(&manifest, g, pair.first, pair.second);
- }
- return manifest;
-}
-
-inline std::unique_ptr<MetadataBuilder> NewFakeMetadata(
- const DeltaArchiveManifest& manifest) {
- auto builder =
- MetadataBuilder::New(kDefaultSuperSize, kFakeMetadataSize, kMaxNumSlots);
- for (const auto& group : manifest.dynamic_partition_metadata().groups()) {
- EXPECT_TRUE(builder->AddGroup(group.name(), group.size()));
- for (const auto& partition_name : group.partition_names()) {
- EXPECT_NE(
- nullptr,
- builder->AddPartition(partition_name, group.name(), 0 /* attr */));
- }
- }
- for (const auto& partition : manifest.partitions()) {
- auto p = builder->FindPartition(partition.partition_name());
- EXPECT_TRUE(p && builder->ResizePartition(
- p, partition.new_partition_info().size()));
- }
- return builder;
-}
-
-class MetadataMatcher : public MatcherInterface<MetadataBuilder*> {
- public:
- explicit MetadataMatcher(const PartitionSuffixSizes& partition_sizes)
- : manifest_(PartitionSuffixSizesToManifest(partition_sizes)) {}
- explicit MetadataMatcher(const DeltaArchiveManifest& manifest)
- : manifest_(manifest) {}
-
- bool MatchAndExplain(MetadataBuilder* metadata,
- MatchResultListener* listener) const override {
- bool success = true;
- for (const auto& group : manifest_.dynamic_partition_metadata().groups()) {
- for (const auto& partition_name : group.partition_names()) {
- auto p = metadata->FindPartition(partition_name);
- if (p == nullptr) {
- if (!success)
- *listener << "; ";
- *listener << "No partition " << partition_name;
- success = false;
- continue;
- }
- const auto& partition_updates = manifest_.partitions();
- auto it = std::find_if(partition_updates.begin(),
- partition_updates.end(),
- [&](const auto& p) {
- return p.partition_name() == partition_name;
- });
- if (it == partition_updates.end()) {
- *listener << "Can't find partition update " << partition_name;
- success = false;
- continue;
- }
- auto partition_size = it->new_partition_info().size();
- if (p->size() != partition_size) {
- if (!success)
- *listener << "; ";
- *listener << "Partition " << partition_name << " has size "
- << p->size() << ", expected " << partition_size;
- success = false;
- }
- if (p->group_name() != group.name()) {
- if (!success)
- *listener << "; ";
- *listener << "Partition " << partition_name << " has group "
- << p->group_name() << ", expected " << group.name();
- success = false;
- }
- }
- }
- return success;
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "expect: " << manifest_;
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "expect not: " << manifest_;
- }
-
- private:
- DeltaArchiveManifest manifest_;
-};
-
-inline Matcher<MetadataBuilder*> MetadataMatches(
- const PartitionSuffixSizes& partition_sizes) {
- return MakeMatcher(new MetadataMatcher(partition_sizes));
-}
-
-inline Matcher<MetadataBuilder*> MetadataMatches(
- const DeltaArchiveManifest& manifest) {
- return MakeMatcher(new MetadataMatcher(manifest));
-}
-
-MATCHER_P(HasGroup, group, " has group " + group) {
- auto groups = arg->ListGroups();
- return std::find(groups.begin(), groups.end(), group) != groups.end();
-}
-
-struct TestParam {
- uint32_t source;
- uint32_t target;
-};
-inline std::ostream& operator<<(std::ostream& os, const TestParam& param) {
- return os << "{source: " << param.source << ", target:" << param.target
- << "}";
-}
-
-} // namespace chromeos_update_engine
-
-#endif // UPDATE_ENGINE_DYNAMIC_PARTITION_TEST_UTILS_H_
diff --git a/dynamic_partition_utils.cc b/dynamic_partition_utils.cc
deleted file mode 100644
index f9bd886..0000000
--- a/dynamic_partition_utils.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-#include "update_engine/dynamic_partition_utils.h"
-
-#include <vector>
-
-#include <base/logging.h>
-#include <base/strings/string_util.h>
-
-using android::fs_mgr::MetadataBuilder;
-
-namespace chromeos_update_engine {
-
-void DeleteGroupsWithSuffix(MetadataBuilder* builder,
- const std::string& suffix) {
- std::vector<std::string> groups = builder->ListGroups();
- for (const auto& group_name : groups) {
- if (base::EndsWith(group_name, suffix, base::CompareCase::SENSITIVE)) {
- LOG(INFO) << "Removing group " << group_name;
- builder->RemoveGroupAndPartitions(group_name);
- }
- }
-}
-
-} // namespace chromeos_update_engine
diff --git a/dynamic_partition_utils.h b/dynamic_partition_utils.h
deleted file mode 100644
index 09fce00..0000000
--- a/dynamic_partition_utils.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (C) 2019 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_DYNAMIC_PARTITION_UTILS_H_
-#define UPDATE_ENGINE_DYNAMIC_PARTITION_UTILS_H_
-
-#include <string>
-
-#include <liblp/builder.h>
-
-namespace chromeos_update_engine {
-
-// Delete all groups (and their partitions) in |builder| that have names
-// ending with |suffix|.
-void DeleteGroupsWithSuffix(android::fs_mgr::MetadataBuilder* builder,
- const std::string& suffix);
-
-} // namespace chromeos_update_engine
-
-#endif // UPDATE_ENGINE_DYNAMIC_PARTITION_UTILS_H_
diff --git a/hardware_android.cc b/hardware_android.cc
index 9611ba6..21d4659 100644
--- a/hardware_android.cc
+++ b/hardware_android.cc
@@ -192,13 +192,6 @@
return GetIntProperty<int64_t>(kPropBuildDateUTC, 0);
}
-// Returns true if the device runs an userdebug build, and explicitly allows OTA
-// downgrade.
-bool HardwareAndroid::AllowDowngrade() const {
- return GetBoolProperty("ro.ota.allow_downgrade", false) &&
- GetBoolProperty("ro.debuggable", false);
-}
-
bool HardwareAndroid::GetFirstActiveOmahaPingSent() const {
LOG(WARNING) << "STUB: Assuming first active omaha was never set.";
return false;
diff --git a/hardware_android.h b/hardware_android.h
index 2a8f669..5b3c99d 100644
--- a/hardware_android.h
+++ b/hardware_android.h
@@ -53,7 +53,6 @@
bool GetNonVolatileDirectory(base::FilePath* path) const override;
bool GetPowerwashSafeDirectory(base::FilePath* path) const override;
int64_t GetBuildTimestamp() const override;
- bool AllowDowngrade() const override;
bool GetFirstActiveOmahaPingSent() const override;
bool SetFirstActiveOmahaPingSent() override;
diff --git a/hardware_chromeos.h b/hardware_chromeos.h
index 57be3b0..8829866 100644
--- a/hardware_chromeos.h
+++ b/hardware_chromeos.h
@@ -58,7 +58,6 @@
bool GetNonVolatileDirectory(base::FilePath* path) const override;
bool GetPowerwashSafeDirectory(base::FilePath* path) const override;
int64_t GetBuildTimestamp() const override;
- bool AllowDowngrade() const override { return false; }
bool GetFirstActiveOmahaPingSent() const override;
bool SetFirstActiveOmahaPingSent() override;
diff --git a/mock_dynamic_partition_control.h b/mock_dynamic_partition_control.h
index 8146e0f..24aca06 100644
--- a/mock_dynamic_partition_control.h
+++ b/mock_dynamic_partition_control.h
@@ -21,8 +21,6 @@
#include <gmock/gmock.h>
-#include "update_engine/common/boot_control_interface.h"
-#include "update_engine/dynamic_partition_control_android.h"
#include "update_engine/dynamic_partition_control_interface.h"
namespace chromeos_update_engine {
@@ -35,32 +33,7 @@
uint32_t,
bool,
std::string*));
- MOCK_METHOD0(Cleanup, void());
- MOCK_METHOD1(DeviceExists, bool(const std::string&));
- MOCK_METHOD1(GetState, ::android::dm::DmDeviceState(const std::string&));
- MOCK_METHOD2(GetDmDevicePathByName, bool(const std::string&, std::string*));
- MOCK_METHOD2(LoadMetadataBuilder,
- std::unique_ptr<::android::fs_mgr::MetadataBuilder>(
- const std::string&, uint32_t));
- MOCK_METHOD1(GetDeviceDir, bool(std::string*));
- MOCK_METHOD0(GetDynamicPartitionsFeatureFlag, FeatureFlag());
- MOCK_METHOD4(PreparePartitionsForUpdate,
- bool(uint32_t, uint32_t, const DeltaArchiveManifest&, bool));
- MOCK_METHOD1(GetSuperPartitionName, std::string(uint32_t));
- MOCK_METHOD0(GetVirtualAbFeatureFlag, FeatureFlag());
- MOCK_METHOD0(FinishUpdate, bool());
-};
-
-class MockDynamicPartitionControlAndroid
- : public DynamicPartitionControlAndroid {
- public:
- MOCK_METHOD5(MapPartitionOnDeviceMapper,
- bool(const std::string&,
- const std::string&,
- uint32_t,
- bool,
- std::string*));
- MOCK_METHOD1(UnmapPartitionOnDeviceMapper, bool(const std::string&));
+ MOCK_METHOD2(UnmapPartitionOnDeviceMapper, bool(const std::string&, bool));
MOCK_METHOD0(Cleanup, void());
MOCK_METHOD1(DeviceExists, bool(const std::string&));
MOCK_METHOD1(GetState, ::android::dm::DmDeviceState(const std::string&));
@@ -73,10 +46,8 @@
android::fs_mgr::MetadataBuilder*,
uint32_t));
MOCK_METHOD1(GetDeviceDir, bool(std::string*));
- MOCK_METHOD0(GetDynamicPartitionsFeatureFlag, FeatureFlag());
- MOCK_METHOD1(GetSuperPartitionName, std::string(uint32_t));
- MOCK_METHOD0(GetVirtualAbFeatureFlag, FeatureFlag());
- MOCK_METHOD0(FinishUpdate, bool());
+ MOCK_METHOD0(IsDynamicPartitionsEnabled, bool());
+ MOCK_METHOD0(IsDynamicPartitionsRetrofit, bool());
};
} // namespace chromeos_update_engine
diff --git a/otacerts.zip b/otacerts.zip
deleted file mode 100644
index 00a5a51..0000000
--- a/otacerts.zip
+++ /dev/null
Binary files differ
diff --git a/payload_consumer/certificate_parser_android.cc b/payload_consumer/certificate_parser_android.cc
deleted file mode 100644
index 4a20547..0000000
--- a/payload_consumer/certificate_parser_android.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-#include "update_engine/payload_consumer/certificate_parser_android.h"
-
-#include <memory>
-#include <utility>
-
-#include <base/logging.h>
-#include <openssl/bio.h>
-#include <openssl/pem.h>
-#include <ziparchive/zip_archive.h>
-
-#include "update_engine/payload_consumer/certificate_parser_interface.h"
-
-namespace {
-bool IterateZipEntriesAndSearchForKeys(
- const ZipArchiveHandle& handle, std::vector<std::vector<uint8_t>>* result) {
- void* cookie;
- int32_t iter_status = StartIteration(handle, &cookie, "", "x509.pem");
- if (iter_status != 0) {
- LOG(ERROR) << "Failed to iterate over entries in the certificate zipfile: "
- << ErrorCodeString(iter_status);
- return false;
- }
- std::unique_ptr<void, decltype(&EndIteration)> guard(cookie, EndIteration);
-
- std::vector<std::vector<uint8_t>> pem_keys;
- std::string_view name;
- ZipEntry entry;
- while ((iter_status = Next(cookie, &entry, &name)) == 0) {
- std::vector<uint8_t> pem_content(entry.uncompressed_length);
- if (int32_t extract_status = ExtractToMemory(
- handle, &entry, pem_content.data(), pem_content.size());
- extract_status != 0) {
- LOG(ERROR) << "Failed to extract " << name << ": "
- << ErrorCodeString(extract_status);
- return false;
- }
- pem_keys.push_back(pem_content);
- }
-
- if (iter_status != -1) {
- LOG(ERROR) << "Error while iterating over zip entries: "
- << ErrorCodeString(iter_status);
- return false;
- }
-
- *result = std::move(pem_keys);
- return true;
-}
-
-} // namespace
-
-namespace chromeos_update_engine {
-bool CertificateParserAndroid::ReadPublicKeysFromCertificates(
- const std::string& path,
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>>*
- out_public_keys) {
- out_public_keys->clear();
-
- ZipArchiveHandle handle;
- if (int32_t open_status = OpenArchive(path.c_str(), &handle);
- open_status != 0) {
- LOG(ERROR) << "Failed to open " << path << ": "
- << ErrorCodeString(open_status);
- return false;
- }
-
- std::vector<std::vector<uint8_t>> pem_certs;
- if (!IterateZipEntriesAndSearchForKeys(handle, &pem_certs)) {
- CloseArchive(handle);
- return false;
- }
- CloseArchive(handle);
-
- // Convert the certificates into public keys. Stop and return false if we
- // encounter an error.
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>> result;
- for (const auto& cert : pem_certs) {
- std::unique_ptr<BIO, decltype(&BIO_free)> input(
- BIO_new_mem_buf(cert.data(), cert.size()), BIO_free);
-
- std::unique_ptr<X509, decltype(&X509_free)> x509(
- PEM_read_bio_X509(input.get(), nullptr, nullptr, nullptr), X509_free);
- if (!x509) {
- LOG(ERROR) << "Failed to read x509 certificate";
- return false;
- }
-
- std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> public_key(
- X509_get_pubkey(x509.get()), EVP_PKEY_free);
- if (!public_key) {
- LOG(ERROR) << "Failed to extract the public key from x509 certificate";
- return false;
- }
- result.push_back(std::move(public_key));
- }
-
- *out_public_keys = std::move(result);
- return true;
-}
-
-std::unique_ptr<CertificateParserInterface> CreateCertificateParser() {
- return std::make_unique<CertificateParserAndroid>();
-}
-
-} // namespace chromeos_update_engine
diff --git a/payload_consumer/certificate_parser_android.h b/payload_consumer/certificate_parser_android.h
deleted file mode 100644
index ccb9293..0000000
--- a/payload_consumer/certificate_parser_android.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright (C) 2019 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_CERTIFICATE_PARSER_ANDROID_H_
-#define UPDATE_ENGINE_CERTIFICATE_PARSER_ANDROID_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/macros.h>
-
-#include "payload_consumer/certificate_parser_interface.h"
-
-namespace chromeos_update_engine {
-// This class parses the certificates from a zip file. Because the Android
-// build system stores the certs in otacerts.zip.
-class CertificateParserAndroid : public CertificateParserInterface {
- public:
- CertificateParserAndroid() = default;
-
- bool ReadPublicKeysFromCertificates(
- const std::string& path,
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>>*
- out_public_keys) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CertificateParserAndroid);
-};
-
-} // namespace chromeos_update_engine
-
-#endif
diff --git a/payload_consumer/certificate_parser_android_unittest.cc b/payload_consumer/certificate_parser_android_unittest.cc
deleted file mode 100644
index e300414..0000000
--- a/payload_consumer/certificate_parser_android_unittest.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-#include "update_engine/payload_consumer/certificate_parser_interface.h"
-
-#include <string>
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include "update_engine/common/hash_calculator.h"
-#include "update_engine/common/test_utils.h"
-#include "update_engine/common/utils.h"
-#include "update_engine/payload_consumer/payload_verifier.h"
-#include "update_engine/payload_generator/payload_signer.h"
-
-namespace chromeos_update_engine {
-
-extern const char* kUnittestPrivateKeyPath;
-const char* kUnittestOtacertsPath = "otacerts.zip";
-
-TEST(CertificateParserAndroidTest, ParseZipArchive) {
- std::string ota_cert =
- test_utils::GetBuildArtifactsPath(kUnittestOtacertsPath);
- ASSERT_TRUE(utils::FileExists(ota_cert.c_str()));
-
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>> keys;
- auto parser = CreateCertificateParser();
- ASSERT_TRUE(parser->ReadPublicKeysFromCertificates(ota_cert, &keys));
- ASSERT_EQ(1u, keys.size());
-}
-
-TEST(CertificateParserAndroidTest, VerifySignature) {
- brillo::Blob hash_blob;
- ASSERT_TRUE(HashCalculator::RawHashOfData({'x'}, &hash_blob));
- brillo::Blob sig_blob;
- ASSERT_TRUE(PayloadSigner::SignHash(
- hash_blob,
- test_utils::GetBuildArtifactsPath(kUnittestPrivateKeyPath),
- &sig_blob));
-
- auto verifier = PayloadVerifier::CreateInstanceFromZipPath(
- test_utils::GetBuildArtifactsPath(kUnittestOtacertsPath));
- ASSERT_TRUE(verifier != nullptr);
- ASSERT_TRUE(verifier->VerifyRawSignature(sig_blob, hash_blob, nullptr));
-}
-
-} // namespace chromeos_update_engine
diff --git a/payload_consumer/certificate_parser_interface.h b/payload_consumer/certificate_parser_interface.h
deleted file mode 100644
index dad23d2..0000000
--- a/payload_consumer/certificate_parser_interface.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (C) 2019 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_CERTIFICATE_PARSER_INTERFACE_H_
-#define UPDATE_ENGINE_CERTIFICATE_PARSER_INTERFACE_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <openssl/pem.h>
-
-namespace chromeos_update_engine {
-
-// This class parses the PEM encoded X509 certificates from |path|; and
-// passes the parsed public keys to the caller.
-class CertificateParserInterface {
- public:
- virtual ~CertificateParserInterface() = default;
-
- virtual bool ReadPublicKeysFromCertificates(
- const std::string& path,
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>>*
- out_public_keys) = 0;
-};
-
-std::unique_ptr<CertificateParserInterface> CreateCertificateParser();
-
-} // namespace chromeos_update_engine
-
-#endif
diff --git a/payload_consumer/certificate_parser_stub.cc b/payload_consumer/certificate_parser_stub.cc
deleted file mode 100644
index 95fd6e8..0000000
--- a/payload_consumer/certificate_parser_stub.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-#include <payload_consumer/certificate_parser_stub.h>
-
-namespace chromeos_update_engine {
-bool CertificateParserStub::ReadPublicKeysFromCertificates(
- const std::string& path,
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>>*
- out_public_keys) {
- return true;
-}
-
-std::unique_ptr<CertificateParserInterface> CreateCertificateParser() {
- return std::make_unique<CertificateParserStub>();
-}
-
-} // namespace chromeos_update_engine
diff --git a/payload_consumer/certificate_parser_stub.h b/payload_consumer/certificate_parser_stub.h
deleted file mode 100644
index f4f8825..0000000
--- a/payload_consumer/certificate_parser_stub.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (C) 2019 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_CERTIFICATE_PARSER_STUB_H_
-#define UPDATE_ENGINE_CERTIFICATE_PARSER_STUB_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <base/macros.h>
-
-#include "payload_consumer/certificate_parser_interface.h"
-
-namespace chromeos_update_engine {
-class CertificateParserStub : public CertificateParserInterface {
- public:
- CertificateParserStub() = default;
-
- bool ReadPublicKeysFromCertificates(
- const std::string& path,
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>>*
- out_public_keys) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CertificateParserStub);
-};
-
-} // namespace chromeos_update_engine
-
-#endif // UPDATE_ENGINE_CERTIFICATE_PARSER_STUB_H_
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 8b3f61c..d76a959 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -46,7 +46,6 @@
#include "update_engine/common/terminator.h"
#include "update_engine/payload_consumer/bzip_extent_writer.h"
#include "update_engine/payload_consumer/cached_file_descriptor.h"
-#include "update_engine/payload_consumer/certificate_parser_interface.h"
#include "update_engine/payload_consumer/download_action.h"
#include "update_engine/payload_consumer/extent_reader.h"
#include "update_engine/payload_consumer/extent_writer.h"
@@ -527,19 +526,17 @@
<< "Trusting metadata size in payload = " << metadata_size_;
}
- auto [payload_verifier, perform_verification] = CreatePayloadVerifier();
- if (!payload_verifier) {
- LOG(ERROR) << "Failed to create payload verifier.";
+ string public_key;
+ if (!GetPublicKey(&public_key)) {
+ LOG(ERROR) << "Failed to get public key.";
*error = ErrorCode::kDownloadMetadataSignatureVerificationError;
- if (perform_verification) {
- return MetadataParseResult::kError;
- }
- } else {
- // We have the full metadata in |payload|. Verify its integrity
- // and authenticity based on the information we have in Omaha response.
- *error = payload_metadata_.ValidateMetadataSignature(
- payload, payload_->metadata_signature, *payload_verifier);
+ return MetadataParseResult::kError;
}
+
+ // We have the full metadata in |payload|. Verify its integrity
+ // and authenticity based on the information we have in Omaha response.
+ *error = payload_metadata_.ValidateMetadataSignature(
+ payload, payload_->metadata_signature, public_key);
if (*error != ErrorCode::kSuccess) {
if (install_plan_->hash_checks_mandatory) {
// The autoupdate_CatchBadSignatures test checks for this string
@@ -811,6 +808,7 @@
for (const PartitionUpdate& partition : manifest_.partitions()) {
partitions_.push_back(partition);
}
+ manifest_.clear_partitions();
} else if (major_payload_version_ == kChromeOSMajorPayloadVersion) {
LOG(INFO) << "Converting update information from old format.";
PartitionUpdate root_part;
@@ -925,16 +923,12 @@
}
if (install_plan_->target_slot != BootControlInterface::kInvalidSlot) {
- if (!PreparePartitionsForUpdate()) {
+ if (!InitPartitionMetadata()) {
*error = ErrorCode::kInstallDeviceOpenError;
return false;
}
}
- if (major_payload_version_ == kBrilloMajorPayloadVersion) {
- manifest_.clear_partitions();
- }
-
if (!install_plan_->LoadPartitionsFromSlots(boot_control_)) {
LOG(ERROR) << "Unable to determine all the partition devices.";
*error = ErrorCode::kInstallDeviceOpenError;
@@ -944,18 +938,45 @@
return true;
}
-bool DeltaPerformer::PreparePartitionsForUpdate() {
+bool DeltaPerformer::InitPartitionMetadata() {
+ BootControlInterface::PartitionMetadata partition_metadata;
+ if (manifest_.has_dynamic_partition_metadata()) {
+ std::map<string, uint64_t> partition_sizes;
+ for (const auto& partition : install_plan_->partitions) {
+ partition_sizes.emplace(partition.name, partition.target_size);
+ }
+ for (const auto& group : manifest_.dynamic_partition_metadata().groups()) {
+ BootControlInterface::PartitionMetadata::Group e;
+ e.name = group.name();
+ e.size = group.size();
+ for (const auto& partition_name : group.partition_names()) {
+ auto it = partition_sizes.find(partition_name);
+ if (it == partition_sizes.end()) {
+ // TODO(tbao): Support auto-filling partition info for framework-only
+ // OTA.
+ LOG(ERROR) << "dynamic_partition_metadata contains partition "
+ << partition_name
+ << " but it is not part of the manifest. "
+ << "This is not supported.";
+ return false;
+ }
+ e.partitions.push_back({partition_name, it->second});
+ }
+ partition_metadata.groups.push_back(std::move(e));
+ }
+ }
+
bool metadata_updated = false;
prefs_->GetBoolean(kPrefsDynamicPartitionMetadataUpdated, &metadata_updated);
- if (!boot_control_->PreparePartitionsForUpdate(
- install_plan_->target_slot, manifest_, !metadata_updated)) {
+ if (!boot_control_->InitPartitionMetadata(
+ install_plan_->target_slot, partition_metadata, !metadata_updated)) {
LOG(ERROR) << "Unable to initialize partition metadata for slot "
<< BootControlInterface::SlotName(install_plan_->target_slot);
return false;
}
TEST_AND_RETURN_FALSE(
prefs_->SetBoolean(kPrefsDynamicPartitionMetadataUpdated, true));
- LOG(INFO) << "PreparePartitionsForUpdate done.";
+ LOG(INFO) << "InitPartitionMetadata done.";
return true;
}
@@ -1599,32 +1620,10 @@
return brillo::data_encoding::Base64Decode(install_plan_->public_key_rsa,
out_public_key);
}
- LOG(INFO) << "No public keys found for verification.";
+
return true;
}
-std::pair<std::unique_ptr<PayloadVerifier>, bool>
-DeltaPerformer::CreatePayloadVerifier() {
- if (utils::FileExists(update_certificates_path_.c_str())) {
- LOG(INFO) << "Verifying using certificates: " << update_certificates_path_;
- return {
- PayloadVerifier::CreateInstanceFromZipPath(update_certificates_path_),
- true};
- }
-
- string public_key;
- if (!GetPublicKey(&public_key)) {
- LOG(ERROR) << "Failed to read public key";
- return {nullptr, true};
- }
-
- // Skips the verification if the public key is empty.
- if (public_key.empty()) {
- return {nullptr, false};
- }
- return {PayloadVerifier::CreateInstance(public_key), true};
-}
-
ErrorCode DeltaPerformer::ValidateManifest() {
// Perform assorted checks to sanity check the manifest, make sure it
// matches data from other sources, and that it is a supported version.
@@ -1692,11 +1691,7 @@
<< hardware_->GetBuildTimestamp()
<< ") is newer than the maximum timestamp in the manifest ("
<< manifest_.max_timestamp() << ")";
- if (!hardware_->AllowDowngrade()) {
- return ErrorCode::kPayloadTimestampError;
- }
- LOG(INFO) << "The current OS build allows downgrade, continuing to apply"
- " the payload with an older timestamp.";
+ return ErrorCode::kPayloadTimestampError;
}
if (major_payload_version_ == kChromeOSMajorPayloadVersion) {
@@ -1789,6 +1784,12 @@
ErrorCode DeltaPerformer::VerifyPayload(
const brillo::Blob& update_check_response_hash,
const uint64_t update_check_response_size) {
+ string public_key;
+ if (!GetPublicKey(&public_key)) {
+ LOG(ERROR) << "Failed to get public key.";
+ return ErrorCode::kDownloadPayloadPubKeyVerificationError;
+ }
+
// Verifies the download size.
if (update_check_response_size !=
metadata_size_ + metadata_signature_size_ + buffer_offset_) {
@@ -1806,22 +1807,19 @@
ErrorCode::kPayloadHashMismatchError,
payload_hash_calculator_.raw_hash() == update_check_response_hash);
+ // Verifies the signed payload hash.
+ if (public_key.empty()) {
+ LOG(WARNING) << "Not verifying signed delta payload -- missing public key.";
+ return ErrorCode::kSuccess;
+ }
TEST_AND_RETURN_VAL(ErrorCode::kSignedDeltaPayloadExpectedError,
!signatures_message_data_.empty());
brillo::Blob hash_data = signed_hash_calculator_.raw_hash();
TEST_AND_RETURN_VAL(ErrorCode::kDownloadPayloadPubKeyVerificationError,
hash_data.size() == kSHA256Size);
- auto [payload_verifier, perform_verification] = CreatePayloadVerifier();
- if (!perform_verification) {
- LOG(WARNING) << "Not verifying signed delta payload -- missing public key.";
- return ErrorCode::kSuccess;
- }
- if (!payload_verifier) {
- LOG(ERROR) << "Failed to create the payload verifier.";
- return ErrorCode::kDownloadPayloadPubKeyVerificationError;
- }
- if (!payload_verifier->VerifySignature(signatures_message_data_, hash_data)) {
+ if (!PayloadVerifier::VerifySignature(
+ signatures_message_data_, public_key, hash_data)) {
// The autoupdate_CatchBadSignatures test checks for this string
// in log-files. Keep in sync.
LOG(ERROR) << "Public key verification failed, thus update failed.";
diff --git a/payload_consumer/delta_performer.h b/payload_consumer/delta_performer.h
index 4c64dfa..17cb599 100644
--- a/payload_consumer/delta_performer.h
+++ b/payload_consumer/delta_performer.h
@@ -20,9 +20,7 @@
#include <inttypes.h>
#include <limits>
-#include <memory>
#include <string>
-#include <utility>
#include <vector>
#include <base/time/time.h>
@@ -36,7 +34,6 @@
#include "update_engine/payload_consumer/file_writer.h"
#include "update_engine/payload_consumer/install_plan.h"
#include "update_engine/payload_consumer/payload_metadata.h"
-#include "update_engine/payload_consumer/payload_verifier.h"
#include "update_engine/update_metadata.pb.h"
namespace chromeos_update_engine {
@@ -159,11 +156,6 @@
public_key_path_ = public_key_path;
}
- void set_update_certificates_path(
- const std::string& update_certificates_path) {
- update_certificates_path_ = update_certificates_path;
- }
-
// Return true if header parsing is finished and no errors occurred.
bool IsHeaderParsed() const;
@@ -281,15 +273,9 @@
// |out_public_key|. Returns false on failures.
bool GetPublicKey(std::string* out_public_key);
- // Creates a PayloadVerifier from the zip file containing certificates. If the
- // path to the zip file doesn't exist, falls back to use the public key.
- // Returns a tuple with the created PayloadVerifier and if we should perform
- // the verification.
- std::pair<std::unique_ptr<PayloadVerifier>, bool> CreatePayloadVerifier();
-
// After install_plan_ is filled with partition names and sizes, initialize
// metadata of partitions and map necessary devices before opening devices.
- bool PreparePartitionsForUpdate();
+ bool InitPartitionMetadata();
// Update Engine preference store.
PrefsInterface* prefs_;
@@ -397,9 +383,6 @@
// override with test keys.
std::string public_key_path_{constants::kUpdatePayloadPublicKeyPath};
- // The path to the zip file with X509 certificates.
- std::string update_certificates_path_{constants::kUpdateCertificatesPath};
-
// The number of bytes received so far, used for progress tracking.
size_t total_bytes_received_{0};
diff --git a/payload_consumer/delta_performer_integration_test.cc b/payload_consumer/delta_performer_integration_test.cc
index a2ad77b..6b4771d 100644
--- a/payload_consumer/delta_performer_integration_test.cc
+++ b/payload_consumer/delta_performer_integration_test.cc
@@ -60,8 +60,6 @@
extern const char* kUnittestPublicKeyPath;
extern const char* kUnittestPrivateKey2Path;
extern const char* kUnittestPublicKey2Path;
-extern const char* kUnittestPrivateKeyECPath;
-extern const char* kUnittestPublicKeyECPath;
static const uint32_t kDefaultKernelSize = 4096; // Something small for a test
// clang-format off
@@ -109,7 +107,6 @@
kSignatureGeneratedPlaceholder, // Insert placeholder signatures, then real.
kSignatureGeneratedPlaceholderMismatch, // Insert a wrong sized placeholder.
kSignatureGeneratedShell, // Sign the generated payload through shell cmds.
- kSignatureGeneratedShellECKey, // Sign with a EC key through shell cmds.
kSignatureGeneratedShellBadKey, // Sign with a bad key through shell cmds.
kSignatureGeneratedShellRotateCl1, // Rotate key, test client v1
kSignatureGeneratedShellRotateCl2, // Rotate key, test client v2
@@ -167,127 +164,53 @@
return true;
}
-static bool InsertSignaturePlaceholder(size_t signature_size,
+static size_t GetSignatureSize(const string& private_key_path) {
+ const brillo::Blob data(1, 'x');
+ brillo::Blob hash;
+ EXPECT_TRUE(HashCalculator::RawHashOfData(data, &hash));
+ brillo::Blob signature;
+ EXPECT_TRUE(PayloadSigner::SignHash(hash, private_key_path, &signature));
+ return signature.size();
+}
+
+static bool InsertSignaturePlaceholder(int signature_size,
const string& payload_path,
uint64_t* out_metadata_size) {
vector<brillo::Blob> signatures;
signatures.push_back(brillo::Blob(signature_size, 0));
- return PayloadSigner::AddSignatureToPayload(payload_path,
- {signature_size},
- signatures,
- {},
- payload_path,
- out_metadata_size);
+ return PayloadSigner::AddSignatureToPayload(
+ payload_path, signatures, {}, payload_path, out_metadata_size);
}
static void SignGeneratedPayload(const string& payload_path,
uint64_t* out_metadata_size) {
string private_key_path = GetBuildArtifactsPath(kUnittestPrivateKeyPath);
- size_t signature_size;
- ASSERT_TRUE(PayloadSigner::GetMaximumSignatureSize(private_key_path,
- &signature_size));
+ int signature_size = GetSignatureSize(private_key_path);
brillo::Blob hash;
ASSERT_TRUE(PayloadSigner::HashPayloadForSigning(
payload_path, {signature_size}, &hash, nullptr));
brillo::Blob signature;
ASSERT_TRUE(PayloadSigner::SignHash(hash, private_key_path, &signature));
- ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(payload_path,
- {signature_size},
- {signature},
- {},
- payload_path,
- out_metadata_size));
+ ASSERT_TRUE(PayloadSigner::AddSignatureToPayload(
+ payload_path, {signature}, {}, payload_path, out_metadata_size));
EXPECT_TRUE(PayloadSigner::VerifySignedPayload(
payload_path, GetBuildArtifactsPath(kUnittestPublicKeyPath)));
}
-static void SignGeneratedShellPayloadWithKeys(
- const string& payload_path,
- const vector<string>& private_key_paths,
- const string& public_key_path,
- bool verification_success) {
- vector<string> signature_size_strings;
- for (const auto& key_path : private_key_paths) {
- size_t signature_size;
- ASSERT_TRUE(
- PayloadSigner::GetMaximumSignatureSize(key_path, &signature_size));
- signature_size_strings.push_back(base::StringPrintf("%zu", signature_size));
- }
- string signature_size_string = base::JoinString(signature_size_strings, ":");
-
- test_utils::ScopedTempFile hash_file("hash.XXXXXX");
- string delta_generator_path = GetBuildArtifactsPath("delta_generator");
- ASSERT_EQ(0,
- System(base::StringPrintf(
- "%s -in_file=%s -signature_size=%s -out_hash_file=%s",
- delta_generator_path.c_str(),
- payload_path.c_str(),
- signature_size_string.c_str(),
- hash_file.path().c_str())));
-
- // Sign the hash with all private keys.
- vector<test_utils::ScopedTempFile> sig_files;
- vector<string> sig_file_paths;
- for (const auto& key_path : private_key_paths) {
- brillo::Blob hash, signature;
- ASSERT_TRUE(utils::ReadFile(hash_file.path(), &hash));
- ASSERT_TRUE(PayloadSigner::SignHash(hash, key_path, &signature));
-
- test_utils::ScopedTempFile sig_file("signature.XXXXXX");
- ASSERT_TRUE(test_utils::WriteFileVector(sig_file.path(), signature));
- sig_file_paths.push_back(sig_file.path());
- sig_files.push_back(std::move(sig_file));
- }
- string sig_files_string = base::JoinString(sig_file_paths, ":");
-
- // Add the signature to the payload.
- ASSERT_EQ(0,
- System(base::StringPrintf("%s --signature_size=%s -in_file=%s "
- "-payload_signature_file=%s -out_file=%s",
- delta_generator_path.c_str(),
- signature_size_string.c_str(),
- payload_path.c_str(),
- sig_files_string.c_str(),
- payload_path.c_str())));
-
- int verify_result = System(base::StringPrintf("%s -in_file=%s -public_key=%s",
- delta_generator_path.c_str(),
- payload_path.c_str(),
- public_key_path.c_str()));
-
- if (verification_success) {
- ASSERT_EQ(0, verify_result);
- } else {
- ASSERT_NE(0, verify_result);
- }
-}
-
static void SignGeneratedShellPayload(SignatureTest signature_test,
const string& payload_path) {
- vector<SignatureTest> supported_test = {
- kSignatureGeneratedShell,
- kSignatureGeneratedShellBadKey,
- kSignatureGeneratedShellECKey,
- kSignatureGeneratedShellRotateCl1,
- kSignatureGeneratedShellRotateCl2,
- };
- ASSERT_TRUE(std::find(supported_test.begin(),
- supported_test.end(),
- signature_test) != supported_test.end());
-
- string private_key_path;
+ string private_key_path = GetBuildArtifactsPath(kUnittestPrivateKeyPath);
if (signature_test == kSignatureGeneratedShellBadKey) {
ASSERT_TRUE(utils::MakeTempFile("key.XXXXXX", &private_key_path, nullptr));
- } else if (signature_test == kSignatureGeneratedShellECKey) {
- private_key_path = GetBuildArtifactsPath(kUnittestPrivateKeyECPath);
} else {
- private_key_path = GetBuildArtifactsPath(kUnittestPrivateKeyPath);
+ ASSERT_TRUE(signature_test == kSignatureGeneratedShell ||
+ signature_test == kSignatureGeneratedShellRotateCl1 ||
+ signature_test == kSignatureGeneratedShellRotateCl2);
}
ScopedPathUnlinker key_unlinker(private_key_path);
key_unlinker.set_should_remove(signature_test ==
kSignatureGeneratedShellBadKey);
-
// Generates a new private key that will not match the public key.
if (signature_test == kSignatureGeneratedShellBadKey) {
LOG(INFO) << "Generating a mismatched private key.";
@@ -306,26 +229,64 @@
fclose(fprikey);
RSA_free(rsa);
}
+ int signature_size = GetSignatureSize(private_key_path);
+ test_utils::ScopedTempFile hash_file("hash.XXXXXX");
+ string signature_size_string;
+ if (signature_test == kSignatureGeneratedShellRotateCl1 ||
+ signature_test == kSignatureGeneratedShellRotateCl2)
+ signature_size_string =
+ base::StringPrintf("%d:%d", signature_size, signature_size);
+ else
+ signature_size_string = base::StringPrintf("%d", signature_size);
+ string delta_generator_path = GetBuildArtifactsPath("delta_generator");
+ ASSERT_EQ(0,
+ System(base::StringPrintf(
+ "%s -in_file=%s -signature_size=%s -out_hash_file=%s",
+ delta_generator_path.c_str(),
+ payload_path.c_str(),
+ signature_size_string.c_str(),
+ hash_file.path().c_str())));
- vector<string> private_key_paths = {private_key_path};
+ // Sign the hash
+ brillo::Blob hash, signature;
+ ASSERT_TRUE(utils::ReadFile(hash_file.path(), &hash));
+ ASSERT_TRUE(PayloadSigner::SignHash(hash, private_key_path, &signature));
+
+ test_utils::ScopedTempFile sig_file("signature.XXXXXX");
+ ASSERT_TRUE(test_utils::WriteFileVector(sig_file.path(), signature));
+ string sig_files = sig_file.path();
+
+ test_utils::ScopedTempFile sig_file2("signature.XXXXXX");
if (signature_test == kSignatureGeneratedShellRotateCl1 ||
signature_test == kSignatureGeneratedShellRotateCl2) {
- private_key_paths.push_back(
- GetBuildArtifactsPath(kUnittestPrivateKey2Path));
+ ASSERT_TRUE(PayloadSigner::SignHash(
+ hash, GetBuildArtifactsPath(kUnittestPrivateKey2Path), &signature));
+ ASSERT_TRUE(test_utils::WriteFileVector(sig_file2.path(), signature));
+ // Append second sig file to first path
+ sig_files += ":" + sig_file2.path();
}
- std::string public_key;
- if (signature_test == kSignatureGeneratedShellRotateCl2) {
- public_key = GetBuildArtifactsPath(kUnittestPublicKey2Path);
- } else if (signature_test == kSignatureGeneratedShellECKey) {
- public_key = GetBuildArtifactsPath(kUnittestPublicKeyECPath);
+ ASSERT_EQ(0,
+ System(base::StringPrintf(
+ "%s -in_file=%s -payload_signature_file=%s -out_file=%s",
+ delta_generator_path.c_str(),
+ payload_path.c_str(),
+ sig_files.c_str(),
+ payload_path.c_str())));
+ int verify_result = System(base::StringPrintf(
+ "%s -in_file=%s -public_key=%s -public_key_version=%d",
+ delta_generator_path.c_str(),
+ payload_path.c_str(),
+ (signature_test == kSignatureGeneratedShellRotateCl2
+ ? GetBuildArtifactsPath(kUnittestPublicKey2Path)
+ : GetBuildArtifactsPath(kUnittestPublicKeyPath))
+ .c_str(),
+ signature_test == kSignatureGeneratedShellRotateCl2 ? 2 : 1));
+ if (signature_test == kSignatureGeneratedShellBadKey) {
+ ASSERT_NE(0, verify_result);
} else {
- public_key = GetBuildArtifactsPath(kUnittestPublicKeyPath);
+ ASSERT_EQ(0, verify_result);
}
-
- bool verification_success = signature_test != kSignatureGeneratedShellBadKey;
- SignGeneratedShellPayloadWithKeys(
- payload_path, private_key_paths, public_key, verification_success);
}
static void GenerateDeltaFile(bool full_kernel,
@@ -570,9 +531,8 @@
if (signature_test == kSignatureGeneratedPlaceholder ||
signature_test == kSignatureGeneratedPlaceholderMismatch) {
- size_t signature_size;
- ASSERT_TRUE(PayloadSigner::GetMaximumSignatureSize(
- GetBuildArtifactsPath(kUnittestPrivateKeyPath), &signature_size));
+ int signature_size =
+ GetSignatureSize(GetBuildArtifactsPath(kUnittestPrivateKeyPath));
LOG(INFO) << "Inserting placeholder signature.";
ASSERT_TRUE(InsertSignaturePlaceholder(
signature_size, state->delta_path, &state->metadata_size));
@@ -595,7 +555,6 @@
LOG(INFO) << "Signing payload.";
SignGeneratedPayload(state->delta_path, &state->metadata_size);
} else if (signature_test == kSignatureGeneratedShell ||
- signature_test == kSignatureGeneratedShellECKey ||
signature_test == kSignatureGeneratedShellBadKey ||
signature_test == kSignatureGeneratedShellRotateCl1 ||
signature_test == kSignatureGeneratedShellRotateCl2) {
@@ -638,15 +597,14 @@
else
EXPECT_EQ(1, sigs_message.signatures_size());
const Signatures::Signature& signature = sigs_message.signatures(0);
+ EXPECT_EQ(1U, signature.version());
+ uint64_t expected_sig_data_length = 0;
vector<string> key_paths{GetBuildArtifactsPath(kUnittestPrivateKeyPath)};
- if (signature_test == kSignatureGeneratedShellECKey) {
- key_paths = {GetBuildArtifactsPath(kUnittestPrivateKeyECPath)};
- } else if (signature_test == kSignatureGeneratedShellRotateCl1 ||
- signature_test == kSignatureGeneratedShellRotateCl2) {
+ if (signature_test == kSignatureGeneratedShellRotateCl1 ||
+ signature_test == kSignatureGeneratedShellRotateCl2) {
key_paths.push_back(GetBuildArtifactsPath(kUnittestPrivateKey2Path));
}
- uint64_t expected_sig_data_length = 0;
EXPECT_TRUE(PayloadSigner::SignatureBlobLength(
key_paths, &expected_sig_data_length));
EXPECT_EQ(expected_sig_data_length, manifest.signatures_size());
@@ -759,9 +717,7 @@
ASSERT_TRUE(PayloadSigner::GetMetadataSignature(
state->delta.data(),
state->metadata_size,
- (signature_test == kSignatureGeneratedShellECKey)
- ? GetBuildArtifactsPath(kUnittestPrivateKeyECPath)
- : GetBuildArtifactsPath(kUnittestPrivateKeyPath),
+ GetBuildArtifactsPath(kUnittestPrivateKeyPath),
&install_plan->payloads[0].metadata_signature));
EXPECT_FALSE(install_plan->payloads[0].metadata_signature.empty());
@@ -772,12 +728,9 @@
install_plan,
&install_plan->payloads[0],
false /* interactive */);
- string public_key_path = signature_test == kSignatureGeneratedShellECKey
- ? GetBuildArtifactsPath(kUnittestPublicKeyECPath)
- : GetBuildArtifactsPath(kUnittestPublicKeyPath);
+ string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath);
EXPECT_TRUE(utils::FileExists(public_key_path.c_str()));
(*performer)->set_public_key_path(public_key_path);
- (*performer)->set_update_certificates_path("");
EXPECT_EQ(static_cast<off_t>(state->image_size),
HashCalculator::RawHashOfFile(
@@ -1107,17 +1060,6 @@
}
TEST(DeltaPerformerIntegrationTest,
- RunAsRootSmallImageSignGeneratedShellECKeyTest) {
- DoSmallImageTest(false,
- false,
- false,
- -1,
- kSignatureGeneratedShellECKey,
- false,
- kInPlaceMinorPayloadVersion);
-}
-
-TEST(DeltaPerformerIntegrationTest,
RunAsRootSmallImageSignGeneratedShellBadKeyTest) {
DoSmallImageTest(false,
false,
diff --git a/payload_consumer/delta_performer_unittest.cc b/payload_consumer/delta_performer_unittest.cc
index e9022ba..b7a38cc 100644
--- a/payload_consumer/delta_performer_unittest.cc
+++ b/payload_consumer/delta_performer_unittest.cc
@@ -159,11 +159,6 @@
install_plan_.target_slot = 1;
EXPECT_CALL(mock_delegate_, ShouldCancel(_))
.WillRepeatedly(testing::Return(false));
- performer_.set_update_certificates_path("");
- // Set the public key corresponding to the unittest private key.
- string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath);
- EXPECT_TRUE(utils::FileExists(public_key_path.c_str()));
- performer_.set_public_key_path(public_key_path);
}
// Test helper placed where it can easily be friended from DeltaPerformer.
@@ -393,6 +388,12 @@
expected_error = ErrorCode::kSuccess;
}
+ // Use the public key corresponding to the private key used above to
+ // sign the metadata.
+ string public_key_path = GetBuildArtifactsPath(kUnittestPublicKeyPath);
+ EXPECT_TRUE(utils::FileExists(public_key_path.c_str()));
+ performer_.set_public_key_path(public_key_path);
+
// Init actual_error with an invalid value so that we make sure
// ParsePayloadMetadata properly populates it in all cases.
actual_error = ErrorCode::kUmaReportedMax;
@@ -919,6 +920,7 @@
brillo::Blob payload_data = GeneratePayload(
{}, {}, true, kBrilloMajorPayloadVersion, kSourceMinorPayloadVersion);
install_plan_.hash_checks_mandatory = true;
+ performer_.set_public_key_path(GetBuildArtifactsPath(kUnittestPublicKeyPath));
ErrorCode error;
EXPECT_EQ(MetadataParseResult::kSuccess,
performer_.ParsePayloadMetadata(payload_data, &error));
diff --git a/payload_consumer/install_plan.cc b/payload_consumer/install_plan.cc
index 766b27c..2e7b6d4 100644
--- a/payload_consumer/install_plan.cc
+++ b/payload_consumer/install_plan.cc
@@ -19,7 +19,6 @@
#include <base/format_macros.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
-#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include "update_engine/common/utils.h"
@@ -81,18 +80,11 @@
base::StringPrintf(", system_version: %s", system_version.c_str());
}
- string url_str = download_url;
- if (base::StartsWith(
- url_str, "fd://", base::CompareCase::INSENSITIVE_ASCII)) {
- int fd = std::stoi(url_str.substr(strlen("fd://")));
- url_str = utils::GetFilePath(fd);
- }
-
LOG(INFO) << "InstallPlan: " << (is_resume ? "resume" : "new_update")
<< version_str
<< ", source_slot: " << BootControlInterface::SlotName(source_slot)
<< ", target_slot: " << BootControlInterface::SlotName(target_slot)
- << ", url: " << url_str << payloads_str << partitions_str
+ << ", url: " << download_url << payloads_str << partitions_str
<< ", hash_checks_mandatory: "
<< utils::ToString(hash_checks_mandatory)
<< ", powerwash_required: " << utils::ToString(powerwash_required)
diff --git a/payload_consumer/payload_metadata.cc b/payload_consumer/payload_metadata.cc
index 0952646..3739767 100644
--- a/payload_consumer/payload_metadata.cc
+++ b/payload_consumer/payload_metadata.cc
@@ -159,7 +159,7 @@
ErrorCode PayloadMetadata::ValidateMetadataSignature(
const brillo::Blob& payload,
const string& metadata_signature,
- const PayloadVerifier& payload_verifier) const {
+ const string& pem_public_key) const {
if (payload.size() < metadata_size_ + metadata_signature_size_)
return ErrorCode::kDownloadMetadataSignatureError;
@@ -202,18 +202,31 @@
}
if (!metadata_signature_blob.empty()) {
- brillo::Blob decrypted_signature;
- if (!payload_verifier.VerifyRawSignature(
- metadata_signature_blob, metadata_hash, &decrypted_signature)) {
- LOG(ERROR) << "Manifest hash verification failed. Decrypted hash = ";
- utils::HexDumpVector(decrypted_signature);
- LOG(ERROR) << "Calculated hash before padding = ";
- utils::HexDumpVector(metadata_hash);
+ brillo::Blob expected_metadata_hash;
+ if (!PayloadVerifier::GetRawHashFromSignature(
+ metadata_signature_blob, pem_public_key, &expected_metadata_hash)) {
+ LOG(ERROR) << "Unable to compute expected hash from metadata signature";
+ return ErrorCode::kDownloadMetadataSignatureError;
+ }
+
+ brillo::Blob padded_metadata_hash = metadata_hash;
+ if (!PayloadVerifier::PadRSASHA256Hash(&padded_metadata_hash,
+ expected_metadata_hash.size())) {
+ LOG(ERROR) << "Failed to pad the SHA256 hash to "
+ << expected_metadata_hash.size() << " bytes.";
+ return ErrorCode::kDownloadMetadataSignatureVerificationError;
+ }
+
+ if (padded_metadata_hash != expected_metadata_hash) {
+ LOG(ERROR) << "Manifest hash verification failed. Expected hash = ";
+ utils::HexDumpVector(expected_metadata_hash);
+ LOG(ERROR) << "Calculated hash = ";
+ utils::HexDumpVector(padded_metadata_hash);
return ErrorCode::kDownloadMetadataSignatureMismatch;
}
} else {
- if (!payload_verifier.VerifySignature(metadata_signature_protobuf,
- metadata_hash)) {
+ if (!PayloadVerifier::VerifySignature(
+ metadata_signature_protobuf, pem_public_key, metadata_hash)) {
LOG(ERROR) << "Manifest hash verification failed.";
return ErrorCode::kDownloadMetadataSignatureMismatch;
}
diff --git a/payload_consumer/payload_metadata.h b/payload_consumer/payload_metadata.h
index 75ef8f9..1b4c5c8 100644
--- a/payload_consumer/payload_metadata.h
+++ b/payload_consumer/payload_metadata.h
@@ -27,7 +27,6 @@
#include "update_engine/common/error_code.h"
#include "update_engine/common/platform_constants.h"
-#include "update_engine/payload_consumer/payload_verifier.h"
#include "update_engine/update_metadata.pb.h"
namespace chromeos_update_engine {
@@ -66,10 +65,9 @@
// metadata is parsed so that a man-in-the-middle attack on the SSL connection
// to the payload server doesn't exploit any vulnerability in the code that
// parses the protocol buffer.
- ErrorCode ValidateMetadataSignature(
- const brillo::Blob& payload,
- const std::string& metadata_signature,
- const PayloadVerifier& payload_verifier) const;
+ ErrorCode ValidateMetadataSignature(const brillo::Blob& payload,
+ const std::string& metadata_signature,
+ const std::string& pem_public_key) const;
// Returns the major payload version. If the version was not yet parsed,
// returns zero.
diff --git a/payload_consumer/payload_verifier.cc b/payload_consumer/payload_verifier.cc
index 24e337e..3a3ccbf 100644
--- a/payload_consumer/payload_verifier.cc
+++ b/payload_consumer/payload_verifier.cc
@@ -25,7 +25,6 @@
#include "update_engine/common/constants.h"
#include "update_engine/common/hash_calculator.h"
#include "update_engine/common/utils.h"
-#include "update_engine/payload_consumer/certificate_parser_interface.h"
#include "update_engine/update_metadata.pb.h"
using std::string;
@@ -52,52 +51,9 @@
} // namespace
-std::unique_ptr<PayloadVerifier> PayloadVerifier::CreateInstance(
- const std::string& pem_public_key) {
- std::unique_ptr<BIO, decltype(&BIO_free)> bp(
- BIO_new_mem_buf(pem_public_key.data(), pem_public_key.size()), BIO_free);
- if (!bp) {
- LOG(ERROR) << "Failed to read " << pem_public_key << " into buffer.";
- return nullptr;
- }
-
- auto pub_key = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>(
- PEM_read_bio_PUBKEY(bp.get(), nullptr, nullptr, nullptr), EVP_PKEY_free);
- if (!pub_key) {
- LOG(ERROR) << "Failed to parse the public key in: " << pem_public_key;
- return nullptr;
- }
-
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>> keys;
- keys.emplace_back(std::move(pub_key));
- return std::unique_ptr<PayloadVerifier>(new PayloadVerifier(std::move(keys)));
-}
-
-std::unique_ptr<PayloadVerifier> PayloadVerifier::CreateInstanceFromZipPath(
- const std::string& certificate_zip_path) {
- auto parser = CreateCertificateParser();
- if (!parser) {
- LOG(ERROR) << "Failed to create certificate parser from "
- << certificate_zip_path;
- return nullptr;
- }
-
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>> public_keys;
- if (!parser->ReadPublicKeysFromCertificates(certificate_zip_path,
- &public_keys) ||
- public_keys.empty()) {
- LOG(ERROR) << "Failed to parse public keys in: " << certificate_zip_path;
- return nullptr;
- }
-
- return std::unique_ptr<PayloadVerifier>(
- new PayloadVerifier(std::move(public_keys)));
-}
-
-bool PayloadVerifier::VerifySignature(
- const string& signature_proto, const brillo::Blob& sha256_hash_data) const {
- TEST_AND_RETURN_FALSE(!public_keys_.empty());
-
+bool PayloadVerifier::VerifySignature(const string& signature_proto,
+ const string& pem_public_key,
+ const brillo::Blob& sha256_hash_data) {
Signatures signatures;
LOG(INFO) << "signature blob size = " << signature_proto.size();
TEST_AND_RETURN_FALSE(signatures.ParseFromString(signature_proto));
@@ -111,104 +67,48 @@
// Tries every signature in the signature blob.
for (int i = 0; i < signatures.signatures_size(); i++) {
const Signatures::Signature& signature = signatures.signatures(i);
- brillo::Blob sig_data;
- if (signature.has_unpadded_signature_size()) {
- TEST_AND_RETURN_FALSE(signature.unpadded_signature_size() <=
- signature.data().size());
- LOG(INFO) << "Truncating the signature to its unpadded size: "
- << signature.unpadded_signature_size() << ".";
- sig_data.assign(
- signature.data().begin(),
- signature.data().begin() + signature.unpadded_signature_size());
- } else {
- sig_data.assign(signature.data().begin(), signature.data().end());
- }
-
+ brillo::Blob sig_data(signature.data().begin(), signature.data().end());
brillo::Blob sig_hash_data;
- if (VerifyRawSignature(sig_data, sha256_hash_data, &sig_hash_data)) {
+ if (!GetRawHashFromSignature(sig_data, pem_public_key, &sig_hash_data))
+ continue;
+
+ brillo::Blob padded_hash_data = sha256_hash_data;
+ if (PadRSASHA256Hash(&padded_hash_data, sig_hash_data.size()) &&
+ padded_hash_data == sig_hash_data) {
LOG(INFO) << "Verified correct signature " << i + 1 << " out of "
<< signatures.signatures_size() << " signatures.";
return true;
}
- if (!sig_hash_data.empty()) {
- tested_hashes.push_back(sig_hash_data);
- }
+ tested_hashes.push_back(sig_hash_data);
}
LOG(ERROR) << "None of the " << signatures.signatures_size()
<< " signatures is correct. Expected hash before padding:";
utils::HexDumpVector(sha256_hash_data);
- LOG(ERROR) << "But found RSA decrypted hashes:";
+ LOG(ERROR) << "But found decrypted hashes:";
for (const auto& sig_hash_data : tested_hashes) {
utils::HexDumpVector(sig_hash_data);
}
return false;
}
-bool PayloadVerifier::VerifyRawSignature(
- const brillo::Blob& sig_data,
- const brillo::Blob& sha256_hash_data,
- brillo::Blob* decrypted_sig_data) const {
- TEST_AND_RETURN_FALSE(!public_keys_.empty());
-
- for (const auto& public_key : public_keys_) {
- int key_type = EVP_PKEY_id(public_key.get());
- if (key_type == EVP_PKEY_RSA) {
- brillo::Blob sig_hash_data;
- if (!GetRawHashFromSignature(
- sig_data, public_key.get(), &sig_hash_data)) {
- LOG(WARNING)
- << "Failed to get the raw hash with RSA key. Trying other keys.";
- continue;
- }
-
- if (decrypted_sig_data != nullptr) {
- *decrypted_sig_data = sig_hash_data;
- }
-
- brillo::Blob padded_hash_data = sha256_hash_data;
- TEST_AND_RETURN_FALSE(
- PadRSASHA256Hash(&padded_hash_data, sig_hash_data.size()));
-
- if (padded_hash_data == sig_hash_data) {
- return true;
- }
- }
-
- if (key_type == EVP_PKEY_EC) {
- EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(public_key.get());
- TEST_AND_RETURN_FALSE(ec_key != nullptr);
- if (ECDSA_verify(0,
- sha256_hash_data.data(),
- sha256_hash_data.size(),
- sig_data.data(),
- sig_data.size(),
- ec_key) == 1) {
- return true;
- }
- }
-
- LOG(ERROR) << "Unsupported key type " << key_type;
- return false;
- }
- LOG(INFO) << "Failed to verify the signature with " << public_keys_.size()
- << " keys.";
- return false;
-}
-
-bool PayloadVerifier::GetRawHashFromSignature(
- const brillo::Blob& sig_data,
- const EVP_PKEY* public_key,
- brillo::Blob* out_hash_data) const {
+bool PayloadVerifier::GetRawHashFromSignature(const brillo::Blob& sig_data,
+ const string& pem_public_key,
+ brillo::Blob* out_hash_data) {
// The code below executes the equivalent of:
//
- // openssl rsautl -verify -pubin -inkey <(echo pem_public_key)
+ // openssl rsautl -verify -pubin -inkey <(echo |pem_public_key|)
// -in |sig_data| -out |out_hash_data|
- RSA* rsa = EVP_PKEY_get0_RSA(public_key);
+
+ BIO* bp = BIO_new_mem_buf(pem_public_key.data(), pem_public_key.size());
+ char dummy_password[] = {' ', 0}; // Ensure no password is read from stdin.
+ RSA* rsa = PEM_read_bio_RSA_PUBKEY(bp, nullptr, nullptr, dummy_password);
+ BIO_free(bp);
TEST_AND_RETURN_FALSE(rsa != nullptr);
unsigned int keysize = RSA_size(rsa);
if (sig_data.size() > 2 * keysize) {
LOG(ERROR) << "Signature size is too big for public key size.";
+ RSA_free(rsa);
return false;
}
@@ -216,6 +116,7 @@
brillo::Blob hash_data(keysize);
int decrypt_size = RSA_public_decrypt(
sig_data.size(), sig_data.data(), hash_data.data(), rsa, RSA_NO_PADDING);
+ RSA_free(rsa);
TEST_AND_RETURN_FALSE(decrypt_size > 0 &&
decrypt_size <= static_cast<int>(hash_data.size()));
hash_data.resize(decrypt_size);
diff --git a/payload_consumer/payload_verifier.h b/payload_consumer/payload_verifier.h
index bc5231f..af8e05f 100644
--- a/payload_consumer/payload_verifier.h
+++ b/payload_consumer/payload_verifier.h
@@ -17,24 +17,38 @@
#ifndef UPDATE_ENGINE_PAYLOAD_CONSUMER_PAYLOAD_VERIFIER_H_
#define UPDATE_ENGINE_PAYLOAD_CONSUMER_PAYLOAD_VERIFIER_H_
-#include <memory>
#include <string>
-#include <utility>
-#include <vector>
+#include <base/macros.h>
#include <brillo/secure_blob.h>
-#include <openssl/evp.h>
#include "update_engine/update_metadata.pb.h"
-// This class holds the public keys and implements methods used for payload
-// signature verification. See payload_generator/payload_signer.h for payload
-// signing.
+// This class encapsulates methods used for payload signature verification.
+// See payload_generator/payload_signer.h for payload signing.
namespace chromeos_update_engine {
class PayloadVerifier {
public:
+ // Interprets |signature_proto| as a protocol buffer containing the Signatures
+ // message and decrypts each signature data using the |pem_public_key|.
+ // |pem_public_key| should be a PEM format RSA public key data.
+ // Pads the 32 bytes |sha256_hash_data| to 256 or 512 bytes according to the
+ // PKCS#1 v1.5 standard; and returns whether *any* of the decrypted hashes
+ // matches the padded hash data. In case of any error parsing the signatures
+ // or the public key, returns false.
+ static bool VerifySignature(const std::string& signature_proto,
+ const std::string& pem_public_key,
+ const brillo::Blob& sha256_hash_data);
+
+ // Decrypts |sig_data| with the given |pem_public_key| and populates
+ // |out_hash_data| with the decoded raw hash. |pem_public_key| should be a PEM
+ // format RSA public key data. Returns true if successful, false otherwise.
+ static bool GetRawHashFromSignature(const brillo::Blob& sig_data,
+ const std::string& pem_public_key,
+ brillo::Blob* out_hash_data);
+
// Pads a SHA256 hash so that it may be encrypted/signed with RSA2048 or
// RSA4096 using the PKCS#1 v1.5 scheme.
// hash should be a pointer to vector of exactly 256 bits. |rsa_size| must be
@@ -43,46 +57,9 @@
// Returns true on success, false otherwise.
static bool PadRSASHA256Hash(brillo::Blob* hash, size_t rsa_size);
- // Parses the input as a PEM encoded public string. And creates a
- // PayloadVerifier with that public key for signature verification.
- static std::unique_ptr<PayloadVerifier> CreateInstance(
- const std::string& pem_public_key);
-
- // Extracts the public keys from the certificates contained in the input
- // zip file. And creates a PayloadVerifier with these public keys.
- static std::unique_ptr<PayloadVerifier> CreateInstanceFromZipPath(
- const std::string& certificate_zip_path);
-
- // Interprets |signature_proto| as a protocol buffer containing the
- // |Signatures| message and decrypts each signature data using the stored
- // public key. Pads the 32 bytes |sha256_hash_data| to 256 or 512 bytes
- // according to the PKCS#1 v1.5 standard; and returns whether *any* of the
- // decrypted hashes matches the padded hash data. In case of any error parsing
- // the signatures, returns false.
- bool VerifySignature(const std::string& signature_proto,
- const brillo::Blob& sha256_hash_data) const;
-
- // Verifies if |sig_data| is a raw signature of the hash |sha256_hash_data|.
- // If PayloadVerifier is using RSA as the public key, further puts the
- // decrypted data of |sig_data| into |decrypted_sig_data|.
- bool VerifyRawSignature(const brillo::Blob& sig_data,
- const brillo::Blob& sha256_hash_data,
- brillo::Blob* decrypted_sig_data) const;
-
private:
- explicit PayloadVerifier(
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>>&&
- public_keys)
- : public_keys_(std::move(public_keys)) {}
-
- // Decrypts |sig_data| with the given |public_key| and populates
- // |out_hash_data| with the decoded raw hash. Returns true if successful,
- // false otherwise.
- bool GetRawHashFromSignature(const brillo::Blob& sig_data,
- const EVP_PKEY* public_key,
- brillo::Blob* out_hash_data) const;
-
- std::vector<std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>> public_keys_;
+ // This should never be constructed
+ DISALLOW_IMPLICIT_CONSTRUCTORS(PayloadVerifier);
};
} // namespace chromeos_update_engine
diff --git a/payload_generator/deflate_utils.cc b/payload_generator/deflate_utils.cc
index 01402dd..a7a0503 100644
--- a/payload_generator/deflate_utils.cc
+++ b/payload_generator/deflate_utils.cc
@@ -74,15 +74,6 @@
return false;
}
-bool IsRegularFile(const FilesystemInterface::File& file) {
- // If inode is 0, then stat information is invalid for some psuedo files
- if (file.file_stat.st_ino != 0 &&
- (file.file_stat.st_mode & S_IFMT) == S_IFREG) {
- return true;
- }
- return false;
-}
-
// Realigns subfiles |files| of a splitted file |file| into its correct
// positions. This can be used for squashfs, zip, apk, etc.
bool RealignSplittedFiles(const FilesystemInterface::File& file,
@@ -274,9 +265,7 @@
result_files->reserve(tmp_files.size());
for (auto& file : tmp_files) {
- auto is_regular_file = IsRegularFile(file);
-
- if (is_regular_file && IsSquashfsImage(part.path, file)) {
+ if (IsSquashfsImage(part.path, file)) {
// Read the image into a file.
base::FilePath path;
TEST_AND_RETURN_FALSE(base::CreateTemporaryFile(&path));
@@ -306,7 +295,7 @@
}
}
- if (is_regular_file && extract_deflates) {
+ if (extract_deflates) {
// Search for deflates if the file is in zip or gzip format.
// .zvoice files may eventually move out of rootfs. If that happens,
// remove ".zvoice" (crbug.com/782918).
diff --git a/payload_generator/generate_delta_main.cc b/payload_generator/generate_delta_main.cc
index f035ff1..3cb891f 100644
--- a/payload_generator/generate_delta_main.cc
+++ b/payload_generator/generate_delta_main.cc
@@ -54,15 +54,18 @@
namespace {
void ParseSignatureSizes(const string& signature_sizes_flag,
- vector<size_t>* signature_sizes) {
+ vector<int>* signature_sizes) {
signature_sizes->clear();
vector<string> split_strings = base::SplitString(
signature_sizes_flag, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
for (const string& str : split_strings) {
- size_t size = 0;
- bool parsing_successful = base::StringToSizeT(str, &size);
+ int size = 0;
+ bool parsing_successful = base::StringToInt(str, &size);
LOG_IF(FATAL, !parsing_successful) << "Invalid signature size: " << str;
+ LOG_IF(FATAL, size != 256 && size != 512)
+ << "Only signature sizes of 256 or 512 bytes are supported.";
+
signature_sizes->push_back(size);
}
}
@@ -99,7 +102,7 @@
return true;
}
-void CalculateHashForSigning(const vector<size_t>& sizes,
+void CalculateHashForSigning(const vector<int>& sizes,
const string& out_hash_file,
const string& out_metadata_hash_file,
const string& in_file) {
@@ -135,7 +138,6 @@
void SignPayload(const string& in_file,
const string& out_file,
- const vector<size_t>& signature_sizes,
const string& payload_signature_file,
const string& metadata_signature_file,
const string& out_metadata_size_file) {
@@ -149,7 +151,6 @@
SignatureFileFlagToBlobs(metadata_signature_file, &metadata_signatures);
uint64_t final_metadata_size;
CHECK(PayloadSigner::AddSignatureToPayload(in_file,
- signature_sizes,
payload_signatures,
metadata_signatures,
out_file,
@@ -420,13 +421,6 @@
"",
"An info file specifying dynamic partition metadata. "
"Only allowed in major version 2 or newer.");
- DEFINE_bool(disable_fec_computation,
- false,
- "Disables the fec data computation on device.");
- DEFINE_string(
- out_maximum_signature_size_file,
- "",
- "Path to the output maximum signature size given a private key.");
brillo::FlagHelper::Init(
argc,
@@ -448,34 +442,8 @@
// Initialize the Xz compressor.
XzCompressInit();
- if (!FLAGS_out_maximum_signature_size_file.empty()) {
- LOG_IF(FATAL, FLAGS_private_key.empty())
- << "Private key is not provided when calculating the maximum signature "
- "size.";
-
- size_t maximum_signature_size;
- if (!PayloadSigner::GetMaximumSignatureSize(FLAGS_private_key,
- &maximum_signature_size)) {
- LOG(ERROR) << "Failed to get the maximum signature size of private key: "
- << FLAGS_private_key;
- return 1;
- }
- // Write the size string to output file.
- string signature_size_string = std::to_string(maximum_signature_size);
- if (!utils::WriteFile(FLAGS_out_maximum_signature_size_file.c_str(),
- signature_size_string.c_str(),
- signature_size_string.size())) {
- PLOG(ERROR) << "Failed to write the maximum signature size to "
- << FLAGS_out_maximum_signature_size_file << ".";
- return 1;
- }
- return 0;
- }
-
- vector<size_t> signature_sizes;
- if (!FLAGS_signature_size.empty()) {
- ParseSignatureSizes(FLAGS_signature_size, &signature_sizes);
- }
+ vector<int> signature_sizes;
+ ParseSignatureSizes(FLAGS_signature_size, &signature_sizes);
if (!FLAGS_out_hash_file.empty() || !FLAGS_out_metadata_hash_file.empty()) {
CHECK(FLAGS_out_metadata_size_file.empty());
@@ -488,7 +456,6 @@
if (!FLAGS_payload_signature_file.empty()) {
SignPayload(FLAGS_in_file,
FLAGS_out_file,
- signature_sizes,
FLAGS_payload_signature_file,
FLAGS_metadata_signature_file,
FLAGS_out_metadata_size_file);
@@ -560,8 +527,6 @@
<< "Partition name can't be empty, see --partition_names.";
payload_config.target.partitions.emplace_back(partition_names[i]);
payload_config.target.partitions.back().path = new_partitions[i];
- payload_config.target.partitions.back().disable_fec_computation =
- FLAGS_disable_fec_computation;
if (i < new_mapfiles.size())
payload_config.target.partitions.back().mapfile_path = new_mapfiles[i];
}
diff --git a/payload_generator/payload_generation_config.cc b/payload_generator/payload_generation_config.cc
index 88cca30..648fe8b 100644
--- a/payload_generator/payload_generation_config.cc
+++ b/payload_generator/payload_generation_config.cc
@@ -141,34 +141,25 @@
for (const auto& group_name : group_names) {
DynamicPartitionGroup* group = metadata->add_groups();
group->set_name(group_name);
- if (!store.GetString("super_" + group_name + "_group_size", &buf) &&
- !store.GetString(group_name + "_size", &buf)) {
- LOG(ERROR) << "Missing super_" << group_name + "_group_size or "
- << group_name << "_size.";
+ if (!store.GetString(group_name + "_size", &buf)) {
+ LOG(ERROR) << "Missing " << group_name + "_size.";
return false;
}
uint64_t max_size;
if (!base::StringToUint64(buf, &max_size)) {
- LOG(ERROR) << "Group size for " << group_name << " = " << buf
- << " is not an integer.";
+ LOG(ERROR) << group_name << "_size=" << buf << " is not an integer.";
return false;
}
group->set_size(max_size);
- if (store.GetString("super_" + group_name + "_partition_list", &buf) ||
- store.GetString(group_name + "_partition_list", &buf)) {
+ if (store.GetString(group_name + "_partition_list", &buf)) {
auto partition_names = brillo::string_utils::Split(buf, " ");
for (const auto& partition_name : partition_names) {
group->add_partition_names()->assign(partition_name);
}
}
}
-
- bool snapshot_enabled = false;
- store.GetBoolean("virtual_ab", &snapshot_enabled);
- metadata->set_snapshot_enabled(snapshot_enabled);
-
dynamic_partition_metadata = std::move(metadata);
return true;
}
diff --git a/payload_generator/payload_generation_config.h b/payload_generator/payload_generation_config.h
index e90edde..584ac7b 100644
--- a/payload_generator/payload_generation_config.h
+++ b/payload_generator/payload_generation_config.h
@@ -116,9 +116,6 @@
PostInstallConfig postinstall;
VerityConfig verity;
-
- // Enables the on device fec data computation by default.
- bool disable_fec_computation = false;
};
// The ImageConfig struct describes a pair of binaries kernel and rootfs and the
diff --git a/payload_generator/payload_generation_config_android.cc b/payload_generator/payload_generation_config_android.cc
index d950092..90c053f 100644
--- a/payload_generator/payload_generation_config_android.cc
+++ b/payload_generator/payload_generation_config_android.cc
@@ -63,13 +63,11 @@
part->verity.hash_tree_extent = ExtentForBytes(
hashtree.hash_block_size, hashtree.tree_offset, hashtree.tree_size);
- if (!part->disable_fec_computation) {
- part->verity.fec_data_extent =
- ExtentForBytes(hashtree.data_block_size, 0, hashtree.fec_offset);
- part->verity.fec_extent = ExtentForBytes(
- hashtree.data_block_size, hashtree.fec_offset, hashtree.fec_size);
- part->verity.fec_roots = hashtree.fec_num_roots;
- }
+ part->verity.fec_data_extent =
+ ExtentForBytes(hashtree.data_block_size, 0, hashtree.fec_offset);
+ part->verity.fec_extent = ExtentForBytes(
+ hashtree.data_block_size, hashtree.fec_offset, hashtree.fec_size);
+ part->verity.fec_roots = hashtree.fec_num_roots;
return true;
}
@@ -207,8 +205,7 @@
ExtentForRange(hash_start_block, tree_size / block_size);
}
fec_ecc_metadata ecc_data;
- if (!part.disable_fec_computation && fh.get_ecc_metadata(ecc_data) &&
- ecc_data.valid) {
+ if (fh.get_ecc_metadata(ecc_data) && ecc_data.valid) {
TEST_AND_RETURN_FALSE(block_size == FEC_BLOCKSIZE);
part.verity.fec_data_extent = ExtentForRange(0, ecc_data.blocks);
part.verity.fec_extent =
diff --git a/payload_generator/payload_generation_config_android_unittest.cc b/payload_generator/payload_generation_config_android_unittest.cc
index 44eaf55..53378c2 100644
--- a/payload_generator/payload_generation_config_android_unittest.cc
+++ b/payload_generator/payload_generation_config_android_unittest.cc
@@ -160,24 +160,6 @@
EXPECT_EQ(2u, verity.fec_roots);
}
-TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigDisableFecTest) {
- brillo::Blob part = GetAVBPartition();
- test_utils::WriteFileVector(temp_file_.path(), part);
- image_config_.partitions[0].disable_fec_computation = true;
- EXPECT_TRUE(image_config_.LoadImageSize());
- EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem());
- EXPECT_TRUE(image_config_.LoadVerityConfig());
- const VerityConfig& verity = image_config_.partitions[0].verity;
- EXPECT_FALSE(verity.IsEmpty());
- EXPECT_EQ(ExtentForRange(0, 2), verity.hash_tree_data_extent);
- EXPECT_EQ(ExtentForRange(2, 1), verity.hash_tree_extent);
- EXPECT_EQ("sha1", verity.hash_tree_algorithm);
- brillo::Blob salt(kHashTreeSalt, std::end(kHashTreeSalt));
- EXPECT_EQ(salt, verity.hash_tree_salt);
- EXPECT_EQ(0u, verity.fec_data_extent.num_blocks());
- EXPECT_EQ(0u, verity.fec_extent.num_blocks());
-}
-
TEST_F(PayloadGenerationConfigAndroidTest,
LoadVerityConfigInvalidHashTreeTest) {
brillo::Blob part = GetAVBPartition();
diff --git a/payload_generator/payload_generation_config_unittest.cc b/payload_generator/payload_generation_config_unittest.cc
index aca9655..70a3df3 100644
--- a/payload_generator/payload_generation_config_unittest.cc
+++ b/payload_generator/payload_generation_config_unittest.cc
@@ -59,7 +59,7 @@
ASSERT_TRUE(
store.LoadFromString("super_partition_groups=group_a group_b\n"
"group_a_size=3221225472\n"
- "group_a_partition_list=system system_ext\n"
+ "group_a_partition_list=system product_services\n"
"group_b_size=2147483648\n"
"group_b_partition_list=vendor\n"));
EXPECT_TRUE(image_config.LoadDynamicPartitionMetadata(store));
@@ -72,7 +72,7 @@
EXPECT_EQ(3221225472u, group_a.size());
ASSERT_EQ(2, group_a.partition_names_size());
EXPECT_EQ("system", group_a.partition_names(0));
- EXPECT_EQ("system_ext", group_a.partition_names(1));
+ EXPECT_EQ("product_services", group_a.partition_names(1));
const auto& group_b = image_config.dynamic_partition_metadata->groups(1);
EXPECT_EQ("group_b", group_b.name());
@@ -108,17 +108,17 @@
PartitionConfig system("system");
system.size = 2147483648u;
- PartitionConfig system_ext("system_ext");
- system_ext.size = 1073741824u;
+ PartitionConfig product_services("product_services");
+ product_services.size = 1073741824u;
image_config.partitions.push_back(std::move(system));
- image_config.partitions.push_back(std::move(system_ext));
+ image_config.partitions.push_back(std::move(product_services));
brillo::KeyValueStore store;
ASSERT_TRUE(
store.LoadFromString("super_partition_groups=foo\n"
"foo_size=3221225472\n"
- "foo_partition_list=system system_ext\n"));
+ "foo_partition_list=system product_services\n"));
EXPECT_TRUE(image_config.LoadDynamicPartitionMetadata(store));
EXPECT_NE(nullptr, image_config.dynamic_partition_metadata);
diff --git a/payload_generator/payload_signer.cc b/payload_generator/payload_signer.cc
index 72780b1..92313dc 100644
--- a/payload_generator/payload_signer.cc
+++ b/payload_generator/payload_signer.cc
@@ -18,7 +18,6 @@
#include <endian.h>
-#include <memory>
#include <utility>
#include <base/logging.h>
@@ -47,29 +46,23 @@
namespace chromeos_update_engine {
namespace {
+
+// The payload verifier will check all the signatures included in the payload
+// regardless of the version field. Old version of the verifier require the
+// version field to be included and be 1.
+const uint32_t kSignatureMessageLegacyVersion = 1;
+
// Given raw |signatures|, packs them into a protobuf and serializes it into a
// string. Returns true on success, false otherwise.
bool ConvertSignaturesToProtobuf(const vector<brillo::Blob>& signatures,
- const vector<size_t>& padded_signature_sizes,
string* out_serialized_signature) {
- TEST_AND_RETURN_FALSE(signatures.size() == padded_signature_sizes.size());
// Pack it into a protobuf
Signatures out_message;
- for (size_t i = 0; i < signatures.size(); i++) {
- const auto& signature = signatures[i];
- const auto& padded_signature_size = padded_signature_sizes[i];
- TEST_AND_RETURN_FALSE(padded_signature_size >= signature.size());
+ for (const brillo::Blob& signature : signatures) {
Signatures::Signature* sig_message = out_message.add_signatures();
- // Skip assigning the same version number because we don't need to be
- // compatible with old major version 1 client anymore.
-
- // TODO(Xunchang) don't need to set the unpadded_signature_size field for
- // RSA key signed signatures.
- sig_message->set_unpadded_signature_size(signature.size());
- brillo::Blob padded_signature = signature;
- padded_signature.insert(
- padded_signature.end(), padded_signature_size - signature.size(), 0);
- sig_message->set_data(padded_signature.data(), padded_signature.size());
+ // Set all the signatures with the same version number.
+ sig_message->set_version(kSignatureMessageLegacyVersion);
+ sig_message->set_data(signature.data(), signature.size());
}
// Serialize protobuf
@@ -210,35 +203,8 @@
return true;
}
-std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> CreatePrivateKeyFromPath(
- const string& private_key_path) {
- FILE* fprikey = fopen(private_key_path.c_str(), "rb");
- if (!fprikey) {
- PLOG(ERROR) << "Failed to read " << private_key_path;
- return {nullptr, nullptr};
- }
-
- auto private_key = std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)>(
- PEM_read_PrivateKey(fprikey, nullptr, nullptr, nullptr), EVP_PKEY_free);
- fclose(fprikey);
- return private_key;
-}
-
} // namespace
-bool PayloadSigner::GetMaximumSignatureSize(const string& private_key_path,
- size_t* signature_size) {
- *signature_size = 0;
- auto private_key = CreatePrivateKeyFromPath(private_key_path);
- if (!private_key) {
- LOG(ERROR) << "Failed to create private key from " << private_key_path;
- return false;
- }
-
- *signature_size = EVP_PKEY_size(private_key.get());
- return true;
-}
-
void PayloadSigner::AddSignatureToManifest(uint64_t signature_blob_offset,
uint64_t signature_blob_length,
bool add_dummy_op,
@@ -289,18 +255,14 @@
string public_key;
TEST_AND_RETURN_FALSE(utils::ReadFile(public_key_path, &public_key));
TEST_AND_RETURN_FALSE(payload_hash.size() == kSHA256Size);
-
- auto payload_verifier = PayloadVerifier::CreateInstance(public_key);
- TEST_AND_RETURN_FALSE(payload_verifier != nullptr);
-
TEST_AND_RETURN_FALSE(
- payload_verifier->VerifySignature(signature, payload_hash));
+ PayloadVerifier::VerifySignature(signature, public_key, payload_hash));
if (metadata_signature_size) {
signature.assign(payload.begin() + metadata_size,
payload.begin() + metadata_size + metadata_signature_size);
TEST_AND_RETURN_FALSE(metadata_hash.size() == kSHA256Size);
TEST_AND_RETURN_FALSE(
- payload_verifier->VerifySignature(signature, metadata_hash));
+ PayloadVerifier::VerifySignature(signature, public_key, metadata_hash));
}
return true;
}
@@ -316,61 +278,29 @@
// openssl rsautl -raw -sign -inkey |private_key_path|
// -in |padded_hash| -out |out_signature|
- auto private_key = CreatePrivateKeyFromPath(private_key_path);
- if (!private_key) {
- LOG(ERROR) << "Failed to create private key from " << private_key_path;
+ FILE* fprikey = fopen(private_key_path.c_str(), "rb");
+ TEST_AND_RETURN_FALSE(fprikey != nullptr);
+ RSA* rsa = PEM_read_RSAPrivateKey(fprikey, nullptr, nullptr, nullptr);
+ fclose(fprikey);
+ TEST_AND_RETURN_FALSE(rsa != nullptr);
+
+ brillo::Blob padded_hash = hash;
+ PayloadVerifier::PadRSASHA256Hash(&padded_hash, RSA_size(rsa));
+
+ brillo::Blob signature(RSA_size(rsa));
+ ssize_t signature_size = RSA_private_encrypt(padded_hash.size(),
+ padded_hash.data(),
+ signature.data(),
+ rsa,
+ RSA_NO_PADDING);
+ RSA_free(rsa);
+ if (signature_size < 0) {
+ LOG(ERROR) << "Signing hash failed: "
+ << ERR_error_string(ERR_get_error(), nullptr);
return false;
}
-
- int key_type = EVP_PKEY_id(private_key.get());
- brillo::Blob signature;
- if (key_type == EVP_PKEY_RSA) {
- RSA* rsa = EVP_PKEY_get0_RSA(private_key.get());
- TEST_AND_RETURN_FALSE(rsa != nullptr);
-
- brillo::Blob padded_hash = hash;
- PayloadVerifier::PadRSASHA256Hash(&padded_hash, RSA_size(rsa));
-
- signature.resize(RSA_size(rsa));
- ssize_t signature_size = RSA_private_encrypt(padded_hash.size(),
- padded_hash.data(),
- signature.data(),
- rsa,
- RSA_NO_PADDING);
-
- if (signature_size < 0) {
- LOG(ERROR) << "Signing hash failed: "
- << ERR_error_string(ERR_get_error(), nullptr);
- return false;
- }
- TEST_AND_RETURN_FALSE(static_cast<size_t>(signature_size) ==
- signature.size());
- } else if (key_type == EVP_PKEY_EC) {
- EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(private_key.get());
- TEST_AND_RETURN_FALSE(ec_key != nullptr);
-
- signature.resize(ECDSA_size(ec_key));
- unsigned int signature_size;
- if (ECDSA_sign(0,
- hash.data(),
- hash.size(),
- signature.data(),
- &signature_size,
- ec_key) != 1) {
- LOG(ERROR) << "Signing hash failed: "
- << ERR_error_string(ERR_get_error(), nullptr);
- return false;
- }
-
- // NIST P-256
- LOG(ERROR) << "signature max size " << signature.size() << " size "
- << signature_size;
- TEST_AND_RETURN_FALSE(signature.size() >= signature_size);
- signature.resize(signature_size);
- } else {
- LOG(ERROR) << "key_type " << key_type << " isn't supported for signing";
- return false;
- }
+ TEST_AND_RETURN_FALSE(static_cast<size_t>(signature_size) ==
+ signature.size());
out_signature->swap(signature);
return true;
}
@@ -379,19 +309,13 @@
const vector<string>& private_key_paths,
string* out_serialized_signature) {
vector<brillo::Blob> signatures;
- vector<size_t> padded_signature_sizes;
for (const string& path : private_key_paths) {
brillo::Blob signature;
TEST_AND_RETURN_FALSE(SignHash(hash_data, path, &signature));
signatures.push_back(signature);
-
- size_t padded_signature_size;
- TEST_AND_RETURN_FALSE(
- GetMaximumSignatureSize(path, &padded_signature_size));
- padded_signature_sizes.push_back(padded_signature_size);
}
- TEST_AND_RETURN_FALSE(ConvertSignaturesToProtobuf(
- signatures, padded_signature_sizes, out_serialized_signature));
+ TEST_AND_RETURN_FALSE(
+ ConvertSignaturesToProtobuf(signatures, out_serialized_signature));
return true;
}
@@ -428,7 +352,7 @@
}
bool PayloadSigner::HashPayloadForSigning(const string& payload_path,
- const vector<size_t>& signature_sizes,
+ const vector<int>& signature_sizes,
brillo::Blob* out_payload_hash_data,
brillo::Blob* out_metadata_hash) {
// Create a signature blob with signatures filled with 0.
@@ -438,8 +362,7 @@
signatures.emplace_back(signature_size, 0);
}
string signature;
- TEST_AND_RETURN_FALSE(
- ConvertSignaturesToProtobuf(signatures, signature_sizes, &signature));
+ TEST_AND_RETURN_FALSE(ConvertSignaturesToProtobuf(signatures, &signature));
brillo::Blob payload;
uint64_t metadata_size, signatures_offset;
@@ -463,7 +386,6 @@
bool PayloadSigner::AddSignatureToPayload(
const string& payload_path,
- const vector<size_t>& padded_signature_sizes,
const vector<brillo::Blob>& payload_signatures,
const vector<brillo::Blob>& metadata_signatures,
const string& signed_payload_path,
@@ -472,11 +394,11 @@
// Loads the payload and adds the signature op to it.
string payload_signature, metadata_signature;
- TEST_AND_RETURN_FALSE(ConvertSignaturesToProtobuf(
- payload_signatures, padded_signature_sizes, &payload_signature));
+ TEST_AND_RETURN_FALSE(
+ ConvertSignaturesToProtobuf(payload_signatures, &payload_signature));
if (!metadata_signatures.empty()) {
- TEST_AND_RETURN_FALSE(ConvertSignaturesToProtobuf(
- metadata_signatures, padded_signature_sizes, &metadata_signature));
+ TEST_AND_RETURN_FALSE(
+ ConvertSignaturesToProtobuf(metadata_signatures, &metadata_signature));
}
brillo::Blob payload;
uint64_t signatures_offset;
diff --git a/payload_generator/payload_signer.h b/payload_generator/payload_signer.h
index bd1e32f..7854e12 100644
--- a/payload_generator/payload_signer.h
+++ b/payload_generator/payload_signer.h
@@ -91,7 +91,7 @@
//
// The changes to payload are not preserved or written to disk.
static bool HashPayloadForSigning(const std::string& payload_path,
- const std::vector<size_t>& signature_sizes,
+ const std::vector<int>& signature_sizes,
brillo::Blob* out_payload_hash_data,
brillo::Blob* out_metadata_hash);
@@ -105,7 +105,6 @@
// otherwise.
static bool AddSignatureToPayload(
const std::string& payload_path,
- const std::vector<size_t>& padded_signature_sizes,
const std::vector<brillo::Blob>& payload_signatures,
const std::vector<brillo::Blob>& metadata_signatures,
const std::string& signed_payload_path,
@@ -123,13 +122,6 @@
static bool ExtractPayloadProperties(const std::string& payload_path,
brillo::KeyValueStore* properties);
- // This function calculates the maximum size, in bytes, of a signature signed
- // by private_key_path. For an RSA key, this returns the number of bytes
- // needed to represent the modulus. For an EC key, this returns the maximum
- // size of a DER-encoded ECDSA signature.
- static bool GetMaximumSignatureSize(const std::string& private_key_path,
- size_t* signature_size);
-
private:
// This should never be constructed
DISALLOW_IMPLICIT_CONSTRUCTORS(PayloadSigner);
diff --git a/payload_generator/payload_signer_unittest.cc b/payload_generator/payload_signer_unittest.cc
index bf7100b..75fc694 100644
--- a/payload_generator/payload_signer_unittest.cc
+++ b/payload_generator/payload_signer_unittest.cc
@@ -46,8 +46,6 @@
const char* kUnittestPublicKey2Path = "unittest_key2.pub.pem";
const char* kUnittestPrivateKeyRSA4096Path = "unittest_key_RSA4096.pem";
const char* kUnittestPublicKeyRSA4096Path = "unittest_key_RSA4096.pub.pem";
-const char* kUnittestPrivateKeyECPath = "unittest_key_EC.pem";
-const char* kUnittestPublicKeyECPath = "unittest_key_EC.pub.pem";
// Some data and its corresponding hash and signature:
const char kDataToSign[] = "This is some data to sign.";
@@ -117,6 +115,7 @@
EXPECT_TRUE(signatures.ParseFromString(signature));
EXPECT_EQ(1, signatures.signatures_size());
const Signatures::Signature& sig = signatures.signatures(0);
+ EXPECT_EQ(1U, sig.version());
const string& sig_data = sig.data();
ASSERT_EQ(arraysize(kDataSignature), sig_data.size());
for (size_t i = 0; i < arraysize(kDataSignature); i++) {
@@ -129,20 +128,22 @@
SignSampleData(&signature,
{GetBuildArtifactsPath(kUnittestPrivateKeyPath),
GetBuildArtifactsPath(kUnittestPrivateKey2Path),
- GetBuildArtifactsPath(kUnittestPrivateKeyRSA4096Path),
- GetBuildArtifactsPath(kUnittestPrivateKeyECPath)});
+ GetBuildArtifactsPath(kUnittestPrivateKeyRSA4096Path)});
// Either public key should pass the verification.
- for (const auto& path : {kUnittestPublicKeyPath,
- kUnittestPublicKey2Path,
- kUnittestPublicKeyRSA4096Path,
- kUnittestPublicKeyECPath}) {
- string public_key;
- EXPECT_TRUE(utils::ReadFile(GetBuildArtifactsPath(path), &public_key));
- auto payload_verifier = PayloadVerifier::CreateInstance(public_key);
- EXPECT_TRUE(payload_verifier != nullptr);
- EXPECT_TRUE(payload_verifier->VerifySignature(signature, hash_data_));
- }
+ string public_key;
+ EXPECT_TRUE(utils::ReadFile(GetBuildArtifactsPath(kUnittestPublicKeyPath),
+ &public_key));
+ EXPECT_TRUE(
+ PayloadVerifier::VerifySignature(signature, public_key, hash_data_));
+ EXPECT_TRUE(utils::ReadFile(GetBuildArtifactsPath(kUnittestPublicKey2Path),
+ &public_key));
+ EXPECT_TRUE(
+ PayloadVerifier::VerifySignature(signature, public_key, hash_data_));
+ EXPECT_TRUE(utils::ReadFile(
+ GetBuildArtifactsPath(kUnittestPublicKeyRSA4096Path), &public_key));
+ EXPECT_TRUE(
+ PayloadVerifier::VerifySignature(signature, public_key, hash_data_));
}
TEST_F(PayloadSignerTest, VerifySignatureTest) {
@@ -152,17 +153,13 @@
string public_key;
EXPECT_TRUE(utils::ReadFile(GetBuildArtifactsPath(kUnittestPublicKeyPath),
&public_key));
- auto payload_verifier = PayloadVerifier::CreateInstance(public_key);
- EXPECT_TRUE(payload_verifier != nullptr);
- EXPECT_TRUE(payload_verifier->VerifySignature(signature, hash_data_));
-
+ EXPECT_TRUE(
+ PayloadVerifier::VerifySignature(signature, public_key, hash_data_));
// Passing the invalid key should fail the verification.
- public_key.clear();
EXPECT_TRUE(utils::ReadFile(GetBuildArtifactsPath(kUnittestPublicKey2Path),
&public_key));
- payload_verifier = PayloadVerifier::CreateInstance(public_key);
- EXPECT_TRUE(payload_verifier != nullptr);
- EXPECT_FALSE(payload_verifier->VerifySignature(signature, hash_data_));
+ EXPECT_TRUE(
+ PayloadVerifier::VerifySignature(signature, public_key, hash_data_));
}
TEST_F(PayloadSignerTest, SkipMetadataSignatureTest) {
@@ -174,7 +171,7 @@
uint64_t metadata_size;
EXPECT_TRUE(payload.WritePayload(
payload_file.path(), "/dev/null", "", &metadata_size));
- const vector<size_t> sizes = {256};
+ const vector<int> sizes = {256};
brillo::Blob unsigned_payload_hash, unsigned_metadata_hash;
EXPECT_TRUE(PayloadSigner::HashPayloadForSigning(payload_file.path(),
sizes,
diff --git a/scripts/brillo_update_payload b/scripts/brillo_update_payload
index d9c18ff..f535185 100755
--- a/scripts/brillo_update_payload
+++ b/scripts/brillo_update_payload
@@ -28,16 +28,12 @@
# check verify a payload using paycheck (static testing)
#
# Generate command arguments:
-# --payload generated unsigned payload output file
-# --source_image if defined, generate a delta payload from the
-# specified image to the target_image
-# --target_image the target image that should be sent to clients
-# --metadata_size_file if defined, generate a file containing the size
-# of the ayload metadata in bytes to the specified
-# file
-# --disable_fec_computation Disable the on device fec data computation for
-# incremental update. This feature is enabled by
-# default
+# --payload generated unsigned payload output file
+# --source_image if defined, generate a delta payload from the specified
+# image to the target_image
+# --target_image the target image that should be sent to clients
+# --metadata_size_file if defined, generate a file containing the size of the
+# payload metadata in bytes to the specified file
#
# Hash command arguments:
# --unsigned_payload the input unsigned payload to generate the hash from
@@ -186,9 +182,6 @@
"Optional: The maximum unix timestamp of the OS allowed to apply this \
payload, should be set to a number higher than the build timestamp of the \
system running on the device, 0 if not specified."
- DEFINE_string disable_fec_computation "" \
- "Optional: Disables the on device fec data computation for incremental \
-update. This feature is enabled by default."
fi
if [[ "${COMMAND}" == "hash" || "${COMMAND}" == "sign" ]]; then
DEFINE_string unsigned_payload "" "Path to the input unsigned payload."
@@ -281,7 +274,7 @@
local option_key="$2"
local default_value="${3:-}"
local value
- if value=$(grep "^${option_key}=" "${file_txt}" | tail -n 1); then
+ if value=$(look "${option_key}=" "${file_txt}" | tail -n 1); then
if value=$(echo "${value}" | cut -f 2- -d "=" | grep -E "^[0-9]+$"); then
echo "${value}"
return
@@ -334,25 +327,6 @@
trap cleanup_on_error INT TERM ERR
trap cleanup_on_exit EXIT
-# extract_file <zip_file> <entry_name> <destination>
-#
-# Extracts |entry_name| from |zip_file| to |destination|.
-extract_file() {
- local zip_file="$1"
- local entry_name="$2"
- local destination="$3"
-
- # unzip -p won't report error upon ENOSPC. Therefore, create a temp directory
- # as the destination of the unzip, and move the file to the intended
- # destination.
- local output_directory=$(
- mktemp --directory --tmpdir="${FLAGS_work_dir}" "TEMP.XXXXXX")
- unzip "${zip_file}" "${entry_name}" -d "${output_directory}" ||
- { rm -rf "${output_directory}"; die "Failed to extract ${entry_name}"; }
-
- mv "${output_directory}/${entry_name}" "${destination}"
- rm -rf "${output_directory}"
-}
# extract_image <image> <partitions_array> [partitions_order]
#
@@ -443,7 +417,7 @@
fi
done
[[ -n "${path_in_zip}" ]] || die "Failed to find ${part}.img"
- extract_file "${image}" "${path_in_zip}/${part}.img" "${part_file}"
+ unzip -p "${image}" "${path_in_zip}/${part}.img" >"${part_file}"
# If the partition is stored as an Android sparse image file, we need to
# convert them to a raw image for the update.
@@ -457,9 +431,8 @@
fi
# Extract the .map file (if one is available).
- if unzip -l "${image}" "${path_in_zip}/${part}.map" > /dev/null; then
- extract_file "${image}" "${path_in_zip}/${part}.map" "${part_map_file}"
- fi
+ unzip -p "${image}" "${path_in_zip}/${part}.map" >"${part_map_file}" \
+ 2>/dev/null || true
# delta_generator only supports images multiple of 4 KiB. For target images
# we pad the data with zeros if needed, but for source images we truncate
@@ -493,8 +466,7 @@
local ab_partitions_list
ab_partitions_list=$(create_tempfile "ab_partitions_list.XXXXXX")
CLEANUP_FILES+=("${ab_partitions_list}")
- if unzip -l "${image}" "META/ab_partitions.txt" > /dev/null; then
- extract_file "${image}" "META/ab_partitions.txt" "${ab_partitions_list}"
+ if unzip -p "${image}" "META/ab_partitions.txt" >"${ab_partitions_list}"; then
if grep -v -E '^[a-zA-Z0-9_-]*$' "${ab_partitions_list}" >&2; then
die "Invalid partition names found in the partition list."
fi
@@ -519,9 +491,8 @@
# Source image
local ue_config=$(create_tempfile "ue_config.XXXXXX")
CLEANUP_FILES+=("${ue_config}")
- if unzip -l "${image}" "META/update_engine_config.txt" > /dev/null; then
- extract_file "${image}" "META/update_engine_config.txt" "${ue_config}"
- else
+ if ! unzip -p "${image}" "META/update_engine_config.txt" \
+ >"${ue_config}"; then
warn "No update_engine_config.txt found. Assuming pre-release image, \
using payload minor version 2"
fi
@@ -542,16 +513,14 @@
# Target image
local postinstall_config=$(create_tempfile "postinstall_config.XXXXXX")
CLEANUP_FILES+=("${postinstall_config}")
- if unzip -l "${image}" "META/postinstall_config.txt" > /dev/null; then
- extract_file "${image}" "META/postinstall_config.txt" \
- "${postinstall_config}"
+ if unzip -p "${image}" "META/postinstall_config.txt" \
+ >"${postinstall_config}"; then
POSTINSTALL_CONFIG_FILE="${postinstall_config}"
fi
local dynamic_partitions_info=$(create_tempfile "dynamic_partitions_info.XXXXXX")
CLEANUP_FILES+=("${dynamic_partitions_info}")
- if unzip -l "${image}" "META/dynamic_partitions_info.txt" > /dev/null; then
- extract_file "${image}" "META/dynamic_partitions_info.txt" \
- "${dynamic_partitions_info}"
+ if unzip -p "${image}" "META/dynamic_partitions_info.txt" \
+ >"${dynamic_partitions_info}"; then
DYNAMIC_PARTITION_INFO_FILE="${dynamic_partitions_info}"
fi
fi
@@ -663,10 +632,6 @@
if [[ -n "${FORCE_MINOR_VERSION}" ]]; then
GENERATOR_ARGS+=( --minor_version="${FORCE_MINOR_VERSION}" )
fi
- if [[ -n "${FLAGS_disable_fec_computation}" ]]; then
- GENERATOR_ARGS+=(
- --disable_fec_computation="${FLAGS_disable_fec_computation}" )
- fi
fi
if [[ -n "${FORCE_MAJOR_VERSION}" ]]; then
diff --git a/scripts/update_device.py b/scripts/update_device.py
index 49f766d..5c19b89 100755
--- a/scripts/update_device.py
+++ b/scripts/update_device.py
@@ -83,24 +83,17 @@
# Android OTA package file paths.
OTA_PAYLOAD_BIN = 'payload.bin'
OTA_PAYLOAD_PROPERTIES_TXT = 'payload_properties.txt'
- SECONDARY_OTA_PAYLOAD_BIN = 'secondary/payload.bin'
- SECONDARY_OTA_PAYLOAD_PROPERTIES_TXT = 'secondary/payload_properties.txt'
- def __init__(self, otafilename, secondary_payload=False):
+ def __init__(self, otafilename):
self.otafilename = otafilename
otazip = zipfile.ZipFile(otafilename, 'r')
- payload_entry = (self.SECONDARY_OTA_PAYLOAD_BIN if secondary_payload else
- self.OTA_PAYLOAD_BIN)
- payload_info = otazip.getinfo(payload_entry)
+ payload_info = otazip.getinfo(self.OTA_PAYLOAD_BIN)
self.offset = payload_info.header_offset
self.offset += zipfile.sizeFileHeader
self.offset += len(payload_info.extra) + len(payload_info.filename)
self.size = payload_info.file_size
-
- property_entry = (self.SECONDARY_OTA_PAYLOAD_PROPERTIES_TXT if
- secondary_payload else self.OTA_PAYLOAD_PROPERTIES_TXT)
- self.properties = otazip.read(property_entry)
+ self.properties = otazip.read(self.OTA_PAYLOAD_PROPERTIES_TXT)
class UpdateHandler(BaseHTTPServer.BaseHTTPRequestHandler):
@@ -285,9 +278,9 @@
return t
-def AndroidUpdateCommand(ota_filename, secondary, payload_url, extra_headers):
+def AndroidUpdateCommand(ota_filename, payload_url, extra_headers):
"""Return the command to run to start the update in the Android device."""
- ota = AndroidOTAPackage(ota_filename, secondary)
+ ota = AndroidOTAPackage(ota_filename)
headers = ota.properties
headers += 'USER_AGENT=Dalvik (something, something)\n'
headers += 'NETWORK_ID=0\n'
@@ -370,8 +363,6 @@
help='Override the public key used to verify payload.')
parser.add_argument('--extra-headers', type=str, default='',
help='Extra headers to pass to the device.')
- parser.add_argument('--secondary', action='store_true',
- help='Update with the secondary payload in the package.')
args = parser.parse_args()
logging.basicConfig(
level=logging.WARNING if args.no_verbose else logging.INFO)
@@ -407,7 +398,7 @@
# command.
payload_url = 'http://127.0.0.1:%d/payload' % DEVICE_PORT
if use_omaha and zipfile.is_zipfile(args.otafile):
- ota = AndroidOTAPackage(args.otafile, args.secondary)
+ ota = AndroidOTAPackage(args.otafile)
serving_range = (ota.offset, ota.size)
else:
serving_range = (0, os.stat(args.otafile).st_size)
@@ -435,8 +426,8 @@
update_cmd = \
OmahaUpdateCommand('http://127.0.0.1:%d/update' % DEVICE_PORT)
else:
- update_cmd = AndroidUpdateCommand(args.otafile, args.secondary,
- payload_url, args.extra_headers)
+ update_cmd = \
+ AndroidUpdateCommand(args.otafile, payload_url, args.extra_headers)
cmds.append(['shell', 'su', '0'] + update_cmd)
for cmd in cmds:
diff --git a/scripts/update_payload/update_metadata_pb2.py b/scripts/update_payload/update_metadata_pb2.py
index cb8f4c2..7f1648b 100644
--- a/scripts/update_payload/update_metadata_pb2.py
+++ b/scripts/update_payload/update_metadata_pb2.py
@@ -1,27 +1,19 @@
-# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: update_metadata.proto
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
+from google.protobuf import descriptor_pb2
# @@protoc_insertion_point(imports)
-_sym_db = _symbol_database.Default()
-
DESCRIPTOR = _descriptor.FileDescriptor(
name='update_metadata.proto',
package='chromeos_update_engine',
- syntax='proto2',
- serialized_options=_b('H\003'),
- serialized_pb=_b('\n\x15update_metadata.proto\x12\x16\x63hromeos_update_engine\"1\n\x06\x45xtent\x12\x13\n\x0bstart_block\x18\x01 \x01(\x04\x12\x12\n\nnum_blocks\x18\x02 \x01(\x04\"z\n\nSignatures\x12@\n\nsignatures\x18\x01 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x1a*\n\tSignature\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"+\n\rPartitionInfo\x12\x0c\n\x04size\x18\x01 \x01(\x04\x12\x0c\n\x04hash\x18\x02 \x01(\x0c\"w\n\tImageInfo\x12\r\n\x05\x62oard\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x03 \x01(\t\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x15\n\rbuild_channel\x18\x05 \x01(\t\x12\x15\n\rbuild_version\x18\x06 \x01(\t\"\xee\x03\n\x10InstallOperation\x12;\n\x04type\x18\x01 \x02(\x0e\x32-.chromeos_update_engine.InstallOperation.Type\x12\x13\n\x0b\x64\x61ta_offset\x18\x02 \x01(\x04\x12\x13\n\x0b\x64\x61ta_length\x18\x03 \x01(\x04\x12\x33\n\x0bsrc_extents\x18\x04 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\nsrc_length\x18\x05 \x01(\x04\x12\x33\n\x0b\x64st_extents\x18\x06 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\ndst_length\x18\x07 \x01(\x04\x12\x18\n\x10\x64\x61ta_sha256_hash\x18\x08 \x01(\x0c\x12\x17\n\x0fsrc_sha256_hash\x18\t \x01(\x0c\"\xad\x01\n\x04Type\x12\x0b\n\x07REPLACE\x10\x00\x12\x0e\n\nREPLACE_BZ\x10\x01\x12\x0c\n\x04MOVE\x10\x02\x1a\x02\x08\x01\x12\x0e\n\x06\x42SDIFF\x10\x03\x1a\x02\x08\x01\x12\x0f\n\x0bSOURCE_COPY\x10\x04\x12\x11\n\rSOURCE_BSDIFF\x10\x05\x12\x0e\n\nREPLACE_XZ\x10\x08\x12\x08\n\x04ZERO\x10\x06\x12\x0b\n\x07\x44ISCARD\x10\x07\x12\x11\n\rBROTLI_BSDIFF\x10\n\x12\x0c\n\x08PUFFDIFF\x10\t\"\xd7\x05\n\x0fPartitionUpdate\x12\x16\n\x0epartition_name\x18\x01 \x02(\t\x12\x17\n\x0frun_postinstall\x18\x02 \x01(\x08\x12\x18\n\x10postinstall_path\x18\x03 \x01(\t\x12\x17\n\x0f\x66ilesystem_type\x18\x04 \x01(\t\x12M\n\x17new_partition_signature\x18\x05 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x12\x41\n\x12old_partition_info\x18\x06 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12\x41\n\x12new_partition_info\x18\x07 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12<\n\noperations\x18\x08 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12\x1c\n\x14postinstall_optional\x18\t \x01(\x08\x12=\n\x15hash_tree_data_extent\x18\n \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x38\n\x10hash_tree_extent\x18\x0b \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x1b\n\x13hash_tree_algorithm\x18\x0c \x01(\t\x12\x16\n\x0ehash_tree_salt\x18\r \x01(\x0c\x12\x37\n\x0f\x66\x65\x63_data_extent\x18\x0e \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x32\n\nfec_extent\x18\x0f \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x14\n\tfec_roots\x18\x10 \x01(\r:\x01\x32\"L\n\x15\x44ynamicPartitionGroup\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x0c\n\x04size\x18\x02 \x01(\x04\x12\x17\n\x0fpartition_names\x18\x03 \x03(\t\"s\n\x18\x44ynamicPartitionMetadata\x12=\n\x06groups\x18\x01 \x03(\x0b\x32-.chromeos_update_engine.DynamicPartitionGroup\x12\x18\n\x10snapshot_enabled\x18\x02 \x01(\x08\"\xb1\x06\n\x14\x44\x65ltaArchiveManifest\x12\x44\n\x12install_operations\x18\x01 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12K\n\x19kernel_install_operations\x18\x02 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12\x18\n\nblock_size\x18\x03 \x01(\r:\x04\x34\x30\x39\x36\x12\x19\n\x11signatures_offset\x18\x04 \x01(\x04\x12\x17\n\x0fsignatures_size\x18\x05 \x01(\x04\x12>\n\x0fold_kernel_info\x18\x06 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12>\n\x0fnew_kernel_info\x18\x07 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12>\n\x0fold_rootfs_info\x18\x08 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12>\n\x0fnew_rootfs_info\x18\t \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12\x39\n\x0eold_image_info\x18\n \x01(\x0b\x32!.chromeos_update_engine.ImageInfo\x12\x39\n\x0enew_image_info\x18\x0b \x01(\x0b\x32!.chromeos_update_engine.ImageInfo\x12\x18\n\rminor_version\x18\x0c \x01(\r:\x01\x30\x12;\n\npartitions\x18\r \x03(\x0b\x32\'.chromeos_update_engine.PartitionUpdate\x12\x15\n\rmax_timestamp\x18\x0e \x01(\x03\x12T\n\x1a\x64ynamic_partition_metadata\x18\x0f \x01(\x0b\x32\x30.chromeos_update_engine.DynamicPartitionMetadataB\x02H\x03')
-)
+ serialized_pb='\n\x15update_metadata.proto\x12\x16\x63hromeos_update_engine\"1\n\x06\x45xtent\x12\x13\n\x0bstart_block\x18\x01 \x01(\x04\x12\x12\n\nnum_blocks\x18\x02 \x01(\x04\"z\n\nSignatures\x12@\n\nsignatures\x18\x01 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x1a*\n\tSignature\x12\x0f\n\x07version\x18\x01 \x01(\r\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c\"+\n\rPartitionInfo\x12\x0c\n\x04size\x18\x01 \x01(\x04\x12\x0c\n\x04hash\x18\x02 \x01(\x0c\"w\n\tImageInfo\x12\r\n\x05\x62oard\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\t\x12\x0f\n\x07\x63hannel\x18\x03 \x01(\t\x12\x0f\n\x07version\x18\x04 \x01(\t\x12\x15\n\rbuild_channel\x18\x05 \x01(\t\x12\x15\n\rbuild_version\x18\x06 \x01(\t\"\xe6\x03\n\x10InstallOperation\x12;\n\x04type\x18\x01 \x02(\x0e\x32-.chromeos_update_engine.InstallOperation.Type\x12\x13\n\x0b\x64\x61ta_offset\x18\x02 \x01(\x04\x12\x13\n\x0b\x64\x61ta_length\x18\x03 \x01(\x04\x12\x33\n\x0bsrc_extents\x18\x04 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\nsrc_length\x18\x05 \x01(\x04\x12\x33\n\x0b\x64st_extents\x18\x06 \x03(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x12\n\ndst_length\x18\x07 \x01(\x04\x12\x18\n\x10\x64\x61ta_sha256_hash\x18\x08 \x01(\x0c\x12\x17\n\x0fsrc_sha256_hash\x18\t \x01(\x0c\"\xa5\x01\n\x04Type\x12\x0b\n\x07REPLACE\x10\x00\x12\x0e\n\nREPLACE_BZ\x10\x01\x12\x08\n\x04MOVE\x10\x02\x12\n\n\x06\x42SDIFF\x10\x03\x12\x0f\n\x0bSOURCE_COPY\x10\x04\x12\x11\n\rSOURCE_BSDIFF\x10\x05\x12\x0e\n\nREPLACE_XZ\x10\x08\x12\x08\n\x04ZERO\x10\x06\x12\x0b\n\x07\x44ISCARD\x10\x07\x12\x11\n\rBROTLI_BSDIFF\x10\n\x12\x0c\n\x08PUFFDIFF\x10\t\"\xd7\x05\n\x0fPartitionUpdate\x12\x16\n\x0epartition_name\x18\x01 \x02(\t\x12\x17\n\x0frun_postinstall\x18\x02 \x01(\x08\x12\x18\n\x10postinstall_path\x18\x03 \x01(\t\x12\x17\n\x0f\x66ilesystem_type\x18\x04 \x01(\t\x12M\n\x17new_partition_signature\x18\x05 \x03(\x0b\x32,.chromeos_update_engine.Signatures.Signature\x12\x41\n\x12old_partition_info\x18\x06 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12\x41\n\x12new_partition_info\x18\x07 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12<\n\noperations\x18\x08 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12\x1c\n\x14postinstall_optional\x18\t \x01(\x08\x12=\n\x15hash_tree_data_extent\x18\n \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x38\n\x10hash_tree_extent\x18\x0b \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x1b\n\x13hash_tree_algorithm\x18\x0c \x01(\t\x12\x16\n\x0ehash_tree_salt\x18\r \x01(\x0c\x12\x37\n\x0f\x66\x65\x63_data_extent\x18\x0e \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x32\n\nfec_extent\x18\x0f \x01(\x0b\x32\x1e.chromeos_update_engine.Extent\x12\x14\n\tfec_roots\x18\x10 \x01(\r:\x01\x32\"L\n\x15\x44ynamicPartitionGroup\x12\x0c\n\x04name\x18\x01 \x02(\t\x12\x0c\n\x04size\x18\x02 \x01(\x04\x12\x17\n\x0fpartition_names\x18\x03 \x03(\t\"Y\n\x18\x44ynamicPartitionMetadata\x12=\n\x06groups\x18\x01 \x03(\x0b\x32-.chromeos_update_engine.DynamicPartitionGroup\"\xb1\x06\n\x14\x44\x65ltaArchiveManifest\x12\x44\n\x12install_operations\x18\x01 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12K\n\x19kernel_install_operations\x18\x02 \x03(\x0b\x32(.chromeos_update_engine.InstallOperation\x12\x18\n\nblock_size\x18\x03 \x01(\r:\x04\x34\x30\x39\x36\x12\x19\n\x11signatures_offset\x18\x04 \x01(\x04\x12\x17\n\x0fsignatures_size\x18\x05 \x01(\x04\x12>\n\x0fold_kernel_info\x18\x06 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12>\n\x0fnew_kernel_info\x18\x07 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12>\n\x0fold_rootfs_info\x18\x08 \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12>\n\x0fnew_rootfs_info\x18\t \x01(\x0b\x32%.chromeos_update_engine.PartitionInfo\x12\x39\n\x0eold_image_info\x18\n \x01(\x0b\x32!.chromeos_update_engine.ImageInfo\x12\x39\n\x0enew_image_info\x18\x0b \x01(\x0b\x32!.chromeos_update_engine.ImageInfo\x12\x18\n\rminor_version\x18\x0c \x01(\r:\x01\x30\x12;\n\npartitions\x18\r \x03(\x0b\x32\'.chromeos_update_engine.PartitionUpdate\x12\x15\n\rmax_timestamp\x18\x0e \x01(\x03\x12T\n\x1a\x64ynamic_partition_metadata\x18\x0f \x01(\x0b\x32\x30.chromeos_update_engine.DynamicPartitionMetadataB\x02H\x03')
@@ -33,55 +25,54 @@
values=[
_descriptor.EnumValueDescriptor(
name='REPLACE', index=0, number=0,
- serialized_options=None,
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='REPLACE_BZ', index=1, number=1,
- serialized_options=None,
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='MOVE', index=2, number=2,
- serialized_options=_b('\010\001'),
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='BSDIFF', index=3, number=3,
- serialized_options=_b('\010\001'),
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='SOURCE_COPY', index=4, number=4,
- serialized_options=None,
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='SOURCE_BSDIFF', index=5, number=5,
- serialized_options=None,
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='REPLACE_XZ', index=6, number=8,
- serialized_options=None,
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='ZERO', index=7, number=6,
- serialized_options=None,
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='DISCARD', index=8, number=7,
- serialized_options=None,
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='BROTLI_BSDIFF', index=9, number=10,
- serialized_options=None,
+ options=None,
type=None),
_descriptor.EnumValueDescriptor(
name='PUFFDIFF', index=10, number=9,
- serialized_options=None,
+ options=None,
type=None),
],
containing_type=None,
- serialized_options=None,
+ options=None,
serialized_start=712,
- serialized_end=885,
+ serialized_end=877,
)
-_sym_db.RegisterEnumDescriptor(_INSTALLOPERATION_TYPE)
_EXTENT = _descriptor.Descriptor(
@@ -97,26 +88,23 @@
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='num_blocks', full_name='chromeos_update_engine.Extent.num_blocks', index=1,
number=2, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
serialized_start=49,
serialized_end=98,
)
@@ -135,26 +123,23 @@
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='data', full_name='chromeos_update_engine.Signatures.Signature.data', index=1,
number=2, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
+ has_default_value=False, default_value="",
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
serialized_start=180,
serialized_end=222,
)
@@ -172,19 +157,16 @@
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
nested_types=[_SIGNATURES_SIGNATURE, ],
enum_types=[
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
serialized_start=100,
serialized_end=222,
)
@@ -203,26 +185,23 @@
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='hash', full_name='chromeos_update_engine.PartitionInfo.hash', index=1,
number=2, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
+ has_default_value=False, default_value="",
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
serialized_start=224,
serialized_end=267,
)
@@ -238,57 +217,54 @@
_descriptor.FieldDescriptor(
name='board', full_name='chromeos_update_engine.ImageInfo.board', index=0,
number=1, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='key', full_name='chromeos_update_engine.ImageInfo.key', index=1,
number=2, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='channel', full_name='chromeos_update_engine.ImageInfo.channel', index=2,
number=3, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='version', full_name='chromeos_update_engine.ImageInfo.version', index=3,
number=4, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='build_channel', full_name='chromeos_update_engine.ImageInfo.build_channel', index=4,
number=5, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='build_version', full_name='chromeos_update_engine.ImageInfo.build_version', index=5,
number=6, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
serialized_start=269,
serialized_end=388,
)
@@ -307,63 +283,63 @@
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='data_offset', full_name='chromeos_update_engine.InstallOperation.data_offset', index=1,
number=2, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='data_length', full_name='chromeos_update_engine.InstallOperation.data_length', index=2,
number=3, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='src_extents', full_name='chromeos_update_engine.InstallOperation.src_extents', index=3,
number=4, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='src_length', full_name='chromeos_update_engine.InstallOperation.src_length', index=4,
number=5, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='dst_extents', full_name='chromeos_update_engine.InstallOperation.dst_extents', index=5,
number=6, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='dst_length', full_name='chromeos_update_engine.InstallOperation.dst_length', index=6,
number=7, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='data_sha256_hash', full_name='chromeos_update_engine.InstallOperation.data_sha256_hash', index=7,
number=8, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
+ has_default_value=False, default_value="",
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='src_sha256_hash', full_name='chromeos_update_engine.InstallOperation.src_sha256_hash', index=8,
number=9, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
+ has_default_value=False, default_value="",
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
@@ -371,14 +347,11 @@
enum_types=[
_INSTALLOPERATION_TYPE,
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
serialized_start=391,
- serialized_end=885,
+ serialized_end=877,
)
@@ -392,129 +365,126 @@
_descriptor.FieldDescriptor(
name='partition_name', full_name='chromeos_update_engine.PartitionUpdate.partition_name', index=0,
number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='run_postinstall', full_name='chromeos_update_engine.PartitionUpdate.run_postinstall', index=1,
number=2, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='postinstall_path', full_name='chromeos_update_engine.PartitionUpdate.postinstall_path', index=2,
number=3, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='filesystem_type', full_name='chromeos_update_engine.PartitionUpdate.filesystem_type', index=3,
number=4, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='new_partition_signature', full_name='chromeos_update_engine.PartitionUpdate.new_partition_signature', index=4,
number=5, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='old_partition_info', full_name='chromeos_update_engine.PartitionUpdate.old_partition_info', index=5,
number=6, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='new_partition_info', full_name='chromeos_update_engine.PartitionUpdate.new_partition_info', index=6,
number=7, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='operations', full_name='chromeos_update_engine.PartitionUpdate.operations', index=7,
number=8, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='postinstall_optional', full_name='chromeos_update_engine.PartitionUpdate.postinstall_optional', index=8,
number=9, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='hash_tree_data_extent', full_name='chromeos_update_engine.PartitionUpdate.hash_tree_data_extent', index=9,
number=10, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='hash_tree_extent', full_name='chromeos_update_engine.PartitionUpdate.hash_tree_extent', index=10,
number=11, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='hash_tree_algorithm', full_name='chromeos_update_engine.PartitionUpdate.hash_tree_algorithm', index=11,
number=12, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='hash_tree_salt', full_name='chromeos_update_engine.PartitionUpdate.hash_tree_salt', index=12,
number=13, type=12, cpp_type=9, label=1,
- has_default_value=False, default_value=_b(""),
+ has_default_value=False, default_value="",
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='fec_data_extent', full_name='chromeos_update_engine.PartitionUpdate.fec_data_extent', index=13,
number=14, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='fec_extent', full_name='chromeos_update_engine.PartitionUpdate.fec_extent', index=14,
number=15, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='fec_roots', full_name='chromeos_update_engine.PartitionUpdate.fec_roots', index=15,
number=16, type=13, cpp_type=3, label=1,
has_default_value=True, default_value=2,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
- serialized_start=888,
- serialized_end=1615,
+ serialized_start=880,
+ serialized_end=1607,
)
@@ -528,38 +498,35 @@
_descriptor.FieldDescriptor(
name='name', full_name='chromeos_update_engine.DynamicPartitionGroup.name', index=0,
number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=_b("").decode('utf-8'),
+ has_default_value=False, default_value=unicode("", "utf-8"),
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='size', full_name='chromeos_update_engine.DynamicPartitionGroup.size', index=1,
number=2, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='partition_names', full_name='chromeos_update_engine.DynamicPartitionGroup.partition_names', index=2,
number=3, type=9, cpp_type=9, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1617,
- serialized_end=1693,
+ serialized_start=1609,
+ serialized_end=1685,
)
@@ -576,28 +543,18 @@
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
- _descriptor.FieldDescriptor(
- name='snapshot_enabled', full_name='chromeos_update_engine.DynamicPartitionMetadata.snapshot_enabled', index=1,
- number=2, type=8, cpp_type=7, label=1,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1695,
- serialized_end=1810,
+ serialized_start=1687,
+ serialized_end=1776,
)
@@ -614,127 +571,124 @@
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='kernel_install_operations', full_name='chromeos_update_engine.DeltaArchiveManifest.kernel_install_operations', index=1,
number=2, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='block_size', full_name='chromeos_update_engine.DeltaArchiveManifest.block_size', index=2,
number=3, type=13, cpp_type=3, label=1,
has_default_value=True, default_value=4096,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='signatures_offset', full_name='chromeos_update_engine.DeltaArchiveManifest.signatures_offset', index=3,
number=4, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='signatures_size', full_name='chromeos_update_engine.DeltaArchiveManifest.signatures_size', index=4,
number=5, type=4, cpp_type=4, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='old_kernel_info', full_name='chromeos_update_engine.DeltaArchiveManifest.old_kernel_info', index=5,
number=6, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='new_kernel_info', full_name='chromeos_update_engine.DeltaArchiveManifest.new_kernel_info', index=6,
number=7, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='old_rootfs_info', full_name='chromeos_update_engine.DeltaArchiveManifest.old_rootfs_info', index=7,
number=8, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='new_rootfs_info', full_name='chromeos_update_engine.DeltaArchiveManifest.new_rootfs_info', index=8,
number=9, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='old_image_info', full_name='chromeos_update_engine.DeltaArchiveManifest.old_image_info', index=9,
number=10, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='new_image_info', full_name='chromeos_update_engine.DeltaArchiveManifest.new_image_info', index=10,
number=11, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='minor_version', full_name='chromeos_update_engine.DeltaArchiveManifest.minor_version', index=11,
number=12, type=13, cpp_type=3, label=1,
has_default_value=True, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='partitions', full_name='chromeos_update_engine.DeltaArchiveManifest.partitions', index=12,
number=13, type=11, cpp_type=10, label=3,
has_default_value=False, default_value=[],
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='max_timestamp', full_name='chromeos_update_engine.DeltaArchiveManifest.max_timestamp', index=13,
number=14, type=3, cpp_type=2, label=1,
has_default_value=False, default_value=0,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
_descriptor.FieldDescriptor(
name='dynamic_partition_metadata', full_name='chromeos_update_engine.DeltaArchiveManifest.dynamic_partition_metadata', index=14,
number=15, type=11, cpp_type=10, label=1,
has_default_value=False, default_value=None,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR),
+ options=None),
],
extensions=[
],
nested_types=[],
enum_types=[
],
- serialized_options=None,
+ options=None,
is_extendable=False,
- syntax='proto2',
extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1813,
- serialized_end=2630,
+ serialized_start=1779,
+ serialized_end=2596,
)
-_SIGNATURES_SIGNATURE.containing_type = _SIGNATURES
+_SIGNATURES_SIGNATURE.containing_type = _SIGNATURES;
_SIGNATURES.fields_by_name['signatures'].message_type = _SIGNATURES_SIGNATURE
_INSTALLOPERATION.fields_by_name['type'].enum_type = _INSTALLOPERATION_TYPE
_INSTALLOPERATION.fields_by_name['src_extents'].message_type = _EXTENT
_INSTALLOPERATION.fields_by_name['dst_extents'].message_type = _EXTENT
-_INSTALLOPERATION_TYPE.containing_type = _INSTALLOPERATION
+_INSTALLOPERATION_TYPE.containing_type = _INSTALLOPERATION;
_PARTITIONUPDATE.fields_by_name['new_partition_signature'].message_type = _SIGNATURES_SIGNATURE
_PARTITIONUPDATE.fields_by_name['old_partition_info'].message_type = _PARTITIONINFO
_PARTITIONUPDATE.fields_by_name['new_partition_info'].message_type = _PARTITIONINFO
@@ -763,81 +717,68 @@
DESCRIPTOR.message_types_by_name['DynamicPartitionGroup'] = _DYNAMICPARTITIONGROUP
DESCRIPTOR.message_types_by_name['DynamicPartitionMetadata'] = _DYNAMICPARTITIONMETADATA
DESCRIPTOR.message_types_by_name['DeltaArchiveManifest'] = _DELTAARCHIVEMANIFEST
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-Extent = _reflection.GeneratedProtocolMessageType('Extent', (_message.Message,), {
- 'DESCRIPTOR' : _EXTENT,
- '__module__' : 'update_metadata_pb2'
+class Extent(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = _EXTENT
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.Extent)
- })
-_sym_db.RegisterMessage(Extent)
-Signatures = _reflection.GeneratedProtocolMessageType('Signatures', (_message.Message,), {
+class Signatures(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
- 'Signature' : _reflection.GeneratedProtocolMessageType('Signature', (_message.Message,), {
- 'DESCRIPTOR' : _SIGNATURES_SIGNATURE,
- '__module__' : 'update_metadata_pb2'
+ class Signature(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = _SIGNATURES_SIGNATURE
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.Signatures.Signature)
- })
- ,
- 'DESCRIPTOR' : _SIGNATURES,
- '__module__' : 'update_metadata_pb2'
+ DESCRIPTOR = _SIGNATURES
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.Signatures)
- })
-_sym_db.RegisterMessage(Signatures)
-_sym_db.RegisterMessage(Signatures.Signature)
-PartitionInfo = _reflection.GeneratedProtocolMessageType('PartitionInfo', (_message.Message,), {
- 'DESCRIPTOR' : _PARTITIONINFO,
- '__module__' : 'update_metadata_pb2'
+class PartitionInfo(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = _PARTITIONINFO
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.PartitionInfo)
- })
-_sym_db.RegisterMessage(PartitionInfo)
-ImageInfo = _reflection.GeneratedProtocolMessageType('ImageInfo', (_message.Message,), {
- 'DESCRIPTOR' : _IMAGEINFO,
- '__module__' : 'update_metadata_pb2'
+class ImageInfo(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = _IMAGEINFO
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.ImageInfo)
- })
-_sym_db.RegisterMessage(ImageInfo)
-InstallOperation = _reflection.GeneratedProtocolMessageType('InstallOperation', (_message.Message,), {
- 'DESCRIPTOR' : _INSTALLOPERATION,
- '__module__' : 'update_metadata_pb2'
+class InstallOperation(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = _INSTALLOPERATION
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.InstallOperation)
- })
-_sym_db.RegisterMessage(InstallOperation)
-PartitionUpdate = _reflection.GeneratedProtocolMessageType('PartitionUpdate', (_message.Message,), {
- 'DESCRIPTOR' : _PARTITIONUPDATE,
- '__module__' : 'update_metadata_pb2'
+class PartitionUpdate(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = _PARTITIONUPDATE
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.PartitionUpdate)
- })
-_sym_db.RegisterMessage(PartitionUpdate)
-DynamicPartitionGroup = _reflection.GeneratedProtocolMessageType('DynamicPartitionGroup', (_message.Message,), {
- 'DESCRIPTOR' : _DYNAMICPARTITIONGROUP,
- '__module__' : 'update_metadata_pb2'
+class DynamicPartitionGroup(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = _DYNAMICPARTITIONGROUP
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.DynamicPartitionGroup)
- })
-_sym_db.RegisterMessage(DynamicPartitionGroup)
-DynamicPartitionMetadata = _reflection.GeneratedProtocolMessageType('DynamicPartitionMetadata', (_message.Message,), {
- 'DESCRIPTOR' : _DYNAMICPARTITIONMETADATA,
- '__module__' : 'update_metadata_pb2'
+class DynamicPartitionMetadata(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = _DYNAMICPARTITIONMETADATA
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.DynamicPartitionMetadata)
- })
-_sym_db.RegisterMessage(DynamicPartitionMetadata)
-DeltaArchiveManifest = _reflection.GeneratedProtocolMessageType('DeltaArchiveManifest', (_message.Message,), {
- 'DESCRIPTOR' : _DELTAARCHIVEMANIFEST,
- '__module__' : 'update_metadata_pb2'
+class DeltaArchiveManifest(_message.Message):
+ __metaclass__ = _reflection.GeneratedProtocolMessageType
+ DESCRIPTOR = _DELTAARCHIVEMANIFEST
+
# @@protoc_insertion_point(class_scope:chromeos_update_engine.DeltaArchiveManifest)
- })
-_sym_db.RegisterMessage(DeltaArchiveManifest)
-DESCRIPTOR._options = None
-_INSTALLOPERATION_TYPE.values_by_name["MOVE"]._options = None
-_INSTALLOPERATION_TYPE.values_by_name["BSDIFF"]._options = None
+DESCRIPTOR.has_options = True
+DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), 'H\003')
# @@protoc_insertion_point(module_scope)
diff --git a/service_delegate_android_interface.h b/service_delegate_android_interface.h
index 6bd75b6..5267bb0 100644
--- a/service_delegate_android_interface.h
+++ b/service_delegate_android_interface.h
@@ -47,13 +47,6 @@
const std::vector<std::string>& key_value_pair_headers,
brillo::ErrorPtr* error) = 0;
- virtual bool ApplyPayload(
- int fd,
- int64_t payload_offset,
- int64_t payload_size,
- const std::vector<std::string>& key_value_pair_headers,
- brillo::ErrorPtr* error) = 0;
-
// Suspend an ongoing update. Returns true if there was an update ongoing and
// it was suspended. In case of failure, it returns false and sets |error|
// accordingly.
diff --git a/sideload_logging_android.cc b/sideload_logging_android.cc
deleted file mode 100644
index f82259f..0000000
--- a/sideload_logging_android.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-#include "update_engine/sideload_logging_android.h"
-
-#include <android-base/logging.h>
-
-namespace chromeos_update_engine {
-
-void SetupAndroidLogging(char* argv[]) {
- android::base::InitLogging(argv, android::base::StdioLogger);
-}
-
-} // namespace chromeos_update_engine
diff --git a/sideload_logging_android.h b/sideload_logging_android.h
deleted file mode 100644
index 0bb8714..0000000
--- a/sideload_logging_android.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//
-// Copyright (C) 2019 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.
-//
-
-#pragma once
-
-namespace chromeos_update_engine {
-
-// Some depending modules uses logging functions from android-base.
-// Redirect android-base logging to stdio, which redirects to /tmp/recovery.log.
-void SetupAndroidLogging(char* argv[]);
-
-} // namespace chromeos_update_engine
diff --git a/sideload_main.cc b/sideload_main.cc
index 29d6f2c..818fa5c 100644
--- a/sideload_main.cc
+++ b/sideload_main.cc
@@ -36,7 +36,6 @@
#include "update_engine/common/subprocess.h"
#include "update_engine/common/terminator.h"
#include "update_engine/common/utils.h"
-#include "update_engine/sideload_logging_android.h"
#include "update_engine/update_attempter_android.h"
using std::string;
@@ -197,7 +196,6 @@
chromeos_update_engine::Terminator::Init();
chromeos_update_engine::SetupLogging();
- chromeos_update_engine::SetupAndroidLogging(argv);
brillo::FlagHelper::Init(argc, argv, "Update Engine Sideload");
LOG(INFO) << "Update Engine Sideloading starting";
diff --git a/test_config.xml b/test_config.xml
deleted file mode 100644
index 2639e7f..0000000
--- a/test_config.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2019 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.
--->
-<configuration description="Config to run update_engine_unittests on device">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-native" />
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="push" value="update_engine_unittests->/data/local/tmp/update_engine_unittests" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.GTest" >
- <option name="native-test-device-path" value="/data/local/tmp" />
- <!-- The following rules avoid test runner from calling the following helper executables
- directly as gtests. -->
- <option name="file-exclusion-filter-regex" value=".*/delta_generator$" />
- <option name="file-exclusion-filter-regex" value=".*/test_http_server$" />
- <option name="file-exclusion-filter-regex" value=".*/test_subprocess$" />
- <option name="module-name" value="update_engine_unittests" />
- </test>
-</configuration>
diff --git a/unittest_key_EC.pem b/unittest_key_EC.pem
deleted file mode 100644
index 9e65a68..0000000
--- a/unittest_key_EC.pem
+++ /dev/null
@@ -1,5 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgGaguGj8Yb1KkqKHd
-ISblUsjtOCbzAuVpX81i02sm8FWhRANCAARBnuotwKOsuvjH6iwTDhOAi7Q5pLWz
-xDkZjg2pcfbfi9FFTvLYETas7B2W6fx9PUezUmHTFTDV2JZuMYYFdZOw
------END PRIVATE KEY-----
diff --git a/update_attempter_android.cc b/update_attempter_android.cc
index 5bffc42..1cc8505 100644
--- a/update_attempter_android.cc
+++ b/update_attempter_android.cc
@@ -22,7 +22,6 @@
#include <utility>
#include <android-base/properties.h>
-#include <android-base/unique_fd.h>
#include <base/bind.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
@@ -39,7 +38,6 @@
#include "update_engine/metrics_reporter_interface.h"
#include "update_engine/metrics_utils.h"
#include "update_engine/network_selector.h"
-#include "update_engine/payload_consumer/certificate_parser_interface.h"
#include "update_engine/payload_consumer/delta_performer.h"
#include "update_engine/payload_consumer/download_action.h"
#include "update_engine/payload_consumer/file_descriptor.h"
@@ -47,7 +45,6 @@
#include "update_engine/payload_consumer/filesystem_verifier_action.h"
#include "update_engine/payload_consumer/payload_constants.h"
#include "update_engine/payload_consumer/payload_metadata.h"
-#include "update_engine/payload_consumer/payload_verifier.h"
#include "update_engine/payload_consumer/postinstall_runner_action.h"
#include "update_engine/update_boot_flags_action.h"
#include "update_engine/update_status_utils.h"
@@ -58,7 +55,6 @@
#include "update_engine/libcurl_http_fetcher.h"
#endif
-using android::base::unique_fd;
using base::Bind;
using base::Time;
using base::TimeDelta;
@@ -292,19 +288,6 @@
return true;
}
-bool UpdateAttempterAndroid::ApplyPayload(
- int fd,
- int64_t payload_offset,
- int64_t payload_size,
- const vector<string>& key_value_pair_headers,
- brillo::ErrorPtr* error) {
- payload_fd_.reset(dup(fd));
- const string payload_url = "fd://" + std::to_string(payload_fd_.get());
-
- return ApplyPayload(
- payload_url, payload_offset, payload_size, key_value_pair_headers, error);
-}
-
bool UpdateAttempterAndroid::SuspendUpdate(brillo::ErrorPtr* error) {
if (!processor_->IsRunning())
return LogAndSetError(error, FROM_HERE, "No ongoing update to suspend.");
@@ -412,16 +395,12 @@
}
fd->Close();
- auto payload_verifier = PayloadVerifier::CreateInstanceFromZipPath(
- constants::kUpdateCertificatesPath);
- if (!payload_verifier) {
- return LogAndSetError(error,
- FROM_HERE,
- "Failed to create the payload verifier from " +
- std::string(constants::kUpdateCertificatesPath));
+ string public_key;
+ if (!utils::ReadFile(constants::kUpdatePayloadPublicKeyPath, &public_key)) {
+ return LogAndSetError(error, FROM_HERE, "Failed to read public key.");
}
- errorcode = payload_metadata.ValidateMetadataSignature(
- metadata, "", *payload_verifier);
+ errorcode =
+ payload_metadata.ValidateMetadataSignature(metadata, "", public_key);
if (errorcode != ErrorCode::kSuccess) {
return LogAndSetError(error,
FROM_HERE,
@@ -604,7 +583,6 @@
(error_code == ErrorCode::kSuccess ? UpdateStatus::UPDATED_NEED_REBOOT
: UpdateStatus::IDLE);
SetStatusAndNotify(new_status);
- payload_fd_.reset();
// The network id is only applicable to one download attempt and once it's
// done the network id should not be re-used anymore.
@@ -756,15 +734,11 @@
total_bytes_downloaded;
int download_overhead_percentage = 0;
- if (total_bytes_downloaded >= payload_size) {
- CHECK_GT(payload_size, 0);
+ if (current_bytes_downloaded > 0) {
download_overhead_percentage =
- (total_bytes_downloaded - payload_size) * 100ull / payload_size;
- } else {
- LOG(WARNING) << "Downloaded bytes " << total_bytes_downloaded
- << " is smaller than the payload size " << payload_size;
+ (total_bytes_downloaded - current_bytes_downloaded) * 100ull /
+ current_bytes_downloaded;
}
-
metrics_reporter_->ReportSuccessfulUpdateMetrics(
static_cast<int>(attempt_number),
0, // update abandoned count
diff --git a/update_attempter_android.h b/update_attempter_android.h
index 7e1949d..c4710ad 100644
--- a/update_attempter_android.h
+++ b/update_attempter_android.h
@@ -23,7 +23,6 @@
#include <string>
#include <vector>
-#include <android-base/unique_fd.h>
#include <base/time/time.h>
#include "update_engine/client_library/include/update_engine/update_status.h"
@@ -66,11 +65,6 @@
int64_t payload_size,
const std::vector<std::string>& key_value_pair_headers,
brillo::ErrorPtr* error) override;
- bool ApplyPayload(int fd,
- int64_t payload_offset,
- int64_t payload_size,
- const std::vector<std::string>& key_value_pair_headers,
- brillo::ErrorPtr* error) override;
bool SuspendUpdate(brillo::ErrorPtr* error) override;
bool ResumeUpdate(brillo::ErrorPtr* error) override;
bool CancelUpdate(brillo::ErrorPtr* error) override;
@@ -197,8 +191,6 @@
std::unique_ptr<MetricsReporterInterface> metrics_reporter_;
- ::android::base::unique_fd payload_fd_;
-
DISALLOW_COPY_AND_ASSIGN(UpdateAttempterAndroid);
};
diff --git a/update_attempter_android_unittest.cc b/update_attempter_android_unittest.cc
index 721b735..3be0b7e 100644
--- a/update_attempter_android_unittest.cc
+++ b/update_attempter_android_unittest.cc
@@ -18,7 +18,6 @@
#include <memory>
#include <string>
-#include <utility>
#include <android-base/properties.h>
#include <base/time/time.h>
@@ -58,11 +57,6 @@
update_attempter_android_.status_ = status;
}
- void AddPayload(InstallPlan::Payload&& payload) {
- update_attempter_android_.install_plan_.payloads.push_back(
- std::move(payload));
- }
-
UpdateAttempterAndroid update_attempter_android_{
&daemon_state_, &prefs_, &boot_control_, &hardware_};
@@ -149,13 +143,9 @@
.Times(1);
EXPECT_CALL(*metrics_reporter_,
ReportSuccessfulUpdateMetrics(
- 2, 0, _, 50, _, _, duration, duration_uptime, 3, _))
+ 2, 0, _, _, _, _, duration, duration_uptime, 3, _))
.Times(1);
- // Adds a payload of 50 bytes to the InstallPlan.
- InstallPlan::Payload payload;
- payload.size = 50;
- AddPayload(std::move(payload));
SetUpdateStatus(UpdateStatus::UPDATE_AVAILABLE);
update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kSuccess);
@@ -189,20 +179,15 @@
_,
_,
_,
- 50,
+ _,
test_utils::DownloadSourceMatcher(total_bytes),
- 80,
+ 125,
_,
_,
_,
_))
.Times(1);
- // Adds a payload of 50 bytes to the InstallPlan.
- InstallPlan::Payload payload;
- payload.size = 50;
- AddPayload(std::move(payload));
-
// The first update fails after receiving 50 bytes in total.
update_attempter_android_.BytesReceived(30, 50, 200);
update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kError);
@@ -214,7 +199,7 @@
metrics_utils::GetPersistedValue(kPrefsTotalBytesDownloaded, &prefs_));
// The second update succeeds after receiving 40 bytes, which leads to a
- // overhead of (90 - 50) / 50 = 80%.
+ // overhead of 50 / 40 = 125%.
update_attempter_android_.BytesReceived(40, 40, 50);
update_attempter_android_.ProcessingDone(nullptr, ErrorCode::kSuccess);
// Both prefs should be cleared.
diff --git a/update_engine.rc b/update_engine.rc
index b9f80fc..90ca4c6 100644
--- a/update_engine.rc
+++ b/update_engine.rc
@@ -2,7 +2,7 @@
class late_start
user root
group root system wakelock inet cache media_rw
- writepid /dev/cpuset/system-background/tasks /dev/blkio/background/tasks
+ writepid /dev/cpuset/system-background/tasks
disabled
on property:ro.boot.slot_suffix=*
diff --git a/update_metadata.proto b/update_metadata.proto
index 9bc0d8a..7e8e7d4 100644
--- a/update_metadata.proto
+++ b/update_metadata.proto
@@ -126,17 +126,8 @@
message Signatures {
message Signature {
- optional uint32 version = 1 [deprecated = true];
+ optional uint32 version = 1;
optional bytes data = 2;
-
- // The DER encoded signature size of EC keys is nondeterministic for
- // different input of sha256 hash. However, we need the size of the
- // serialized signatures protobuf string to be fixed before signing;
- // because this size is part of the content to be signed. Therefore, we
- // always pad the signature data to the maximum possible signature size of
- // a given key. And the payload verifier will truncate the signature to
- // its correct size based on the value of |unpadded_signature_size|.
- optional fixed32 unpadded_signature_size = 3;
}
repeated Signature signatures = 1;
}
@@ -311,12 +302,6 @@
// - If an updatable group is in the manifest but not on the device, the group
// is added to the device.
repeated DynamicPartitionGroup groups = 1;
-
- // Whether dynamic partitions have snapshots during the update. If this is
- // set to true, the update_engine daemon creates snapshots for all dynamic
- // partitions if possible. If this is unset, the update_engine daemon MUST
- // NOT create snapshots for dynamic partitions.
- optional bool snapshot_enabled = 2;
}
message DeltaArchiveManifest {