Add support for kernel overlays

Core Kernel modules are now installed to
/usr/lib/kernel-overlays/base/lib/modules instead of /usr/lib/modules

Firmware files are installed to
/usr/lib/kernel-overlays/base/lib/firmware instead of /usr/lib/firmware

Packages can choose to install their modules and/or firmwareinto a
different overlay directory than base so they are not automatically enabled.

A new systemd service kernel-overlays, which is run before any modules
are loaded, adds overlays enabled via /storage/.cache/kernel-overlays/*.conf

These conf files must either contain the name of a system overlay,
which will then be searched for in /usr/lib/kernel-overlays/, or an
absolute path starting with '/'.

Overlaying is implemented by symlinking files from the overlays
to /usr/lib/modules and /usr/lib/firmware as not all platforms
support overlayfs.

This overlaying system can also be used by addons to provide optional
kernel modules and/or firmware by storing the absolute path to the addon
directory in the conf file and shipping kernel modules in
<addondir>/lib/modules/<KERNELVER>.

To save space only symlinks for modules matching the currently
running kernel version are created as addons may want to ship
modules for older kernel versions as well to be backward-compatible
to older LibreELEC versions.

Changes since v1:
- fixup kernel-overlays-service: add before kmod-static-nodes.service
  Fix static device nodes for module autoloading not being created.
- fixup kernel-overlays-service: fail if /usr/lib/modules exists
- squash kernel overlays: use get_kernel_overlay_dir in linux/package.mk
- Add support for firmware files via kernel overlays
- config/functions: include kernel overlays in addon installation

Signed-off-by: Matthias Reichl <hias@horus.com>
This commit is contained in:
Matthias Reichl 2017-09-05 09:17:30 +02:00
parent d3b73a8320
commit ad9e8dc372
12 changed files with 143 additions and 19 deletions

View File

@ -143,17 +143,24 @@ kernel_version() {
# get kernel module dir
get_module_dir() {
basename $(ls -d $(get_build_dir linux)/.install_pkg/usr/lib/modules/*)
basename $(ls -d $(get_build_dir linux)/.install_pkg/usr/lib/kernel-overlays/base/lib/modules/*)
}
# get base path to kernel modules and firmware
get_kernel_overlay_dir() {
echo "/usr/lib/kernel-overlays/${1:-base}"
}
# get full path to kernel module dir
# optional parameter specifies overlay level (default is base)
get_full_module_dir() {
echo "/usr/lib/modules/$(get_module_dir)"
echo "$(get_kernel_overlay_dir $1)/lib/modules/$(get_module_dir)"
}
# get full path to firmware dir
# optional parameter specifies overlay level (default is base)
get_full_firmware_dir() {
echo "/usr/lib/firmware"
echo "$(get_kernel_overlay_dir $1)/lib/firmware"
}
# get package's build dir
@ -192,6 +199,11 @@ install_binary_addon() {
cp -L $PKG_BUILD/.install_pkg/usr/lib/$MEDIACENTER/addons/$addon_id/$addon_so $ADDON_BUILD/$addon_id/
chmod +x $ADDON_BUILD/$addon_id/$addon_so
fi
if [ -d $PKG_BUILD/.install_pkg/usr/lib/kernel-overlays/$addon_id ] ; then
mkdir -p $ADDON_BUILD/$addon_id/kernel-overlay
cp -PR $PKG_BUILD/.install_pkg/usr/lib/kernel-overlays/$addon_id/* $ADDON_BUILD/$addon_id/kernel-overlay
fi
}
install_addon_source() {

View File

@ -36,7 +36,7 @@ make_target() {
}
makeinstall_target() {
DESTDIR=$INSTALL/usr ./install
DESTDIR=$INSTALL/$(get_kernel_overlay_dir) ./install
}
post_makeinstall_target() {

View File

@ -35,5 +35,5 @@ make_target() {
}
makeinstall_target() {
DESTDIR=$INSTALL/usr ./install
DESTDIR=$INSTALL/$(get_kernel_overlay_dir) ./install
}

View File

@ -36,5 +36,5 @@ make_target() {
}
makeinstall_target() {
DESTDIR=$INSTALL/usr ./install
DESTDIR=$INSTALL/$(get_kernel_overlay_dir) ./install
}

View File

@ -36,5 +36,5 @@ make_target() {
}
makeinstall_target() {
DESTDIR=$INSTALL/usr ./install
DESTDIR=$INSTALL/$(get_kernel_overlay_dir) ./install
}

View File

@ -36,5 +36,5 @@ make_target() {
}
makeinstall_target() {
DESTDIR=$INSTALL/usr ./install
DESTDIR=$INSTALL/$(get_kernel_overlay_dir) ./install
}

View File

@ -194,9 +194,9 @@ pre_make_target() {
make_target() {
LDFLAGS="" make modules
LDFLAGS="" make INSTALL_MOD_PATH=$INSTALL/usr DEPMOD="$TOOLCHAIN/bin/depmod" modules_install
rm -f $INSTALL/usr/lib/modules/*/build
rm -f $INSTALL/usr/lib/modules/*/source
LDFLAGS="" make INSTALL_MOD_PATH=$INSTALL/$(get_kernel_overlay_dir) DEPMOD="$TOOLCHAIN/bin/depmod" modules_install
rm -f $INSTALL/$(get_kernel_overlay_dir)/lib/modules/*/build
rm -f $INSTALL/$(get_kernel_overlay_dir)/lib/modules/*/source
( cd $ROOT
rm -rf $BUILD/initramfs

View File

@ -1011,7 +1011,7 @@
mount --move /flash /sysroot/flash
mount --move /storage /sysroot/storage
if [ ! -d "/sysroot/usr/lib/modules/$(uname -r)/" -a -f "/sysroot/usr/lib/systemd/systemd" ]; then
if [ ! -d "/sysroot/usr/lib/kernel-overlays/base/lib/modules/$(uname -r)/" -a -f "/sysroot/usr/lib/systemd/systemd" ]; then
echo ""
echo "NEVER TOUCH boot= in extlinux.conf / cmdline.txt!"
echo "If you don't know what you are doing,"

View File

@ -205,8 +205,10 @@ post_makeinstall_target() {
cp $PKG_DIR/scripts/systemd-machine-id-setup $INSTALL/usr/bin
cp $PKG_DIR/scripts/userconfig-setup $INSTALL/usr/bin
# provide 'halt', 'shutdown', 'reboot' & co.
mkdir -p $INSTALL/usr/sbin
cp $PKG_DIR/scripts/kernel-overlays-setup $INSTALL/usr/sbin
# provide 'halt', 'shutdown', 'reboot' & co.
ln -sf /usr/bin/systemctl $INSTALL/usr/sbin/halt
ln -sf /usr/bin/systemctl $INSTALL/usr/sbin/poweroff
ln -sf /usr/bin/systemctl $INSTALL/usr/sbin/reboot
@ -255,5 +257,6 @@ post_install() {
enable_service machine-id.service
enable_service debugconfig.service
enable_service userconfig.service
enable_service kernel-overlays.service
enable_service hwdb.service
}

View File

@ -0,0 +1,90 @@
#!/bin/sh
################################################################################
# This file is part of LibreELEC - https://libreelec.tv
# Copyright (C) 2017-present Team LibreELEC
#
# LibreELEC 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.
#
# LibreELEC 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.
#
# You should have received a copy of the GNU General Public License
# along with LibreELEC. If not, see <http://www.gnu.org/licenses/>.
################################################################################
SYSTEM_OVERLAYS_DIR=/usr/lib/kernel-overlays
OVERLAY_CONFIG_DIR=/storage/.cache/kernel-overlays
KVER=$(uname -r)
MODULES_DIR="/var/lib/modules/${KVER}"
FIRMWARE_DIR="/var/lib/firmware"
mkdir -p "${MODULES_DIR}"
mkdir -p "${FIRMWARE_DIR}"
mkdir -p "${OVERLAY_CONFIG_DIR}"
log() {
echo "kernel-overlays-setup: $@" > /dev/kmsg
}
apply_overlay() {
case "$1" in
/*)
modules_overlay_dir="${1}/lib/modules/${KVER}"
firmware_overlay_dir="${1}/lib/firmware"
;;
*)
modules_overlay_dir="${SYSTEM_OVERLAYS_DIR}/${1}/lib/modules/${KVER}"
firmware_overlay_dir="${SYSTEM_OVERLAYS_DIR}/${1}/lib/firmware"
;;
esac
if [ -d "${modules_overlay_dir}" ] ; then
GOT_MODULE_OVERLAY="yes"
if cp -rfs "${modules_overlay_dir}"/* "${MODULES_DIR}" ; then
log "added modules from $modules_overlay_dir"
else
log "failed to add modules from $modules_overlay_dir"
fi
fi
if [ -d "${firmware_overlay_dir}" ] ; then
if cp -rfs "${firmware_overlay_dir}"/* "${FIRMWARE_DIR}" ; then
log "added firmware from $firmware_overlay_dir"
else
log "failed to add firmware from $firmware_overlay_dir"
fi
fi
}
# setup system base modules
log "setup base modules"
apply_overlay base
# apply user-configured module overlays
if [ -d "${OVERLAY_CONFIG_DIR}" ] ; then
log "adding overlays from ${OVERLAY_CONFIG_DIR}"
GOT_MODULE_OVERLAY="no"
for conf in "${OVERLAY_CONFIG_DIR}/"*.conf ; do
if [ -e "$conf" ] ; then
log "processing conf $conf"
overlay=$(cat "$conf")
[ -n "$overlay" ] && apply_overlay "$overlay"
fi
done
if [ "yes" = "$GOT_MODULE_OVERLAY" ] ; then
log "running depmod"
/usr/sbin/depmod -a
fi
fi
log "done"

View File

@ -0,0 +1,12 @@
[Unit]
Description=Create kernel modules tree from overlays
DefaultDependencies=no
After=var.mount
Before=systemd-udevd.service systemd-udev-trigger.service systemd-modules-load.service systemd-remount-fs.service swap.service machine-id.service kmod-static-nodes.service
[Service]
Type=oneshot
ExecStart=/usr/sbin/kernel-overlays-setup
[Install]
WantedBy=local-fs.target

View File

@ -215,20 +215,27 @@ if [ -n "$DEVICE" -a -d "$PROJECT_DIR/$PROJECT/devices/$DEVICE/filesystem" ]; th
done
fi
# run depmod
MODVER=$(basename $(ls -d $INSTALL/usr/lib/modules/*))
find $INSTALL/usr/lib/modules/$MODVER/ -name *.ko | \
sed -e "s,$INSTALL/usr/lib/modules/$MODVER/,," > $INSTALL/usr/lib/modules/$MODVER/modules.order
$TOOLCHAIN/bin/depmod -b $INSTALL/usr -a -e -F "$BUILD/linux-$(kernel_version)/System.map" $MODVER
# run depmod for base overlay modules
MODVER=$(basename $(ls -d $INSTALL/usr/lib/kernel-overlays/base/lib/modules/*))
find $INSTALL/usr/lib/kernel-overlays/base/lib/modules/$MODVER/ -name *.ko | \
sed -e "s,$INSTALL/usr/lib/kernel-overlays/base/lib/modules/$MODVER/,," \
> $INSTALL/usr/lib/kernel-overlays/base/lib/modules/$MODVER/modules.order
$TOOLCHAIN/bin/depmod -b $INSTALL/usr/lib/kernel-overlays/base -a -e -F "$BUILD/linux-$(kernel_version)/System.map" $MODVER
# strip kernel modules
if [ "$TARGET_KERNEL_ARCH" = "arm64" -a "$TARGET_ARCH" = "arm" ]; then
STRIP=$TOOLCHAIN/lib/gcc-linaro-aarch64-elf/bin/aarch64-elf-strip
fi
for MOD in `find $INSTALL/usr/lib/modules/ -type f -name *.ko`; do
for MOD in `find $INSTALL/usr/lib/kernel-overlays/ -type f -name *.ko`; do
$STRIP --strip-debug $MOD
done
# symlink overlayed modules to /usr/lib/modules
ln -sT /var/lib/modules $INSTALL/usr/lib/modules
# symlink overlayed firmware to /usr/lib/firmware
ln -sT /var/lib/firmware $INSTALL/usr/lib/firmware
# make target dir
mkdir -p $TARGET_IMG
rm -rf $TARGET_IMG/$IMAGE_NAME.kernel