ueventd: Allow pattern matching to find external firmware handler
Only the exact same devpath uevent can launch external handler specified in ueventd.rc. So, you should specify all possible devpaths, even firmware with different filenames on the same device. Pattern mactching can be used to simplify this. Test: atest CtsInitTestCases Signed-off-by: Suchang Woo <suchang.woo@samsung.com> Change-Id: If3b7a2cabb8055bf4b768d928f0fc0012da3c177
This commit is contained in:
parent
78e26beb02
commit
22fdd0ae13
3 changed files with 54 additions and 3 deletions
|
@ -17,6 +17,7 @@
|
|||
#include "firmware_handler.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <fnmatch.h>
|
||||
#include <glob.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
|
@ -46,6 +47,20 @@ using android::base::WriteFully;
|
|||
namespace android {
|
||||
namespace init {
|
||||
|
||||
namespace {
|
||||
bool PrefixMatch(const std::string& pattern, const std::string& path) {
|
||||
return android::base::StartsWith(path, pattern);
|
||||
}
|
||||
|
||||
bool FnMatch(const std::string& pattern, const std::string& path) {
|
||||
return fnmatch(pattern.c_str(), path.c_str(), 0) == 0;
|
||||
}
|
||||
|
||||
bool EqualMatch(const std::string& pattern, const std::string& path) {
|
||||
return pattern == path;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
static void LoadFirmware(const std::string& firmware, const std::string& root, int fw_fd,
|
||||
size_t fw_size, int loading_fd, int data_fd) {
|
||||
// Start transfer.
|
||||
|
@ -66,6 +81,22 @@ static bool IsBooting() {
|
|||
return access("/dev/.booting", F_OK) == 0;
|
||||
}
|
||||
|
||||
ExternalFirmwareHandler::ExternalFirmwareHandler(std::string devpath, uid_t uid,
|
||||
std::string handler_path)
|
||||
: devpath(std::move(devpath)), uid(uid), handler_path(std::move(handler_path)) {
|
||||
auto wildcard_position = this->devpath.find('*');
|
||||
if (wildcard_position != std::string::npos) {
|
||||
if (wildcard_position == this->devpath.length() - 1) {
|
||||
this->devpath.pop_back();
|
||||
match = std::bind(PrefixMatch, this->devpath, std::placeholders::_1);
|
||||
} else {
|
||||
match = std::bind(FnMatch, this->devpath, std::placeholders::_1);
|
||||
}
|
||||
} else {
|
||||
match = std::bind(EqualMatch, this->devpath, std::placeholders::_1);
|
||||
}
|
||||
}
|
||||
|
||||
FirmwareHandler::FirmwareHandler(std::vector<std::string> firmware_directories,
|
||||
std::vector<ExternalFirmwareHandler> external_firmware_handlers)
|
||||
: firmware_directories_(std::move(firmware_directories)),
|
||||
|
@ -160,7 +191,7 @@ Result<std::string> FirmwareHandler::RunExternalHandler(const std::string& handl
|
|||
|
||||
std::string FirmwareHandler::GetFirmwarePath(const Uevent& uevent) const {
|
||||
for (const auto& external_handler : external_firmware_handlers_) {
|
||||
if (external_handler.devpath == uevent.path) {
|
||||
if (external_handler.match(uevent.path)) {
|
||||
LOG(INFO) << "Launching external firmware handler '" << external_handler.handler_path
|
||||
<< "' for devpath: '" << uevent.path << "' firmware: '" << uevent.firmware
|
||||
<< "'";
|
||||
|
|
|
@ -30,11 +30,13 @@ namespace android {
|
|||
namespace init {
|
||||
|
||||
struct ExternalFirmwareHandler {
|
||||
ExternalFirmwareHandler(std::string devpath, uid_t uid, std::string handler_path)
|
||||
: devpath(std::move(devpath)), uid(uid), handler_path(std::move(handler_path)) {}
|
||||
ExternalFirmwareHandler(std::string devpath, uid_t uid, std::string handler_path);
|
||||
|
||||
std::string devpath;
|
||||
uid_t uid;
|
||||
std::string handler_path;
|
||||
|
||||
std::function<bool(const std::string&)> match;
|
||||
};
|
||||
|
||||
class FirmwareHandler : public UeventHandler {
|
||||
|
|
|
@ -154,6 +154,9 @@ TEST(ueventd_parser, ExternalFirmwareHandlers) {
|
|||
external_firmware_handler devpath root handler_path
|
||||
external_firmware_handler /devices/path/firmware/something001.bin system /vendor/bin/firmware_handler.sh
|
||||
external_firmware_handler /devices/path/firmware/something002.bin radio "/vendor/bin/firmware_handler.sh --has --arguments"
|
||||
external_firmware_handler /devices/path/firmware/* root "/vendor/bin/firmware_handler.sh"
|
||||
external_firmware_handler /devices/path/firmware/something* system "/vendor/bin/firmware_handler.sh"
|
||||
external_firmware_handler /devices/path/*/firmware/something*.bin radio "/vendor/bin/firmware_handler.sh"
|
||||
)";
|
||||
|
||||
auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
|
||||
|
@ -172,6 +175,21 @@ external_firmware_handler /devices/path/firmware/something002.bin radio "/vendor
|
|||
AID_RADIO,
|
||||
"/vendor/bin/firmware_handler.sh --has --arguments",
|
||||
},
|
||||
{
|
||||
"/devices/path/firmware/",
|
||||
AID_ROOT,
|
||||
"/vendor/bin/firmware_handler.sh",
|
||||
},
|
||||
{
|
||||
"/devices/path/firmware/something",
|
||||
AID_SYSTEM,
|
||||
"/vendor/bin/firmware_handler.sh",
|
||||
},
|
||||
{
|
||||
"/devices/path/*/firmware/something*.bin",
|
||||
AID_RADIO,
|
||||
"/vendor/bin/firmware_handler.sh",
|
||||
},
|
||||
};
|
||||
|
||||
TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers});
|
||||
|
|
Loading…
Reference in a new issue