[paver] Correct current slot name checking

Also ensure we don't accidently send "set unbootable" command for
recovery partition in netsvc.

Also remove SetActiveConfigurationHealthy call from netsvc as has health
check has landed.

BUG: 37818
BUG: 22860

TESTED: runtests -t paver-test
TESTED: runtests -t netsvc-test

Change-Id: I8d70d32cbc3b3ee95a060d24d6af6afde4583e7f
diff --git a/zircon/system/core/netsvc/paver.cc b/zircon/system/core/netsvc/paver.cc
index 531b218..1b27adc 100644
--- a/zircon/system/core/netsvc/paver.cc
+++ b/zircon/system/core/netsvc/paver.cc
@@ -179,7 +179,7 @@
     }
   }
   // Make sure to mark the configuration we are about to pave as no longer bootable.
-  if (abr_supported) {
+  if (abr_supported && configuration_ != ::llcpp::fuchsia::paver::Configuration::RECOVERY) {
     auto result = paver_svc_->SetConfigurationUnbootable(configuration_);
     auto status = result.ok() ? result->status : result.status();
     if (status != ZX_OK) {
@@ -209,16 +209,6 @@
       return status;
     }
   }
-  // TODO(22860): Set configuration A as healthy until system_updater starts doing this on
-  // boot correctly.
-  {
-    auto result = paver_svc_->SetActiveConfigurationHealthy();
-    auto status = result.ok() ? result->status : result.status();
-    if (status != ZX_OK) {
-      fprintf(stderr, "netsvc: Unable to set configuration as healthy.\n");
-      return status;
-    }
-  }
   return ClearSysconfig(devfs_root_);
 }
 
diff --git a/zircon/system/core/netsvc/test/paver-test.cc b/zircon/system/core/netsvc/test/paver-test.cc
index d67ec52..a147d14 100644
--- a/zircon/system/core/netsvc/test/paver-test.cc
+++ b/zircon/system/core/netsvc/test/paver-test.cc
@@ -105,13 +105,29 @@
   void SetConfigurationActive(::llcpp::fuchsia::paver::Configuration configuration,
                               SetConfigurationActiveCompleter::Sync completer) {
     last_command_ = Command::kSetConfigurationActive;
-    completer.Reply(abr_supported_ && abr_initialized_ ? ZX_OK : ZX_ERR_NOT_SUPPORTED);
+    zx_status_t status = ZX_ERR_NOT_SUPPORTED;
+    if (abr_supported_ && abr_initialized_) {
+      if (configuration == ::llcpp::fuchsia::paver::Configuration::A) {
+        status = ZX_OK;
+      } else {
+        status = ZX_ERR_INVALID_ARGS;
+      }
+    }
+    completer.Reply(status);
   }
 
   void SetConfigurationUnbootable(::llcpp::fuchsia::paver::Configuration configuration,
                                    SetConfigurationUnbootableCompleter::Sync completer) {
     last_command_ = Command::kSetConfigurationUnbootable;
-    completer.Reply(abr_supported_ && abr_initialized_ ? ZX_OK : ZX_ERR_NOT_SUPPORTED);
+    zx_status_t status = ZX_ERR_NOT_SUPPORTED;
+    if (abr_supported_ && abr_initialized_) {
+      if (configuration == ::llcpp::fuchsia::paver::Configuration::RECOVERY) {
+        status = ZX_ERR_INVALID_ARGS;
+      } else {
+        status = ZX_OK;
+      }
+    }
+    completer.Reply(status);
   }
 
   void SetActiveConfigurationHealthy(
@@ -444,6 +460,19 @@
   ASSERT_EQ(fake_svc_.fake_paver().last_command(), Command::kWriteAsset);
 }
 
+TEST_F(PaverTest, WriteZirconRWithABRSupported) {
+  size_t size = sizeof(kFakeData);
+  fake_svc_.fake_paver().set_abr_supported(true);
+  fake_svc_.fake_paver().set_expected_payload_size(size);
+  ASSERT_EQ(paver_.OpenWrite(NB_ZIRCONR_FILENAME, size), TFTP_NO_ERROR);
+  ASSERT_EQ(paver_.Write(kFakeData, &size, 0), TFTP_NO_ERROR);
+  ASSERT_EQ(size, sizeof(kFakeData));
+  paver_.Close();
+  Wait();
+  ASSERT_OK(paver_.exit_code());
+  ASSERT_EQ(fake_svc_.fake_paver().last_command(), Command::kWriteAsset);
+}
+
 TEST_F(PaverTest, WriteVbMetaAWithABRSupported) {
   size_t size = sizeof(kFakeData);
   fake_svc_.fake_paver().set_abr_supported(true);
@@ -454,7 +483,7 @@
   paver_.Close();
   Wait();
   ASSERT_OK(paver_.exit_code());
-  ASSERT_EQ(fake_svc_.fake_paver().last_command(), Command::kSetActiveConfigurationHealthy);
+  ASSERT_EQ(fake_svc_.fake_paver().last_command(), Command::kSetConfigurationActive);
 }
 
 TEST_F(PaverTest, WriteVbMetaBWithABRSupported) {
@@ -470,6 +499,19 @@
   ASSERT_EQ(fake_svc_.fake_paver().last_command(), Command::kWriteAsset);
 }
 
+TEST_F(PaverTest, WriteVbMetaRWithABRSupported) {
+  size_t size = sizeof(kFakeData);
+  fake_svc_.fake_paver().set_abr_supported(true);
+  fake_svc_.fake_paver().set_expected_payload_size(size);
+  ASSERT_EQ(paver_.OpenWrite(NB_VBMETAR_FILENAME, size), TFTP_NO_ERROR);
+  ASSERT_EQ(paver_.Write(kFakeData, &size, 0), TFTP_NO_ERROR);
+  ASSERT_EQ(size, sizeof(kFakeData));
+  paver_.Close();
+  Wait();
+  ASSERT_OK(paver_.exit_code());
+  ASSERT_EQ(fake_svc_.fake_paver().last_command(), Command::kWriteAsset);
+}
+
 TEST_F(PaverTest, WriteZirconAWithABRSupportedTwice) {
   size_t size = sizeof(kFakeData);
   fake_svc_.fake_paver().set_abr_supported(true);
diff --git a/zircon/system/ulib/paver/device-partitioner.cc b/zircon/system/ulib/paver/device-partitioner.cc
index e6ae2f2..8d3ef02 100644
--- a/zircon/system/ulib/paver/device-partitioner.cc
+++ b/zircon/system/ulib/paver/device-partitioner.cc
@@ -1342,10 +1342,12 @@
     return ZX_ERR_NOT_SUPPORTED;
   }
 
-  if (slot->compare("_a") == 0) {
+  if (slot->compare("-a") == 0) {
     *boot_config_ = Configuration::A;
-  } else if (slot->compare("_b") == 0) {
+  } else if (slot->compare("-b") == 0) {
     *boot_config_ = Configuration::B;
+  } else if (slot->compare("-r") == 0) {
+    *boot_config_ = Configuration::RECOVERY;
   } else {
     ERROR("Invalid value `%.*s` found in zvb.current_slot!\n", static_cast<int>(slot->size()),
           slot->data());
diff --git a/zircon/system/ulib/paver/paver.cc b/zircon/system/ulib/paver/paver.cc
index 8a02684..739cbe0 100644
--- a/zircon/system/ulib/paver/paver.cc
+++ b/zircon/system/ulib/paver/paver.cc
@@ -714,7 +714,7 @@
     response.configuration = *config;
     result.set_response(response);
   } else {
-    result.set_err(ZX_ERR_BAD_STATE);
+    result.set_err(ZX_ERR_NOT_SUPPORTED);
   }
   completer.Reply(std::move(result));
 }
diff --git a/zircon/system/ulib/paver/test/paversvc-test.cc b/zircon/system/ulib/paver/test/paversvc-test.cc
index 655439c..864ef68 100644
--- a/zircon/system/ulib/paver/test/paversvc-test.cc
+++ b/zircon/system/ulib/paver/test/paversvc-test.cc
@@ -143,7 +143,7 @@
   }
 
  private:
-  static constexpr char kArgs[] = "zvb.current_slot=_a";
+  static constexpr char kArgs[] = "zvb.current_slot=-a";
 };
 
 class FakeSvc {
@@ -374,6 +374,19 @@
   ASSERT_STATUS(result->result.err(), ZX_ERR_NOT_SUPPORTED);
 }
 
+TEST_F(PaverServiceSkipBlockTest, QueryActiveConfigurationBothPriority0) {
+  abr::Data abr_data = kAbrData;
+  abr_data.slots[0].priority = 0;
+  abr_data.slots[1].priority = 0;
+  ComputeCrc(&abr_data);
+  SetAbr(abr_data);
+
+  auto result = client_->QueryActiveConfiguration();
+  ASSERT_OK(result.status());
+  ASSERT_TRUE(result->result.is_err());
+  ASSERT_STATUS(result->result.err(), ZX_ERR_NOT_SUPPORTED);
+}
+
 TEST_F(PaverServiceSkipBlockTest, QueryActiveConfigurationSlotB) {
   abr::Data abr_data = kAbrData;
   ComputeCrc(&abr_data);