Merge "Revert "Set block device as RO/RW before mount"" into main
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index 32e8b88..192232d 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -34,6 +34,9 @@
],
"kernel-presubmit": [
{
+ "name": "adb-remount-sh"
+ },
+ {
"name": "libdm_test"
},
{
diff --git a/fs_mgr/libfstab/fstab.cpp b/fs_mgr/libfstab/fstab.cpp
index f00e0dc..21d2e2e 100644
--- a/fs_mgr/libfstab/fstab.cpp
+++ b/fs_mgr/libfstab/fstab.cpp
@@ -520,6 +520,24 @@
} // namespace
+// Return the path to the recovery fstab file. There may be multiple fstab files;
+// the one that is returned will be the first that exists of recovery.fstab.<fstab_suffix>,
+// recovery.fstab.<hardware>, and recovery.fstab.<hardware.platform>.
+std::string GetRecoveryFstabPath() {
+ for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
+ std::string suffix;
+
+ if (!fs_mgr_get_boot_config(prop, &suffix)) continue;
+
+ std::string fstab_path = "/etc/recovery.fstab." + suffix;
+ if (access(fstab_path.c_str(), F_OK) == 0) {
+ return fstab_path;
+ }
+ }
+
+ return "/etc/recovery.fstab";
+}
+
// Return the path to the fstab file. There may be multiple fstab files; the
// one that is returned will be the first that exists of fstab.<fstab_suffix>,
// fstab.<hardware>, and fstab.<hardware.platform>. The fstab is searched for
@@ -529,7 +547,7 @@
// the system/etc directory is supported too and is the preferred location.
std::string GetFstabPath() {
if (InRecovery()) {
- return "/etc/recovery.fstab";
+ return GetRecoveryFstabPath();
}
for (const char* prop : {"fstab_suffix", "hardware", "hardware.platform"}) {
std::string suffix;
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
index 2e948dd..62f9901 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -229,6 +229,10 @@
// Enable direct reads from source device
bool o_direct = 12;
+
+ // Number of cow operations to be merged at once
+ uint32 cow_op_merge_size = 13;
+
}
// Next: 10
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 1ec8634..4a3ec1d 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -831,6 +831,8 @@
// Check if direct reads are enabled for the source image
bool UpdateUsesODirect(LockedFile* lock);
+ // Get value of maximum cow op merge size
+ uint32_t GetUpdateCowOpMergeSize(LockedFile* lock);
// Wrapper around libdm, with diagnostics.
bool DeleteDeviceIfExists(const std::string& name,
const std::chrono::milliseconds& timeout_ms = {});
diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
index 90813fe..0afd8bd 100644
--- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
@@ -30,6 +30,8 @@
#include <storage_literals/storage_literals.h>
#include <update_engine/update_metadata.pb.h>
+#include "utility.h"
+
namespace android {
namespace snapshot {
@@ -234,5 +236,21 @@
#define RETURN_IF_NON_VIRTUAL_AB() RETURN_IF_NON_VIRTUAL_AB_MSG("")
+#define SKIP_IF_VENDOR_ON_ANDROID_S() \
+ do { \
+ if (IsVendorFromAndroid12()) \
+ GTEST_SKIP() << "Skip test as Vendor partition is on Android S"; \
+ } while (0)
+
+#define RETURN_IF_VENDOR_ON_ANDROID_S_MSG(msg) \
+ do { \
+ if (IsVendorFromAndroid12()) { \
+ std::cerr << (msg); \
+ return; \
+ } \
+ } while (0)
+
+#define RETURN_IF_VENDOR_ON_ANDROID_S() RETURN_IF_VENDOR_ON_ANDROID_S_MSG("")
+
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 6674378..265445b 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -20,6 +20,7 @@
#include <sys/file.h>
#include <sys/types.h>
#include <sys/unistd.h>
+#include <sys/xattr.h>
#include <chrono>
#include <filesystem>
@@ -91,6 +92,8 @@
static constexpr char kRollbackIndicatorPath[] = "/metadata/ota/rollback-indicator";
static constexpr char kSnapuserdFromSystem[] = "/metadata/ota/snapuserd-from-system";
static constexpr auto kUpdateStateCheckInterval = 2s;
+static constexpr char kOtaFileContext[] = "u:object_r:ota_metadata_file:s0";
+
/*
* The readahead size is set to 32kb so that
* there is no significant memory pressure (/proc/pressure/memory) during boot.
@@ -1706,6 +1709,10 @@
if (UpdateUsesODirect(lock.get())) {
snapuserd_argv->emplace_back("-o_direct");
}
+ uint cow_op_merge_size = GetUpdateCowOpMergeSize(lock.get());
+ if (cow_op_merge_size != 0) {
+ snapuserd_argv->emplace_back("-cow_op_merge_size=" + std::to_string(cow_op_merge_size));
+ }
}
size_t num_cows = 0;
@@ -2128,6 +2135,11 @@
return update_status.o_direct();
}
+uint32_t SnapshotManager::GetUpdateCowOpMergeSize(LockedFile* lock) {
+ SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
+ return update_status.cow_op_merge_size();
+}
+
bool SnapshotManager::MarkSnapuserdFromSystem() {
auto path = GetSnapuserdFromSystemPath();
@@ -2135,6 +2147,24 @@
PLOG(ERROR) << "Unable to write to vendor update path: " << path;
return false;
}
+
+ unique_fd fd(open(path.c_str(), O_PATH));
+ if (fd < 0) {
+ PLOG(ERROR) << "Failed to open file: " << path;
+ return false;
+ }
+
+ /*
+ * This function is invoked by first stage init and hence we need to
+ * explicitly set the correct selinux label for this file as update_engine
+ * will try to remove this file later on once the snapshot merge is
+ * complete.
+ */
+ if (fsetxattr(fd.get(), XATTR_NAME_SELINUX, kOtaFileContext, strlen(kOtaFileContext) + 1, 0) <
+ 0) {
+ PLOG(ERROR) << "fsetxattr for the path: " << path << " failed";
+ }
+
return true;
}
@@ -2185,18 +2215,24 @@
*
*/
bool SnapshotManager::IsLegacySnapuserdPostReboot() {
- if (is_legacy_snapuserd_.has_value() && is_legacy_snapuserd_.value() == true) {
- auto slot = GetCurrentSlot();
- if (slot == Slot::Target) {
- // If this marker is present, then daemon can handle userspace
- // snapshots; also, it indicates that the vendor partition was
- // updated from Android 12.
- if (access(GetSnapuserdFromSystemPath().c_str(), F_OK) == 0) {
- return false;
- }
+ auto slot = GetCurrentSlot();
+ if (slot == Slot::Target) {
+ /*
+ If this marker is present, the daemon can handle userspace snapshots.
+ During post-OTA reboot, this implies that the vendor partition is
+ Android 13 or higher. If the snapshots were created on an
+ Android 12 vendor, this means the vendor partition has been updated.
+ */
+ if (access(GetSnapuserdFromSystemPath().c_str(), F_OK) == 0) {
+ is_snapshot_userspace_ = true;
+ return false;
+ }
+ // If the marker isn't present and if the vendor is still in Android 12
+ if (is_legacy_snapuserd_.has_value() && is_legacy_snapuserd_.value() == true) {
return true;
}
}
+
return false;
}
@@ -3065,6 +3101,7 @@
status.set_io_uring_enabled(old_status.io_uring_enabled());
status.set_legacy_snapuserd(old_status.legacy_snapuserd());
status.set_o_direct(old_status.o_direct());
+ status.set_cow_op_merge_size(old_status.cow_op_merge_size());
}
return WriteSnapshotUpdateStatus(lock, status);
}
@@ -3447,6 +3484,8 @@
status.set_legacy_snapuserd(true);
LOG(INFO) << "Setting legacy_snapuserd to true";
}
+ status.set_cow_op_merge_size(
+ android::base::GetUintProperty<uint32_t>("ro.virtual_ab.cow_op_merge_size", 0));
} else if (legacy_compression) {
LOG(INFO) << "Virtual A/B using legacy snapuserd";
} else {
@@ -3882,6 +3921,7 @@
ss << "Using userspace snapshots: " << update_status.userspace_snapshots() << std::endl;
ss << "Using io_uring: " << update_status.io_uring_enabled() << std::endl;
ss << "Using o_direct: " << update_status.o_direct() << std::endl;
+ ss << "Cow op merge size (0 for uncapped): " << update_status.cow_op_merge_size() << std::endl;
ss << "Using XOR compression: " << GetXorCompressionEnabledProperty() << std::endl;
ss << "Current slot: " << device_->GetSlotSuffix() << std::endl;
ss << "Boot indicator: booting from " << GetCurrentSlot() << " slot" << std::endl;
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 1435b12..b2e36d4 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -122,6 +122,7 @@
LOG(INFO) << "Starting test: " << test_name_;
SKIP_IF_NON_VIRTUAL_AB();
+ SKIP_IF_VENDOR_ON_ANDROID_S();
SetupProperties();
if (!DeviceSupportsMode()) {
@@ -168,6 +169,7 @@
void TearDown() override {
RETURN_IF_NON_VIRTUAL_AB();
+ RETURN_IF_VENDOR_ON_ANDROID_S();
LOG(INFO) << "Tearing down SnapshotTest test: " << test_name_;
@@ -1015,6 +1017,7 @@
public:
void SetUp() override {
SKIP_IF_NON_VIRTUAL_AB();
+ SKIP_IF_VENDOR_ON_ANDROID_S();
SnapshotTest::SetUp();
if (!image_manager_) {
@@ -1097,6 +1100,7 @@
}
void TearDown() override {
RETURN_IF_NON_VIRTUAL_AB();
+ RETURN_IF_VENDOR_ON_ANDROID_S();
LOG(INFO) << "Tearing down SnapshotUpdateTest test: " << test_name_;
@@ -2661,6 +2665,7 @@
status.set_o_direct(true);
status.set_io_uring_enabled(true);
status.set_userspace_snapshots(true);
+ status.set_cow_op_merge_size(16);
sm->WriteSnapshotUpdateStatus(lock_.get(), status);
// Ensure a connection to the second-stage daemon, but use the first-stage
@@ -2682,6 +2687,8 @@
snapuserd_argv.end());
ASSERT_TRUE(std::find(snapuserd_argv.begin(), snapuserd_argv.end(), "-user_snapshot") !=
snapuserd_argv.end());
+ ASSERT_TRUE(std::find(snapuserd_argv.begin(), snapuserd_argv.end(), "-cow_op_merge_size=16") !=
+ snapuserd_argv.end());
}
class FlashAfterUpdateTest : public SnapshotUpdateTest,
@@ -2833,6 +2840,7 @@
// that is fixed, don't call GTEST_SKIP here, but instead call GTEST_SKIP in individual test
// suites.
RETURN_IF_NON_VIRTUAL_AB_MSG("Virtual A/B is not enabled, skipping global setup.\n");
+ RETURN_IF_VENDOR_ON_ANDROID_S_MSG("Test not enabled for Vendor on Android S.\n");
std::vector<std::string> paths = {
// clang-format off
@@ -2887,6 +2895,8 @@
void SnapshotTestEnvironment::TearDown() {
RETURN_IF_NON_VIRTUAL_AB();
+ RETURN_IF_VENDOR_ON_ANDROID_S();
+
if (super_images_ != nullptr) {
DeleteBackingImage(super_images_.get(), "fake-super");
}
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
index 67e9e52..dd2dd56 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
@@ -30,6 +30,7 @@
DEFINE_bool(user_snapshot, false, "If true, user-space snapshots are used");
DEFINE_bool(io_uring, false, "If true, io_uring feature is enabled");
DEFINE_bool(o_direct, false, "If true, enable direct reads on source device");
+DEFINE_int32(cow_op_merge_size, 0, "number of operations to be processed at once");
namespace android {
namespace snapshot {
@@ -106,7 +107,6 @@
}
return user_server_.Run();
}
-
for (int i = arg_start; i < argc; i++) {
auto parts = android::base::Split(argv[i], ",");
@@ -114,8 +114,8 @@
LOG(ERROR) << "Malformed message, expected at least four sub-arguments.";
return false;
}
- auto handler =
- user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3], FLAGS_o_direct);
+ auto handler = user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3],
+ FLAGS_o_direct, FLAGS_cow_op_merge_size);
if (!handler || !user_server_.StartHandler(parts[0])) {
return false;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
index c85331b..ef4ba93 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/extractor.cpp
@@ -41,7 +41,7 @@
bool Extractor::Init() {
auto opener = factory_.CreateTestOpener(control_name_);
handler_ = std::make_shared<SnapshotHandler>(control_name_, cow_path_, base_path_, base_path_,
- opener, 1, false, false, false);
+ opener, 1, false, false, false, 0);
if (!handler_->InitCowDevice()) {
return false;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
index ea11f0e..fdd9cce 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
@@ -53,10 +53,10 @@
const std::string& misc_name, const std::string& cow_device_path,
const std::string& backing_device, const std::string& base_path_merge,
std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads, bool use_iouring,
- bool o_direct) {
+ bool o_direct, uint32_t cow_op_merge_size) {
auto snapuserd = std::make_shared<SnapshotHandler>(
misc_name, cow_device_path, backing_device, base_path_merge, opener, num_worker_threads,
- use_iouring, perform_verification_, o_direct);
+ use_iouring, perform_verification_, o_direct, cow_op_merge_size);
if (!snapuserd->InitCowDevice()) {
LOG(ERROR) << "Failed to initialize Snapuserd";
return nullptr;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
index f23f07e..ecf5d5c 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
@@ -52,13 +52,11 @@
virtual ~ISnapshotHandlerManager() {}
// Add a new snapshot handler but do not start serving requests yet.
- virtual std::shared_ptr<HandlerThread> AddHandler(const std::string& misc_name,
- const std::string& cow_device_path,
- const std::string& backing_device,
- const std::string& base_path_merge,
- std::shared_ptr<IBlockServerOpener> opener,
- int num_worker_threads, bool use_iouring,
- bool o_direct) = 0;
+ virtual std::shared_ptr<HandlerThread> AddHandler(
+ const std::string& misc_name, const std::string& cow_device_path,
+ const std::string& backing_device, const std::string& base_path_merge,
+ std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads, bool use_iouring,
+ bool o_direct, uint32_t cow_op_merge_size) = 0;
// Start serving requests on a snapshot handler.
virtual bool StartHandler(const std::string& misc_name) = 0;
@@ -98,7 +96,7 @@
const std::string& base_path_merge,
std::shared_ptr<IBlockServerOpener> opener,
int num_worker_threads, bool use_iouring,
- bool o_direct) override;
+ bool o_direct, uint32_t cow_op_merge_size) override;
bool StartHandler(const std::string& misc_name) override;
bool DeleteHandler(const std::string& misc_name) override;
bool InitiateMerge(const std::string& misc_name) override;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
index e6a9a29..e2c5874 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
@@ -32,12 +32,18 @@
MergeWorker::MergeWorker(const std::string& cow_device, const std::string& misc_name,
const std::string& base_path_merge,
- std::shared_ptr<SnapshotHandler> snapuserd)
- : Worker(cow_device, misc_name, base_path_merge, snapuserd) {}
+ std::shared_ptr<SnapshotHandler> snapuserd, uint32_t cow_op_merge_size)
+ : Worker(cow_device, misc_name, base_path_merge, snapuserd),
+ cow_op_merge_size_(cow_op_merge_size) {}
int MergeWorker::PrepareMerge(uint64_t* source_offset, int* pending_ops,
std::vector<const CowOperation*>* replace_zero_vec) {
int num_ops = *pending_ops;
+ // 0 indicates ro.virtual_ab.cow_op_merge_size was not set in the build
+ if (cow_op_merge_size_ != 0) {
+ num_ops = std::min(cow_op_merge_size_, static_cast<uint32_t>(*pending_ops));
+ }
+
int nr_consecutive = 0;
bool checkOrderedOp = (replace_zero_vec == nullptr);
size_t num_blocks = 1;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.h
index 478d4c8..a19352d 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.h
@@ -23,7 +23,8 @@
class MergeWorker : public Worker {
public:
MergeWorker(const std::string& cow_device, const std::string& misc_name,
- const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd);
+ const std::string& base_path_merge, std::shared_ptr<SnapshotHandler> snapuserd,
+ uint32_t cow_op_merge_size);
bool Run();
private:
@@ -53,6 +54,7 @@
// syscalls and fallback to synchronous I/O, we
// don't want huge queue depth
int queue_depth_ = 8;
+ uint32_t cow_op_merge_size_ = 0;
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
index 05ba047..7c9a64e 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
@@ -36,7 +36,8 @@
SnapshotHandler::SnapshotHandler(std::string misc_name, std::string cow_device,
std::string backing_device, std::string base_path_merge,
std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads,
- bool use_iouring, bool perform_verification, bool o_direct) {
+ bool use_iouring, bool perform_verification, bool o_direct,
+ uint32_t cow_op_merge_size) {
misc_name_ = std::move(misc_name);
cow_device_ = std::move(cow_device);
backing_store_device_ = std::move(backing_device);
@@ -46,6 +47,7 @@
is_io_uring_enabled_ = use_iouring;
perform_verification_ = perform_verification;
o_direct_ = o_direct;
+ cow_op_merge_size_ = cow_op_merge_size;
}
bool SnapshotHandler::InitializeWorkers() {
@@ -60,12 +62,11 @@
worker_threads_.push_back(std::move(wt));
}
-
merge_thread_ = std::make_unique<MergeWorker>(cow_device_, misc_name_, base_path_merge_,
- GetSharedPtr());
+ GetSharedPtr(), cow_op_merge_size_);
read_ahead_thread_ = std::make_unique<ReadAhead>(cow_device_, backing_store_device_, misc_name_,
- GetSharedPtr());
+ GetSharedPtr(), cow_op_merge_size_);
update_verify_ = std::make_unique<UpdateVerify>(misc_name_);
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
index 9b7238a..c7de995 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
@@ -104,7 +104,8 @@
public:
SnapshotHandler(std::string misc_name, std::string cow_device, std::string backing_device,
std::string base_path_merge, std::shared_ptr<IBlockServerOpener> opener,
- int num_workers, bool use_iouring, bool perform_verification, bool o_direct);
+ int num_workers, bool use_iouring, bool perform_verification, bool o_direct,
+ uint32_t cow_op_merge_size);
bool InitCowDevice();
bool Start();
@@ -247,7 +248,7 @@
bool resume_merge_ = false;
bool merge_complete_ = false;
bool o_direct_ = false;
-
+ uint32_t cow_op_merge_size_ = 0;
std::unique_ptr<UpdateVerify> update_verify_;
std::shared_ptr<IBlockServerOpener> block_server_opener_;
};
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
index 2baf20d..6b1ed0c 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
@@ -18,6 +18,7 @@
#include <pthread.h>
+#include "android-base/properties.h"
#include "snapuserd_core.h"
#include "utility.h"
@@ -29,11 +30,13 @@
using android::base::unique_fd;
ReadAhead::ReadAhead(const std::string& cow_device, const std::string& backing_device,
- const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd) {
+ const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd,
+ uint32_t cow_op_merge_size) {
cow_device_ = cow_device;
backing_store_device_ = backing_device;
misc_name_ = misc_name;
snapuserd_ = snapuserd;
+ cow_op_merge_size_ = cow_op_merge_size;
}
void ReadAhead::CheckOverlap(const CowOperation* cow_op) {
@@ -62,8 +65,11 @@
std::vector<uint64_t>& blocks,
std::vector<const CowOperation*>& xor_op_vec) {
int num_ops = *pending_ops;
- int nr_consecutive = 0;
+ if (cow_op_merge_size_ != 0) {
+ num_ops = std::min(static_cast<int>(cow_op_merge_size_), *pending_ops);
+ }
+ int nr_consecutive = 0;
bool is_ops_present = (!RAIterDone() && num_ops);
if (!is_ops_present) {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
index d3ba126..4885c96 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
@@ -35,7 +35,8 @@
class ReadAhead {
public:
ReadAhead(const std::string& cow_device, const std::string& backing_device,
- const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd);
+ const std::string& misc_name, std::shared_ptr<SnapshotHandler> snapuserd,
+ uint32_t cow_op_merge_size);
bool RunThread();
private:
@@ -106,6 +107,7 @@
// syscalls and fallback to synchronous I/O, we
// don't want huge queue depth
int queue_depth_ = 8;
+ uint32_t cow_op_merge_size_;
std::unique_ptr<struct io_uring> ring_;
};
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
index 0b881b6..c0af5c5 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
@@ -347,7 +347,8 @@
const std::string& cow_device_path,
const std::string& backing_device,
const std::string& base_path_merge,
- const bool o_direct) {
+ const bool o_direct,
+ uint32_t cow_op_merge_size) {
// We will need multiple worker threads only during
// device boot after OTA. For all other purposes,
// one thread is sufficient. We don't want to consume
@@ -369,7 +370,8 @@
auto opener = block_server_factory_->CreateOpener(misc_name);
return handlers_->AddHandler(misc_name, cow_device_path, backing_device, base_path_merge,
- opener, num_worker_threads, io_uring_enabled_, o_direct);
+ opener, num_worker_threads, io_uring_enabled_, o_direct,
+ cow_op_merge_size);
}
bool UserSnapshotServer::WaitForSocket() {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
index d9cf97f..ceea36a 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
@@ -87,7 +87,8 @@
const std::string& cow_device_path,
const std::string& backing_device,
const std::string& base_path_merge,
- bool o_direct = false);
+ bool o_direct = false,
+ uint32_t cow_op_merge_size = 0);
bool StartHandler(const std::string& misc_name);
void SetTerminating() { terminating_ = true; }
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
index 6d0ae3d..9042f2b 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
@@ -67,6 +67,7 @@
std::string compression;
int block_size;
int num_threads;
+ uint32_t cow_op_merge_size;
};
class SnapuserdTestBase : public ::testing::TestWithParam<TestParam> {
@@ -708,9 +709,9 @@
auto opener = factory->CreateOpener(system_device_ctrl_name_);
handlers_->DisableVerification();
const TestParam params = GetParam();
- auto handler = handlers_->AddHandler(system_device_ctrl_name_, cow_system_->path,
- base_dev_->GetPath(), base_dev_->GetPath(), opener, 1,
- params.io_uring, params.o_direct);
+ auto handler = handlers_->AddHandler(
+ system_device_ctrl_name_, cow_system_->path, base_dev_->GetPath(), base_dev_->GetPath(),
+ opener, 1, params.io_uring, params.o_direct, params.cow_op_merge_size);
ASSERT_NE(handler, nullptr);
ASSERT_NE(handler->snapuserd(), nullptr);
#ifdef __ANDROID__
@@ -1227,9 +1228,9 @@
ASSERT_NE(opener_, nullptr);
const TestParam params = GetParam();
- handler_ = std::make_shared<SnapshotHandler>(system_device_ctrl_name_, cow_system_->path,
- base_dev_->GetPath(), base_dev_->GetPath(),
- opener_, 1, false, false, params.o_direct);
+ handler_ = std::make_shared<SnapshotHandler>(
+ system_device_ctrl_name_, cow_system_->path, base_dev_->GetPath(), base_dev_->GetPath(),
+ opener_, 1, false, false, params.o_direct, params.cow_op_merge_size);
ASSERT_TRUE(handler_->InitCowDevice());
ASSERT_TRUE(handler_->InitializeWorkers());
@@ -1507,6 +1508,7 @@
param.num_threads = thread;
param.io_uring = io_uring;
param.o_direct = false;
+ param.cow_op_merge_size = 0;
testParams.push_back(std::move(param));
}
}
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index 26af13b..54b469b 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -306,8 +306,8 @@
if (!batt_anim_.run || now < next_screen_transition_) return;
- // If battery level is not ready, keep checking in the defined time
- if (health_info_.battery_level == 0 && health_info_.battery_status == BatteryStatus::UNKNOWN) {
+ // If battery status is not ready, keep checking in the defined time
+ if (health_info_.battery_status == BatteryStatus::UNKNOWN) {
if (wait_batt_level_timestamp_ == 0) {
// Set max delay time and skip drawing screen
wait_batt_level_timestamp_ = now + MAX_BATT_LEVEL_WAIT_TIME;
@@ -317,7 +317,7 @@
// Do nothing, keep waiting
return;
}
- // If timeout and battery level is still not ready, draw unknown battery
+ // If timeout and battery status is still not ready, draw unknown battery
}
if (healthd_draw_ == nullptr) return;
diff --git a/init/Android.bp b/init/Android.bp
index c70a5de..ffb6380 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -330,7 +330,7 @@
static_libs: ["libinit.microdroid"],
cflags: ["-DMICRODROID=1"],
no_full_install: true,
- visibility: ["//packages/modules/Virtualization/microdroid"],
+ visibility: ["//packages/modules/Virtualization/build/microdroid"],
}
soong_config_module_type {
diff --git a/init/README.md b/init/README.md
index 11c4e1c..0bb26e8 100644
--- a/init/README.md
+++ b/init/README.md
@@ -499,9 +499,11 @@
4. `late-fs` - Mount partitions marked as latemounted.
5. `post-fs-data` - Mount and configure `/data`; set up encryption. `/metadata` is
reformatted here if it couldn't mount in first-stage init.
- 6. `zygote-start` - Start the zygote.
- 7. `early-boot` - After zygote has started.
- 8. `boot` - After `early-boot` actions have completed.
+ 6. `post-fs-data-checkpointed` - Triggered when vold has completed committing a checkpoint
+ after an OTA update. Not triggered if checkpointing is not needed or supported.
+ 7. `zygote-start` - Start the zygote.
+ 8. `early-boot` - After zygote has started.
+ 9. `boot` - After `early-boot` actions have completed.
Commands
--------
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 2443b7c..b804c1b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -1087,6 +1087,9 @@
# Update dm-verity state and set partition.*.verified properties.
verity_update_state
+on property:vold.checkpoint_committed=1
+ trigger post-fs-data-checkpointed
+
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index b249013..aca59b6 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -44,7 +44,7 @@
"libtrusty",
"libkeymaster_messages",
"libkeymaster3device",
- "android.hardware.keymaster@3.0"
+ "android.hardware.keymaster@3.0",
],
}
@@ -74,7 +74,7 @@
"libtrusty",
"libkeymaster_messages",
"libkeymaster4",
- "android.hardware.keymaster@4.0"
+ "android.hardware.keymaster@4.0",
],
vintf_fragments: ["4.0/android.hardware.keymaster@4.0-service.trusty.xml"],
@@ -208,3 +208,36 @@
"-Werror",
],
}
+
+prebuilt_etc {
+ name: "rkp_uds_cert_test.xml",
+ vendor: true,
+ src: "set_uds_certs/rkp_uds_cert_test.xml",
+}
+
+cc_binary {
+ name: "trusty_rkp_set_uds_cert",
+ vendor: true,
+
+ srcs: [
+ "set_uds_certs/set_uds_certificates.cpp",
+ "ipc/trusty_keymaster_ipc.cpp",
+ ],
+
+ local_include_dirs: ["include"],
+
+ shared_libs: [
+ "libc",
+ "libcrypto",
+ "liblog",
+ "libtrusty",
+ "libhardware",
+ "libkeymaster_messages",
+ "libutils",
+ "libxml2",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
index 09f696b..822e933 100644
--- a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
+++ b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
@@ -78,6 +78,8 @@
KM_SET_ATTESTATION_IDS = (0xc000 << KEYMASTER_REQ_SHIFT),
KM_SET_ATTESTATION_IDS_KM3 = (0xc001 << KEYMASTER_REQ_SHIFT),
KM_CONFIGURE_BOOT_PATCHLEVEL = (0xd000 << KEYMASTER_REQ_SHIFT),
+ KM_APPEND_UDS_CERT_CHAIN = (0xe0000 << KEYMASTER_REQ_SHIFT),
+ KM_CLEAR_UDS_CERT_CHAIN = (0xe0001 << KEYMASTER_REQ_SHIFT),
};
#ifdef __ANDROID__
diff --git a/trusty/keymaster/set_uds_certs/rkp_uds_cert_test.xml b/trusty/keymaster/set_uds_certs/rkp_uds_cert_test.xml
new file mode 100644
index 0000000..73b7b4c
--- /dev/null
+++ b/trusty/keymaster/set_uds_certs/rkp_uds_cert_test.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<PixelUdsCertificates>
+ <CertificateChain>
+ <NumberOfCertificates>3</NumberOfCertificates>
+ <Certificate format="pem">
+-----BEGIN CERTIFICATE-----
+MIIBWTCB3qADAgECAgUA3q2+7zAMBggqhkjOPQQDAwUAMBIxEDAOBgNVBAMMB0dT
+TUkxLjAwIhgPMjAyNDAxMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowEjEQMA4G
+A1UEAwwHR1NNSTEuMDB2MBAGByqGSM49AgEGBSuBBAAiA2IABFsNPdsPmx2NKNiT
+7oReF36HTXjftRfGffYgPf/vEhrT7XLJ7dThkcb+OFYWYlOckdk3DRgqTNWQXsot
+UsZhwRveU8huEjOBO5+dwDiWPs+s9jSRAn5inlTqJ0YGAmdHRzAMBggqhkjOPQQD
+AwUAA2gAMGUCMQCuiJwmRWOgfWbqdSlnXfhCbphjdWc6sHelLkkM21vxQ3RZkhC2
+ERh90RA1rxB+XTgCMHZrYG3leS0PEoz5hUviv27LbBHBU6GeOzrS2e0VH0BMSNXN
+iP9Wnit+mJw58niEGw==
+-----END CERTIFICATE-----
+ </Certificate>
+ <Certificate format="pem">
+-----BEGIN CERTIFICATE-----
+MIIBWTCB3qADAgECAgUA3q2+7zAMBggqhkjOPQQDAwUAMBIxEDAOBgNVBAMMB0dT
+TUkxLjAwIhgPMjAyNDAxMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowEjEQMA4G
+A1UEAwwHR1NNSTEuMDB2MBAGByqGSM49AgEGBSuBBAAiA2IABFsNPdsPmx2NKNiT
+7oReF36HTXjftRfGffYgPf/vEhrT7XLJ7dThkcb+OFYWYlOckdk3DRgqTNWQXsot
+UsZhwRveU8huEjOBO5+dwDiWPs+s9jSRAn5inlTqJ0YGAmdHRzAMBggqhkjOPQQD
+AwUAA2gAMGUCMQCuiJwmRWOgfWbqdSlnXfhCbphjdWc6sHelLkkM21vxQ3RZkhC2
+ERh90RA1rxB+XTgCMHZrYG3leS0PEoz5hUviv27LbBHBU6GeOzrS2e0VH0BMSNXN
+iP9Wnit+mJw58niEGw==
+-----END CERTIFICATE-----
+ </Certificate>
+ <Certificate format="pem">
+-----BEGIN CERTIFICATE-----
+MIIBWTCB3qADAgECAgUA3q2+7zAMBggqhkjOPQQDAwUAMBIxEDAOBgNVBAMMB0dT
+TUkxLjAwIhgPMjAyNDAxMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowEjEQMA4G
+A1UEAwwHR1NNSTEuMDB2MBAGByqGSM49AgEGBSuBBAAiA2IABFsNPdsPmx2NKNiT
+7oReF36HTXjftRfGffYgPf/vEhrT7XLJ7dThkcb+OFYWYlOckdk3DRgqTNWQXsot
+UsZhwRveU8huEjOBO5+dwDiWPs+s9jSRAn5inlTqJ0YGAmdHRzAMBggqhkjOPQQD
+AwUAA2gAMGUCMQCuiJwmRWOgfWbqdSlnXfhCbphjdWc6sHelLkkM21vxQ3RZkhC2
+ERh90RA1rxB+XTgCMHZrYG3leS0PEoz5hUviv27LbBHBU6GeOzrS2e0VH0BMSNXN
+iP9Wnit+mJw58niEGw==
+-----END CERTIFICATE-----
+ </Certificate>
+ </CertificateChain>
+</PixelUdsCertificates>
diff --git a/trusty/keymaster/set_uds_certs/set_uds_certificates.cpp b/trusty/keymaster/set_uds_certs/set_uds_certificates.cpp
new file mode 100644
index 0000000..13356a9
--- /dev/null
+++ b/trusty/keymaster/set_uds_certs/set_uds_certificates.cpp
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2020 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 <errno.h>
+#include <getopt.h>
+#include <libxml/xmlreader.h>
+#include <openssl/pem.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <string>
+
+#include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
+
+static const char* _sopts = "h";
+static const struct option _lopts[] = {
+ {"help", no_argument, 0, 'h'},
+ {0, 0, 0, 0},
+};
+
+static const char* usage =
+ "Usage: %s [options] xml-file\n"
+ "\n"
+ "options:\n"
+ " -h, --help prints this message and exit\n"
+ "\n";
+
+static void print_usage_and_exit(const char* prog, int code) {
+ fprintf(stderr, usage, prog);
+ exit(code);
+}
+
+static void parse_options(int argc, char** argv) {
+ int c;
+ int oidx = 0;
+
+ while (1) {
+ c = getopt_long(argc, argv, _sopts, _lopts, &oidx);
+ if (c == -1) {
+ break; /* done */
+ }
+
+ switch (c) {
+ case 'h':
+ print_usage_and_exit(argv[0], EXIT_SUCCESS);
+ break;
+
+ default:
+ print_usage_and_exit(argv[0], EXIT_FAILURE);
+ }
+ }
+}
+
+struct AppendUdsCertificateRequest : public keymaster::KeymasterMessage {
+ explicit AppendUdsCertificateRequest(int32_t ver = keymaster::kDefaultMessageVersion)
+ : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return cert_data.SerializedSize(); }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t* end) const override {
+ return cert_data.Serialize(buf, end);
+ }
+ bool Deserialize(const uint8_t** buf_ptr, const uint8_t* end) override {
+ return cert_data.Deserialize(buf_ptr, end);
+ }
+
+ keymaster::Buffer cert_data;
+};
+
+struct ClearUdsCertificateRequest : public keymaster::KeymasterMessage {
+ explicit ClearUdsCertificateRequest(int32_t ver = keymaster::kDefaultMessageVersion)
+ : KeymasterMessage(ver) {}
+
+ size_t SerializedSize() const override { return 0; }
+ uint8_t* Serialize(uint8_t* buf, const uint8_t*) const override { return buf; }
+ bool Deserialize(const uint8_t**, const uint8_t*) override { return true; };
+};
+
+struct KeymasterNoResponse : public keymaster::KeymasterResponse{
+ explicit KeymasterNoResponse(int32_t ver = keymaster::kDefaultMessageVersion)
+ : keymaster::KeymasterResponse(ver) {}
+
+ size_t NonErrorSerializedSize() const override { return 0; }
+ uint8_t* NonErrorSerialize(uint8_t* buf, const uint8_t*) const override { return buf; }
+ bool NonErrorDeserialize(const uint8_t**, const uint8_t*) override { return true; }
+};
+
+struct AppendUdsCertificateResponse : public KeymasterNoResponse {};
+struct ClearUdsCertificateResponse : public KeymasterNoResponse {};
+
+static int set_uds_cert_bin(uint32_t cmd, const void* cert_data, size_t cert_data_size) {
+ int ret;
+
+ AppendUdsCertificateRequest req;
+ req.cert_data.Reinitialize(cert_data, cert_data_size);
+ AppendUdsCertificateResponse rsp;
+
+ ret = trusty_keymaster_send(cmd, req, &rsp);
+ if (ret) {
+ fprintf(stderr, "trusty_keymaster_send cmd 0x%x failed %d\n", cmd, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int set_uds_cert_pem(uint32_t cmd, const xmlChar* pemkey) {
+ int ret;
+ int sslret;
+
+ /* Convert from pem to binary */
+ BIO* bio = BIO_new_mem_buf(pemkey, xmlStrlen(pemkey));
+ if (!bio) {
+ fprintf(stderr, "BIO_new_mem_buf failed\n");
+ ERR_print_errors_fp(stderr);
+ return -1;
+ }
+
+ char* key_name;
+ char* key_header;
+ uint8_t* key;
+ long keylen;
+ sslret = PEM_read_bio(bio, &key_name, &key_header, &key, &keylen);
+ BIO_free(bio);
+
+ if (!sslret) {
+ fprintf(stderr, "PEM_read_bio failed\n");
+ ERR_print_errors_fp(stderr);
+ return -1;
+ }
+
+ /* Send key in binary format to trusty */
+ ret = set_uds_cert_bin(cmd, key, keylen);
+
+ OPENSSL_free(key_name);
+ OPENSSL_free(key_header);
+ OPENSSL_free(key);
+
+ return ret;
+}
+
+static int set_uds_cert(uint32_t cmd, const xmlChar* format, const xmlChar* str) {
+ int ret;
+
+ if (xmlStrEqual(format, BAD_CAST "pem")) {
+ ret = set_uds_cert_pem(cmd, str);
+ } else {
+ printf("unsupported key/cert format: %s\n", format);
+ return -1;
+ }
+ return ret;
+}
+
+// TODO: Guard by Production Mode
+static int clear_cert_chain() {
+ int ret;
+ ClearUdsCertificateRequest req;
+ ClearUdsCertificateResponse rsp;
+
+ ret = trusty_keymaster_send(KM_CLEAR_UDS_CERT_CHAIN, req, &rsp);
+ if (ret) {
+ fprintf(stderr, "%s: trusty_keymaster_send failed %d\n", __func__, ret);
+ return ret;
+ }
+ return 0;
+}
+
+static int process_xml(xmlTextReaderPtr xml) {
+ int ret;
+ const xmlChar* element = NULL;
+ const xmlChar* element_format = NULL;
+ bool isPixelUdsCert = false;
+
+ while ((ret = xmlTextReaderRead(xml)) == 1) {
+ int nodetype = xmlTextReaderNodeType(xml);
+ const xmlChar *name, *value;
+ name = xmlTextReaderConstName(xml);
+ switch (nodetype) {
+ case XML_READER_TYPE_ELEMENT:
+ element = name;
+ element_format = xmlTextReaderGetAttribute(xml, BAD_CAST "format");
+ if (isPixelUdsCert || xmlStrEqual(name, BAD_CAST "PixelUdsCertificates")) {
+ // The first element name must be "PixelUdsCertificates"
+ isPixelUdsCert = true;
+ } else {
+ fprintf(stderr, "Not a PixelUdsCertificates: \"%s\"\n", name);
+ return -1;
+ }
+ if (xmlStrEqual(name, BAD_CAST "CertificateChain")) {
+ ret = clear_cert_chain();
+ if (ret) {
+ fprintf(stderr, "%s: Clear cert chain cmd failed, %d\n", element, ret);
+ return ret;
+ }
+ printf("%s: Clear cert chain cmd done\n", element);
+ }
+ break;
+ case XML_READER_TYPE_TEXT:
+ value = xmlTextReaderConstValue(xml);
+ uint32_t cmd;
+ if (xmlStrEqual(element, BAD_CAST "Certificate")) {
+ cmd = KM_APPEND_UDS_CERT_CHAIN;
+ } else {
+ break;
+ }
+
+ ret = set_uds_cert(cmd, element_format, value);
+ if (ret) {
+ fprintf(stderr, "%s, format %s: Cmd 0x%x failed, %d\n", element, element_format,
+ cmd, ret);
+ return ret;
+ }
+ printf("%s, format %s: Cmd 0x%x done\n", element, element_format, cmd);
+ break;
+ case XML_READER_TYPE_END_ELEMENT:
+ element = NULL;
+ break;
+ }
+ }
+ return ret;
+}
+
+static int parse_and_provision_xml_file(const char* filename) {
+ int ret;
+ xmlTextReaderPtr xml = xmlReaderForFile(filename, NULL, 0);
+ if (!xml) {
+ fprintf(stderr, "failed to open %s\n", filename);
+ return -1;
+ }
+
+ ret = process_xml(xml);
+
+ xmlFreeTextReader(xml);
+ if (ret != 0) {
+ fprintf(stderr, "Failed to parse or process %s\n", filename);
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char** argv) {
+ int ret = 0;
+
+ parse_options(argc, argv);
+ if (optind + 1 != argc) {
+ print_usage_and_exit(argv[0], EXIT_FAILURE);
+ }
+
+ ret = trusty_keymaster_connect();
+ if (ret) {
+ fprintf(stderr, "trusty_keymaster_connect failed %d\n", ret);
+ return EXIT_FAILURE;
+ }
+
+ ret = parse_and_provision_xml_file(argv[optind]);
+ if (ret) {
+ fprintf(stderr, "parse_and_provision_xml_file failed %d\n", ret);
+ trusty_keymaster_disconnect();
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c
index 6d0c616..ca39f6a 100644
--- a/trusty/storage/proxy/storage.c
+++ b/trusty/storage/proxy/storage.c
@@ -55,7 +55,7 @@
static struct storage_mapping_node* storage_mapping_head;
/*
- * Property set to 1 after we have opened a file under ssdir_name. The backing
+ * Properties set to 1 after we have opened a file under ssdir_name. The backing
* files for both TD and TDP are currently located under /data/vendor/ss and can
* only be opened once userdata is mounted. This storageproxyd service is
* restarted when userdata is available, which causes the Trusty storage service
@@ -64,11 +64,16 @@
* ports will be available (although they may block if still being initialized),
* and connections will not be reset after this point (assuming the
* storageproxyd service stays running).
+ *
+ * fs_ready - secure storage is read-only (due to checkpointing after upgrade)
+ * fs_ready_rw - secure storage is readable and writable
*/
#define FS_READY_PROPERTY "ro.vendor.trusty.storage.fs_ready"
+#define FS_READY_RW_PROPERTY "ro.vendor.trusty.storage.fs_ready_rw"
/* has FS_READY_PROPERTY been set? */
-static bool fs_ready_initialized = false;
+static bool fs_ready_set = false;
+static bool fs_ready_rw_set = false;
static enum sync_state fs_state;
static enum sync_state fd_state[FD_TBL_SIZE];
@@ -80,6 +85,17 @@
uint8_t data[MAX_READ_SIZE];
} read_rsp;
+static bool property_set_helper(const char* prop) {
+ int rc = property_set(prop, "1");
+ if (rc == 0) {
+ ALOGI("Set property %s\n", prop);
+ } else {
+ ALOGE("Could not set property %s, rc: %d\n", prop, rc);
+ }
+
+ return rc == 0;
+}
+
static uint32_t insert_fd(int open_flags, int fd, struct storage_mapping_node* node) {
uint32_t handle = fd;
@@ -520,12 +536,20 @@
path = NULL;
/* a backing file has been opened, notify any waiting init steps */
- if (!fs_ready_initialized) {
- rc = property_set(FS_READY_PROPERTY, "1");
- if (rc == 0) {
- fs_ready_initialized = true;
+ if (!fs_ready_set || !fs_ready_rw_set) {
+ bool is_checkpoint_active = false;
+
+ rc = is_data_checkpoint_active(&is_checkpoint_active);
+ if (rc != 0) {
+ ALOGE("is_data_checkpoint_active() failed (%d)\n", rc);
} else {
- ALOGE("Could not set property %s, rc: %d\n", FS_READY_PROPERTY, rc);
+ if (!fs_ready_rw_set && !is_checkpoint_active) {
+ fs_ready_rw_set = property_set_helper(FS_READY_RW_PROPERTY);
+ }
+
+ if (!fs_ready_set) {
+ fs_ready_set = property_set_helper(FS_READY_PROPERTY);
+ }
}
}