blob: 61cb4f90008283c4a2108f280a75d5c96a93faae [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 <fidl/fuchsia.kernel/cpp/wire.h>
#include <fidl/fuchsia.logger/cpp/wire.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/component/outgoing/cpp/outgoing_directory.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include "src/bringup/bin/console/console.h"
#include "src/sys/lib/stdout-to-debuglog/cpp/stdout-to-debuglog.h"
namespace {
zx::resource GetDebugResource() {
auto client_end = component::Connect<fuchsia_kernel::DebugResource>();
if (client_end.is_error()) {
printf("console: Could not connect to DebugResource service: %s\n", client_end.status_string());
return {};
}
fidl::WireSyncClient client{std::move(client_end.value())};
auto result = client->Get();
if (result.status() != ZX_OK) {
printf("console: Could not retrieve DebugResource: %s\n",
zx_status_get_string(result.status()));
return {};
}
return std::move(result->resource);
}
} // namespace
int main(int argc, const char** argv) {
if (zx_status_t status = StdoutToDebuglog::Init(); status != ZX_OK) {
printf("console: StdoutToDebuglog::Init() = %s\n", zx_status_get_string(status));
return status;
}
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
// Provide a RxSource that grabs the data from the kernel serial connection
Console::RxSource rx_source = [debug_resource = GetDebugResource()](uint8_t* byte) {
size_t length = 0;
zx_status_t status =
zx_debug_read(debug_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;
}
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);
};
zx::eventpair event1, event2;
if (zx_status_t status = zx::eventpair::create(0, &event1, &event2); status != ZX_OK) {
printf("console: zx::eventpair::create() = %s\n", zx_status_get_string(status));
return status;
}
auto console = std::make_unique<Console>(loop.dispatcher(), std::move(event1), std::move(event2),
std::move(rx_source), std::move(tx_sink));
component::OutgoingDirectory outgoing = component::OutgoingDirectory(loop.dispatcher());
if (zx::result status = outgoing.AddProtocol<fuchsia_hardware_pty::Device>(std::move(console));
status.is_error()) {
printf("console: outgoing.AddProtocol() = %s\n", status.status_string());
return status.status_value();
}
if (zx::result status = outgoing.ServeFromStartupInfo(); status.is_error()) {
printf("console: outgoing.ServeFromStartupInfo() = %s\n", status.status_string());
return status.status_value();
}
if (zx_status_t status = loop.Run(); status != ZX_OK) {
printf("console: lop.Run() = %s\n", zx_status_get_string(status));
return status;
}
return 0;
}