blob: 290311e0c4ceb06b9cd3a968fc5638bc826e3168 [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 ZIRCON_SYSTEM_ULIB_PAVER_PAVER_H_
#define ZIRCON_SYSTEM_ULIB_PAVER_PAVER_H_
#include <fuchsia/paver/llcpp/fidl.h>
#include <lib/zx/channel.h>
#include <zircon/types.h>
#include <variant>
#include <fbl/string.h>
#include <fbl/unique_fd.h>
#include "abr-client.h"
#include "device-partitioner.h"
#include "lib/async/dispatcher.h"
namespace paver {
class Paver : public ::llcpp::fuchsia::paver::Paver::Interface {
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 FindBootManager(zx::channel boot_manager, FindBootManagerCompleter::Sync completer) override;
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(zx::channel svc_root) { svc_root_ = std::move(svc_root); }
private:
// Used for test injection.
fbl::unique_fd devfs_root_;
zx::channel svc_root_;
async_dispatcher_t* dispatcher_ = nullptr;
};
// 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_t ReadAsset(::llcpp::fuchsia::paver::Configuration configuration,
::llcpp::fuchsia::paver::Asset asset, ::llcpp::fuchsia::mem::Buffer* buf);
zx_status_t 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(
fidl::StringView type, ::llcpp::fuchsia::mem::Buffer payload);
zx_status_t WriteVolumes(zx::channel payload_stream);
zx_status_t WriteBootloader(::llcpp::fuchsia::mem::Buffer payload);
zx_status_t WriteDataFile(fidl::StringView filename, ::llcpp::fuchsia::mem::Buffer payload);
zx_status_t WipeVolume(zx::channel* out);
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::Interface {
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, zx::channel svc_root,
zx::channel server);
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)));
}
void WriteFirmware(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)));
}
void WriteBootloader(::llcpp::fuchsia::mem::Buffer payload,
WriteBootloaderCompleter::Sync completer) override {
completer.Reply(sink_.WriteBootloader(std::move(payload)));
}
void WriteDataFile(fidl::StringView filename, ::llcpp::fuchsia::mem::Buffer payload,
WriteDataFileCompleter::Sync completer) override {
completer.Reply(sink_.WriteDataFile(std::move(filename), std::move(payload)));
}
void WipeVolume(WipeVolumeCompleter::Sync completer) override;
private:
DataSinkImpl sink_;
};
class DynamicDataSink : public ::llcpp::fuchsia::paver::DynamicDataSink::Interface {
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, zx::channel svc_root,
zx::channel block_device, zx::channel server);
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)));
}
void WriteFirmware(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)));
}
void WriteBootloader(::llcpp::fuchsia::mem::Buffer payload,
WriteBootloaderCompleter::Sync completer) override {
completer.Reply(sink_.WriteBootloader(std::move(payload)));
}
void WriteDataFile(fidl::StringView filename, ::llcpp::fuchsia::mem::Buffer payload,
WriteDataFileCompleter::Sync completer) override {
completer.Reply(sink_.WriteDataFile(std::move(filename), std::move(payload)));
}
void WipeVolume(WipeVolumeCompleter::Sync completer) override;
private:
DataSinkImpl sink_;
};
class BootManager : public ::llcpp::fuchsia::paver::BootManager::Interface {
public:
BootManager(std::unique_ptr<abr::Client> abr_client) : abr_client_(std::move(abr_client)) {}
static void Bind(async_dispatcher_t* dispatcher, fbl::unique_fd devfs_root, zx::channel svc_root,
zx::channel server);
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 SetActiveConfigurationHealthy(
SetActiveConfigurationHealthyCompleter::Sync completer) override;
private:
std::unique_ptr<abr::Client> abr_client_;
};
} // namespace paver
#endif // ZIRCON_SYSTEM_ULIB_PAVER_PAVER_H_