blob: 26490887952dd71ce5ae8d43aa9337aa49bbd4ad [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 "sysinfo.h"
#include <fcntl.h>
#include <fuchsia/boot/llcpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls/resource.h>
#include <zircon/types.h>
#include <fbl/unique_fd.h>
namespace sysinfo {
void SysInfo::GetHypervisorResource(GetHypervisorResourceCompleter::Sync &completer) {
zx::resource hypervisor;
zx_status_t status = GetHypervisorResource(&hypervisor);
completer.Reply(status, std::move(hypervisor));
}
void SysInfo::GetBoardName(GetBoardNameCompleter::Sync &completer) {
std::string board_name;
zx_status_t status = GetBoardName(&board_name);
completer.Reply(status, fidl::unowned_str(board_name));
}
void SysInfo::GetBoardRevision(GetBoardRevisionCompleter::Sync &completer) {
uint32_t revision;
zx_status_t status = GetBoardRevision(&revision);
completer.Reply(status, revision);
}
void SysInfo::GetBootloaderVendor(GetBootloaderVendorCompleter::Sync &completer) {
std::string bootloader_vendor;
zx_status_t status = GetBootloaderVendor(&bootloader_vendor);
completer.Reply(status, fidl::unowned_str(bootloader_vendor));
}
void SysInfo::GetInterruptControllerInfo(GetInterruptControllerInfoCompleter::Sync &completer) {
llcpp::fuchsia::sysinfo::InterruptControllerInfo info = {};
zx_status_t status = GetInterruptControllerInfo(&info);
completer.Reply(status, fidl::unowned_ptr(&info));
}
// TODO(fxbug.dev/43777): Separate out GetHypervisorResource from sysinfo
zx_status_t SysInfo::GetHypervisorResource(zx::resource *hypervisor) {
zx::channel local, remote;
zx_status_t status = zx::channel::create(0, &local, &remote);
if (status != ZX_OK) {
printf("sysinfo: channel create failed: %s\n", zx_status_get_string(status));
return status;
}
auto svc_name = "/svc/" + std::string(llcpp::fuchsia::boot::RootResource::Name);
status = fdio_service_connect(svc_name.c_str(), remote.release());
if (status != ZX_OK) {
printf("sysinfo: Could not connect to RootResource service: %s\n",
zx_status_get_string(status));
return status;
}
llcpp::fuchsia::boot::RootResource::SyncClient client(std::move(local));
auto result = client.Get();
if (result.status() != ZX_OK) {
printf("sysinfo: Could not retrieve RootResource: %s\n", zx_status_get_string(result.status()));
return result.status();
}
zx::resource root_resource(std::move(result->resource));
const char name[] = "hypervisor";
status = zx::resource::create(root_resource, ZX_RSRC_KIND_HYPERVISOR, 0, 0, name, sizeof(name),
hypervisor);
return status;
}
zx_status_t SysInfo::GetBoardName(std::string *board_name) {
llcpp::fuchsia::sysinfo::SysInfo::SyncClient client{zx::channel()};
zx_status_t status = ConnectToPBus(&client);
if (status != ZX_OK) {
return status;
}
// Get board name from platform bus
auto result = client.GetBoardName();
if (!result.ok()) {
printf("sysinfo: Could not GetBoardName: %s\n", result.error());
return result.status();
}
*board_name = std::string(result->name.cbegin(), result->name.size());
return status;
}
zx_status_t SysInfo::GetBoardRevision(uint32_t *board_revision) {
llcpp::fuchsia::sysinfo::SysInfo::SyncClient client{zx::channel()};
zx_status_t status = ConnectToPBus(&client);
if (status != ZX_OK) {
return status;
}
// Get board revision from platform bus
auto result = client.GetBoardRevision();
if (!result.ok()) {
printf("sysinfo: Could not GetBoardRevision: %s\n", result.error());
return result.status();
}
*board_revision = result->revision;
return status;
}
zx_status_t SysInfo::GetBootloaderVendor(std::string *bootloader_vendor) {
llcpp::fuchsia::sysinfo::SysInfo::SyncClient client{zx::channel()};
zx_status_t status = ConnectToPBus(&client);
if (status != ZX_OK) {
return status;
}
// Get bootloader vendor from platform bus
auto result = client.GetBootloaderVendor();
if (!result.ok()) {
printf("sysinfo: Could not GetBootloaderVendor: %s\n", result.error());
return result.status();
}
*bootloader_vendor = std::string(result->vendor.cbegin(), result->vendor.size());
return status;
}
zx_status_t SysInfo::GetInterruptControllerInfo(
llcpp::fuchsia::sysinfo::InterruptControllerInfo *info) {
llcpp::fuchsia::sysinfo::SysInfo::SyncClient client{zx::channel()};
zx_status_t status = ConnectToPBus(&client);
if (status != ZX_OK) {
return status;
}
// Get interrupt controller information from platform bus
auto result = client.GetInterruptControllerInfo();
if (!result.ok()) {
printf("sysinfo: Could not GetInterruptControllerInfo: %s\n", result.error());
return result.status();
}
info->type = result->info->type;
return status;
}
zx_status_t SysInfo::ConnectToPBus(llcpp::fuchsia::sysinfo::SysInfo::SyncClient *client) {
zx::channel remote;
zx_status_t status = zx::channel::create(0, client->mutable_channel(), &remote);
if (status != ZX_OK) {
printf("sysinfo: Channel create failed: %s\n", zx_status_get_string(status));
return status;
}
status = fdio_service_connect("/dev/sys/platform", remote.release());
if (status != ZX_OK) {
printf("sysinfo: Could not connect to platform bus: %s\n", zx_status_get_string(status));
return status;
}
return ZX_OK;
}
} // namespace sysinfo