blob: 3c5eea9ae8e3f84763e50364b657a58c7095a603 [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 <fuchsia/boot/llcpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fs-pty/service.h>
#include <lib/svc/outgoing.h>
#include <lib/zx/eventpair.h>
#include <lib/zx/resource.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include "console.h"
namespace {
zx::resource GetRootResource() {
zx::channel local, remote;
zx_status_t status = zx::channel::create(0, &local, &remote);
if (status != ZX_OK) {
return {};
}
status = fdio_service_connect("/svc/fuchsia.boot.RootResource", remote.release());
if (status != ZX_OK) {
printf("console: Could not connect to RootResource service: %s\n",
zx_status_get_string(status));
return {};
}
::llcpp::fuchsia::boot::RootResource::SyncClient client(std::move(local));
auto result = client.Get();
if (result.status() != ZX_OK) {
printf("console: Could not retrieve RootResource: %s\n", zx_status_get_string(result.status()));
return {};
}
zx::resource root_resource(std::move(result.Unwrap()->resource));
return root_resource;
}
} // namespace
int main(int argc, const char** argv) {
zx::resource root_resource(GetRootResource());
// Provide a RxSource that grabs the data from the kernel serial connection
Console::RxSource rx_source = [root_resource = std::move(root_resource)](uint8_t* byte) {
size_t length = 0;
zx_status_t status =
zx_debug_read(root_resource.get(), reinterpret_cast<char*>(byte), sizeof(*byte), &length);
if (status == ZX_ERR_NOT_SUPPORTED) {
// Suppress the error print in this case. No console on this machine.
return status;
} else if (status != ZX_OK) {
printf("console: error %s, length %zu from zx_debug_read syscall, exiting.\n",
zx_status_get_string(status), length);
return status;
}
if (length != 1) {
return ZX_ERR_SHOULD_WAIT;
}
return ZX_OK;
};
Console::TxSink tx_sink = [](const uint8_t* buffer, size_t length) {
return zx_debug_write(reinterpret_cast<const char*>(buffer), length);
};
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
async_dispatcher_t* dispatcher = loop.dispatcher();
fbl::RefPtr<Console> console;
zx_status_t status =
Console::Create(dispatcher, std::move(rx_source), std::move(tx_sink), &console);
if (status != ZX_OK) {
printf("console: Console::Create() = %s\n", zx_status_get_string(status));
return -1;
}
svc::Outgoing outgoing(dispatcher);
status = outgoing.ServeFromStartupInfo();
if (status != ZX_OK) {
printf("console: outgoing.ServeFromStartupInfo() = %s\n", zx_status_get_string(status));
return -1;
}
using Vnode =
fs_pty::TtyService<fs_pty::SimpleConsoleOps<fbl::RefPtr<Console>>, fbl::RefPtr<Console>>;
outgoing.svc_dir()->AddEntry("fuchsia.hardware.pty.Device",
fbl::AdoptRef(new Vnode(std::move(console))));
status = loop.Run();
ZX_ASSERT(status == ZX_OK);
return 0;
}