[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