blob: e7fa7890b347d25bb87201283ac21aebd3112a82 [file] [log] [blame]
// Copyright 2021 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 "driver_loader.h"
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/fdio/directory.h>
#include <sched.h>
#include <threads.h>
#include <unistd.h>
#include <fbl/unique_fd.h>
#include "coordinator.h"
#include "src/devices/lib/log/log.h"
DriverLoader::~DriverLoader() {
if (loading_thread_) {
thrd_join(loading_thread_.value(), nullptr);
}
}
void DriverLoader::StartLoadingThread(Coordinator* coordinator) {
if (loading_thread_) {
LOGF(ERROR, "DriverLoader: StartLoadingThread cannot be called twice!\n");
return;
}
thrd_t t;
int ret = thrd_create_with_name(
&t,
[](void* arg) {
reinterpret_cast<DriverLoader*>(arg)->LoadDrivers();
return 0;
},
this, "driver-loader-thread");
if (ret != thrd_success) {
LOGF(ERROR, "DriverLoader: starting a new thread failed!\n");
return;
}
loading_thread_ = t;
coordinator_ = coordinator;
}
void DriverLoader::LoadDrivers() {
fbl::unique_fd fd(open("/system-delayed", O_RDONLY));
if (fd.get() < 0) {
LOGF(WARNING, "Unabled to open '/system-delayed', system drivers are disabled");
return;
}
find_loadable_drivers("/system/driver", fit::bind_member(this, &DriverLoader::DriverAdded));
async::PostTask(coordinator_->dispatcher(),
[coordinator = coordinator_, drivers = std::move(drivers_)]() mutable {
coordinator->AddAndBindDrivers(std::move(drivers));
coordinator->BindFallbackDrivers();
});
}
void DriverLoader::DriverAdded(Driver* drv, const char* version) {
std::unique_ptr<Driver> driver(drv);
LOGF(INFO, "Adding driver '%s' '%s'", driver->name.data(), driver->libname.data());
if (load_vmo(driver->libname.data(), &driver->dso_vmo)) {
LOGF(ERROR, "Driver '%s' '%s' could not cache DSO", driver->name.data(),
driver->libname.data());
}
if (version[0] == '*') {
// de-prioritize drivers that are "fallback"
drivers_.push_back(std::move(driver));
} else {
drivers_.push_front(std::move(driver));
}
}