blob: 879c5954039c629fff382ed37c4b128aa0ee40d2 [file] [log] [blame]
// Copyright 2019 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 "svcfs-service.h"
#include <fuchsia/boot/c/fidl.h>
#include <lib/fidl-async/bind.h>
#include <lib/zx/job.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include "util.h"
namespace {
struct ArgumentsData {
zx::vmo vmo;
size_t size;
};
zx_status_t ArgumentsGet(void* ctx, fidl_txn_t* txn) {
auto data = static_cast<const ArgumentsData*>(ctx);
zx::vmo dup;
zx_status_t status = data->vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup);
if (status != ZX_OK) {
printf("bootsvc: Failed to duplicate boot arguments VMO: %s\n",
zx_status_get_string(status));
return status;
}
return fuchsia_boot_ArgumentsGet_reply(txn, dup.release(), data->size);
}
constexpr fuchsia_boot_Arguments_ops kArgumentsOps = {
.Get = ArgumentsGet,
};
struct ItemsData {
zx::vmo vmo;
bootsvc::ItemMap map;
};
zx_status_t ItemsGet(void* ctx, uint32_t type, uint32_t extra, fidl_txn_t* txn) {
auto data = static_cast<const ItemsData*>(ctx);
auto it = data->map.find(bootsvc::ItemKey{type, extra});
if (it == data->map.end()) {
return fuchsia_boot_ItemsGet_reply(txn, ZX_HANDLE_INVALID, 0);
}
auto& item = it->second;
auto buf = std::make_unique<uint8_t[]>(item.length);
zx_status_t status = data->vmo.read(buf.get(), item.offset, item.length);
if (status != ZX_OK) {
printf("bootsvc: Failed to read from boot image VMO: %s\n", zx_status_get_string(status));
return status;
}
zx::vmo payload;
status = zx::vmo::create(item.length, 0, &payload);
if (status != ZX_OK) {
printf("bootsvc: Failed to create payload VMO: %s\n", zx_status_get_string(status));
return status;
}
status = payload.write(buf.get(), 0, item.length);
if (status != ZX_OK) {
printf("bootsvc: Failed to write to payload VMO: %s\n", zx_status_get_string(status));
return status;
}
return fuchsia_boot_ItemsGet_reply(txn, payload.release(), item.length);
}
constexpr fuchsia_boot_Items_ops kItemsOps = {
.Get = ItemsGet,
};
zx_status_t RootJobGet(void* ctx, fidl_txn_t* txn) {
zx::job dup;
zx_status_t status = zx::job::default_job()->duplicate(ZX_RIGHT_SAME_RIGHTS, &dup);
if (status != ZX_OK) {
printf("bootsvc: Failed to duplicate root job: %s\n", zx_status_get_string(status));
return status;
}
return fuchsia_boot_RootJobGet_reply(txn, dup.release());
}
constexpr fuchsia_boot_RootJob_ops kRootJobOps = {
.Get = RootJobGet,
};
zx_status_t RootResourceGet(void* ctx, fidl_txn_t* txn) {
zx::resource resource(zx_take_startup_handle(PA_HND(PA_RESOURCE, 0)));
if (!resource.is_valid()) {
printf("bootsvc: Invalid root resource\n");
return ZX_ERR_NOT_FOUND;
}
return fuchsia_boot_RootResourceGet_reply(txn, resource.release());
}
constexpr fuchsia_boot_RootResource_ops kRootResourceOps = {
.Get = RootResourceGet,
};
} // namespace
namespace bootsvc {
fbl::RefPtr<SvcfsService> SvcfsService::Create(async_dispatcher_t* dispatcher) {
return fbl::AdoptRef(new SvcfsService(dispatcher));
}
SvcfsService::SvcfsService(async_dispatcher_t* dispatcher)
: vfs_(dispatcher), root_(fbl::MakeRefCounted<fs::PseudoDir>()) {}
void SvcfsService::AddService(const char* service_name, fbl::RefPtr<fs::Service> service) {
root_->AddEntry(service_name, std::move(service));
}
zx_status_t SvcfsService::CreateRootConnection(zx::channel* out) {
return CreateVnodeConnection(&vfs_, root_, out);
}
fbl::RefPtr<fs::Service> CreateArgumentsService(async_dispatcher_t* dispatcher, zx::vmo vmo,
uint64_t size) {
ArgumentsData data{std::move(vmo), size};
return fbl::MakeRefCounted<fs::Service>(
[dispatcher, data = std::move(data)](zx::channel channel) mutable {
auto dispatch = reinterpret_cast<fidl_dispatch_t*>(fuchsia_boot_Arguments_dispatch);
return fidl_bind(dispatcher, channel.release(), dispatch, &data, &kArgumentsOps);
});
}
fbl::RefPtr<fs::Service> CreateItemsService(async_dispatcher_t* dispatcher, zx::vmo vmo,
ItemMap map) {
ItemsData data{std::move(vmo), std::move(map)};
return fbl::MakeRefCounted<fs::Service>(
[dispatcher, data = std::move(data)](zx::channel channel) mutable {
auto dispatch = reinterpret_cast<fidl_dispatch_t*>(fuchsia_boot_Items_dispatch);
return fidl_bind(dispatcher, channel.release(), dispatch, &data, &kItemsOps);
});
}
fbl::RefPtr<fs::Service> CreateRootJobService(async_dispatcher_t* dispatcher) {
return fbl::MakeRefCounted<fs::Service>([dispatcher](zx::channel channel) {
auto dispatch = reinterpret_cast<fidl_dispatch_t*>(fuchsia_boot_RootJob_dispatch);
return fidl_bind(dispatcher, channel.release(), dispatch, nullptr, &kRootJobOps);
});
}
fbl::RefPtr<fs::Service> CreateRootResourceService(async_dispatcher_t* dispatcher) {
return fbl::MakeRefCounted<fs::Service>([dispatcher](zx::channel channel) {
auto dispatch = reinterpret_cast<fidl_dispatch_t*>(fuchsia_boot_RootResource_dispatch);
return fidl_bind(dispatcher, channel.release(), dispatch, nullptr, &kRootResourceOps);
});
}
} // namespace bootsvc