Parse BCB command to enter rescue mode.

bootloader will set `boot-rescue` in BCB command field to indicate
booting into rescue mode. This CL adds the matching parsing code.

This CL changes the on-screen UI to display the default image while
waiting for each sideload / rescue command.

It also changes the minadbd reboot handlers to use REBOOT_ instead of
the previous ENTER_ actions. This ensures a reboot going through
bootloader, which may load a newly installed bootloader/recovery.

Bug: 128505466
Test: Boot into rescue mode. Run `adb rescue getprop` and `adb rescue
      install`. Check the UI. Then run `adb reboot rescue`.
Change-Id: I5b7de9dfd898ed8e14bea0d4ad7385a9bae26e94
diff --git a/recovery_main.cpp b/recovery_main.cpp
index 0eb2962..6e69b70 100644
--- a/recovery_main.cpp
+++ b/recovery_main.cpp
@@ -155,9 +155,11 @@
   }
 
   // Finally, if no arguments were specified, check whether we should boot
-  // into fastboot.
+  // into fastboot or rescue mode.
   if (args.size() == 1 && boot_command == "boot-fastboot") {
     args.emplace_back("--fastboot");
+  } else if (args.size() == 1 && boot_command == "boot-rescue") {
+    args.emplace_back("--rescue");
   }
 
   return args;
@@ -469,6 +471,7 @@
     switch (ret) {
       case Device::SHUTDOWN:
         ui->Print("Shutting down...\n");
+        // TODO: Move all the reboots to reboot(), which should conditionally set quiescent flag.
         android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,");
         break;
 
@@ -477,11 +480,32 @@
         android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
         break;
 
-      case Device::REBOOT_RESCUE:
-        ui->Print("Rebooting to rescue...\n");
-        android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,rescue");
+      case Device::REBOOT_FASTBOOT:
+        ui->Print("Rebooting to recovery/fastboot...\n");
+        android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot");
         break;
 
+      case Device::REBOOT_RECOVERY:
+        ui->Print("Rebooting to recovery...\n");
+        reboot("reboot,recovery");
+        break;
+
+      case Device::REBOOT_RESCUE: {
+        // Not using `reboot("reboot,rescue")`, as it requires matching support in kernel and/or
+        // bootloader.
+        bootloader_message boot = {};
+        strlcpy(boot.command, "boot-rescue", sizeof(boot.command));
+        std::string err;
+        if (!write_bootloader_message(boot, &err)) {
+          LOG(ERROR) << "Failed to write bootloader message: " << err;
+          // Stay under recovery on failure.
+          continue;
+        }
+        ui->Print("Rebooting to recovery/rescue...\n");
+        reboot("reboot,recovery");
+        break;
+      }
+
       case Device::ENTER_FASTBOOT:
         if (logical_partitions_mapped()) {
           ui->Print("Partitions may be mounted - rebooting to enter fastboot.");