summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYo Chiang <yochiang@google.com>2020-11-04 05:21:02 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-11-04 05:21:02 +0000
commit88aea73ed64163e0a099c94372be0c18db9a9b4a (patch)
tree5bbee05b278bde5feb0345b77c2c9764c65b2e1e
parent0c7782468fdc140087d38f7a3ec8272cf7667d01 (diff)
parent62f1f1894d5426ac6164c051efb816c6ef53fc46 (diff)
downloadgsid-88aea73ed64163e0a099c94372be0c18db9a9b4a.tar.gz
Merge "Add "create-partition" debugging API to gsi_tool" am: 802d4c6a7b am: 0b094013ed am: 74198d437c am: 62f1f1894d
Original change: https://android-review.googlesource.com/c/platform/system/gsid/+/1469543 Change-Id: I3b64c0c6032c90d9806b6bd0820caaf235dfd4cf
-rw-r--r--gsi_tool.cpp124
1 files changed, 124 insertions, 0 deletions
diff --git a/gsi_tool.cpp b/gsi_tool.cpp
index 8839246..56d6de1 100644
--- a/gsi_tool.cpp
+++ b/gsi_tool.cpp
@@ -50,6 +50,7 @@ using CommandCallback = std::function<int(sp<IGsiService>, int, char**)>;
static int Disable(sp<IGsiService> gsid, int argc, char** argv);
static int Enable(sp<IGsiService> gsid, int argc, char** argv);
static int Install(sp<IGsiService> gsid, int argc, char** argv);
+static int CreatePartition(sp<IGsiService> gsid, int argc, char** argv);
static int Wipe(sp<IGsiService> gsid, int argc, char** argv);
static int WipeData(sp<IGsiService> gsid, int argc, char** argv);
static int Status(sp<IGsiService> gsid, int argc, char** argv);
@@ -60,6 +61,7 @@ static const std::map<std::string, CommandCallback> kCommandMap = {
{"disable", Disable},
{"enable", Enable},
{"install", Install},
+ {"create-partition", CreatePartition},
{"wipe", Wipe},
{"wipe-data", WipeData},
{"status", Status},
@@ -322,6 +324,128 @@ static int Install(sp<IGsiService> gsid, int argc, char** argv) {
return 0;
}
+// Experimental API
+static int CreatePartition(sp<IGsiService> gsid, int argc, char** argv) {
+ std::string installDir;
+ std::string partitionName;
+ bool readOnly = true;
+ int64_t partitionSize = 0;
+
+ struct option options[] = {
+ {"install-dir", required_argument, nullptr, 'i'},
+ {"partition-name", required_argument, nullptr, 'p'},
+ {"readwrite", no_argument, nullptr, 'r'},
+ {"size", required_argument, nullptr, 's'},
+ {nullptr, 0, nullptr, 0},
+ };
+
+ int rv = 0;
+ while ((rv = getopt_long_only(argc, argv, "", options, nullptr)) != -1) {
+ switch (rv) {
+ case 'i':
+ installDir = optarg;
+ break;
+ case 'p':
+ partitionName = optarg;
+ break;
+ case 'r':
+ readOnly = false;
+ break;
+ case 's':
+ if (!android::base::ParseInt(optarg, &partitionSize)) {
+ std::cerr << "Could not parse partition size: " << optarg << std::endl;
+ return EX_USAGE;
+ }
+ break;
+ default:
+ return EX_USAGE;
+ }
+ }
+
+ if (getuid() != 0) {
+ std::cerr << "must be root to install a DSU" << std::endl;
+ return EX_NOPERM;
+ }
+
+ bool gsiRunning = false;
+ auto status = gsid->isGsiRunning(&gsiRunning);
+ if (!status.isOk()) {
+ std::cerr << "Could not get DSU running status: " << ErrorMessage(status) << std::endl;
+ return EX_SOFTWARE;
+ }
+ if (gsiRunning) {
+ std::cerr << "Could not install DSU within an active DSU." << std::endl;
+ return EX_SOFTWARE;
+ }
+
+ if (partitionSize <= 0) {
+ std::cerr << "Partition size must be greater than zero: " << partitionSize << std::endl;
+ return EX_USAGE;
+ }
+
+ // Note: the progress bar needs to be re-started in between each call.
+ ProgressBar progress(gsid);
+ progress.Display();
+
+ int error;
+ status = gsid->openInstall(installDir, &error);
+ if (!status.isOk() || error != IGsiService::INSTALL_OK) {
+ std::cerr << "Could not open DSU installation: " << ErrorMessage(status, error)
+ << std::endl;
+ return EX_SOFTWARE;
+ }
+
+ status = gsid->createPartition(partitionName, partitionSize, readOnly, &error);
+ if (!status.isOk() || error != IGsiService::INSTALL_OK) {
+ std::cerr << "Could not create DSU partition: " << ErrorMessage(status, error) << std::endl;
+ return EX_SOFTWARE;
+ }
+
+ if (readOnly) {
+ android::base::unique_fd input(dup(STDIN_FILENO));
+ if (input < 0) {
+ std::cerr << "Error duplicating descriptor: " << strerror(errno) << std::endl;
+ return EX_SOFTWARE;
+ }
+ android::os::ParcelFileDescriptor stream(std::move(input));
+
+ bool ok = false;
+ status = gsid->commitGsiChunkFromStream(stream, partitionSize, &ok);
+ if (!ok) {
+ std::cerr << "Could not commit data from stdin: " << ErrorMessage(status) << std::endl;
+ return EX_SOFTWARE;
+ }
+ }
+
+ status = gsid->closeInstall(&error);
+ if (!status.isOk() || error != IGsiService::INSTALL_OK) {
+ std::cerr << "Could not close DSU installation: " << ErrorMessage(status, error)
+ << std::endl;
+ return EX_SOFTWARE;
+ }
+
+ progress.Finish();
+
+ std::string dsuSlot;
+ status = gsid->getActiveDsuSlot(&dsuSlot);
+ if (!status.isOk()) {
+ std::cerr << "Could not get the active DSU slot: " << ErrorMessage(status) << std::endl;
+ return EX_SOFTWARE;
+ }
+
+ // Immediately enable DSU after a partition is installed to ensure the installation status file
+ // is created.
+ status = gsid->enableGsi(/* one_shot = */ true, dsuSlot, &error);
+ if (!status.isOk() || error != IGsiService::INSTALL_OK) {
+ std::cerr << "Could not make DSU bootable: " << ErrorMessage(status, error) << std::endl;
+ return EX_SOFTWARE;
+ }
+
+ std::cout << "Enabled DSU slot: " << dsuSlot << std::endl;
+ std::cout << "Please reboot to use the DSU." << std::endl;
+ return 0;
+}
+
static int Wipe(sp<IGsiService> gsid, int argc, char** /* argv */) {
if (argc > 1) {
std::cerr << "Unrecognized arguments to wipe." << std::endl;