blob: 9063b67abe1fde33fc1de856283bdef544914ebf [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.
#include "garnet/bin/guest/runner/runner_impl.h"
#include <fuchsia/guest/vmm/cpp/fidl.h>
#include <memory>
#include "lib/fxl/logging.h"
#include "lib/svc/cpp/service_provider_bridge.h"
namespace guest_runner {
RunnerImpl::RunnerImpl()
: context_(component::StartupContext::CreateFromStartupInfo()) {
context_->environment()->GetLauncher(launcher_.NewRequest());
context_->outgoing().AddPublicService(bindings_.GetHandler(this));
}
void RunnerImpl::StartComponent(
fuchsia::sys::Package application, fuchsia::sys::StartupInfo startup_info,
::fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) {
fuchsia::sys::LaunchInfo launch_info;
// Pass-through our arguments directly to the vmm package.
launch_info.url = "fuchsia-pkg://fuchsia.com/vmm#meta/vmm.cmx";
launch_info.arguments = std::move(startup_info.launch_info.arguments);
launch_info.directory_request =
std::move(startup_info.launch_info.directory_request);
launch_info.flat_namespace = fuchsia::sys::FlatNamespace::New();
for (size_t i = 0; i < startup_info.flat_namespace.paths->size(); ++i) {
const auto& path = (*startup_info.flat_namespace.paths)[i];
if (path == "/pkg") {
// Expose the specific guest package under the /guest namespace.
launch_info.flat_namespace->paths.push_back("/guest");
launch_info.flat_namespace->directories.push_back(
std::move((*startup_info.flat_namespace.directories)[i]));
} else if (path == "/svc") {
// Hack: We've provided some 'additional_services' to the vmm, but those
// are loaded in the /svc in the provided flat_namespace here. Appmgr
// doesn't allow overriding the /svc namespace of the vmm, instead it
// initialized it to the set of services requested in the vmm.cmx.
//
// The solution here is to invert the dependency between guestmgr and the
// guest_runner. Apps that call the guestmgr directly can just embed the
// artifacts they need into their own package and don't need to use a
// companion guest package. Then the runner can be used for the
// standalone guest packages (ex: linux_guest/zircon_guest).
//
// Note: the leaking of the |ServiceProviderBridge| is intentional. We
// could wrap the ComponentController in one that we retain here so we can
// intercept the error event and cleanup, but since this is temporary we
// can live with this.
//
// See: MAC-181
auto bridge = new component::ServiceProviderBridge;
auto service_list = fuchsia::sys::ServiceList::New();
// This must list every service the vmm depends on. We don't provide
// any implementations here since the ServiceProviderBridge takes care
// of that for us via the backing_dir, which is the above /svc directory.
service_list->names.push_back(
fuchsia::guest::vmm::LaunchInfoProvider::Name_);
bridge->set_backing_dir(
std::move((*startup_info.flat_namespace.directories)[i]));
service_list->provider = bridge->AddBinding();
launch_info.additional_services = std::move(service_list);
}
}
launcher_->CreateComponent(std::move(launch_info), std::move(controller));
}
} // namespace guest_runner