blob: 5159a978cbc1a53566af5810b65cd361acf0201b [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 "isolated_devmgr.h"
#include <fcntl.h>
#include <lib/async/default.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/unsafe.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/vmo.h>
#include <zircon/boot/image.h>
#include <zircon/status.h>
#include <zircon/syscalls/debug.h>
#include <ddk/platform-defs.h>
#include <sdk/lib/sys/cpp/component_context.h>
namespace isolated_devmgr {
zx_status_t IsolatedDevmgr::WaitForFile(const char* path) {
fbl::unique_fd out;
return devmgr_integration_test::RecursiveWaitForFile(devmgr_.devfs_root(), path, &out);
}
void IsolatedDevmgr::Connect(zx::channel req) {
fdio_cpp::UnownedFdioCaller fd(devmgr_.devfs_root().get());
fdio_service_clone_to(fd.borrow_channel(), req.release());
}
namespace {
// This board driver knows how to interpret the metadata for which devices to
// spawn.
const zbi_platform_id_t kPlatformId = []() {
zbi_platform_id_t plat_id = {};
plat_id.vid = PDEV_VID_TEST;
plat_id.pid = PDEV_PID_INTEGRATION_TEST;
strcpy(plat_id.board_name, "driver-integration-test");
return plat_id;
}();
#define BOARD_REVISION_TEST 42
const zbi_board_info_t kBoardInfo = []() {
zbi_board_info_t board_info = {};
board_info.revision = BOARD_REVISION_TEST;
return board_info;
}();
// This function is responsible for serializing driver data. It must be kept
// updated with the function that deserialized the data. This function
// is TestBoard::FetchAndDeserialize.
zx_status_t GetBootItem(const fbl::Vector<board_test::DeviceEntry>& entries, uint32_t type,
uint32_t extra, zx::vmo* out, uint32_t* length) {
zx::vmo vmo;
switch (type) {
case ZBI_TYPE_PLATFORM_ID: {
zx_status_t status = zx::vmo::create(sizeof(kPlatformId), 0, &vmo);
if (status != ZX_OK) {
return status;
}
status = vmo.write(&kPlatformId, 0, sizeof(kPlatformId));
if (status != ZX_OK) {
return status;
}
*length = sizeof(kPlatformId);
break;
}
case ZBI_TYPE_DRV_BOARD_INFO: {
zx_status_t status = zx::vmo::create(sizeof(kBoardInfo), 0, &vmo);
if (status != ZX_OK) {
return status;
}
status = vmo.write(&kBoardInfo, 0, sizeof(kBoardInfo));
if (status != ZX_OK) {
return status;
}
*length = sizeof(kBoardInfo);
break;
}
case ZBI_TYPE_DRV_BOARD_PRIVATE: {
size_t list_size = sizeof(board_test::DeviceList);
size_t entry_size = entries.size() * sizeof(board_test::DeviceEntry);
size_t metadata_size = 0;
for (board_test::DeviceEntry& entry : entries) {
metadata_size += entry.metadata_size;
}
zx_status_t status = zx::vmo::create(list_size + entry_size + metadata_size, 0, &vmo);
if (status != ZX_OK) {
return status;
}
// Write DeviceList to vmo.
board_test::DeviceList list{.count = entries.size()};
status = vmo.write(&list, 0, sizeof(list));
if (status != ZX_OK) {
return status;
}
// Write DeviceEntries to vmo.
status = vmo.write(entries.data(), list_size, entry_size);
if (status != ZX_OK) {
return status;
}
// Write Metadata to vmo.
size_t write_offset = list_size + entry_size;
for (board_test::DeviceEntry& entry : entries) {
status = vmo.write(entry.metadata, write_offset, entry.metadata_size);
if (status != ZX_OK) {
return status;
}
write_offset += entry.metadata_size;
}
*length = static_cast<uint32_t>(list_size + entry_size + metadata_size);
break;
}
default:
break;
}
*out = std::move(vmo);
return ZX_OK;
}
} // namespace
std::unique_ptr<IsolatedDevmgr> IsolatedDevmgr::Create(
devmgr_launcher::Args args,
std::unique_ptr<fbl::Vector<board_test::DeviceEntry>> device_list_unique_ptr,
async_dispatcher_t* dispatcher) {
if (dispatcher == nullptr) {
dispatcher = async_get_default_dispatcher();
}
devmgr_integration_test::IsolatedDevmgr devmgr;
if (device_list_unique_ptr != nullptr) {
args.get_boot_item = [dev_list_ptr = std::move(device_list_unique_ptr)](
uint32_t type, uint32_t extra, zx::vmo* out, uint32_t* length) {
return GetBootItem(*dev_list_ptr, type, extra, out, length);
};
}
zx_status_t status =
devmgr_integration_test::IsolatedDevmgr::Create(std::move(args), dispatcher, &devmgr);
if (status == ZX_OK) {
return std::make_unique<IsolatedDevmgr>(std::move(devmgr));
} else {
FX_LOGS(ERROR) << "Failed to create devmgr: " << zx_status_get_string(status);
return nullptr;
}
}
} // namespace isolated_devmgr