diff options
author | Yo Chiang <yochiang@google.com> | 2020-11-04 03:46:39 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-11-04 03:46:39 +0000 |
commit | 0b094013edc9634a9d496fc00314a0ccffb819e6 (patch) | |
tree | 5bbee05b278bde5feb0345b77c2c9764c65b2e1e | |
parent | b465fe24cdc5c1fcfb69c49d8f0e2700c9657bae (diff) | |
parent | 802d4c6a7b5d2aa60e1c38716d10d50b260a6dd7 (diff) | |
download | gsid-0b094013edc9634a9d496fc00314a0ccffb819e6.tar.gz |
Merge "Add "create-partition" debugging API to gsi_tool" am: 802d4c6a7b
Original change: https://android-review.googlesource.com/c/platform/system/gsid/+/1469543
Change-Id: I6e505d7ae4d9eb2db28902b1e7dd679c4e5fc5e4
-rw-r--r-- | gsi_tool.cpp | 124 |
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; |