From 70671addd6a9b36095c7f4e8e185ae08264296e1 Mon Sep 17 00:00:00 2001 From: Suraj Malhotra <surajmalhotra@google.com> Date: Thu, 9 May 2019 03:24:52 +0000 Subject: [PATCH] [svchost][devmgr][miscsvc] Add miscsvc Was originally submitted as Id411227e4c3d2b8add49978cf6ce1a76de509a48. Startup a miscsvc binary, and provide a channel to it's '/svc/ directory to svchost, which will then forward it services. To start miscsvc only implements the paver service. ZX-3861 Change-Id: I83a630476c08d15e461d74e3321ad55bb21a3c2f --- build/images/zedboot/BUILD.gn | 1 + .../core/devmgr/devcoordinator/BUILD.gn | 1 + .../core/devmgr/devcoordinator/main.cpp | 36 ++++++ zircon/system/core/miscsvc/BUILD.gn | 17 +++ zircon/system/core/miscsvc/README.md | 12 ++ zircon/system/core/miscsvc/miscsvc.cpp | 117 ++++++++++++++++++ zircon/system/core/svchost/BUILD.gn | 1 + zircon/system/core/svchost/svchost.cpp | 9 ++ zircon/system/utest/BUILD.gn | 1 + zircon/system/utest/miscsvc/BUILD.gn | 15 +++ zircon/system/utest/miscsvc/main.cpp | 33 +++++ 11 files changed, 243 insertions(+) create mode 100644 zircon/system/core/miscsvc/BUILD.gn create mode 100644 zircon/system/core/miscsvc/README.md create mode 100644 zircon/system/core/miscsvc/miscsvc.cpp create mode 100644 zircon/system/utest/miscsvc/BUILD.gn create mode 100644 zircon/system/utest/miscsvc/main.cpp diff --git a/build/images/zedboot/BUILD.gn b/build/images/zedboot/BUILD.gn index 702321fe23f..7b4bca6c920 100644 --- a/build/images/zedboot/BUILD.gn +++ b/build/images/zedboot/BUILD.gn @@ -40,6 +40,7 @@ zedboot_binary_patterns = [ "bin/devcoordinator", "bin/dlog", "bin/fshost", + "bin/miscsvc", "bin/netsvc", "bin/pwrbtn-monitor", "bin/svchost", diff --git a/zircon/system/core/devmgr/devcoordinator/BUILD.gn b/zircon/system/core/devmgr/devcoordinator/BUILD.gn index 86cc6ea4bc0..dca2bab5c5b 100644 --- a/zircon/system/core/devmgr/devcoordinator/BUILD.gn +++ b/zircon/system/core/devmgr/devcoordinator/BUILD.gn @@ -19,6 +19,7 @@ executable("devcoordinator") { data_deps = [ ":internal-drivers", "../fshost", + "$zx/system/core/miscsvc", "$zx/system/core/netsvc", "$zx/system/core/svchost", "$zx/system/core/virtcon:virtual-console", diff --git a/zircon/system/core/devmgr/devcoordinator/main.cpp b/zircon/system/core/devmgr/devcoordinator/main.cpp index dc5c1c05269..9f497836661 100644 --- a/zircon/system/core/devmgr/devcoordinator/main.cpp +++ b/zircon/system/core/devmgr/devcoordinator/main.cpp @@ -68,6 +68,12 @@ struct { // If appmgr cannot be launched within a timeout, this handle is closed. zx::channel appmgr_server; + // The handle used to transmit messages to miscsvc. + zx::channel miscsvc_client; + + // The handle used by miscsvc to serve incoming requests. + zx::channel miscsvc_server; + zx::unowned_job root_job; zx::job svc_job; zx::job fuchsia_job; @@ -406,6 +412,8 @@ zx_status_t svchost_start(bool require_system, devmgr::Coordinator* coordinator, zx::debuglog logger; zx::channel appmgr_svc_req; zx::channel appmgr_svc; + zx::channel miscsvc_svc_req; + zx::channel miscsvc_svc; zx_status_t status = zx::channel::create(0, &dir_request, &svchost_local); if (status != ZX_OK) { @@ -428,6 +436,18 @@ zx_status_t svchost_start(bool require_system, devmgr::Coordinator* coordinator, return status; } + status = zx::channel::create(0, &miscsvc_svc_req, &miscsvc_svc); + if (status != ZX_OK) { + return status; + } + + status = + fdio_service_connect_at(g_handles.miscsvc_client.get(), "public", + miscsvc_svc_req.release()); + if (status != ZX_OK) { + return status; + } + const char* name = "svchost"; const char* argv[2] = { "/boot/bin/svchost", @@ -518,6 +538,9 @@ zx_status_t svchost_start(bool require_system, devmgr::Coordinator* coordinator, launchpad_add_handle(lp, virtcon_client.release(), PA_HND(PA_USER0, 5)); } + // Add handle to channel to allow svchost to talk to miscsvc. + launchpad_add_handle(lp, miscsvc_svc.release(), PA_HND(PA_USER0, 6)); + // Give svchost access to /dev/class/sysmem, to enable svchost to forward sysmem service // requests to the sysmem driver. Create a namespace containing /dev/class/sysmem. const char* nametable[1] = {}; @@ -656,6 +679,18 @@ void devmgr_vfs_init(devmgr::Coordinator* coordinator, const devmgr::DevmgrArgs& int service_starter(void* arg) { auto coordinator = static_cast<devmgr::Coordinator*>(arg); + // Launch miscsvc binary with access to: + // * /dev to talk to hardware + // * /boot to dynamically load drivers (zxcrypt) + // * /svc to call launch processes (minfs) + // * /volume to mount (minfs) + const zx_handle_t handles[] = { g_handles.miscsvc_server.release() }; + const uint32_t types[] = { PA_DIRECTORY_REQUEST }; + const char* args[] = { "/boot/bin/miscsvc", nullptr }; + + devmgr::devmgr_launch(g_handles.svc_job, "miscsvc", args, nullptr, -1, handles, + types, countof(handles), nullptr, FS_BOOT | FS_DEV | FS_SVC | FS_VOLUME); + bool netboot = false; bool vruncmd = false; fbl::String vcmd; @@ -978,6 +1013,7 @@ int main(int argc, char** argv) { zx::channel fshost_client, fshost_server; zx::channel::create(0, &fshost_client, &fshost_server); zx::channel::create(0, &g_handles.appmgr_client, &g_handles.appmgr_server); + zx::channel::create(0, &g_handles.miscsvc_client, &g_handles.miscsvc_server); if (devmgr_args.use_system_svchost) { zx::channel dir_request; diff --git a/zircon/system/core/miscsvc/BUILD.gn b/zircon/system/core/miscsvc/BUILD.gn new file mode 100644 index 00000000000..651e491867b --- /dev/null +++ b/zircon/system/core/miscsvc/BUILD.gn @@ -0,0 +1,17 @@ +# 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. + +executable("miscsvc") { + sources = [ + "miscsvc.cpp", + ] + deps = [ + "$zx/system/ulib/async-loop:async-loop-cpp", + "$zx/system/ulib/fbl", + "$zx/system/ulib/fdio", + "$zx/system/ulib/paver", + "$zx/system/ulib/svc", + "$zx/system/ulib/zircon", + ] +} diff --git a/zircon/system/core/miscsvc/README.md b/zircon/system/core/miscsvc/README.md new file mode 100644 index 00000000000..b019e94785a --- /dev/null +++ b/zircon/system/core/miscsvc/README.md @@ -0,0 +1,12 @@ +# Miscellaneous Service + +This service provides a tempoary home for services which need to be available +prior to appmgr being launched, but don't want the tedium of setting up their +own process. These services previously were hosted by svchost, but has proved +problematic, so they have been isolated into a separate process. + +Services implemented by miscsvc are exposed to svchost, which exposes it out +further to other parts of the system. + +Once component manager lands in bootfs, and adequate build support arrives, +these services can be rewritten as components. diff --git a/zircon/system/core/miscsvc/miscsvc.cpp b/zircon/system/core/miscsvc/miscsvc.cpp new file mode 100644 index 00000000000..98a93e2d349 --- /dev/null +++ b/zircon/system/core/miscsvc/miscsvc.cpp @@ -0,0 +1,117 @@ +// 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 <fbl/algorithm.h> +#include <lib/async-loop/cpp/loop.h> +#include <lib/paver/provider.h> +#include <lib/svc/outgoing.h> +#include <zircon/status.h> + +// An instance of a zx_service_provider_t. +// +// Includes the |ctx| pointer for the zx_service_provider_t. +typedef struct zx_service_provider_instance { + // The service provider for which this structure is an instance. + const zx_service_provider_t* provider; + + // The |ctx| pointer returned by the provider's |init| function, if any. + void* ctx; +} zx_service_provider_instance_t; + +static zx_status_t provider_init(zx_service_provider_instance_t* instance) { + if (instance->provider->ops->init) { + zx_status_t status = instance->provider->ops->init(&instance->ctx); + if (status != ZX_OK) + return status; + } + return ZX_OK; +} + +static zx_status_t provider_publish(zx_service_provider_instance_t* instance, + async_dispatcher_t* dispatcher, + const fbl::RefPtr<fs::PseudoDir>& dir) { + const zx_service_provider_t* provider = instance->provider; + + if (!provider->services || !provider->ops->connect) + return ZX_ERR_INVALID_ARGS; + + for (size_t i = 0; provider->services[i]; ++i) { + const char* service_name = provider->services[i]; + zx_status_t status = dir->AddEntry( + service_name, + fbl::MakeRefCounted<fs::Service>( + [instance, dispatcher, service_name](zx::channel request) { + return instance->provider->ops->connect(instance->ctx, dispatcher, service_name, + request.release()); + })); + if (status != ZX_OK) { + for (size_t j = 0; j < i; ++j) + dir->RemoveEntry(provider->services[j]); + return status; + } + } + + return ZX_OK; +} + +static void provider_release(zx_service_provider_instance_t* instance) { + if (instance->provider->ops->release) + instance->provider->ops->release(instance->ctx); + instance->ctx = nullptr; +} + +static zx_status_t provider_load(zx_service_provider_instance_t* instance, + async_dispatcher_t* dispatcher, + const fbl::RefPtr<fs::PseudoDir>& dir) { + if (instance->provider->version != SERVICE_PROVIDER_VERSION) { + return ZX_ERR_INVALID_ARGS; + } + + zx_status_t status = provider_init(instance); + if (status != ZX_OK) { + return status; + } + + status = provider_publish(instance, dispatcher, dir); + if (status != ZX_OK) { + provider_release(instance); + return status; + } + + return ZX_OK; +} + +int main(int argc, char** argv) { + async::Loop loop(&kAsyncLoopConfigNoAttachToThread); + async_dispatcher_t* dispatcher = loop.dispatcher(); + svc::Outgoing outgoing(dispatcher); + + zx_status_t status = outgoing.ServeFromStartupInfo(); + if (status != ZX_OK) { + fprintf(stderr, "miscsvc: error: Failed to serve outgoing directory: %d (%s).\n", + status, zx_status_get_string(status)); + return 1; + } + + zx_service_provider_instance_t service_providers[] = { + {.provider = paver_get_service_provider(), .ctx = nullptr}, + }; + + for (size_t i = 0; i < fbl::count_of(service_providers); ++i) { + status = provider_load(&service_providers[i], dispatcher, outgoing.public_dir()); + if (status != ZX_OK) { + fprintf(stderr, "miscsvc: error: Failed to load service provider %zu: %d (%s).\n", + i, status, zx_status_get_string(status)); + return 1; + } + } + + status = loop.Run(); + + for (size_t i = 0; i < fbl::count_of(service_providers); ++i) { + provider_release(&service_providers[i]); + } + + return status; +} diff --git a/zircon/system/core/svchost/BUILD.gn b/zircon/system/core/svchost/BUILD.gn index cb9f9147f5c..db49f3bfafd 100644 --- a/zircon/system/core/svchost/BUILD.gn +++ b/zircon/system/core/svchost/BUILD.gn @@ -16,6 +16,7 @@ executable("svchost") { "$zx/system/fidl/fuchsia-logger:c", "$zx/system/fidl/fuchsia-mem:c", "$zx/system/fidl/fuchsia-net:c", + "$zx/system/fidl/fuchsia-paver:c", "$zx/system/fidl/fuchsia-process:c", "$zx/system/fidl/fuchsia-scheduler:c", "$zx/system/fidl/fuchsia-sysmem:c", diff --git a/zircon/system/core/svchost/svchost.cpp b/zircon/system/core/svchost/svchost.cpp index c0cc5a962cc..642c97b9fc2 100644 --- a/zircon/system/core/svchost/svchost.cpp +++ b/zircon/system/core/svchost/svchost.cpp @@ -9,6 +9,7 @@ #include <fs/remote-dir.h> #include <fuchsia/device/manager/c/fidl.h> #include <fuchsia/fshost/c/fidl.h> +#include <fuchsia/paver/c/fidl.h> #include <fuchsia/virtualconsole/c/fidl.h> #include <fuchsia/net/c/fidl.h> #include <lib/async-loop/cpp/loop.h> @@ -149,6 +150,12 @@ static constexpr const char* fshost_services[] = { nullptr, }; +// Forward these Zircon services to miscsvc. +static constexpr const char* miscsvc_services[] = { + fuchsia_paver_Paver_Name, + nullptr, +}; + // The ServiceProxy is a Vnode which, if opened, connects to a service. // However, if treated like a directory, the service proxy will attempt to // relay the underlying request to the connected service channel. @@ -237,6 +244,7 @@ int main(int argc, char** argv) { zx::channel devmgr_proxy_channel = zx::channel(zx_take_startup_handle(PA_HND(PA_USER0, 3))); zx::channel fshost_svc = zx::channel(zx_take_startup_handle(PA_HND(PA_USER0, 4))); zx::channel virtcon_proxy_channel = zx::channel(zx_take_startup_handle(PA_HND(PA_USER0, 5))); + zx::channel miscsvc_svc = zx::channel(zx_take_startup_handle(PA_HND(PA_USER0, 6))); zx_status_t status = outgoing.ServeFromStartupInfo(); if (status != ZX_OK) { @@ -292,6 +300,7 @@ int main(int argc, char** argv) { publish_services(outgoing.public_dir(), deprecated_services, zx::unowned_channel(appmgr_svc)); publish_services(outgoing.public_dir(), fshost_services, zx::unowned_channel(fshost_svc)); + publish_services(outgoing.public_dir(), miscsvc_services, zx::unowned_channel(miscsvc_svc)); publish_remote_service(outgoing.public_dir(), fuchsia_device_manager_DebugDumper_Name, diff --git a/zircon/system/utest/BUILD.gn b/zircon/system/utest/BUILD.gn index d1f24665fd7..981fd942ab8 100644 --- a/zircon/system/utest/BUILD.gn +++ b/zircon/system/utest/BUILD.gn @@ -141,6 +141,7 @@ if (current_cpu != "") { "log", "logger", "memfs", + "miscsvc", "msd", "namespace", "perftest", diff --git a/zircon/system/utest/miscsvc/BUILD.gn b/zircon/system/utest/miscsvc/BUILD.gn new file mode 100644 index 00000000000..d1f14282681 --- /dev/null +++ b/zircon/system/utest/miscsvc/BUILD.gn @@ -0,0 +1,15 @@ +# 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. + +test("miscsvc") { + sources = [ "main.cpp" ] + deps = [ + "$zx/system/fidl/fuchsia-paver:c", + "$zx/system/ulib/fdio", + "$zx/system/ulib/zircon", + "$zx/system/ulib/zx", + "$zx/system/ulib/zxcpp", + "$zx/system/ulib/zxtest", + ] +} diff --git a/zircon/system/utest/miscsvc/main.cpp b/zircon/system/utest/miscsvc/main.cpp new file mode 100644 index 00000000000..ae47a70eb68 --- /dev/null +++ b/zircon/system/utest/miscsvc/main.cpp @@ -0,0 +1,33 @@ +// 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 <fcntl.h> + +#include <fuchsia/paver/c/fidl.h> +#include <lib/fdio/fd.h> +#include <lib/fdio/fdio.h> +#include <lib/fdio/directory.h> +#include <lib/zx/channel.h> +#include <lib/zx/vmo.h> +#include <zxtest/zxtest.h> +#include <zircon/status.h> +#include <zircon/syscalls.h> + +namespace { + +TEST(MiscSvcTest, PaverSvccEnumeratesSuccessfully) { + zx::channel svc_local, svc_remote; + ASSERT_OK(zx::channel::create(0, &svc_local, &svc_remote)); + ASSERT_OK(fdio_service_connect("/svc", svc_remote.release())); + + zx::channel local, remote; + ASSERT_OK(zx::channel::create(0, &local, &remote)); + ASSERT_OK(fdio_service_connect_at(svc_local.get(), fuchsia_paver_Paver_Name, remote.release())); + + zx_status_t status; + fuchsia_paver_Configuration* configuration; + ASSERT_OK(fuchsia_paver_PaverQueryActiveConfiguration(local.get(), &status, &configuration)); +} + +} // namespace -- GitLab