[OE-core] [PATCH] systemd: restore userspace firmware loading support

Khem Raj raj.khem at gmail.com
Thu Mar 19 05:10:38 UTC 2015


On Thursday, March 19, 2015 03:38:32 PM Jonathan Liu wrote:
> This changes the minimum required Linux version from 3.7 back to 3.0.
> 

what is justification for this patch ? I would rather not regress but go with 
systemd community here.

> [YOCTO #7409]
> 
> Signed-off-by: Jonathan Liu <net147 at gmail.com>
> ---
>  ...evert-rules-remove-firmware-loading-rules.patch |  28 ++
>  ...-remove-userspace-firmware-loading-suppor.patch | 367
> +++++++++++++++++++++ meta/recipes-core/systemd/systemd_219.bb           | 
>  3 +
>  3 files changed, 398 insertions(+)
>  create mode 100644
> meta/recipes-core/systemd/systemd/0014-Revert-rules-remove-firmware-loading
> -rules.patch create mode 100644
> meta/recipes-core/systemd/systemd/0015-Revert-udev-remove-userspace-firmwar
> e-loading-suppor.patch
> 
> diff --git
> a/meta/recipes-core/systemd/systemd/0014-Revert-rules-remove-firmware-loadi
> ng-rules.patch
> b/meta/recipes-core/systemd/systemd/0014-Revert-rules-remove-firmware-loadi
> ng-rules.patch new file mode 100644
> index 0000000..fe2ba53
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0014-Revert-rules-remove-firmware-loadi
> ng-rules.patch @@ -0,0 +1,28 @@
> +From 4f0a722489154da99e7f6b3051afde984eed2f74 Mon Sep 17 00:00:00 2001
> +From: Jonathan Liu <net147 at gmail.com>
> +Date: Thu, 19 Mar 2015 15:01:29 +1100
> +Subject: [PATCH] Revert "rules: remove firmware loading rules"
> +
> +This reverts commit 70e7d754ddb356fb1a2942b262f8cee9650e2a19.
> +Userspace firmware loading support is needed for Linux < 3.7.
> +
> +Upstream-Status: Inappropriate [OE specific]
> +
> +Signed-off-by: Jonathan Liu <net147 at gmail.com>
> +---
> + rules/50-firmware.rules | 3 +++
> + 1 file changed, 3 insertions(+)
> + create mode 100644 rules/50-firmware.rules
> +
> +diff --git a/rules/50-firmware.rules b/rules/50-firmware.rules
> +new file mode 100644
> +index 0000000..f0ae684
> +--- /dev/null
> ++++ b/rules/50-firmware.rules
> +@@ -0,0 +1,3 @@
> ++# do not edit this file, it will be overwritten on update
> ++
> ++SUBSYSTEM=="firmware", ACTION=="add", RUN{builtin}="firmware"
> +--
> +2.3.3
> +
> diff --git
> a/meta/recipes-core/systemd/systemd/0015-Revert-udev-remove-userspace-firmw
> are-loading-suppor.patch
> b/meta/recipes-core/systemd/systemd/0015-Revert-udev-remove-userspace-firmw
> are-loading-suppor.patch new file mode 100644
> index 0000000..3e3aa27
> --- /dev/null
> +++
> b/meta/recipes-core/systemd/systemd/0015-Revert-udev-remove-userspace-firmw
> are-loading-suppor.patch @@ -0,0 +1,367 @@
> +From 7f074def4e32045353ba4336d703e17b8de7ec4e Mon Sep 17 00:00:00 2001
> +From: Jonathan Liu <net147 at gmail.com>
> +Date: Thu, 19 Mar 2015 15:01:33 +1100
> +Subject: [PATCH] Revert "udev: remove userspace firmware loading support"
> +
> +This reverts commit be2ea723b1d023b3d385d3b791ee4607cbfb20ca.
> +Userspace firmware loading support is needed for Linux < 3.7.
> +
> +Upstream-Status: Inappropriate [OE specific]
> +
> +Signed-off-by: Jonathan Liu <net147 at gmail.com>
> +---
> + Makefile.am                      |  12 +++
> + README                           |   9 ++-
> + TODO                             |   1 +
> + configure.ac                     |  20 +++++
> + src/udev/udev-builtin-firmware.c | 154
> +++++++++++++++++++++++++++++++++++++++ + src/udev/udev-builtin.c         
> |   3 +
> + src/udev/udev.h                  |   6 ++
> + src/udev/udevd.c                 |  13 ++++
> + 8 files changed, 214 insertions(+), 4 deletions(-)
> + create mode 100644 src/udev/udev-builtin-firmware.c
> +
> +diff --git a/Makefile.am b/Makefile.am
> +index bf04d31..9394700 100644
> +--- a/Makefile.am
> ++++ b/Makefile.am
> +@@ -3678,6 +3678,18 @@ libudev_core_la_LIBADD = \
> + 	$(BLKID_LIBS) \
> + 	$(KMOD_LIBS)
> +
> ++libudev_core_la_CPPFLAGS = \
> ++	$(AM_CPPFLAGS) \
> ++	-DFIRMWARE_PATH="$(FIRMWARE_PATH)"
> ++
> ++if ENABLE_FIRMWARE
> ++libudev_core_la_SOURCES += \
> ++	src/udev/udev-builtin-firmware.c
> ++
> ++dist_udevrules_DATA += \
> ++	rules/50-firmware.rules
> ++endif
> ++
> + if HAVE_KMOD
> + libudev_core_la_SOURCES += \
> + 	src/udev/udev-builtin-kmod.c
> +diff --git a/README b/README
> +index c722092..db382d2 100644
> +--- a/README
> ++++ b/README
> +@@ -36,7 +36,8 @@ LICENSE:
> +         - except src/udev/* which is (currently still) GPLv2, GPLv2+
> +
> + REQUIREMENTS:
> +-        Linux kernel >= 3.7
> ++        Linux kernel >= 3.0
> ++        Linux kernel >= 3.3 for loop device partition support features
> with nspawn +         Linux kernel >= 3.8 for Smack support
> +
> +         Kernel Config Options:
> +@@ -51,14 +52,14 @@ REQUIREMENTS:
> +           CONFIG_PROC_FS
> +           CONFIG_FHANDLE (libudev, mount and bind mount handling)
> +
> +-        udev will fail to work with the legacy sysfs layout:
> ++        Udev will fail to work with the legacy layout:
> +           CONFIG_SYSFS_DEPRECATED=n
> +
> +         Legacy hotplug slows down the system and confuses udev:
> +           CONFIG_UEVENT_HELPER_PATH=""
> +
> +-        Userspace firmware loading is not supported and should
> +-        be disabled in the kernel:
> ++        Userspace firmware loading is deprecated, will go away, and
> ++        sometimes causes problems:
> +           CONFIG_FW_LOADER_USER_HELPER=n
> +
> +         Some udev rules and virtualization detection relies on it:
> +diff --git a/TODO b/TODO
> +index 255a4f2..407bdd0 100644
> +--- a/TODO
> ++++ b/TODO
> +@@ -727,6 +727,7 @@ Features:
> + * ExecOnFailure=/usr/bin/foo
> +
> + * udev:
> ++  - remove src/udev/udev-builtin-firmware.c
> (CONFIG_FW_LOADER_USER_HELPER=n) +   - move to LGPL
> +   - kill scsi_id
> +   - add trigger --subsystem-match=usb/usb_device device
> +diff --git a/configure.ac b/configure.ac
> +index 97a29d6..13b80ce 100644
> +--- a/configure.ac
> ++++ b/configure.ac
> +@@ -1245,6 +1245,25 @@ fi
> + AM_CONDITIONAL(HAVE_MYHOSTNAME, [test "$have_myhostname" = "yes"])
> +
> + #
> ---------------------------------------------------------------------------
> --- ++AC_ARG_WITH(firmware-path,
> ++       AS_HELP_STRING([--with-firmware-path=DIR[[[:DIR[...]]]]],
> ++          [Firmware search path (default="")]),
> ++       [], [with_firmware_path=""])
> ++OLD_IFS=$IFS
> ++IFS=:
> ++for i in $with_firmware_path; do
> ++       if test "x${FIRMWARE_PATH}" = "x"; then
> ++              FIRMWARE_PATH="\\\"${i}/\\\""
> ++       else
> ++              FIRMWARE_PATH="${FIRMWARE_PATH}, \\\"${i}/\\\""
> ++       fi
> ++done
> ++IFS=$OLD_IFS
> ++AC_SUBST(FIRMWARE_PATH)
> ++AS_IF([test "x${FIRMWARE_PATH}" != "x"], [ AC_DEFINE(HAVE_FIRMWARE, 1,
> [Define if FIRMWARE is available]) ]) ++AM_CONDITIONAL(ENABLE_FIRMWARE,
> [test "x${FIRMWARE_PATH}" != "x"]) ++
> ++#
> ---------------------------------------------------------------------------
> --- + AC_ARG_ENABLE([gudev],
> +        AS_HELP_STRING([--disable-gudev], [disable Gobject libudev support
> @<:@default=enabled@:>@]), +        [], [enable_gudev=yes])
> +@@ -1533,6 +1552,7 @@ AC_MSG_RESULT([
> +         Build Python:            ${PYTHON}
> +         Installation Python:     ${PYTHON_BINARY}
> +         sphinx binary:           ${SPHINX_BUILD}
> ++        firmware path:           ${FIRMWARE_PATH}
> +         PAM modules dir:         ${with_pamlibdir}
> +         PAM configuration dir:   ${with_pamconfdir}
> +         D-Bus policy dir:        ${with_dbuspolicydir}
> +diff --git a/src/udev/udev-builtin-firmware.c
> b/src/udev/udev-builtin-firmware.c +new file mode 100644
> +index 0000000..bd8c2fb
> +--- /dev/null
> ++++ b/src/udev/udev-builtin-firmware.c
> +@@ -0,0 +1,154 @@
> ++/*
> ++ * firmware - Kernel firmware loader
> ++ *
> ++ * Copyright (C) 2009 Piter Punk <piterpunk at slackware.com>
> ++ * Copyright (C) 2009-2011 Kay Sievers <kay at vrfy.org>
> ++ *
> ++ * This program is free software; you can redistribute it and/or
> ++ * modify it under the terms of the GNU General Public License as
> ++ * published by the Free Software Foundation; either version 2 of the
> ++ * License, or (at your option) any later version.
> ++ *
> ++ * This program is distributed in the hope that it will be useful, but
> ++ * WITHOUT ANY WARRANTY; without even the implied warranty of
> ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> ++ * General Public License for more details:*
> ++ */
> ++
> ++#include <unistd.h>
> ++#include <stdlib.h>
> ++#include <string.h>
> ++#include <stdio.h>
> ++#include <getopt.h>
> ++#include <errno.h>
> ++#include <stdbool.h>
> ++#include <sys/utsname.h>
> ++#include <sys/stat.h>
> ++
> ++#include "udev.h"
> ++
> ++static bool set_loading(struct udev *udev, char *loadpath, const char
> *state) { ++        FILE *ldfile;
> ++
> ++        ldfile = fopen(loadpath, "we");
> ++        if (ldfile == NULL) {
> ++                log_error("error: can not open '%s'", loadpath);
> ++                return false;
> ++        };
> ++        fprintf(ldfile, "%s\n", state);
> ++        fclose(ldfile);
> ++        return true;
> ++}
> ++
> ++static bool copy_firmware(struct udev *udev, const char *source, const
> char *target, size_t size) { ++        char *buf;
> ++        FILE *fsource = NULL, *ftarget = NULL;
> ++        bool ret = false;
> ++
> ++        buf = malloc(size);
> ++        if (buf == NULL) {
> ++                log_error("No memory available to load firmware file");
> ++                return false;
> ++        }
> ++
> ++        log_debug("writing '%s' (%zi) to '%s'", source, size, target);
> ++
> ++        fsource = fopen(source, "re");
> ++        if (fsource == NULL)
> ++                goto exit;
> ++        ftarget = fopen(target, "we");
> ++        if (ftarget == NULL)
> ++                goto exit;
> ++        if (fread(buf, size, 1, fsource) != 1)
> ++                goto exit;
> ++        if (fwrite(buf, size, 1, ftarget) == 1)
> ++                ret = true;
> ++exit:
> ++        if (ftarget != NULL)
> ++                fclose(ftarget);
> ++        if (fsource != NULL)
> ++                fclose(fsource);
> ++        free(buf);
> ++        return ret;
> ++}
> ++
> ++static int builtin_firmware(struct udev_device *dev, int argc, char
> *argv[], bool test) { ++        struct udev *udev =
> udev_device_get_udev(dev);
> ++        static const char *searchpath[] = { FIRMWARE_PATH };
> ++        char loadpath[UTIL_PATH_SIZE];
> ++        char datapath[UTIL_PATH_SIZE];
> ++        char fwpath[UTIL_PATH_SIZE];
> ++        const char *firmware;
> ++        FILE *fwfile = NULL;
> ++        struct utsname kernel;
> ++        struct stat statbuf;
> ++        unsigned int i;
> ++        int rc = EXIT_SUCCESS;
> ++
> ++        firmware = udev_device_get_property_value(dev, "FIRMWARE");
> ++        if (firmware == NULL) {
> ++                log_error("firmware parameter missing");
> ++                rc = EXIT_FAILURE;
> ++                goto exit;
> ++        }
> ++
> ++        /* lookup firmware file */
> ++        uname(&kernel);
> ++        for (i = 0; i < ELEMENTSOF(searchpath); i++) {
> ++                strscpyl(fwpath, sizeof(fwpath), searchpath[i],
> kernel.release, "/", firmware, NULL); ++                fwfile =
> fopen(fwpath, "re");
> ++                if (fwfile != NULL)
> ++                        break;
> ++
> ++                strscpyl(fwpath, sizeof(fwpath), searchpath[i], firmware,
> NULL); ++                fwfile = fopen(fwpath, "re");
> ++                if (fwfile != NULL)
> ++                        break;
> ++        }
> ++
> ++        strscpyl(loadpath, sizeof(loadpath), udev_device_get_syspath(dev),
> "/loading", NULL); ++
> ++        if (fwfile == NULL) {
> ++                log_debug("did not find firmware file '%s'", firmware);
> ++                rc = EXIT_FAILURE;
> ++                /*
> ++                 * Do not cancel the request in the initrd, the real root
> might have ++                 * the firmware file and the 'coldplug' run in
> the real root will find ++                 * this pending request and
> fulfill or cancel it. ++                 * */
> ++                if (!in_initrd())
> ++                        set_loading(udev, loadpath, "-1");
> ++                goto exit;
> ++        }
> ++
> ++        if (stat(fwpath, &statbuf) < 0 || statbuf.st_size == 0) {
> ++                if (!in_initrd())
> ++                        set_loading(udev, loadpath, "-1");
> ++                rc = EXIT_FAILURE;
> ++                goto exit;
> ++        }
> ++
> ++        if (!set_loading(udev, loadpath, "1"))
> ++                goto exit;
> ++
> ++        strscpyl(datapath, sizeof(datapath), udev_device_get_syspath(dev),
> "/data", NULL); ++        if (!copy_firmware(udev, fwpath, datapath,
> statbuf.st_size)) { ++                log_error("error sending firmware
> '%s' to device", firmware); ++                set_loading(udev, loadpath,
> "-1");
> ++                rc = EXIT_FAILURE;
> ++                goto exit;
> ++        };
> ++
> ++        set_loading(udev, loadpath, "0");
> ++exit:
> ++        if (fwfile)
> ++                fclose(fwfile);
> ++        return rc;
> ++}
> ++
> ++const struct udev_builtin udev_builtin_firmware = {
> ++        .name = "firmware",
> ++        .cmd = builtin_firmware,
> ++        .help = "kernel firmware loader",
> ++        .run_once = true,
> ++};
> +diff --git a/src/udev/udev-builtin.c b/src/udev/udev-builtin.c
> +index 1950ec2..f21c0b6 100644
> +--- a/src/udev/udev-builtin.c
> ++++ b/src/udev/udev-builtin.c
> +@@ -34,6 +34,9 @@ static const struct udev_builtin *builtins[] = {
> +         [UDEV_BUILTIN_BLKID] = &udev_builtin_blkid,
> + #endif
> +         [UDEV_BUILTIN_BTRFS] = &udev_builtin_btrfs,
> ++#ifdef HAVE_FIRMWARE
> ++        [UDEV_BUILTIN_FIRMWARE] = &udev_builtin_firmware,
> ++#endif
> +         [UDEV_BUILTIN_HWDB] = &udev_builtin_hwdb,
> +         [UDEV_BUILTIN_INPUT_ID] = &udev_builtin_input_id,
> +         [UDEV_BUILTIN_KEYBOARD] = &udev_builtin_keyboard,
> +diff --git a/src/udev/udev.h b/src/udev/udev.h
> +index dece6ec..f7ee1e7 100644
> +--- a/src/udev/udev.h
> ++++ b/src/udev/udev.h
> +@@ -151,6 +151,9 @@ enum udev_builtin_cmd {
> +         UDEV_BUILTIN_BLKID,
> + #endif
> +         UDEV_BUILTIN_BTRFS,
> ++#ifdef HAVE_FIRMWARE
> ++        UDEV_BUILTIN_FIRMWARE,
> ++#endif
> +         UDEV_BUILTIN_HWDB,
> +         UDEV_BUILTIN_INPUT_ID,
> +         UDEV_BUILTIN_KEYBOARD,
> +@@ -179,6 +182,9 @@ struct udev_builtin {
> + extern const struct udev_builtin udev_builtin_blkid;
> + #endif
> + extern const struct udev_builtin udev_builtin_btrfs;
> ++#ifdef HAVE_FIRMWARE
> ++extern const struct udev_builtin udev_builtin_firmware;
> ++#endif
> + extern const struct udev_builtin udev_builtin_hwdb;
> + extern const struct udev_builtin udev_builtin_input_id;
> + extern const struct udev_builtin udev_builtin_keyboard;
> +diff --git a/src/udev/udevd.c b/src/udev/udevd.c
> +index 99d4c89..71af1e1 100644
> +--- a/src/udev/udevd.c
> ++++ b/src/udev/udevd.c
> +@@ -99,6 +99,9 @@ struct event {
> +         dev_t devnum;
> +         int ifindex;
> +         bool is_block;
> ++#ifdef HAVE_FIRMWARE
> ++        bool nodelay;
> ++#endif
> + };
> +
> + static inline struct event *node_to_event(struct udev_list_node *node) {
> +@@ -472,6 +475,10 @@ static int event_queue_insert(struct udev_device *dev)
> { +         event->devnum = udev_device_get_devnum(dev);
> +         event->is_block = streq("block", udev_device_get_subsystem(dev));
> +         event->ifindex = udev_device_get_ifindex(dev);
> ++#ifdef HAVE_FIRMWARE
> ++        if (streq(udev_device_get_subsystem(dev), "firmware"))
> ++                event->nodelay = true;
> ++#endif
> +
> +         log_debug("seq %llu queued, '%s' '%s'",
> udev_device_get_seqnum(dev), +              udev_device_get_action(dev),
> udev_device_get_subsystem(dev)); +@@ -548,6 +555,12 @@ static bool
> is_devpath_busy(struct event *event) { +                         return
> true;
> +                 }
> +
> ++#ifdef HAVE_FIRMWARE
> ++                /* allow to bypass the dependency tracking */
> ++                if (event->nodelay)
> ++                        continue;
> ++#endif
> ++
> +                 /* parent device event found */
> +                 if (event->devpath[common] == '/') {
> +                         event->delaying_seqnum = loop_event->seqnum;
> +--
> +2.3.3
> +
> diff --git a/meta/recipes-core/systemd/systemd_219.bb
> b/meta/recipes-core/systemd/systemd_219.bb index e8383c3..b984256 100644
> --- a/meta/recipes-core/systemd/systemd_219.bb
> +++ b/meta/recipes-core/systemd/systemd_219.bb
> @@ -44,6 +44,8 @@ SRC_URI =
> "git://anongit.freedesktop.org/systemd/systemd;branch=master;protocol=
> file://0002-tmpfiles-quietly-ignore-ACLs-on-unsupported-filesyst.patch \
> file://0012-systemd-tmpfiles.c-Honor-ordering-within-files-as-th.patch \
> file://0013-journal-fix-Inappropriate-ioctl-for-device-on-ext4.patch \ +   
>        file://0014-Revert-rules-remove-firmware-loading-rules.patch \ +    
>      
> file://0015-Revert-udev-remove-userspace-firmware-loading-suppor.patch \
> file://tmpfiles-pam.patch \
>             file://touchscreen.rules \
>             file://00-create-volatile.conf \
> @@ -110,6 +112,7 @@ EXTRA_OECONF = " --with-rootprefix=${rootprefix} \
>                   --enable-split-usr \
>                   --without-python \
>                   --with-sysvrcnd-path=${sysconfdir} \
> +                 --with-firmware-path=${rootlibdir}/firmware \
>                 "
>  # uclibc does not have NSS
>  EXTRA_OECONF_append_libc-uclibc = " --disable-myhostname "




More information about the Openembedded-core mailing list