From 22fdd0ae13c566527cedc7caf5c96f0a4e5536d4 Mon Sep 17 00:00:00 2001 From: Suchang Woo Date: Tue, 6 Apr 2021 11:22:49 +0900 Subject: [PATCH] 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 Change-Id: If3b7a2cabb8055bf4b768d928f0fc0012da3c177 --- init/firmware_handler.cpp | 33 ++++++++++++++++++++++++++++++++- init/firmware_handler.h | 6 ++++-- init/ueventd_parser_test.cpp | 18 ++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp index ba7e6bd63..bdc292275 100644 --- a/init/firmware_handler.cpp +++ b/init/firmware_handler.cpp @@ -17,6 +17,7 @@ #include "firmware_handler.h" #include +#include #include #include #include @@ -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 firmware_directories, std::vector external_firmware_handlers) : firmware_directories_(std::move(firmware_directories)), @@ -160,7 +191,7 @@ Result 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 << "'"; diff --git a/init/firmware_handler.h b/init/firmware_handler.h index 8b758aee7..3c35b1f16 100644 --- a/init/firmware_handler.h +++ b/init/firmware_handler.h @@ -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 match; }; class FirmwareHandler : public UeventHandler { diff --git a/init/ueventd_parser_test.cpp b/init/ueventd_parser_test.cpp index 4e63ba577..c5aa9e3b5 100644 --- a/init/ueventd_parser_test.cpp +++ b/init/ueventd_parser_test.cpp @@ -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{ @@ -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});