Merge "ueventd: scans /apex/*/firmware for firmwares" am: 62ccfa0c61 am: ed8016598a
Original change: https://android-review.googlesource.com/c/platform/system/core/+/1429856 Change-Id: I655a58d1ffdd5251c19f5529d2ea03187e12946b
This commit is contained in:
commit
d77ba4d7dd
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
|
for a file matching the uevent `FIRMWARE`. It then forks a process to serve this firmware to the
|
||||||
kernel.
|
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
|
The list of firmware directories is customized by a `firmware_directories` line in a ueventd.rc
|
||||||
file. This line takes the format of
|
file. This line takes the format of
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
#include "firmware_handler.h"
|
#include "firmware_handler.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <glob.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -30,6 +31,7 @@
|
||||||
#include <android-base/chrono_utils.h>
|
#include <android-base/chrono_utils.h>
|
||||||
#include <android-base/file.h>
|
#include <android-base/file.h>
|
||||||
#include <android-base/logging.h>
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/scopeguard.h>
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
#include <android-base/unique_fd.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;
|
std::vector<std::string> attempted_paths_and_errors;
|
||||||
|
auto TryLoadFirmware = [&](const std::string& firmware_directory) {
|
||||||
int booting = IsBooting();
|
|
||||||
try_loading_again:
|
|
||||||
attempted_paths_and_errors.clear();
|
|
||||||
for (const auto& firmware_directory : firmware_directories_) {
|
|
||||||
std::string file = firmware_directory + firmware;
|
std::string file = firmware_directory + firmware;
|
||||||
unique_fd fw_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
|
unique_fd fw_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
|
||||||
if (fw_fd == -1) {
|
if (fw_fd == -1) {
|
||||||
attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
|
attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
|
||||||
", open failed: " + strerror(errno));
|
", open failed: " + strerror(errno));
|
||||||
continue;
|
return false;
|
||||||
}
|
}
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if (fstat(fw_fd, &sb) == -1) {
|
if (fstat(fw_fd, &sb) == -1) {
|
||||||
attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
|
attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
|
||||||
", fstat failed: " + strerror(errno));
|
", fstat failed: " + strerror(errno));
|
||||||
continue;
|
return false;
|
||||||
}
|
}
|
||||||
LoadFirmware(firmware, root, fw_fd, sb.st_size, loading_fd, data_fd);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,6 +247,33 @@ try_loading_again:
|
||||||
write(loading_fd, "-1", 2);
|
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) {
|
void FirmwareHandler::HandleUevent(const Uevent& uevent) {
|
||||||
if (uevent.subsystem != "firmware" || uevent.action != "add") return;
|
if (uevent.subsystem != "firmware" || uevent.action != "add") return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
@ -52,6 +53,7 @@ class FirmwareHandler : public UeventHandler {
|
||||||
const Uevent& uevent) const;
|
const Uevent& uevent) const;
|
||||||
std::string GetFirmwarePath(const Uevent& uevent) const;
|
std::string GetFirmwarePath(const Uevent& uevent) const;
|
||||||
void ProcessFirmwareEvent(const std::string& root, const std::string& firmware) 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<std::string> firmware_directories_;
|
||||||
std::vector<ExternalFirmwareHandler> external_firmware_handlers_;
|
std::vector<ExternalFirmwareHandler> external_firmware_handlers_;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue