Loading init/README.ueventd.md +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading init/firmware_handler.cpp +39 −7 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "firmware_handler.h" #include <fcntl.h> #include <glob.h> #include <pwd.h> #include <signal.h> #include <stdlib.h> Loading @@ -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> Loading Loading @@ -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; } Loading @@ -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; Loading init/firmware_handler.h +2 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <pwd.h> #include <functional> #include <string> #include <vector> Loading Loading @@ -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 Loading
init/README.ueventd.md +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
init/firmware_handler.cpp +39 −7 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "firmware_handler.h" #include <fcntl.h> #include <glob.h> #include <pwd.h> #include <signal.h> #include <stdlib.h> Loading @@ -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> Loading Loading @@ -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; } Loading @@ -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; Loading
init/firmware_handler.h +2 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <pwd.h> #include <functional> #include <string> #include <vector> Loading Loading @@ -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