summaryrefslogtreecommitdiffstats
path: root/fastboot/fastboot.cpp
diff options
context:
space:
mode:
authorDavid Anderson <dvander@google.com>2018-11-16 15:53:35 -0800
committerDavid Anderson <dvander@google.com>2018-11-20 12:10:16 -0800
commit8956964ee2f211ea7792832582b8c0d139260cb0 (patch)
tree26100530302eef9c7d2426add5fe005d787f7c43 /fastboot/fastboot.cpp
parenta3c47e63a659515d457e1a0509171b586a236e44 (diff)
downloadsystem_core-8956964ee2f211ea7792832582b8c0d139260cb0.tar.gz
system_core-8956964ee2f211ea7792832582b8c0d139260cb0.tar.bz2
system_core-8956964ee2f211ea7792832582b8c0d139260cb0.zip
fastboot: Warn when flashing dynamic partitions in the bootloader.
On retrofit devices, it is easy to accidentally overwrite system/vendor/product by flashing system in the bootloader. The reason is that GPT system_a is really the super partition, and the bootloader doesn't know it. Addressing this in bootloaders would require two separate commands: one that rejects flashing system/vendor/product, and another for expert/factory use that would allow direct flashing. This patch introduces protection into the host fastboot tool instead. It's not mutually exclusive with bootloader changes; having protection in the host tool affords us better and consistent UI. However it does rely on users having newer builds. With this change, the following will not work in the bootloader: fastboot flash system # or vendor, product, etc The message is the same whether or not the device is a retrofit. To continue anyway, you can do: fastboot flash --force system If we decide on bootloader protection as well, the --force flag can be re-used. Bug: 119689480 Test: fastboot flash system # disallowed in bootloader, allowed in fastbootd fastboot flash --force system # allowed in bootloader Change-Id: I0861e3f28a15be925886d5c30c7ebd4b20c477cf
Diffstat (limited to 'fastboot/fastboot.cpp')
-rw-r--r--fastboot/fastboot.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 3e090d7a5..e066bfff7 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -58,6 +58,7 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <build/version.h>
+#include <liblp/liblp.h>
#include <platform_tools_version.h>
#include <sparse/sparse.h>
#include <ziparchive/zip_archive.h>
@@ -407,6 +408,7 @@ static int show_help() {
" -s SERIAL Specify a USB device.\n"
" -s tcp|udp:HOST[:PORT] Specify a network device.\n"
" -S SIZE[K|M|G] Break into sparse files no larger than SIZE.\n"
+ " --force Force a flash operation that may be unsafe.\n"
" --slot SLOT Use SLOT; 'all' for both slots, 'other' for\n"
" non-current slot (default: current active slot).\n"
" --set-active[=SLOT] Sets the active slot before rebooting.\n"
@@ -1505,6 +1507,31 @@ failed:
fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str());
}
+static bool should_flash_in_userspace(const std::string& partition_name) {
+ auto path = find_item_given_name("super_empty.img");
+ if (path.empty()) {
+ return false;
+ }
+ auto metadata = android::fs_mgr::ReadFromImageFile(path);
+ if (!metadata) {
+ return false;
+ }
+ for (const auto& partition : metadata->partitions) {
+ auto candidate = android::fs_mgr::GetPartitionName(partition);
+ if (partition.attributes & LP_PARTITION_ATTR_SLOT_SUFFIXED) {
+ // On retrofit devices, we don't know if, or whether, the A or B
+ // slot has been flashed for dynamic partitions. Instead we add
+ // both names to the list as a conservative guess.
+ if (candidate + "_a" == partition_name || candidate + "_b" == partition_name) {
+ return true;
+ }
+ } else if (candidate == partition_name) {
+ return true;
+ }
+ }
+ return false;
+}
+
int FastBootTool::Main(int argc, char* argv[]) {
bool wants_wipe = false;
bool wants_reboot = false;
@@ -1515,6 +1542,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
bool wants_set_active = false;
bool skip_secondary = false;
bool set_fbe_marker = false;
+ bool force_flash = false;
int longindex;
std::string slot_override;
std::string next_active;
@@ -1530,6 +1558,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
{"cmdline", required_argument, 0, 0},
{"disable-verification", no_argument, 0, 0},
{"disable-verity", no_argument, 0, 0},
+ {"force", no_argument, 0, 0},
{"header-version", required_argument, 0, 0},
{"help", no_argument, 0, 'h'},
{"kernel-offset", required_argument, 0, 0},
@@ -1565,6 +1594,8 @@ int FastBootTool::Main(int argc, char* argv[]) {
g_disable_verification = true;
} else if (name == "disable-verity") {
g_disable_verity = true;
+ } else if (name == "force") {
+ force_flash = true;
} else if (name == "header-version") {
g_boot_img_hdr.header_version = strtoul(optarg, nullptr, 0);
} else if (name == "kernel-offset") {
@@ -1779,6 +1810,16 @@ int FastBootTool::Main(int argc, char* argv[]) {
if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
auto flash = [&](const std::string &partition) {
+ if (should_flash_in_userspace(partition) && !is_userspace_fastboot() &&
+ !force_flash) {
+ die("The partition you are trying to flash is dynamic, and "
+ "should be flashed via fastbootd. Please run:\n"
+ "\n"
+ " fastboot reboot fastboot\n"
+ "\n"
+ "And try again. If you are intentionally trying to "
+ "overwrite a fixed partition, use --force.");
+ }
do_flash(partition.c_str(), fname.c_str());
};
do_for_partitions(pname.c_str(), slot_override, flash, true);