// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "paver.h"

#include <dirent.h>
#include <fcntl.h>
#include <lib/fdio/directory.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/zx/channel.h>
#include <lib/zx/time.h>
#include <lib/zx/vmo.h>
#include <libgen.h>
#include <stddef.h>
#include <string.h>
#include <zircon/device/block.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include <utility>

#include <fbl/algorithm.h>
#include <fbl/unique_fd.h>
#include <fbl/unique_ptr.h>
#include <fs-management/fvm.h>
#include <fs-management/mount.h>
#include <zxcrypt/fdio-volume.h>

#include "fvm.h"
#include "pave-logging.h"
#include "stream-reader.h"
#include "vmo-reader.h"

#define ZXCRYPT_DRIVER_LIB "/boot/driver/zxcrypt.so"

namespace paver {
namespace {

using ::llcpp::fuchsia::paver::Asset;
using ::llcpp::fuchsia::paver::Configuration;

Partition PartitionType(Configuration configuration, Asset asset) {
  switch (asset) {
    case Asset::KERNEL: {
      switch (configuration) {
        case Configuration::A:
          return Partition::kZirconA;
        case Configuration::B:
          return Partition::kZirconB;
        case Configuration::RECOVERY:
          return Partition::kZirconR;
      };
      break;
    }
    case Asset::VERIFIED_BOOT_METADATA: {
      switch (configuration) {
        case Configuration::A:
          return Partition::kVbMetaA;
        case Configuration::B:
          return Partition::kVbMetaB;
        case Configuration::RECOVERY:
          return Partition::kVbMetaR;
      };
      break;
    }
  };
  return Partition::kUnknown;
}

// Best effort attempt to see if payload contents match what is already inside
// of the partition.
bool CheckIfSame(PartitionClient* partition, const zx::vmo& vmo, size_t payload_size,
                 size_t block_size) {
  const size_t payload_size_aligned = fbl::round_up(payload_size, block_size);
  zx::vmo read_vmo;
  auto status = zx::vmo::create(fbl::round_up(payload_size_aligned, ZX_PAGE_SIZE), 0, &read_vmo);
  if (status != ZX_OK) {
    ERROR("Failed to create VMO: %s\n", zx_status_get_string(status));
    return false;
  }

  if ((status = partition->Read(read_vmo, payload_size_aligned)) != ZX_OK) {
    return false;
  }

  fzl::VmoMapper first_mapper;
  fzl::VmoMapper second_mapper;

  status = first_mapper.Map(vmo, 0, 0, ZX_VM_PERM_READ);
  if (status != ZX_OK) {
    ERROR("Error mapping vmo: %s\n", zx_status_get_string(status));
    return false;
  }

  status = second_mapper.Map(read_vmo, 0, 0, ZX_VM_PERM_READ);
  if (status != ZX_OK) {
    ERROR("Error mapping vmo: %s\n", zx_status_get_string(status));
    return false;
  }

  return memcmp(first_mapper.start(), second_mapper.start(), payload_size) == 0;
}

#if 0
// Checks first few bytes of buffer to ensure it is a ZBI.
// Also validates architecture in kernel header matches the target.
bool ValidateKernelZbi(const uint8_t* buffer, size_t size, Arch arch) {
    const auto payload = reinterpret_cast<const zircon_kernel_t*>(buffer);
    const uint32_t expected_kernel =
        (arch == Arch::X64) ? ZBI_TYPE_KERNEL_X64 : ZBI_TYPE_KERNEL_ARM64;

    const auto crc_valid = [](const zbi_header_t* hdr) {
        const uint32_t crc = crc32(0, reinterpret_cast<const uint8_t*>(hdr + 1), hdr->length);
        return hdr->crc32 == crc;
    };

    return size >= sizeof(zircon_kernel_t) &&
           // Container header
           payload->hdr_file.type == ZBI_TYPE_CONTAINER &&
           payload->hdr_file.extra == ZBI_CONTAINER_MAGIC &&
           (payload->hdr_file.length - offsetof(zircon_kernel_t, hdr_kernel)) <= size &&
           payload->hdr_file.magic == ZBI_ITEM_MAGIC &&
           payload->hdr_file.flags == ZBI_FLAG_VERSION &&
           payload->hdr_file.crc32 == ZBI_ITEM_NO_CRC32 &&
           // Kernel header
           payload->hdr_kernel.type == expected_kernel &&
           (payload->hdr_kernel.length - offsetof(zircon_kernel_t, data_kernel)) <= size &&
           payload->hdr_kernel.magic == ZBI_ITEM_MAGIC &&
           (payload->hdr_kernel.flags & ZBI_FLAG_VERSION) == ZBI_FLAG_VERSION &&
           ((payload->hdr_kernel.flags & ZBI_FLAG_CRC32)
                ? crc_valid(&payload->hdr_kernel)
                : payload->hdr_kernel.crc32 == ZBI_ITEM_NO_CRC32);
}

// Parses a partition and validates that it matches the expected format.
zx_status_t ValidateKernelPayload(const fzl::ResizeableVmoMapper& mapper, size_t vmo_size,
                                  Partition partition_type, Arch arch) {
    // TODO(surajmalhotra): Re-enable this as soon as we have a good way to
    // determine whether the payload is signed or not. (Might require bootserver
    // changes).
    if (false) {
        const auto* buffer = reinterpret_cast<uint8_t*>(mapper.start());
        switch (partition_type) {
        case Partition::kZirconA:
        case Partition::kZirconB:
        case Partition::kZirconR:
            if (!ValidateKernelZbi(buffer, vmo_size, arch)) {
                ERROR("Invalid ZBI payload!");
                return ZX_ERR_BAD_STATE;
            }
            break;

        default:
            // TODO(surajmalhotra): Validate non-zbi payloads as well.
            LOG("Skipping validation as payload is not a ZBI\n");
            break;
        }
    }

    return ZX_OK;
}
#endif

zx_status_t FvmPave(const DevicePartitioner& partitioner,
                    fbl::unique_ptr<fvm::ReaderInterface> payload) {
  LOG("Paving partition.\n");

  constexpr auto partition_type = Partition::kFuchsiaVolumeManager;
  zx_status_t status;
  std::unique_ptr<PartitionClient> partition;
  if ((status = partitioner.FindPartition(partition_type, &partition)) != ZX_OK) {
    if (status != ZX_ERR_NOT_FOUND) {
      ERROR("Failure looking for partition: %s\n", zx_status_get_string(status));
      return status;
    }

    LOG("Coud not find \"%s\" Partition on device. Attemping to add new partition\n",
        PartitionName(partition_type));

    if ((status = partitioner.AddPartition(partition_type, &partition)) != ZX_OK) {
      ERROR("Failure creating partition: %s\n", zx_status_get_string(status));
      return status;
    }
  } else {
    LOG("Partition already exists\n");
  }

  if (partitioner.IsFvmWithinFtl()) {
    LOG("Attempting to format FTL...\n");
    status = partitioner.WipeFvm();
    if (status != ZX_OK) {
      ERROR("Failed to format FTL: %s\n", zx_status_get_string(status));
    } else {
      LOG("Formatted successfully!\n");
    }
  }
  LOG("Streaming partitions...\n");
  if ((status = FvmStreamPartitions(std::move(partition), std::move(payload))) != ZX_OK) {
    ERROR("Failed to stream partitions: %s\n", zx_status_get_string(status));
    return status;
  }
  LOG("Completed successfully\n");
  return ZX_OK;
}

// Reads an image from disk into a vmo.
zx_status_t PartitionRead(const DevicePartitioner& partitioner, Partition partition_type,
                          zx::vmo* out_vmo, size_t* out_vmo_size) {
  LOG("Reading partition.\n");

  std::unique_ptr<PartitionClient> partition;
  if (zx_status_t status = partitioner.FindPartition(partition_type, &partition); status != ZX_OK) {
    ERROR("Coud not find \"%s\" Partition on device: %s\n", PartitionName(partition_type),
          zx_status_get_string(status));
    return status;
  }

  uint64_t partition_size;
  if (zx_status_t status = partition->GetPartitionSize(&partition_size); status != ZX_OK) {
    ERROR("Error getting partition size: %s\n", zx_status_get_string(status));
    return status;
  }

  zx::vmo vmo;
  if (zx_status_t status = zx::vmo::create(fbl::round_up(partition_size, ZX_PAGE_SIZE), 0, &vmo);
      status != ZX_OK) {
    ERROR("Error creating vmo: %s\n", zx_status_get_string(status));
    return status;
  }

  if (zx_status_t status = partition->Read(vmo, static_cast<size_t>(partition_size));
      status != ZX_OK) {
    ERROR("Error writing partition data: %s\n", zx_status_get_string(status));
    return status;
  }

  *out_vmo = std::move(vmo);
  *out_vmo_size = static_cast<size_t>(partition_size);
  LOG("Completed successfully\n");
  return ZX_OK;
}

// Paves an image onto the disk.
zx_status_t PartitionPave(const DevicePartitioner& partitioner, zx::vmo payload_vmo,
                          size_t payload_size, Partition partition_type) {
  LOG("Paving partition.\n");

  zx_status_t status;
  std::unique_ptr<PartitionClient> partition;
  if ((status = partitioner.FindPartition(partition_type, &partition)) != ZX_OK) {
    if (status != ZX_ERR_NOT_FOUND) {
      ERROR("Failure looking for partition: %s\n", zx_status_get_string(status));
      return status;
    }

    LOG("Coud not find \"%s\" Partition on device. Attemping to add new partition\n",
        PartitionName(partition_type));

    if ((status = partitioner.AddPartition(partition_type, &partition)) != ZX_OK) {
      ERROR("Failure creating partition: %s\n", zx_status_get_string(status));
      return status;
    }
  } else {
    LOG("Partition already exists\n");
  }

  size_t block_size_bytes;
  if ((status = partition->GetBlockSize(&block_size_bytes)) != ZX_OK) {
    ERROR("Couldn't get partition block size\n");
    return status;
  }

  if (CheckIfSame(partition.get(), payload_vmo, payload_size, block_size_bytes)) {
    LOG("Skipping write as partition contents match payload.\n");
  } else {
    // Pad payload with 0s to make it block size aligned.
    if (payload_size % block_size_bytes != 0) {
      const size_t remaining_bytes = block_size_bytes - (payload_size % block_size_bytes);
      size_t vmo_size;
      if ((status = payload_vmo.get_size(&vmo_size)) != ZX_OK) {
        ERROR("Couldn't get vmo size\n");
        return status;
      }
      // Grow VMO if it's too small.
      if (vmo_size < payload_size + remaining_bytes) {
        const auto new_size = fbl::round_up(payload_size + remaining_bytes, ZX_PAGE_SIZE);
        status = payload_vmo.set_size(new_size);
        if (status != ZX_OK) {
          ERROR("Couldn't grow vmo\n");
          return status;
        }
      }
      auto buffer = std::make_unique<uint8_t[]>(remaining_bytes);
      memset(buffer.get(), 0, remaining_bytes);
      status = payload_vmo.write(buffer.get(), payload_size, remaining_bytes);
      if (status != ZX_OK) {
        ERROR("Failed to write padding to vmo\n");
        return status;
      }
      payload_size += remaining_bytes;
    }
    if ((status = partition->Write(payload_vmo, payload_size)) != ZX_OK) {
      ERROR("Error writing partition data: %s\n", zx_status_get_string(status));
      return status;
    }
  }

  if ((status = partitioner.FinalizePartition(partition_type)) != ZX_OK) {
    ERROR("Failed to finalize partition\n");
    return status;
  }

  LOG("Completed successfully\n");
  return ZX_OK;
}

zx::channel OpenServiceRoot() {
  zx::channel request, service_root;
  if (zx::channel::create(0, &request, &service_root) != ZX_OK) {
    return zx::channel();
  }
  if (fdio_service_connect("/svc/.", request.release()) != ZX_OK) {
    return zx::channel();
  }
  return service_root;
}

bool IsBootable(const abr::SlotData& slot) {
  return slot.priority > 0 && (slot.tries_remaining > 0 || slot.successful_boot);
}

std::optional<Configuration> GetActiveConfiguration(const abr::Client& abr_client) {
  const bool config_a_bootable = IsBootable(abr_client.Data().slots[0]);
  const bool config_b_bootable = IsBootable(abr_client.Data().slots[1]);
  const uint8_t config_a_priority = abr_client.Data().slots[0].priority;
  const uint8_t config_b_priority = abr_client.Data().slots[1].priority;

  // A wins on ties.
  if (config_a_bootable && (config_a_priority >= config_b_priority || !config_b_bootable)) {
    return Configuration::A;
  } else if (config_b_bootable) {
    return Configuration::B;
  } else {
    return std::nullopt;
  }
}

}  // namespace

bool Paver::InitializePartitioner(zx::channel block_device,
                                  std::unique_ptr<DevicePartitioner>* partitioner) {
  if (!*partitioner) {
    // Use global devfs if one wasn't injected via set_devfs_root.
    if (!devfs_root_) {
      devfs_root_ = fbl::unique_fd(open("/dev", O_RDONLY));
    }
    if (!svc_root_) {
      svc_root_ = OpenServiceRoot();
    }

#if defined(__x86_64__)
    Arch arch = Arch::kX64;
#elif defined(__aarch64__)
    Arch arch = Arch::kArm64;
#else
#error "Unknown arch"
#endif
    *partitioner = DevicePartitioner::Create(devfs_root_.duplicate(), std::move(svc_root_), arch,
                                             std::move(block_device));
    if (!partitioner) {
      ERROR("Unable to initialize a partitioner.\n");
      return false;
    }
  }
  return true;
}

void Paver::ReadAsset(Configuration configuration, Asset asset,
                      ReadAssetCompleter::Sync completer) {
  ::llcpp::fuchsia::paver::Paver_ReadAsset_Result result;
  if (!InitializePartitioner(&partitioner_)) {
    result.set_err(ZX_ERR_BAD_STATE);
    completer.Reply(std::move(result));
    return;
  }
  ::llcpp::fuchsia::paver::Paver_ReadAsset_Response response;
  zx_status_t status = PartitionRead(*partitioner_, PartitionType(configuration, asset),
                                     &response.asset.vmo, &response.asset.size);
  if (status != ZX_OK) {
    result.set_err(status);
  } else {
    result.set_response(std::move(response));
  }
  completer.Reply(std::move(result));
}

void Paver::WriteAsset(Configuration configuration, Asset asset,
                       ::llcpp::fuchsia::mem::Buffer payload, WriteAssetCompleter::Sync completer) {
  if (!InitializePartitioner(&partitioner_)) {
    completer.Reply(ZX_ERR_BAD_STATE);
    return;
  }
  completer.Reply(PartitionPave(*partitioner_, std::move(payload.vmo), payload.size,
                                PartitionType(configuration, asset)));
}

void Paver::WriteVolumes(zx::channel payload_stream, WriteVolumesCompleter::Sync completer) {
  if (!InitializePartitioner(&partitioner_)) {
    completer.Reply(ZX_ERR_BAD_STATE);
  }

  std::unique_ptr<StreamReader> reader;
  zx_status_t status = StreamReader::Create(std::move(payload_stream), &reader);
  if (status != ZX_OK) {
    ERROR("Unable to create stream.\n");
    completer.Reply(status);
    return;
  }
  completer.Reply(FvmPave(*partitioner_, std::move(reader)));
}

void Paver::WriteBootloader(::llcpp::fuchsia::mem::Buffer payload,
                            WriteBootloaderCompleter::Sync completer) {
  if (!InitializePartitioner(&partitioner_)) {
    completer.Reply(ZX_ERR_BAD_STATE);
    return;
  }
  completer.Reply(
      PartitionPave(*partitioner_, std::move(payload.vmo), payload.size, Partition::kBootloader));
}

void Paver::WriteDataFile(fidl::StringView filename, ::llcpp::fuchsia::mem::Buffer payload,
                          WriteDataFileCompleter::Sync completer) {

  // Use global devfs if one wasn't injected via set_devfs_root.
  if (!devfs_root_) {
    devfs_root_ = fbl::unique_fd(open("/dev", O_RDONLY));
  }

  const char* mount_path = "/volume/data";
  const uint8_t data_guid[] = GUID_DATA_VALUE;
  char minfs_path[PATH_MAX] = {0};
  char path[PATH_MAX] = {0};
  zx_status_t status = ZX_OK;

  fbl::unique_fd part_fd(
      open_partition_with_devfs(devfs_root_.get(), nullptr, data_guid, ZX_SEC(1), path));
  if (!part_fd) {
    ERROR("DATA partition not found in FVM\n");
    completer.Reply(ZX_ERR_NOT_FOUND);
    return;
  }

  auto disk_format = detect_disk_format(part_fd.get());
  fbl::unique_fd mountpoint_dev_fd;
  // By the end of this switch statement, mountpoint_dev_fd needs to be an
  // open handle to the block device that we want to mount at mount_path.
  switch (disk_format) {
    case DISK_FORMAT_MINFS:
      // If the disk we found is actually minfs, we can just use the block
      // device path we were given by open_partition.
      strncpy(minfs_path, path, PATH_MAX);
      mountpoint_dev_fd.reset(open(minfs_path, O_RDWR));
      break;

    case DISK_FORMAT_ZXCRYPT: {
      fbl::unique_ptr<zxcrypt::FdioVolume> zxc_volume;
      uint8_t slot = 0;
      if ((status = zxcrypt::FdioVolume::UnlockWithDeviceKey(
               std::move(part_fd), devfs_root_.duplicate(), static_cast<zxcrypt::key_slot_t>(slot),
               &zxc_volume)) != ZX_OK) {
        ERROR("Couldn't unlock zxcrypt volume: %s\n", zx_status_get_string(status));
        completer.Reply(status);
        return;
      }

      // Most of the time we'll expect the volume to actually already be
      // unsealed, because we created it and unsealed it moments ago to
      // format minfs.
      if ((status = zxc_volume->Open(zx::sec(0), &mountpoint_dev_fd)) == ZX_OK) {
        // Already unsealed, great, early exit.
        break;
      }

      // Ensure zxcrypt volume manager is bound.
      zx::channel zxc_manager_chan;
      if ((status = zxc_volume->OpenManager(zx::sec(5),
                                            zxc_manager_chan.reset_and_get_address())) != ZX_OK) {
        ERROR("Couldn't open zxcrypt volume manager: %s\n", zx_status_get_string(status));
        completer.Reply(status);
        return;
      }

      // Unseal.
      zxcrypt::FdioVolumeManager zxc_manager(std::move(zxc_manager_chan));
      if ((status = zxc_manager.UnsealWithDeviceKey(slot)) != ZX_OK) {
        ERROR("Couldn't unseal zxcrypt volume: %s\n", zx_status_get_string(status));
        completer.Reply(status);
        return;
      }

      // Wait for the device to appear, and open it.
      if ((status = zxc_volume->Open(zx::sec(5), &mountpoint_dev_fd)) != ZX_OK) {
        ERROR("Couldn't open block device atop unsealed zxcrypt volume: %s\n",
              zx_status_get_string(status));
        completer.Reply(status);
        return;
      }
    } break;

    default:
      ERROR("unsupported disk format at %s\n", path);
      completer.Reply(ZX_ERR_NOT_SUPPORTED);
      return;
  }

  mount_options_t opts(default_mount_options);
  opts.create_mountpoint = true;
  if ((status = mount(mountpoint_dev_fd.get(), mount_path, DISK_FORMAT_MINFS, &opts,
                      launch_logs_async)) != ZX_OK) {
    ERROR("mount error: %s\n", zx_status_get_string(status));
    completer.Reply(status);
    return;
  }

  int filename_size = static_cast<int>(filename.size());

  // mkdir any intermediate directories between mount_path and basename(filename).
  snprintf(path, sizeof(path), "%s/%.*s", mount_path, filename_size, filename.data());
  size_t cur = strlen(mount_path);
  size_t max = strlen(path) - strlen(basename(path));
  // note: the call to basename above modifies path, so it needs reconstruction.
  snprintf(path, sizeof(path), "%s/%.*s", mount_path, filename_size, filename.data());
  while (cur < max) {
    ++cur;
    if (path[cur] == '/') {
      path[cur] = 0;
      // errors ignored, let the open() handle that later.
      mkdir(path, 0700);
      path[cur] = '/';
    }
  }

  // We append here, because the primary use case here is to send SSH keys
  // which can be appended, but we may want to revisit this choice for other
  // files in the future.
  {
    uint8_t buf[8192];
    fbl::unique_fd kfd(open(path, O_CREAT | O_WRONLY | O_APPEND, 0600));
    if (!kfd) {
      umount(mount_path);
      ERROR("open %.*s error: %s\n", filename_size, filename.data(), strerror(errno));
      completer.Reply(ZX_ERR_IO);
      return;
    }
    VmoReader reader(std::move(payload));
    size_t actual;
    while ((status = reader.Read(buf, sizeof(buf), &actual)) == ZX_OK && actual > 0) {
      if (write(kfd.get(), buf, actual) != static_cast<ssize_t>(actual)) {
        umount(mount_path);
        ERROR("write %.*s error: %s\n", filename_size, filename.data(), strerror(errno));
        completer.Reply(ZX_ERR_IO);
        return;
      }
    }
    fsync(kfd.get());
  }

  if ((status = umount(mount_path)) != ZX_OK) {
    ERROR("unmount %s failed: %s\n", mount_path, zx_status_get_string(status));
    completer.Reply(status);
    return;
  }

  LOG("Wrote %.*s\n", filename_size, filename.data());
  completer.Reply(ZX_OK);
}

void Paver::WipeVolumes(zx::channel block_device, WipeVolumesCompleter::Sync completer) {
  partitioner_.reset();
  abr_client_.reset();

  std::unique_ptr<DevicePartitioner> partitioner;
  if (!InitializePartitioner(std::move(block_device), &partitioner)) {
    completer.Reply(ZX_ERR_BAD_STATE);
    return;
  }

  completer.Reply(partitioner->WipeFvm());
}

void Paver::InitializePartitionTables(zx::channel block_device,
                                      InitializePartitionTablesCompleter::Sync completer) {
  std::unique_ptr<DevicePartitioner> partitioner;
  if (!InitializePartitioner(std::move(block_device), &partitioner)) {
    completer.Reply(ZX_ERR_BAD_STATE);
    return;
  }

  constexpr auto partition_type = Partition::kFuchsiaVolumeManager;
  zx_status_t status;
  std::unique_ptr<PartitionClient> partition;
  if ((status = partitioner->FindPartition(partition_type, &partition)) != ZX_OK) {
    if (status != ZX_ERR_NOT_FOUND) {
      ERROR("Failure looking for partition: %s\n", zx_status_get_string(status));
      completer.Reply(status);
      return;
    }

    LOG("Could not find \"%s\" Partition on device. Attemping to add new partition\n",
        PartitionName(partition_type));

    if ((status = partitioner->AddPartition(partition_type, &partition)) != ZX_OK) {
      ERROR("Failure creating partition: %s\n", zx_status_get_string(status));
      completer.Reply(status);
      return;
    }
  }
  partitioner_ = std::move(partitioner);
  LOG("Successfully initialized gpt.\n");
  completer.Reply(ZX_OK);
}

void Paver::WipePartitionTables(zx::channel block_device,
                                WipePartitionTablesCompleter::Sync completer) {
  partitioner_.reset();
  abr_client_.reset();

  std::unique_ptr<DevicePartitioner> partitioner;
  if (!InitializePartitioner(std::move(block_device), &partitioner)) {
    completer.Reply(ZX_ERR_BAD_STATE);
    return;
  }

  completer.Reply(partitioner->WipePartitionTables());
}

zx_status_t Paver::InitializeAbrClient() {
  if (abr_client_) {
    return ZX_OK;
  }

  if (!InitializePartitioner(&partitioner_)) {
    return ZX_ERR_BAD_STATE;
  }

  std::unique_ptr<abr::Client> abr_client;
  if (zx_status_t status = partitioner_->GetAbrClient(&abr_client); status != ZX_OK) {
    ERROR("Failed to get ABR client: %s\n", zx_status_get_string(status));
    return status;
  }

  if (!abr_client->IsValid()) {
    ERROR("ABR metadata is not valid!\n");
    return ZX_ERR_NOT_SUPPORTED;
  }
  abr_client_ = std::move(abr_client);
  return ZX_OK;
}

void Paver::InitializeAbr(InitializeAbrCompleter::Sync completer) {
  if (abr_client_) {
    completer.Reply(ZX_OK);
    return;
  }

  if (!InitializePartitioner(&partitioner_)) {
    completer.Reply(ZX_ERR_BAD_STATE);
    return;
  }

  std::unique_ptr<abr::Client> abr_client;
  if (zx_status_t status = partitioner_->GetAbrClient(&abr_client); status != ZX_OK) {
    ERROR("Failed to get ABR client: %s\n", zx_status_get_string(status));
    completer.Reply(status);
    return;
  }

  if (abr_client->IsValid()) {
    abr_client_ = std::move(abr_client);
    completer.Reply(ZX_OK);
    return;
  }

  abr::Data data = abr_client->Data();
  memset(&data, 0, sizeof(data));
  memcpy(data.magic, abr::kMagic, sizeof(abr::kMagic));
  data.version_major = abr::kMajorVersion;
  data.version_minor = abr::kMinorVersion;

  if (zx_status_t status = abr_client->Persist(data); status != ZX_OK) {
    ERROR("Unabled to persist ABR metadata %s\n", zx_status_get_string(status));
    completer.Reply(status);
    return;
  }

  ZX_DEBUG_ASSERT(abr_client->IsValid());
  abr_client_ = std::move(abr_client);
  completer.Reply(ZX_OK);
}

void Paver::QueryActiveConfiguration(QueryActiveConfigurationCompleter::Sync completer) {
  ::llcpp::fuchsia::paver::Paver_QueryActiveConfiguration_Result result;
  if (zx_status_t status = InitializeAbrClient(); status != ZX_OK) {
    result.set_err(status);
    completer.Reply(std::move(result));
    return;
  }

  std::optional<Configuration> config = GetActiveConfiguration(*abr_client_);
  if (config) {
    ::llcpp::fuchsia::paver::Paver_QueryActiveConfiguration_Response response;
    response.configuration = *config;
    result.set_response(response);
  } else {
    result.set_err(ZX_ERR_NOT_SUPPORTED);
  }
  completer.Reply(std::move(result));
}

void Paver::QueryConfigurationStatus(Configuration configuration,
                                     QueryConfigurationStatusCompleter::Sync completer) {
  ::llcpp::fuchsia::paver::Paver_QueryConfigurationStatus_Result result;
  if (zx_status_t status = InitializeAbrClient(); status != ZX_OK) {
    result.set_err(status);
    completer.Reply(std::move(result));
    return;
  }
  const abr::SlotData* slot;
  switch (configuration) {
    case Configuration::A:
      slot = &abr_client_->Data().slots[0];
      break;
    case Configuration::B:
      slot = &abr_client_->Data().slots[1];
      break;
    default:
      ERROR("Unexpected configuration: %d\n", static_cast<uint32_t>(configuration));
      result.set_err(ZX_ERR_INVALID_ARGS);
      completer.Reply(std::move(result));
      return;
  }

  ::llcpp::fuchsia::paver::Paver_QueryConfigurationStatus_Response response;
  if (!IsBootable(*slot)) {
    response.status = ::llcpp::fuchsia::paver::ConfigurationStatus::UNBOOTABLE;
  } else if (slot->successful_boot == 0) {
    response.status = ::llcpp::fuchsia::paver::ConfigurationStatus::PENDING;
  } else {
    response.status = ::llcpp::fuchsia::paver::ConfigurationStatus::HEALTHY;
  }

  result.set_response(response);
  completer.Reply(std::move(result));
}

void Paver::SetConfigurationActive(Configuration configuration,
                                   SetConfigurationActiveCompleter::Sync completer) {
  if (zx_status_t status = InitializeAbrClient(); status != ZX_OK) {
    completer.Reply(status);
    return;
  }
  abr::Data data = abr_client_->Data();

  abr::SlotData *primary, *secondary;
  switch (configuration) {
    case Configuration::A:
      primary = &data.slots[0];
      secondary = &data.slots[1];
      break;
    case Configuration::B:
      primary = &data.slots[1];
      secondary = &data.slots[0];
      break;
    default:
      ERROR("Unexpected configuration: %d\n", static_cast<uint32_t>(configuration));
      completer.Reply(ZX_ERR_INVALID_ARGS);
      return;
  }
  if (secondary->priority >= abr::kMaxPriority) {
    // 0 means unbootable, so we reset down to 1 to indicate lowest priority.
    secondary->priority = 1;
  }
  primary->successful_boot = 0;
  primary->tries_remaining = abr::kMaxTriesRemaining;
  primary->priority = static_cast<uint8_t>(secondary->priority + 1);

  if (zx_status_t status = abr_client_->Persist(data); status != ZX_OK) {
    ERROR("Unabled to persist ABR metadata %s\n", zx_status_get_string(status));
    completer.Reply(status);
    return;
  }

  completer.Reply(ZX_OK);
}

void Paver::SetConfigurationUnbootable(Configuration configuration,
                                        SetConfigurationUnbootableCompleter::Sync completer) {
  if (zx_status_t status = InitializeAbrClient(); status != ZX_OK) {
    completer.Reply(status);
    return;
  }
  auto data = abr_client_->Data();

  abr::SlotData *slot;
  switch (configuration) {
    case Configuration::A:
      slot = &data.slots[0];
      break;
    case Configuration::B:
      slot = &data.slots[1];
      break;
    default:
      ERROR("Unexpected configuration: %d\n", static_cast<uint32_t>(configuration));
      completer.Reply(ZX_ERR_INVALID_ARGS);
      return;
  }
  slot->successful_boot = 0;
  slot->tries_remaining = 0;
  slot->priority = 0;

  if (zx_status_t status = abr_client_->Persist(data); status != ZX_OK) {
    ERROR("Unabled to persist ABR metadata %s\n", zx_status_get_string(status));
    completer.Reply(status);
    return;
  }

  completer.Reply(ZX_OK);
}

void Paver::SetActiveConfigurationHealthy(
    SetActiveConfigurationHealthyCompleter::Sync completer) {
  if (zx_status_t status = InitializeAbrClient(); status != ZX_OK) {
    completer.Reply(status);
    return;
  }
  abr::Data data = abr_client_->Data();

  std::optional<Configuration> config = GetActiveConfiguration(*abr_client_);
  if (!config) {
    ERROR("No configuration bootable. Cannot mark as successful boot.\n");
    completer.Reply(ZX_ERR_BAD_STATE);
    return;
  }

  abr::SlotData *slot;
  switch (*config) {
    case Configuration::A:
      slot = &data.slots[0];
      break;
    case Configuration::B:
      slot = &data.slots[1];
      break;
    default:
      // We've previously validated active is A or B.
      ZX_ASSERT(false);
  }
  slot->tries_remaining = 0;
  slot->successful_boot = 1;

  if (zx_status_t status = abr_client_->Persist(data); status != ZX_OK) {
    ERROR("Unabled to persist ABR metadata %s\n", zx_status_get_string(status));
    completer.Reply(status);
    return;
  }

  completer.Reply(ZX_OK);
}

}  //  namespace paver
