Merge "fastboot: Warn when flashing dynamic partitions in the bootloader." am: 8771a95e4c
am: 1904e1eea1

Change-Id: I16887d849621fcc35e93e0e0df1ce03fe446c843
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index 50d18ed..faed376 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -43,6 +43,7 @@
         "libgtest_main",
         "libbase",
         "libadb_host",
+        "liblp",
     ],
 
     header_libs: [
@@ -173,6 +174,11 @@
 
             host_ldlibs: ["-lws2_32"],
         },
+        not_windows: {
+            static_libs: [
+                "libext4_utils",
+            ],
+        },
     },
 
     stl: "libc++_static",
@@ -193,6 +199,8 @@
         "libbase",
         "libcutils",
         "libgtest_host",
+        "liblp",
+        "libcrypto",
     ],
 }
 
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 3e090d7..e066bff 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 @@
             " -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 @@
     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 @@
     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 @@
         {"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 @@
                 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 @@
             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);
diff --git a/fastboot/fuzzy_fastboot/Android.bp b/fastboot/fuzzy_fastboot/Android.bp
index 301534b..277cc3a 100644
--- a/fastboot/fuzzy_fastboot/Android.bp
+++ b/fastboot/fuzzy_fastboot/Android.bp
@@ -26,6 +26,9 @@
     "libadb_host",
     "libtinyxml2",
     "libsparse",
+    "liblp",
+    "libcrypto",
+    "libext4_utils",
   ],
 
   // Static libs (libfastboot2) shared library dependencies are not transitively included
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index cae93e8..5a498f9 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -67,10 +67,10 @@
     return ParseMetadata(geometry, metadata_buffer, metadata_buffer_size);
 }
 
-std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file) {
-    unique_fd fd(open(file, O_RDONLY | O_CLOEXEC));
+std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file) {
+    unique_fd fd(open(image_file.c_str(), O_RDONLY | O_CLOEXEC));
     if (fd < 0) {
-        PERROR << __PRETTY_FUNCTION__ << " open failed: " << file;
+        PERROR << __PRETTY_FUNCTION__ << " open failed: " << image_file;
         return nullptr;
     }
     return ReadFromImageFile(fd);
diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h
index 1af1e80..6348f55 100644
--- a/fs_mgr/liblp/include/liblp/liblp.h
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -75,7 +75,7 @@
 bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size,
                        const std::map<std::string, std::string>& images);
 bool WriteToImageFile(const char* file, const LpMetadata& metadata);
-std::unique_ptr<LpMetadata> ReadFromImageFile(const char* file);
+std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file);
 std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes);
 
 // Similar to WriteToSparseFile, this will generate an image that can be