blob: 4cb1b08ab615732c3d43a744362270fc87cc8a69 [file] [log] [blame] [edit]
// 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 "src/virtualization/bin/guest/launch.h"
#include <lib/syslog/cpp/macros.h>
#include <zircon/status.h>
#include <unordered_map>
#include "fuchsia/virtualization/cpp/fidl.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/virtualization/bin/guest/serial.h"
namespace {
const std::unordered_map<std::string, std::string> kGuestTypes = {
{"zircon", "fuchsia-pkg://fuchsia.com/zircon_guest#meta/zircon_guest.cmx"},
{"debian", "fuchsia-pkg://fuchsia.com/debian_guest#meta/debian_guest.cmx"},
{"termina", "fuchsia-pkg://fuchsia.com/termina_guest#meta/termina_guest.cmx"},
};
void PrintSupportedGuests(const char* guest) {
fprintf(stderr, "Unrecognized guest type: %s. Supported guests:\n", guest);
for (const auto& it : kGuestTypes) {
fprintf(stderr, " %s\n", it.first.c_str());
}
}
std::string GetGuestUrl(const std::string& guest) {
auto it = kGuestTypes.find(guest);
return it == kGuestTypes.end() ? "" : it->second;
}
} // namespace
zx_status_t handle_launch(int argc, const char** argv, async::Loop* loop,
fuchsia::virtualization::GuestConfig cfg,
sys::ComponentContext* context) {
std::string guest_url = GetGuestUrl(argv[0]);
if (guest_url.empty()) {
PrintSupportedGuests(argv[0]);
return ZX_ERR_INVALID_ARGS;
}
fprintf(stdout, "Starting %s with package %s.\n", argv[0], guest_url.c_str());
// Create environment.
fuchsia::virtualization::ManagerPtr manager;
zx_status_t status = context->svc()->Connect(manager.NewRequest());
if (status != ZX_OK) {
printf("Failed to connect to guest manager: %s\n", zx_status_get_string(status));
return status;
}
fuchsia::virtualization::RealmPtr realm;
manager->Create(argv[0], realm.NewRequest());
// Launch guest.
fuchsia::virtualization::GuestPtr guest;
realm->LaunchInstance(guest_url, cpp17::nullopt, std::move(cfg), guest.NewRequest(),
[](uint32_t) {});
// Set up error handling.
guest.set_error_handler([&loop](zx_status_t status) {
fprintf(stderr, "Connection to guest closed: %s\n", zx_status_get_string(status));
loop->Quit();
});
// Set up serial output.
OutputWriter serial(loop);
guest->GetSerial([&loop, &serial](fuchsia::virtualization::Guest_GetSerial_Result result) {
if (result.is_err()) {
fprintf(stderr, "Could not connect to guest serial: %s\n",
zx_status_get_string(result.err()));
loop->Quit();
return;
}
serial.Start(std::move(result.response()).socket);
});
// Set up guest console.
GuestConsole console(loop);
guest->GetConsole([&loop, &console](fuchsia::virtualization::Guest_GetConsole_Result result) {
if (result.is_err()) {
fprintf(stderr, "Could not connect to guest console: %s.\n",
zx_status_get_string(result.err()));
loop->Quit();
return;
}
console.Start(std::move(result.response()).socket);
});
return loop->Run();
}