fastboot driver: add fetch command in driver

The `fastboot fetch` command is a wrapper around
the fetch protocol. It:

- getvar max-fetch-size
- get the size of the partition
- read the data by chunks, chunk size = max-fetch-size.

The name of the partition is passed directly to the device
(with the usual has-slot magic for flashing etc.) If we support
fetching partitions other than vendor_boot in the future, no change
in the driver is needed.

Bug: 173654501
Test: manual

Change-Id: Ie576eea668234df236b096a372e65c5e91c1e48c
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index cf70635..b72f3fe 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -712,13 +712,20 @@
     // If successfully opened, ret_ is left untouched. Otherwise, ret_ is set to the value
     // that FetchHandler should return.
     bool Open() {
-        partition_name_ = args_->at(1);
-        if (partition_name_ != "vendor_boot") {
-            ret_ = device_->WriteFail("Fetch is only allowed on vendor_boot");
+        if (args_->size() < 2) {
+            ret_ = device_->WriteFail("Missing partition arg");
             return false;
         }
 
-        if (!OpenPartition(device_, partition_name_, &handle_)) {
+        partition_name_ = args_->at(1);
+        if (std::find(kAllowedPartitions.begin(), kAllowedPartitions.end(), partition_name_) ==
+            kAllowedPartitions.end()) {
+            ret_ = device_->WriteFail("Fetch is only allowed on [" +
+                                      android::base::Join(kAllowedPartitions, ", ") + "]");
+            return false;
+        }
+
+        if (!OpenPartition(device_, partition_name_, &handle_, true /* read */)) {
             ret_ = device_->WriteFail(
                     android::base::StringPrintf("Cannot open %s", partition_name_.c_str()));
             return false;
@@ -826,6 +833,12 @@
                 start_offset_, total_size_to_read_));
     }
 
+    static constexpr std::array<const char*, 3> kAllowedPartitions{
+            "vendor_boot",
+            "vendor_boot_a",
+            "vendor_boot_b",
+    };
+
     FastbootDevice* device_;
     const std::vector<std::string>* args_ = nullptr;
     std::string partition_name_;