// 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 "src/storage/lib/paver/paver.h"

#include <dirent.h>
#include <fcntl.h>
#include <lib/fdio/directory.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/fidl/epitaph.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/service/llcpp/service.h>
#include <lib/stdcompat/span.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/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>

#include <memory>
#include <string_view>
#include <utility>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/unique_fd.h>

#include "src/lib/storage/fs_management/cpp/fvm.h"
#include "src/lib/storage/fs_management/cpp/mount.h"
#include "src/security/zxcrypt/client.h"
#include "src/storage/fshost/constants.h"
#include "src/storage/lib/paver/fvm.h"
#include "src/storage/lib/paver/pave-logging.h"
#include "src/storage/lib/paver/stream-reader.h"
#include "src/storage/lib/paver/validation.h"
#include "src/storage/lib/paver/vmo-reader.h"
#include "sysconfig-fidl.h"

namespace paver {
namespace {

using fuchsia_paver::wire::Asset;
using fuchsia_paver::wire::Configuration;
using fuchsia_paver::wire::ConfigurationStatus;
using fuchsia_paver::wire::WriteFirmwareResult;

// Get the architecture of the currently running platform.
inline constexpr Arch GetCurrentArch() {
#if defined(__x86_64__)
  return Arch::kX64;
#elif defined(__aarch64__)
  return Arch::kArm64;
#else
#error "Unknown arch"
#endif
}

Partition PartitionType(Configuration configuration, Asset asset) {
  switch (asset) {
    case Asset::kKernel: {
      switch (configuration) {
        case Configuration::kA:
          return Partition::kZirconA;
        case Configuration::kB:
          return Partition::kZirconB;
        case Configuration::kRecovery:
          return Partition::kZirconR;
      };
      break;
    }
    case Asset::kVerifiedBootMetadata: {
      switch (configuration) {
        case Configuration::kA:
          return Partition::kVbMetaA;
        case Configuration::kB:
          return Partition::kVbMetaB;
        case Configuration::kRecovery:
          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_system_get_page_size()), 0, &read_vmo);
  if (status != ZX_OK) {
    ERROR("Failed to create VMO: %s\n", zx_status_get_string(status));
    return false;
  }

  if (auto status = partition->Read(read_vmo, payload_size_aligned); status.is_error()) {
    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;
}

// Returns a client for the FVM partition. If the FVM volume doesn't exist, a new
// volume will be created, without any associated children partitions.
zx::status<std::unique_ptr<PartitionClient>> GetFvmPartition(const DevicePartitioner& partitioner) {
  // FVM doesn't need content type support, use the default.
  const PartitionSpec spec(Partition::kFuchsiaVolumeManager);
  auto status = partitioner.FindPartition(spec);
  if (status.is_error()) {
    if (status.status_value() != ZX_ERR_NOT_FOUND) {
      ERROR("Failure looking for FVM partition: %s\n", status.status_string());
      return status.take_error();
    }

    LOG("Could not find FVM Partition on device. Attemping to add new partition\n");

    if (auto status = partitioner.AddPartition(spec); status.is_error()) {
      ERROR("Failure creating FVM partition: %s\n", status.status_string());
      return status.take_error();
    } else {
      return status.take_value();
    }
  } else {
    LOG("FVM Partition already exists\n");
  }
  return status.take_value();
}

zx::status<> FvmPave(const fbl::unique_fd& devfs_root, const DevicePartitioner& partitioner,
                     std::unique_ptr<fvm::ReaderInterface> payload) {
  LOG("Paving FVM partition.\n");
  auto status = GetFvmPartition(partitioner);
  if (status.is_error()) {
    return status.take_error();
  }
  std::unique_ptr<PartitionClient>& partition = status.value();

  if (partitioner.IsFvmWithinFtl()) {
    LOG("Attempting to format FTL...\n");
    zx::status<> status = partitioner.WipeFvm();
    if (status.is_error()) {
      ERROR("Failed to format FTL: %s\n", status.status_string());
    } else {
      LOG("Formatted partition successfully!\n");
    }
  }
  LOG("Streaming partitions to FVM...\n");
  {
    auto status = FvmStreamPartitions(devfs_root, std::move(partition), std::move(payload));
    if (status.is_error()) {
      ERROR("Failed to stream partitions to FVM: %s\n", status.status_string());
      return status.take_error();
    }
  }
  LOG("Completed FVM paving successfully\n");
  return zx::ok();
}

zx::status<> FvmReplay(const fbl::unique_fd& devfs_root, const DevicePartitioner& partitioner, 
                       std::unique_ptr<fvm::ReaderInterface> payload) {
  LOG("Replaying FVM partition.\n");
  if (!partitioner.IsFvmWithinFtl()) {
    ERROR("Failed to replay FVM: this action can only be performed on devices where the FVM "
          "resides within the FTL.\n");
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  ERROR("Replaying FVM partition not implemented yet\n");
  return zx::error(ZX_ERR_NOT_SUPPORTED);
  // TODO: open the block device
  // sys/platform/05:00:f/aml-raw_nand/nand/fvm
  // nandpart root = "<devfs_root>/sys/platform/05:00:f/aml-raw_nand/nand/"
  // nandpart child is "fvm"
  // TODO: openat(devfs_root.get(), "sys/platform/05:00:f/aml-raw_nand/nand/fvm");
  // TODO: issue the nandpart client commands here
  // return zx::ok();
}

// Formats the FVM partition and returns a channel to the new volume.
zx::status<zx::channel> FormatFvm(const fbl::unique_fd& devfs_root,
                                  const DevicePartitioner& partitioner) {
  auto status = GetFvmPartition(partitioner);
  if (status.is_error()) {
    return status.take_error();
  }
  std::unique_ptr<PartitionClient> partition = std::move(status.value());

  // TODO(fxbug.dev/39753): Configuration values should come from the build or environment.
  fvm::SparseImage header = {};
  header.slice_size = 1 << 20;

  fbl::unique_fd fvm_fd(
      FvmPartitionFormat(devfs_root, partition->block_fd(), header, BindOption::Reformat));
  if (!fvm_fd) {
    ERROR("Couldn't format FVM partition\n");
    return zx::error(ZX_ERR_IO);
  }

  {
    auto status = AllocateEmptyPartitions(devfs_root, fvm_fd);
    if (status.is_error()) {
      ERROR("Couldn't allocate empty partitions\n");
      return status.take_error();
    }

    zx::channel channel;
    status =
        zx::make_status(fdio_get_service_handle(fvm_fd.release(), channel.reset_and_get_address()));
    if (status.is_error()) {
      ERROR("Couldn't get fvm handle\n");
      return zx::error(ZX_ERR_IO);
    }
    return zx::ok(std::move(channel));
  }
}

// Reads an image from disk into a vmo.
zx::status<fuchsia_mem::wire::Buffer> PartitionRead(const DevicePartitioner& partitioner,
                                                    const PartitionSpec& spec) {
  LOG("Reading partition \"%s\".\n", spec.ToString().c_str());

  auto status = partitioner.FindPartition(spec);
  if (status.is_error()) {
    ERROR("Could not find \"%s\" Partition on device: %s\n", spec.ToString().c_str(),
          status.status_string());
    return status.take_error();
  }
  std::unique_ptr<PartitionClient>& partition = status.value();

  auto status2 = partition->GetPartitionSize();
  if (status2.is_error()) {
    ERROR("Error getting partition \"%s\" size: %s\n", spec.ToString().c_str(),
          status2.status_string());
    return status2.take_error();
  }
  const uint64_t partition_size = status2.value();

  zx::vmo vmo;
  if (auto status = zx::make_status(
          zx::vmo::create(fbl::round_up(partition_size, zx_system_get_page_size()), 0, &vmo));
      status.is_error()) {
    ERROR("Error creating vmo for \"%s\": %s\n", spec.ToString().c_str(), status.status_string());
    return status.take_error();
  }

  if (auto status = partition->Read(vmo, static_cast<size_t>(partition_size)); status.is_error()) {
    ERROR("Error writing partition data for \"%s\": %s\n", spec.ToString().c_str(),
          status.status_string());
    return status.take_error();
  }

  size_t asset_size = static_cast<size_t>(partition_size);
  // Try to find ZBI size if asset is a ZBI. This won't work on signed ZBI, nor vbmeta assets.
  fzl::VmoMapper mapper;
  if (zx::make_status(mapper.Map(vmo, 0, partition_size, ZX_VM_PERM_READ)).is_ok()) {
    auto data = cpp20::span(static_cast<uint8_t*>(mapper.start()), mapper.size());
    const zbi_header_t* container_header;
    cpp20::span<const uint8_t> container_data;
    if (ExtractZbiPayload(data, &container_header, &container_data)) {
      asset_size = container_data.size();
    }
  }

  LOG("Completed successfully\n");
  return zx::ok(fuchsia_mem::wire::Buffer{std::move(vmo), asset_size});
}

zx::status<> ValidatePartitionPayload(const DevicePartitioner& partitioner,
                                      const zx::vmo& payload_vmo, size_t payload_size,
                                      const PartitionSpec& spec) {
  fzl::VmoMapper payload_mapper;
  auto status = zx::make_status(payload_mapper.Map(payload_vmo, 0, 0, ZX_VM_PERM_READ));
  if (status.is_error()) {
    ERROR("Could not map payload into memory: %s\n", status.status_string());
    return status.take_error();
  }
  ZX_ASSERT(payload_mapper.size() >= payload_size);

  auto payload =
      cpp20::span<const uint8_t>(static_cast<const uint8_t*>(payload_mapper.start()), payload_size);
  return partitioner.ValidatePayload(spec, payload);
}

// Paves an image onto the disk.
zx::status<> PartitionPave(const DevicePartitioner& partitioner, zx::vmo payload_vmo,
                           size_t payload_size, const PartitionSpec& spec) {
  LOG("Paving partition \"%s\".\n", spec.ToString().c_str());

  // The payload_vmo might be pager-backed. Commit its pages first before using it for
  // block writes below, to avoid deadlocks in the block server. If all the pages of the
  // payload_vmo are not in memory, the block server might see a read fault in the midst of a write.
  // Read faults need to be fulfilled by the block server itself, so it will deadlock.
  //
  // Note that these pages would be committed anyway when the block server pins them for the write.
  // We're simply committing a little early here.
  //
  // If payload_vmo is pager-backed, committing its pages guarantees that they will remain in memory
  // and not be evicted only if it's a clone of a pager-backed VMO, and not a root pager-backed VMO
  // (directly backed by a pager source). Blobfs only hands out clones of root pager-backed VMOs.
  // Assert that that is indeed the case. This will cause us to fail deterministically if that
  // invariant does not hold. Otherwise, if pages get evicted in the midst of the partition write,
  // the block server can deadlock due to a read fault, putting the device in an unrecoverable
  // state.
  //
  // TODO(fxbug.dev/48145): If it's possible for payload_vmo to be a root pager-backed VMO, we will
  // need to lock it instead of simply committing its pages, to opt it out of eviction. The assert
  // below verifying that it's a pager-backed clone will need to be removed as well.
  zx_info_vmo_t info;
  auto status =
      zx::make_status(payload_vmo.get_info(ZX_INFO_VMO, &info, sizeof(info), nullptr, nullptr));
  if (status.is_error()) {
    ERROR("Failed to get info for payload VMO for partition \"%s\": %s\n", spec.ToString().c_str(),
          status.status_string());
    return status.take_error();
  }
  // If payload_vmo is pager-backed, it is a clone (has a parent).
  ZX_ASSERT(!(info.flags & ZX_INFO_VMO_PAGER_BACKED) || info.parent_koid);

  status = zx::make_status(payload_vmo.op_range(ZX_VMO_OP_COMMIT, 0, payload_size, nullptr, 0));
  if (status.is_error()) {
    ERROR("Failed to commit payload VMO for partition \"%s\": %s\n", spec.ToString().c_str(),
          status.status_string());
    return status.take_error();
  }

  // Perform basic safety checking on the partition before we attempt to write it.
  status = ValidatePartitionPayload(partitioner, payload_vmo, payload_size, spec);
  if (status.is_error()) {
    ERROR("Failed to validate partition \"%s\": %s\n", spec.ToString().c_str(),
          status.status_string());
    return status.take_error();
  }

  // Find or create the appropriate partition.
  std::unique_ptr<PartitionClient> partition;
  if (auto status = partitioner.FindPartition(spec); status.is_ok()) {
    LOG("Partition \"%s\" already exists\n", spec.ToString().c_str());
    partition = std::move(status.value());
  } else {
    if (status.error_value() != ZX_ERR_NOT_FOUND) {
      ERROR("Failure looking for partition \"%s\": %s\n", spec.ToString().c_str(),
            status.status_string());
      return status.take_error();
    }

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

    if (auto status = partitioner.AddPartition(spec); status.is_ok()) {
      partition = std::move(status.value());
    } else {
      ERROR("Failure creating partition \"%s\": %s\n", spec.ToString().c_str(),
            status.status_string());
      return status.take_error();
    }
  }

  zx::status<size_t> status_or_size = partition->GetBlockSize();
  if (status_or_size.is_error()) {
    ERROR("Couldn't get partition \"%s\" block size\n", spec.ToString().c_str());
    return status_or_size.take_error();
  }
  const size_t block_size_bytes = status_or_size.value();

  if (CheckIfSame(partition.get(), payload_vmo, payload_size, block_size_bytes)) {
    LOG("Skipping write as partition \"%s\" contents match payload.\n", spec.ToString().c_str());
  } 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 (auto status = zx::make_status(payload_vmo.get_size(&vmo_size)); status.is_error()) {
        ERROR("Couldn't get vmo size for \"%s\"\n", spec.ToString().c_str());
        return status.take_error();
      }
      // 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_system_get_page_size());
        status = zx::make_status(payload_vmo.set_size(new_size));
        if (status.is_error()) {
          ERROR("Couldn't grow vmo for \"%s\"\n", spec.ToString().c_str());
          return status.take_error();
        }
      }
      auto buffer = std::make_unique<uint8_t[]>(remaining_bytes);
      memset(buffer.get(), 0, remaining_bytes);
      status = zx::make_status(payload_vmo.write(buffer.get(), payload_size, remaining_bytes));
      if (status.is_error()) {
        ERROR("Failed to write padding to vmo for \"%s\"\n", spec.ToString().c_str());
        return status.take_error();
      }
      payload_size += remaining_bytes;
    }
    if (auto status = partition->Write(payload_vmo, payload_size); status.is_error()) {
      ERROR("Error writing partition \"%s\" data: %s\n", spec.ToString().c_str(),
            status.status_string());
      return status.take_error();
    }
  }

  if (auto status = partitioner.FinalizePartition(spec); status.is_error()) {
    ERROR("Failed to finalize partition \"%s\"\n", spec.ToString().c_str());
    return status.take_error();
  }

  LOG("Completed paving partition \"%s\" successfully\n", spec.ToString().c_str());
  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;
}

Configuration SlotIndexToConfiguration(AbrSlotIndex slot_index) {
  switch (slot_index) {
    case kAbrSlotIndexA:
      return Configuration::kA;
    case kAbrSlotIndexB:
      return Configuration::kB;
    case kAbrSlotIndexR:
      return Configuration::kRecovery;
  }
  ERROR("Unknown Abr slot index %d\n", static_cast<int>(slot_index));
  ZX_ASSERT(false);  // Unreachable
}

std::optional<AbrSlotIndex> ConfigurationToSlotIndex(Configuration config) {
  switch (config) {
    case Configuration::kA:
      return kAbrSlotIndexA;
    case Configuration::kB:
      return kAbrSlotIndexB;
    case Configuration::kRecovery:
      return kAbrSlotIndexR;
  }
  ERROR("Unknown configuration %d\n", static_cast<int>(config));
  return std::nullopt;
}

std::optional<Configuration> GetActiveConfiguration(const abr::Client& abr_client) {
  auto slot_index = abr_client.GetBootSlot(false, nullptr);
  if (slot_index == kAbrSlotIndexR) {
    return std::nullopt;
  } else {
    return SlotIndexToConfiguration(slot_index);
  }
}

// Helper to wrap a std::variant with a WriteFirmwareResult union.
//
// This can go away once llcpp unions support owning memory, but until then we
// need the variant to own the underlying data.
//
// |variant| must outlive the returned WriteFirmwareResult.
WriteFirmwareResult CreateWriteFirmwareResult(std::variant<zx_status_t, bool>* variant) {
  WriteFirmwareResult result;
  if (std::holds_alternative<zx_status_t>(*variant)) {
    result.set_status(std::get<zx_status_t>(*variant));
  } else {
    result.set_unsupported(std::get<bool>(*variant));
  }
  return result;
}

}  // namespace

void Paver::FindDataSink(FindDataSinkRequestView request, FindDataSinkCompleter::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));
  }
  if (!svc_root_) {
    svc_root_ = OpenServiceRoot();
  }

  DataSink::Bind(dispatcher_, devfs_root_.duplicate(), std::move(svc_root_),
                 request->data_sink.TakeChannel(), context_);
}

void Paver::UseBlockDevice(UseBlockDeviceRequestView request,
                           UseBlockDeviceCompleter::Sync& _completer) {
  UseBlockDevice(request->block_device.TakeChannel(), request->data_sink.TakeChannel());
}

void Paver::UseBlockDevice(zx::channel block_device, zx::channel dynamic_data_sink) {
  // 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();
  }

  DynamicDataSink::Bind(dispatcher_, devfs_root_.duplicate(), std::move(svc_root_),
                        std::move(block_device), std::move(dynamic_data_sink), context_);
}

void Paver::FindBootManager(FindBootManagerRequestView request,
                            FindBootManagerCompleter::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));
  }
  if (!svc_root_) {
    svc_root_ = OpenServiceRoot();
  }

  BootManager::Bind(dispatcher_, devfs_root_.duplicate(), std::move(svc_root_), context_,
                    request->boot_manager.TakeChannel());
}

void DataSink::ReadAsset(ReadAssetRequestView request, ReadAssetCompleter::Sync& completer) {
  auto status = sink_.ReadAsset(request->configuration, request->asset);
  if (status.is_ok()) {
    completer.ReplySuccess(std::move(status.value()));
  } else {
    completer.ReplyError(status.error_value());
  }
}

void DataSink::WriteFirmware(WriteFirmwareRequestView request,
                             WriteFirmwareCompleter::Sync& completer) {
  auto variant =
      sink_.WriteFirmware(request->configuration, request->type, std::move(request->payload));
  completer.Reply(CreateWriteFirmwareResult(&variant));
}

void DataSink::WipeVolume(WipeVolumeRequestView request, WipeVolumeCompleter::Sync& completer) {
  auto status = sink_.WipeVolume();
  if (status.is_ok()) {
    completer.ReplySuccess(std::move(status.value()));
  } else {
    completer.ReplyError(status.error_value());
  }
}

zx::status<fuchsia_mem::wire::Buffer> DataSinkImpl::ReadAsset(Configuration configuration,
                                                              Asset asset) {
  // No assets support content types yet, use the PartitionSpec default.
  PartitionSpec spec(PartitionType(configuration, asset));

  // Important: if we ever do pass a content type here, do NOT just return
  // ZX_ERR_NOT_SUPPORTED directly - the caller needs to be able to distinguish
  // between unknown asset types (which should be ignored) and actual errors
  // that happen to return this same status code.
  if (!partitioner_->SupportsPartition(spec)) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  auto status = PartitionRead(*partitioner_, spec);
  if (status.is_error()) {
    return status.take_error();
  }
  return zx::ok(std::move(status.value()));
}

zx::status<> DataSinkImpl::WriteAsset(Configuration configuration, Asset asset,
                                      fuchsia_mem::wire::Buffer payload) {
  // No assets support content types yet, use the PartitionSpec default.
  PartitionSpec spec(PartitionType(configuration, asset));

  // Important: if we ever do pass a content type here, do NOT just return
  // ZX_ERR_NOT_SUPPORTED directly - the caller needs to be able to distinguish
  // between unknown asset types (which should be ignored) and actual errors
  // that happen to return this same status code.
  if (!partitioner_->SupportsPartition(spec)) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  return PartitionPave(*partitioner_, std::move(payload.vmo), payload.size, spec);
}

std::variant<zx_status_t, bool> DataSinkImpl::WriteFirmware(Configuration configuration,
                                                            fidl::StringView type,
                                                            fuchsia_mem::wire::Buffer payload) {
  // Currently all our supported firmware lives in Partition::kBootloaderA/B/R.
  Partition part_type;
  switch (configuration) {
    case Configuration::kA:
      part_type = Partition::kBootloaderA;
      break;
    case Configuration::kB:
      part_type = Partition::kBootloaderB;
      break;
    case Configuration::kRecovery:
      part_type = Partition::kBootloaderR;
      break;
  }
  PartitionSpec spec = PartitionSpec(part_type, std::string_view(type.data(), type.size()));

  bool supported = partitioner_->SupportsPartition(spec);
  if (!supported && part_type == Partition::kBootloaderB) {
    // It's possible that the device does not support bootloader A/B. In this case,
    // try writing to configuration A, which is always supported for some expected firmware
    // type.
    LOG("Device may not support firmware A/B. Attempt to write to slot A\n")
    spec.partition = Partition::kBootloaderA;
    supported = partitioner_->SupportsPartition(spec);
  }

  if (supported) {
    return PartitionPave(*partitioner_, std::move(payload.vmo), payload.size, spec).status_value();
  }

  // unsupported_type = true.
  return true;
}

zx::status<> DataSinkImpl::WriteVolumes(zx::channel payload_stream) {
  auto status = StreamReader::Create(std::move(payload_stream));
  if (status.is_error()) {
    ERROR("Unable to create stream.\n");
    return status.take_error();
  }
  return FvmPave(devfs_root_, *partitioner_, std::move(status.value()));
}

zx::status<> DataSinkImpl::WriteRawVolumes(zx::channel payload_stream) {
  auto status = StreamReader::Create(std::move(payload_stream));
  if (status.is_error()) {
    ERROR("Unable to create stream.\n");
    return status.take_error();
  }
  return FvmReplay(devfs_root_, *partitioner_, std::move(status.value()));
}

// Deprecated in favor of WriteFirmware().
// TODO(fxbug.dev/45606): move clients off this function and delete it.
zx::status<> DataSinkImpl::WriteBootloader(fuchsia_mem::wire::Buffer payload) {
  PartitionSpec spec(Partition::kBootloaderA);

  if (!partitioner_->SupportsPartition(spec)) {
    return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  return PartitionPave(*partitioner_, std::move(payload.vmo), payload.size, spec);
}

zx::status<> DataSinkImpl::WriteDataFile(fidl::StringView filename,
                                         fuchsia_mem::wire::Buffer payload) {
  const char* mount_path = "/volume/data";
  const uint8_t data_guid[] = GUID_DATA_VALUE;
  char minfs_path[PATH_MAX] = {0};
  std::string partition_path;
  zx::status<> status = zx::ok();

  const std::string data_partition_names[] = {std::string(fshost::kDataPartitionLabel),
                                              std::string(fshost::kLegacyDataPartitionLabel)};
  const char* c_data_partition_names[] = {data_partition_names[0].c_str(),
                                          data_partition_names[1].c_str()};
  fs_management::PartitionMatcher matcher{
      .type_guid = data_guid,
      .labels = c_data_partition_names,
      .num_labels = 2,
  };
  auto part_fd_or = fs_management::OpenPartitionWithDevfs(devfs_root_.get(), &matcher, ZX_SEC(1),
                                                          &partition_path);
  if (part_fd_or.is_error()) {
    ERROR("DATA partition not found in FVM\n");
    return part_fd_or.take_error();
  }

  auto disk_format = fs_management::DetectDiskFormat(part_fd_or->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 fs_management::kDiskFormatMinfs:
      // 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, partition_path.c_str(), PATH_MAX);
      mountpoint_dev_fd.reset(open(minfs_path, O_RDWR));
      break;

    case fs_management::kDiskFormatZxcrypt: {
      zxcrypt::VolumeManager zxc_volume(*std::move(part_fd_or), devfs_root_.duplicate());

      // 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 = zx::make_status(zxc_volume.OpenInnerBlockDevice(zx::sec(0), &mountpoint_dev_fd));
          status.is_ok()) {
        // Already unsealed, great, early exit.
        break;
      }

      // Ensure zxcrypt volume manager is bound.
      zx::channel zxc_client_chan;
      if (status = zx::make_status(zxc_volume.OpenClient(zx::sec(5), zxc_client_chan));
          status.is_error()) {
        ERROR("Couldn't open zxcrypt volume manager: %s\n", status.status_string());
        return status.take_error();
      }

      // Unseal.
      zxcrypt::EncryptedVolumeClient zxc_client(std::move(zxc_client_chan));
      uint8_t slot = 0;
      if (status = zx::make_status(zxc_client.UnsealWithImplicitKey(slot)); status.is_error()) {
        ERROR("Couldn't unseal zxcrypt volume: %s\n", status.status_string());
        return status.take_error();
      }

      // Wait for the device to appear, and open it.
      if (status = zx::make_status(zxc_volume.OpenInnerBlockDevice(zx::sec(5), &mountpoint_dev_fd));
          status.is_error()) {
        ERROR("Couldn't open block device atop unsealed zxcrypt volume: %s\n",
              status.status_string());
        return status.take_error();
      }
    } break;

    default:
      ERROR("unsupported disk format at %s\n", partition_path.c_str());
      return zx::error(ZX_ERR_NOT_SUPPORTED);
  }

  auto mounted_filesystem_or =
      fs_management::Mount(std::move(mountpoint_dev_fd), mount_path,
                           fs_management::kDiskFormatMinfs, {}, launch_logs_async);
  if (mounted_filesystem_or.is_error()) {
    ERROR("mount error: %s\n", mounted_filesystem_or.status_string());
    return mounted_filesystem_or.take_error();
  }

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

  // mkdir any intermediate directories between mount_path and basename(filename).
  char path[PATH_MAX];
  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) {
      ERROR("open %.*s error: %s\n", filename_size, filename.data(), strerror(errno));
      return zx::error(ZX_ERR_IO);
    }
    VmoReader reader(std::move(payload));
    auto status = reader.Read(buf, sizeof(buf));
    while (status.is_ok() && status.value() > 0) {
      size_t actual = status.value();
      if (write(kfd.get(), buf, actual) != static_cast<ssize_t>(actual)) {
        ERROR("write %.*s error: %s\n", filename_size, filename.data(), strerror(errno));
        return zx::error(ZX_ERR_IO);
      }
      status = reader.Read(buf, sizeof(buf));
    }
    fsync(kfd.get());
  }

  if (auto status = std::move(*mounted_filesystem_or).Unmount(); status.is_error()) {
    ERROR("unmount %s failed: %s\n", mount_path, status.status_string());
    return status.take_error();
  }

  LOG("Wrote %.*s\n", filename_size, filename.data());
  return zx::ok();
}

zx::status<zx::channel> DataSinkImpl::WipeVolume() {
  auto status = GetFvmPartition(*partitioner_);
  if (status.is_error()) {
    return status.take_error();
  }
  std::unique_ptr<PartitionClient> partition = std::move(status.value());

  // Bind the FVM driver to be in a well known state regarding races with block watcher.
  // The block watcher will attempt to bind the FVM driver automatically based on
  // the contents of the partition. However, that operation is not synchronized in
  // any way with this service so the driver can be loaded at any time.
  // WipeFvm basically writes underneath that driver, which means that we should
  // eliminate the races at this point: assuming that the driver can load, either
  // this call or the block watcher will succeed (and the other one will fail),
  // but the driver will be loaded before moving on.
  TryBindToFvmDriver(devfs_root_, partition->block_fd(), zx::sec(3));

  {
    auto status = partitioner_->WipeFvm();
    if (status.is_error()) {
      ERROR("Failure wiping partition: %s\n", status.status_string());
      return status.take_error();
    }
  }

  {
    auto status = FormatFvm(devfs_root_, *partitioner_);
    if (status.is_error()) {
      ERROR("Failure formatting partition: %s\n", status.status_string());
      return status.take_error();
    }

    return zx::ok(std::move(status.value()));
  }
}

void DataSink::Bind(async_dispatcher_t* dispatcher, fbl::unique_fd devfs_root,
                    fidl::ClientEnd<fuchsia_io::Directory> svc_root, zx::channel server,
                    std::shared_ptr<Context> context) {
  auto partitioner = DevicePartitionerFactory::Create(devfs_root.duplicate(), std::move(svc_root),
                                                      GetCurrentArch(), context);
  if (!partitioner) {
    ERROR("Unable to initialize a partitioner.\n");
    fidl_epitaph_write(server.get(), ZX_ERR_BAD_STATE);
    return;
  }
  auto data_sink = std::make_unique<DataSink>(std::move(devfs_root), std::move(partitioner));
  fidl::BindSingleInFlightOnly(dispatcher, std::move(server), std::move(data_sink));
}

void DynamicDataSink::Bind(async_dispatcher_t* dispatcher, fbl::unique_fd devfs_root,
                           fidl::ClientEnd<fuchsia_io::Directory> svc_root,
                           zx::channel block_device, zx::channel server,
                           std::shared_ptr<Context> context) {
  auto partitioner =
      DevicePartitionerFactory::Create(devfs_root.duplicate(), std::move(svc_root),
                                       GetCurrentArch(), context, std::move(block_device));
  if (!partitioner) {
    ERROR("Unable to initialize a partitioner.\n");
    fidl_epitaph_write(server.get(), ZX_ERR_BAD_STATE);
    return;
  }
  auto data_sink = std::make_unique<DynamicDataSink>(std::move(devfs_root), std::move(partitioner));
  fidl::BindSingleInFlightOnly(dispatcher, std::move(server), std::move(data_sink));
}

void DynamicDataSink::InitializePartitionTables(
    InitializePartitionTablesRequestView request,
    InitializePartitionTablesCompleter::Sync& completer) {
  completer.Reply(sink_.partitioner()->InitPartitionTables().status_value());
}

void DynamicDataSink::WipePartitionTables(WipePartitionTablesRequestView request,
                                          WipePartitionTablesCompleter::Sync& completer) {
  completer.Reply(sink_.partitioner()->WipePartitionTables().status_value());
}

void DynamicDataSink::ReadAsset(ReadAssetRequestView request, ReadAssetCompleter::Sync& completer) {
  auto status = sink_.ReadAsset(request->configuration, request->asset);
  if (status.is_ok()) {
    completer.ReplySuccess(std::move(status.value()));
  } else {
    completer.ReplyError(status.error_value());
  }
}

void DynamicDataSink::WriteFirmware(WriteFirmwareRequestView request,
                                    WriteFirmwareCompleter::Sync& completer) {
  auto variant =
      sink_.WriteFirmware(request->configuration, request->type, std::move(request->payload));
  completer.Reply(CreateWriteFirmwareResult(&variant));
}

void DynamicDataSink::WipeVolume(WipeVolumeRequestView request,
                                 WipeVolumeCompleter::Sync& completer) {
  auto status = sink_.WipeVolume();
  if (status.is_ok()) {
    completer.ReplySuccess(std::move(status.value()));
  } else {
    completer.ReplyError(status.error_value());
  }
}

void BootManager::Bind(async_dispatcher_t* dispatcher, fbl::unique_fd devfs_root,
                       fidl::ClientEnd<fuchsia_io::Directory> svc_root,
                       std::shared_ptr<Context> context, zx::channel server) {
  auto status = abr::ClientFactory::Create(devfs_root.duplicate(), svc_root, context);
  if (status.is_error()) {
    ERROR("Failed to get ABR client: %s\n", status.status_string());
    fidl_epitaph_write(server.get(), status.error_value());
    return;
  }
  auto& abr_client = status.value();

  auto boot_manager = std::make_unique<BootManager>(std::move(abr_client), std::move(devfs_root),
                                                    std::move(svc_root));
  fidl::BindSingleInFlightOnly(dispatcher, std::move(server), std::move(boot_manager));
}

void BootManager::QueryCurrentConfiguration(QueryCurrentConfigurationRequestView request,
                                            QueryCurrentConfigurationCompleter::Sync& completer) {
  zx::status<Configuration> status = abr::QueryBootConfig(devfs_root_, svc_root_);
  if (status.is_error()) {
    completer.ReplyError(status.status_value());
    return;
  }
  completer.ReplySuccess(status.value());
}

void BootManager::QueryActiveConfiguration(QueryActiveConfigurationRequestView request,
                                           QueryActiveConfigurationCompleter::Sync& completer) {
  std::optional<Configuration> config = GetActiveConfiguration(*abr_client_);
  if (!config) {
    completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
    return;
  }
  completer.ReplySuccess(config.value());
}

void BootManager::QueryConfigurationLastSetActive(
    QueryConfigurationLastSetActiveRequestView request,
    QueryConfigurationLastSetActiveCompleter::Sync& completer) {
  auto status = abr_client_->GetSlotLastMarkedActive();
  if (status.is_error()) {
    ERROR("Failed to get slot most recently marked active\n");
    completer.ReplyError(status.error_value());
    return;
  }

  completer.ReplySuccess(SlotIndexToConfiguration(status.value()));
}

void BootManager::QueryConfigurationStatus(QueryConfigurationStatusRequestView request,
                                           QueryConfigurationStatusCompleter::Sync& completer) {
  auto slot_index = ConfigurationToSlotIndex(request->configuration);
  auto status = slot_index ? abr_client_->GetSlotInfo(*slot_index) : zx::error(ZX_ERR_INVALID_ARGS);
  if (status.is_error()) {
    ERROR("Failed to get slot info %d\n", static_cast<uint32_t>(request->configuration));
    completer.ReplyError(status.error_value());
    return;
  }
  const AbrSlotInfo& slot = status.value();

  if (!slot.is_bootable) {
    completer.ReplySuccess(ConfigurationStatus::kUnbootable);
  } else if (slot.is_marked_successful == 0) {
    completer.ReplySuccess(ConfigurationStatus::kPending);
  } else {
    completer.ReplySuccess(ConfigurationStatus::kHealthy);
  }
}

void BootManager::SetConfigurationActive(SetConfigurationActiveRequestView request,
                                         SetConfigurationActiveCompleter::Sync& completer) {
  LOG("Setting configuration %d as active\n", static_cast<uint32_t>(request->configuration));

  auto slot_index = ConfigurationToSlotIndex(request->configuration);
  auto status =
      slot_index ? abr_client_->MarkSlotActive(*slot_index) : zx::error(ZX_ERR_INVALID_ARGS);
  if (status.is_error()) {
    ERROR("Failed to set configuration: %d active\n",
          static_cast<uint32_t>(request->configuration));
    completer.Reply(status.error_value());
    return;
  }

  LOG("Set active configuration to %d\n", static_cast<uint32_t>(request->configuration));

  completer.Reply(ZX_OK);
}

void BootManager::SetConfigurationUnbootable(SetConfigurationUnbootableRequestView request,
                                             SetConfigurationUnbootableCompleter::Sync& completer) {
  LOG("Setting configuration %d as unbootable\n", static_cast<uint32_t>(request->configuration));

  auto slot_index = ConfigurationToSlotIndex(request->configuration);
  auto status =
      slot_index ? abr_client_->MarkSlotUnbootable(*slot_index) : zx::error(ZX_ERR_INVALID_ARGS);
  if (status.is_error()) {
    ERROR("Failed to set configuration: %d unbootable\n",
          static_cast<uint32_t>(request->configuration));
    completer.Reply(status.error_value());
    return;
  }

  LOG("Set %d configuration as unbootable\n", static_cast<uint32_t>(request->configuration));

  completer.Reply(ZX_OK);
}

void BootManager::SetConfigurationHealthy(SetConfigurationHealthyRequestView request,
                                          SetConfigurationHealthyCompleter::Sync& completer) {
  LOG("Setting configuration %d as healthy\n", static_cast<uint32_t>(request->configuration));

  auto slot_index = ConfigurationToSlotIndex(request->configuration);
  auto status =
      slot_index ? abr_client_->MarkSlotSuccessful(*slot_index) : zx::error(ZX_ERR_INVALID_ARGS);
  if (status.is_error()) {
    ERROR("Failed to set configuration: %d healthy\n",
          static_cast<uint32_t>(request->configuration));
    completer.Reply(status.error_value());
    return;
  }

  LOG("Set %d configuration as healthy\n", static_cast<uint32_t>(request->configuration));

  completer.Reply(ZX_OK);
}

void Paver::FindSysconfig(FindSysconfigRequestView request,
                          FindSysconfigCompleter::Sync& completer) {
  FindSysconfig(request->sysconfig.TakeChannel());
}

void Paver::FindSysconfig(zx::channel sysconfig) {
  // 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();
  }
  Sysconfig::Bind(dispatcher_, devfs_root_.duplicate(), std::move(svc_root_), context_,
                  std::move(sysconfig));
}

}  // namespace paver
