blob: 95ae1d24c96564f6756898936619d15bf4261260 [file] [log] [blame]
// 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.
#ifndef SRC_STORAGE_LIB_PAVER_PAVER_H_
#define SRC_STORAGE_LIB_PAVER_PAVER_H_
#include <fuchsia/paver/llcpp/fidl.h>
#include <lib/zx/channel.h>
#include <zircon/types.h>
#include <variant>
#include <fbl/mutex.h>
#include <fbl/string.h>
#include <fbl/unique_fd.h>
#include "abr-client.h"
#include "device-partitioner.h"
#include "lib/async/dispatcher.h"
#include "paver-context.h"
namespace paver {
class Paver : public ::llcpp::fuchsia::paver::Paver::RawChannelInterface {
using Interface::FindSysconfig;
using Interface::UseBlockDevice;
public:
void FindDataSink(zx::channel data_sink, FindDataSinkCompleter::Sync& completer) override;
void UseBlockDevice(zx::channel block_device, zx::channel dynamic_data_sink,
UseBlockDeviceCompleter::Sync& completer) override;
void UseBlockDevice(zx::channel block_device, zx::channel dynamic_data_sink);
void FindBootManager(zx::channel boot_manager,
FindBootManagerCompleter::Sync& completer) override;
void FindSysconfig(zx::channel sysconfig, FindSysconfigCompleter::Sync& completer) override;
void FindSysconfig(zx::channel sysconfig);
void set_dispatcher(async_dispatcher_t* dispatcher) { dispatcher_ = dispatcher; }
void set_devfs_root(fbl::unique_fd devfs_root) { devfs_root_ = std::move(devfs_root); }
void set_svc_root(fidl::ClientEnd<::llcpp::fuchsia::io::Directory> svc_root) {
svc_root_ = std::move(svc_root);
}
Paver() : context_(std::make_shared<Context>()) {}
private:
// Used for test injection.
fbl::unique_fd devfs_root_;
fidl::ClientEnd<::llcpp::fuchsia::io::Directory> svc_root_;
async_dispatcher_t* dispatcher_ = nullptr;
// Declared as shared_ptr to avoid life time issues (i.e. Paver exiting before the created device
// partitioners).
std::shared_ptr<Context> context_;
};
// Common shared implementation for DataSink and DynamicDataSink. Necessary to work around lack of
// "is-a" relationship in llcpp bindings.
class DataSinkImpl {
public:
DataSinkImpl(fbl::unique_fd devfs_root, std::unique_ptr<DevicePartitioner> partitioner)
: devfs_root_(std::move(devfs_root)), partitioner_(std::move(partitioner)) {}
zx::status<::llcpp::fuchsia::mem::Buffer> ReadAsset(
::llcpp::fuchsia::paver::Configuration configuration, ::llcpp::fuchsia::paver::Asset asset);
zx::status<> WriteAsset(::llcpp::fuchsia::paver::Configuration configuration,
::llcpp::fuchsia::paver::Asset asset,
::llcpp::fuchsia::mem::Buffer payload);
// FIDL llcpp unions don't currently support memory ownership so we need to
// return something that does own the underlying memory.
//
// Once unions do support owned memory we can just return
// WriteBootloaderResult directly here.
std::variant<zx_status_t, fidl::aligned<bool>> WriteFirmware(
::llcpp::fuchsia::paver::Configuration configuration, fidl::StringView type,
::llcpp::fuchsia::mem::Buffer payload);
zx::status<> WriteVolumes(zx::channel payload_stream);
zx::status<> WriteBootloader(::llcpp::fuchsia::mem::Buffer payload);
zx::status<> WriteDataFile(fidl::StringView filename, ::llcpp::fuchsia::mem::Buffer payload);
zx::status<zx::channel> WipeVolume();
DevicePartitioner* partitioner() { return partitioner_.get(); }
private:
// Used for test injection.
fbl::unique_fd devfs_root_;
std::unique_ptr<DevicePartitioner> partitioner_;
};
class DataSink : public ::llcpp::fuchsia::paver::DataSink::RawChannelInterface {
public:
DataSink(fbl::unique_fd devfs_root, std::unique_ptr<DevicePartitioner> partitioner)
: sink_(std::move(devfs_root), std::move(partitioner)) {}
// Automatically finds block device to use.
static void Bind(async_dispatcher_t* dispatcher, fbl::unique_fd devfs_root,
fidl::ClientEnd<::llcpp::fuchsia::io::Directory> svc_root, zx::channel server,
std::shared_ptr<Context> context);
void ReadAsset(::llcpp::fuchsia::paver::Configuration configuration,
::llcpp::fuchsia::paver::Asset asset,
ReadAssetCompleter::Sync& completer) override;
void WriteAsset(::llcpp::fuchsia::paver::Configuration configuration,
::llcpp::fuchsia::paver::Asset asset, ::llcpp::fuchsia::mem::Buffer payload,
WriteAssetCompleter::Sync& completer) override {
completer.Reply(sink_.WriteAsset(configuration, asset, std::move(payload)).status_value());
}
void WriteFirmware(::llcpp::fuchsia::paver::Configuration configuration, fidl::StringView type,
::llcpp::fuchsia::mem::Buffer payload,
WriteFirmwareCompleter::Sync& completer) override;
void WriteVolumes(zx::channel payload_stream, WriteVolumesCompleter::Sync& completer) override {
completer.Reply(sink_.WriteVolumes(std::move(payload_stream)).status_value());
}
void WriteBootloader(::llcpp::fuchsia::mem::Buffer payload,
WriteBootloaderCompleter::Sync& completer) override {
completer.Reply(sink_.WriteBootloader(std::move(payload)).status_value());
}
void WriteDataFile(fidl::StringView filename, ::llcpp::fuchsia::mem::Buffer payload,
WriteDataFileCompleter::Sync& completer) override {
completer.Reply(sink_.WriteDataFile(std::move(filename), std::move(payload)).status_value());
}
void WipeVolume(WipeVolumeCompleter::Sync& completer) override;
void Flush(FlushCompleter::Sync& completer) override {
completer.Reply(sink_.partitioner()->Flush().status_value());
}
private:
DataSinkImpl sink_;
};
class DynamicDataSink : public ::llcpp::fuchsia::paver::DynamicDataSink::RawChannelInterface {
public:
DynamicDataSink(fbl::unique_fd devfs_root, std::unique_ptr<DevicePartitioner> partitioner)
: sink_(std::move(devfs_root), std::move(partitioner)) {}
static void Bind(async_dispatcher_t* dispatcher, fbl::unique_fd devfs_root,
fidl::ClientEnd<::llcpp::fuchsia::io::Directory> svc_root,
zx::channel block_device, zx::channel server, std::shared_ptr<Context> context);
void InitializePartitionTables(InitializePartitionTablesCompleter::Sync& completer) override;
void WipePartitionTables(WipePartitionTablesCompleter::Sync& completer) override;
void ReadAsset(::llcpp::fuchsia::paver::Configuration configuration,
::llcpp::fuchsia::paver::Asset asset,
ReadAssetCompleter::Sync& completer) override;
void WriteAsset(::llcpp::fuchsia::paver::Configuration configuration,
::llcpp::fuchsia::paver::Asset asset, ::llcpp::fuchsia::mem::Buffer payload,
WriteAssetCompleter::Sync& completer) override {
completer.Reply(sink_.WriteAsset(configuration, asset, std::move(payload)).status_value());
}
void WriteFirmware(::llcpp::fuchsia::paver::Configuration configuration, fidl::StringView type,
::llcpp::fuchsia::mem::Buffer payload,
WriteFirmwareCompleter::Sync& completer) override;
void WriteVolumes(zx::channel payload_stream, WriteVolumesCompleter::Sync& completer) override {
completer.Reply(sink_.WriteVolumes(std::move(payload_stream)).status_value());
}
void WriteBootloader(::llcpp::fuchsia::mem::Buffer payload,
WriteBootloaderCompleter::Sync& completer) override {
completer.Reply(sink_.WriteBootloader(std::move(payload)).status_value());
}
void WriteDataFile(fidl::StringView filename, ::llcpp::fuchsia::mem::Buffer payload,
WriteDataFileCompleter::Sync& completer) override {
completer.Reply(sink_.WriteDataFile(std::move(filename), std::move(payload)).status_value());
}
void WipeVolume(WipeVolumeCompleter::Sync& completer) override;
void Flush(FlushCompleter::Sync& completer) override {
completer.Reply(sink_.partitioner()->Flush().status_value());
}
private:
DataSinkImpl sink_;
};
class BootManager : public ::llcpp::fuchsia::paver::BootManager::Interface {
public:
BootManager(std::unique_ptr<abr::Client> abr_client,
fidl::ClientEnd<::llcpp::fuchsia::io::Directory> svc_root)
: abr_client_(std::move(abr_client)), svc_root_(std::move(svc_root)) {}
static void Bind(async_dispatcher_t* dispatcher, fbl::unique_fd devfs_root,
fidl::ClientEnd<::llcpp::fuchsia::io::Directory> svc_root,
std::shared_ptr<Context> context, zx::channel server);
void QueryCurrentConfiguration(QueryCurrentConfigurationCompleter::Sync& completer) override;
void QueryActiveConfiguration(QueryActiveConfigurationCompleter::Sync& completer) override;
void QueryConfigurationStatus(::llcpp::fuchsia::paver::Configuration configuration,
QueryConfigurationStatusCompleter::Sync& completer) override;
void SetConfigurationActive(::llcpp::fuchsia::paver::Configuration configuration,
SetConfigurationActiveCompleter::Sync& completer) override;
void SetConfigurationUnbootable(::llcpp::fuchsia::paver::Configuration configuration,
SetConfigurationUnbootableCompleter::Sync& completer) override;
void SetConfigurationHealthy(::llcpp::fuchsia::paver::Configuration configuration,
SetConfigurationHealthyCompleter::Sync& completer) override;
void Flush(FlushCompleter::Sync& completer) override {
completer.Reply(abr_client_->Flush().status_value());
}
private:
std::unique_ptr<abr::Client> abr_client_;
fidl::ClientEnd<::llcpp::fuchsia::io::Directory> svc_root_;
};
} // namespace paver
#endif // SRC_STORAGE_LIB_PAVER_PAVER_H_