Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22fdd0ae authored by Suchang Woo's avatar Suchang Woo Committed by David Anderson
Browse files

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: default avatarSuchang Woo <suchang.woo@samsung.com>
Change-Id: If3b7a2cabb8055bf4b768d928f0fc0012da3c177
parent 78e26beb
Loading
Loading
Loading
Loading
+32 −1
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#include "firmware_handler.h"
#include "firmware_handler.h"


#include <fcntl.h>
#include <fcntl.h>
#include <fnmatch.h>
#include <glob.h>
#include <glob.h>
#include <pwd.h>
#include <pwd.h>
#include <signal.h>
#include <signal.h>
@@ -46,6 +47,20 @@ using android::base::WriteFully;
namespace android {
namespace android {
namespace init {
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,
static void LoadFirmware(const std::string& firmware, const std::string& root, int fw_fd,
                         size_t fw_size, int loading_fd, int data_fd) {
                         size_t fw_size, int loading_fd, int data_fd) {
    // Start transfer.
    // Start transfer.
@@ -66,6 +81,22 @@ static bool IsBooting() {
    return access("/dev/.booting", F_OK) == 0;
    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,
FirmwareHandler::FirmwareHandler(std::vector<std::string> firmware_directories,
                                 std::vector<ExternalFirmwareHandler> external_firmware_handlers)
                                 std::vector<ExternalFirmwareHandler> external_firmware_handlers)
    : firmware_directories_(std::move(firmware_directories)),
    : 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 {
std::string FirmwareHandler::GetFirmwarePath(const Uevent& uevent) const {
    for (const auto& external_handler : external_firmware_handlers_) {
    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
            LOG(INFO) << "Launching external firmware handler '" << external_handler.handler_path
                      << "' for devpath: '" << uevent.path << "' firmware: '" << uevent.firmware
                      << "' for devpath: '" << uevent.path << "' firmware: '" << uevent.firmware
                      << "'";
                      << "'";
+4 −2
Original line number Original line Diff line number Diff line
@@ -30,11 +30,13 @@ namespace android {
namespace init {
namespace init {


struct ExternalFirmwareHandler {
struct ExternalFirmwareHandler {
    ExternalFirmwareHandler(std::string devpath, uid_t uid, std::string handler_path)
    ExternalFirmwareHandler(std::string devpath, uid_t uid, std::string handler_path);
        : devpath(std::move(devpath)), uid(uid), handler_path(std::move(handler_path)) {}

    std::string devpath;
    std::string devpath;
    uid_t uid;
    uid_t uid;
    std::string handler_path;
    std::string handler_path;

    std::function<bool(const std::string&)> match;
};
};


class FirmwareHandler : public UeventHandler {
class FirmwareHandler : public UeventHandler {
+18 −0
Original line number Original line Diff line number Diff line
@@ -154,6 +154,9 @@ TEST(ueventd_parser, ExternalFirmwareHandlers) {
external_firmware_handler devpath root handler_path
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/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/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>{
    auto external_firmware_handlers = std::vector<ExternalFirmwareHandler>{
@@ -172,6 +175,21 @@ external_firmware_handler /devices/path/firmware/something002.bin radio "/vendor
                    AID_RADIO,
                    AID_RADIO,
                    "/vendor/bin/firmware_handler.sh --has --arguments",
                    "/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});
    TestUeventdFile(ueventd_file, {{}, {}, {}, {}, external_firmware_handlers});