nixos/device-tree: improve overlays support
Now allows applying external overlays either in form of .dts file, literal dts context added to store or precompiled .dtbo. If overlays are defined, kernel device-trees are compiled with '-@' so the .dtb files contain symbols which we can reference in our overlays. Since `fdtoverlay` doesn't respect `/ compatible` by itself we query compatible strings of both `dtb` and `dtbo(verlay)` and apply only if latter is substring of the former. Also adds support for filtering .dtb files (as there are now nearly 1k dtbs). Co-authored-by: georgewhewell <georgerw@gmail.com> Co-authored-by: Kai Wohlfahrt <kai.wohlfahrt@gmail.com>
This commit is contained in:
parent
51428e8d38
commit
6c9df40a4b
@ -833,6 +833,17 @@ CREATE ROLE postgres LOGIN SUPERUSER;
|
|||||||
of the default <literal>out</literal> output anymore - if you relied on the
|
of the default <literal>out</literal> output anymore - if you relied on the
|
||||||
<literal>notmuch-emacs-mua</literal> binary or the emacs lisp files, access them via
|
<literal>notmuch-emacs-mua</literal> binary or the emacs lisp files, access them via
|
||||||
the <literal>notmuch.emacs</literal> output.
|
the <literal>notmuch.emacs</literal> output.
|
||||||
|
|
||||||
|
Device tree overlay support was improved in
|
||||||
|
<link xlink:href="https://github.com/NixOS/nixpkgs/pull/79370">#79370</link>
|
||||||
|
and now uses <xref linkend="opt-hardware.deviceTree.kernelPackage"/>
|
||||||
|
instead of <option>hardware.deviceTree.base</option>.
|
||||||
|
|
||||||
|
<xref linkend="opt-hardware.deviceTree.overlays"/> configuration was
|
||||||
|
extended to support <literal>.dts</literal> files with symbols.
|
||||||
|
|
||||||
|
Device trees can now be filtered by setting
|
||||||
|
<xref linkend="opt-hardware.deviceTree.filter"/> option.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -4,7 +4,114 @@ with lib;
|
|||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.hardware.deviceTree;
|
cfg = config.hardware.deviceTree;
|
||||||
in {
|
|
||||||
|
overlayType = types.submodule {
|
||||||
|
options = {
|
||||||
|
name = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Name of this overlay
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dtsFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
description = ''
|
||||||
|
Path to .dts overlay file, overlay is applied to
|
||||||
|
each .dtb file matching "compatible" of the overlay.
|
||||||
|
'';
|
||||||
|
default = null;
|
||||||
|
example = literalExample "./dts/overlays.dts";
|
||||||
|
};
|
||||||
|
|
||||||
|
dtsText = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Literal DTS contents, overlay is applied to
|
||||||
|
each .dtb file matching "compatible" of the overlay.
|
||||||
|
'';
|
||||||
|
example = literalExample ''
|
||||||
|
/dts-v1/;
|
||||||
|
/plugin/;
|
||||||
|
/ {
|
||||||
|
compatible = "raspberrypi";
|
||||||
|
fragment@0 {
|
||||||
|
target-path = "/soc";
|
||||||
|
__overlay__ {
|
||||||
|
pps {
|
||||||
|
compatible = "pps-gpio";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
dtboFile = mkOption {
|
||||||
|
type = types.nullOr types.path;
|
||||||
|
default = null;
|
||||||
|
description = ''
|
||||||
|
Path to .dtbo compiled overlay file.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# this requires kernel package
|
||||||
|
dtbsWithSymbols = pkgs.stdenv.mkDerivation {
|
||||||
|
name = "dtbs-with-symbols";
|
||||||
|
inherit (cfg.kernelPackage) src nativeBuildInputs depsBuildBuild;
|
||||||
|
patches = map (patch: patch.patch) cfg.kernelPackage.kernelPatches;
|
||||||
|
buildPhase = ''
|
||||||
|
patchShebangs scripts/*
|
||||||
|
substituteInPlace scripts/Makefile.lib \
|
||||||
|
--replace 'DTC_FLAGS += $(DTC_FLAGS_$(basetarget))' 'DTC_FLAGS += $(DTC_FLAGS_$(basetarget)) -@'
|
||||||
|
make ${pkgs.stdenv.hostPlatform.platform.kernelBaseConfig} ARCH="${pkgs.stdenv.hostPlatform.platform.kernelArch}"
|
||||||
|
make dtbs ARCH="${pkgs.stdenv.hostPlatform.platform.kernelArch}"
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
make dtbs_install INSTALL_DTBS_PATH=$out/dtbs ARCH="${pkgs.stdenv.hostPlatform.platform.kernelArch}"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
filterDTBs = src: if isNull cfg.filter
|
||||||
|
then "${src}/dtbs"
|
||||||
|
else
|
||||||
|
pkgs.runCommand "dtbs-filtered" {} ''
|
||||||
|
mkdir -p $out
|
||||||
|
cd ${src}/dtbs
|
||||||
|
find . -type f -name '${cfg.filter}' -print0 \
|
||||||
|
| xargs -0 cp -v --no-preserve=mode --target-directory $out --parents
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Compile single Device Tree overlay source
|
||||||
|
# file (.dts) into its compiled variant (.dtbo)
|
||||||
|
compileDTS = name: f: pkgs.callPackage({ dtc }: pkgs.stdenv.mkDerivation {
|
||||||
|
name = "${name}-dtbo";
|
||||||
|
|
||||||
|
nativeBuildInputs = [ dtc ];
|
||||||
|
|
||||||
|
buildCommand = ''
|
||||||
|
dtc -I dts ${f} -O dtb -@ -o $out
|
||||||
|
'';
|
||||||
|
}) {};
|
||||||
|
|
||||||
|
# Fill in `dtboFile` for each overlay if not set already.
|
||||||
|
# Existence of one of these is guarded by assertion below
|
||||||
|
withDTBOs = xs: flip map xs (o: o // { dtboFile =
|
||||||
|
if isNull o.dtboFile then
|
||||||
|
if !isNull o.dtsFile then compileDTS o.name o.dtsFile
|
||||||
|
else compileDTS o.name (pkgs.writeText "dts" o.dtsText)
|
||||||
|
else o.dtboFile; } );
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
(mkRemovedOptionModule [ "hardware" "deviceTree" "base" ] "Use hardware.deviceTree.kernelPackage instead")
|
||||||
|
];
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
hardware.deviceTree = {
|
hardware.deviceTree = {
|
||||||
enable = mkOption {
|
enable = mkOption {
|
||||||
@ -16,13 +123,13 @@ in {
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
base = mkOption {
|
kernelPackage = mkOption {
|
||||||
default = "${config.boot.kernelPackages.kernel}/dtbs";
|
default = config.boot.kernelPackages.kernel;
|
||||||
defaultText = "\${config.boot.kernelPackages.kernel}/dtbs";
|
defaultText = "config.boot.kernelPackages.kernel";
|
||||||
example = literalExample "pkgs.device-tree_rpi";
|
example = literalExample "pkgs.linux_latest";
|
||||||
type = types.path;
|
type = types.path;
|
||||||
description = ''
|
description = ''
|
||||||
The path containing the base device-tree (.dtb) to boot. Contains
|
Kernel package containing the base device-tree (.dtb) to boot. Uses
|
||||||
device trees bundled with the Linux kernel by default.
|
device trees bundled with the Linux kernel by default.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
@ -38,14 +145,32 @@ in {
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
filter = mkOption {
|
||||||
|
type = types.nullOr types.str;
|
||||||
|
default = null;
|
||||||
|
example = "*rpi*.dtb";
|
||||||
|
description = ''
|
||||||
|
Only include .dtb files matching glob expression.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
overlays = mkOption {
|
overlays = mkOption {
|
||||||
default = [];
|
default = [];
|
||||||
example = literalExample
|
example = literalExample ''
|
||||||
"[\"\${pkgs.device-tree_rpi.overlays}/w1-gpio.dtbo\"]";
|
[
|
||||||
type = types.listOf types.path;
|
{ name = "pps"; dtsFile = ./dts/pps.dts; }
|
||||||
|
{ name = "spi";
|
||||||
|
dtsText = "...";
|
||||||
|
}
|
||||||
|
{ name = "precompiled"; dtboFile = ./dtbos/example.dtbo; }
|
||||||
|
]
|
||||||
|
'';
|
||||||
|
type = types.listOf (types.coercedTo types.path (path: {
|
||||||
|
name = baseNameOf path;
|
||||||
|
dtboFile = path;
|
||||||
|
}) overlayType);
|
||||||
description = ''
|
description = ''
|
||||||
A path containing device tree overlays (.dtbo) to be applied to all
|
List of overlays to apply to base device-tree (.dtb) files.
|
||||||
base device-trees.
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -54,14 +179,27 @@ in {
|
|||||||
type = types.nullOr types.path;
|
type = types.nullOr types.path;
|
||||||
internal = true;
|
internal = true;
|
||||||
description = ''
|
description = ''
|
||||||
A path containing the result of applying `overlays` to `base`.
|
A path containing the result of applying `overlays` to `kernelPackage`.
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf (cfg.enable) {
|
config = mkIf (cfg.enable) {
|
||||||
|
|
||||||
|
assertions = let
|
||||||
|
invalidOverlay = o: isNull o.dtsFile && isNull o.dtsText && isNull o.dtboFile;
|
||||||
|
in lib.singleton {
|
||||||
|
assertion = lib.all (o: !invalidOverlay o) cfg.overlays;
|
||||||
|
message = ''
|
||||||
|
deviceTree overlay needs one of dtsFile, dtsText or dtboFile set.
|
||||||
|
Offending overlay(s):
|
||||||
|
${toString (map (o: o.name) (builtins.filter invalidOverlay cfg.overlays))}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
hardware.deviceTree.package = if (cfg.overlays != [])
|
hardware.deviceTree.package = if (cfg.overlays != [])
|
||||||
then pkgs.deviceTree.applyOverlays cfg.base cfg.overlays else cfg.base;
|
then pkgs.deviceTree.applyOverlays (filterDTBs dtbsWithSymbols) (withDTBOs cfg.overlays)
|
||||||
|
else (filterDTBs cfg.kernelPackage);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,31 @@
|
|||||||
{ stdenvNoCC, dtc, findutils }:
|
{ stdenvNoCC, dtc, findutils }:
|
||||||
|
|
||||||
with stdenvNoCC.lib; {
|
with stdenvNoCC.lib; {
|
||||||
applyOverlays = (base: overlays: stdenvNoCC.mkDerivation {
|
applyOverlays = (base: overlays': stdenvNoCC.mkDerivation {
|
||||||
name = "device-tree-overlays";
|
name = "device-tree-overlays";
|
||||||
nativeBuildInputs = [ dtc findutils ];
|
nativeBuildInputs = [ dtc findutils ];
|
||||||
buildCommand = let
|
buildCommand = let
|
||||||
quotedDtbos = concatMapStringsSep " " (o: "\"${toString o}\"") (toList overlays);
|
overlays = toList overlays';
|
||||||
in ''
|
in ''
|
||||||
for dtb in $(find ${base} -name "*.dtb" ); do
|
mkdir -p $out
|
||||||
outDtb=$out/$(realpath --relative-to "${base}" "$dtb")
|
cd ${base}
|
||||||
mkdir -p "$(dirname "$outDtb")"
|
find . -type f -name '*.dtb' -print0 \
|
||||||
fdtoverlay -o "$outDtb" -i "$dtb" ${quotedDtbos};
|
| xargs -0 cp -v --no-preserve=mode --target-directory $out --parents
|
||||||
|
|
||||||
|
for dtb in $(find $out -type f -name '*.dtb'); do
|
||||||
|
dtbCompat="$( fdtget -t s $dtb / compatible )"
|
||||||
|
|
||||||
|
${flip (concatMapStringsSep "\n") overlays (o: ''
|
||||||
|
overlayCompat="$( fdtget -t s ${o.dtboFile} / compatible )"
|
||||||
|
# overlayCompat in dtbCompat
|
||||||
|
if [[ "$dtbCompat" =~ "$overlayCompat" ]]; then
|
||||||
|
echo "Applying overlay ${o.name} to $( basename $dtb )"
|
||||||
|
mv $dtb{,.in}
|
||||||
|
fdtoverlay -o "$dtb" -i "$dtb.in" ${o.dtboFile};
|
||||||
|
rm $dtb.in
|
||||||
|
fi
|
||||||
|
'')}
|
||||||
|
|
||||||
done
|
done
|
||||||
'';
|
'';
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user