ueventd: scans /apex/*/firmware for firmwares
In addition to "firmware_directories", ueventd scans /apex/*/firmware/ directory as well to find firmware files. Bug: 167942098 Test: loading firmware from vibrator apex successfully. (sunfish) Change-Id: I90fc8f9ad843a08b1ca98a2be1b5d22c0c5954a3
This commit is contained in:
parent
0407302aa8
commit
21cad321db
3 changed files with 43 additions and 7 deletions
|
@ -86,6 +86,8 @@ Ueventd by default serves firmware requests by searching through a list of firmw
|
|||
for a file matching the uevent `FIRMWARE`. It then forks a process to serve this firmware to the
|
||||
kernel.
|
||||
|
||||
`/apex/*/firmware` is also searched after a list of firmware directories.
|
||||
|
||||
The list of firmware directories is customized by a `firmware_directories` line in a ueventd.rc
|
||||
file. This line takes the format of
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "firmware_handler.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <glob.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include <android-base/chrono_utils.h>
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/scopeguard.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
|
@ -203,25 +205,28 @@ void FirmwareHandler::ProcessFirmwareEvent(const std::string& root,
|
|||
}
|
||||
|
||||
std::vector<std::string> attempted_paths_and_errors;
|
||||
|
||||
int booting = IsBooting();
|
||||
try_loading_again:
|
||||
attempted_paths_and_errors.clear();
|
||||
for (const auto& firmware_directory : firmware_directories_) {
|
||||
auto TryLoadFirmware = [&](const std::string& firmware_directory) {
|
||||
std::string file = firmware_directory + firmware;
|
||||
unique_fd fw_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
|
||||
if (fw_fd == -1) {
|
||||
attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
|
||||
", open failed: " + strerror(errno));
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
struct stat sb;
|
||||
if (fstat(fw_fd, &sb) == -1) {
|
||||
attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
|
||||
", fstat failed: " + strerror(errno));
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
LoadFirmware(firmware, root, fw_fd, sb.st_size, loading_fd, data_fd);
|
||||
return true;
|
||||
};
|
||||
|
||||
int booting = IsBooting();
|
||||
try_loading_again:
|
||||
attempted_paths_and_errors.clear();
|
||||
if (ForEachFirmwareDirectory(TryLoadFirmware)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -242,6 +247,33 @@ try_loading_again:
|
|||
write(loading_fd, "-1", 2);
|
||||
}
|
||||
|
||||
bool FirmwareHandler::ForEachFirmwareDirectory(
|
||||
std::function<bool(const std::string&)> handler) const {
|
||||
for (const std::string& firmware_directory : firmware_directories_) {
|
||||
if (std::invoke(handler, firmware_directory)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
glob_t glob_result;
|
||||
glob("/apex/*/firmware/", GLOB_MARK, nullptr, &glob_result);
|
||||
auto free_glob = android::base::make_scope_guard(std::bind(&globfree, &glob_result));
|
||||
for (size_t i = 0; i < glob_result.gl_pathc; i++) {
|
||||
char* apex_firmware_directory = glob_result.gl_pathv[i];
|
||||
// Filter-out /apex/<name>@<ver> paths. The paths are bind-mounted to
|
||||
// /apex/<name> paths, so unless we filter them out, we will look into the
|
||||
// same apex twice.
|
||||
if (strchr(apex_firmware_directory, '@')) {
|
||||
continue;
|
||||
}
|
||||
if (std::invoke(handler, apex_firmware_directory)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FirmwareHandler::HandleUevent(const Uevent& uevent) {
|
||||
if (uevent.subsystem != "firmware" || uevent.action != "add") return;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <pwd.h>
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -52,6 +53,7 @@ class FirmwareHandler : public UeventHandler {
|
|||
const Uevent& uevent) const;
|
||||
std::string GetFirmwarePath(const Uevent& uevent) const;
|
||||
void ProcessFirmwareEvent(const std::string& root, const std::string& firmware) const;
|
||||
bool ForEachFirmwareDirectory(std::function<bool(const std::string&)> handler) const;
|
||||
|
||||
std::vector<std::string> firmware_directories_;
|
||||
std::vector<ExternalFirmwareHandler> external_firmware_handlers_;
|
||||
|
|
Loading…
Reference in a new issue