at 25.11-pre 14 kB view raw
1{ 2 config, 3 lib, 4 options, 5 pkgs, 6 ... 7}: 8 9with lib; 10 11let 12 13 plymouth = pkgs.plymouth.override { 14 systemd = config.boot.initrd.systemd.package; 15 }; 16 17 cfg = config.boot.plymouth; 18 opt = options.boot.plymouth; 19 20 nixosBreezePlymouth = pkgs.plasma5Packages.breeze-plymouth.override { 21 logoFile = cfg.logo; 22 logoName = "nixos"; 23 osName = "NixOS"; 24 osVersion = config.system.nixos.release; 25 }; 26 27 plymouthLogos = pkgs.runCommand "plymouth-logos" { inherit (cfg) logo; } '' 28 mkdir -p $out 29 30 # For themes that are compiled with PLYMOUTH_LOGO_FILE 31 mkdir -p $out/etc/plymouth 32 ln -s $logo $out/etc/plymouth/logo.png 33 34 # Logo for bgrt theme 35 # Note this is technically an abuse of watermark for the bgrt theme 36 # See: https://gitlab.freedesktop.org/plymouth/plymouth/-/issues/95#note_813768 37 mkdir -p $out/share/plymouth/themes/spinner 38 ln -s $logo $out/share/plymouth/themes/spinner/watermark.png 39 40 # Logo for spinfinity theme 41 # See: https://gitlab.freedesktop.org/plymouth/plymouth/-/issues/106 42 mkdir -p $out/share/plymouth/themes/spinfinity 43 ln -s $logo $out/share/plymouth/themes/spinfinity/header-image.png 44 45 # Logo for catppuccin (two-step) theme 46 for flavour in mocha macchiato latte frappe 47 do 48 mkdir -p $out/share/plymouth/themes/catppuccin-"$flavour" 49 ln -s $logo $out/share/plymouth/themes/catppuccin-"$flavour"/header-image.png 50 done 51 ''; 52 53 themesEnv = pkgs.buildEnv { 54 name = "plymouth-themes"; 55 paths = [ 56 plymouth 57 plymouthLogos 58 ] ++ cfg.themePackages; 59 }; 60 61 configFile = pkgs.writeText "plymouthd.conf" '' 62 [Daemon] 63 ShowDelay=0 64 DeviceTimeout=8 65 Theme=${cfg.theme} 66 ${cfg.extraConfig} 67 ''; 68 69in 70 71{ 72 73 options = { 74 75 boot.plymouth = { 76 77 enable = mkEnableOption "Plymouth boot splash screen"; 78 79 font = mkOption { 80 default = "${pkgs.dejavu_fonts.minimal}/share/fonts/truetype/DejaVuSans.ttf"; 81 defaultText = literalExpression ''"''${pkgs.dejavu_fonts.minimal}/share/fonts/truetype/DejaVuSans.ttf"''; 82 type = types.path; 83 description = '' 84 Font file made available for displaying text on the splash screen. 85 ''; 86 }; 87 88 themePackages = mkOption { 89 default = lib.optional (cfg.theme == "breeze") nixosBreezePlymouth; 90 defaultText = literalMD '' 91 A NixOS branded variant of the breeze theme when 92 `config.${opt.theme} == "breeze"`, otherwise 93 `[ ]`. 94 ''; 95 type = types.listOf types.package; 96 description = '' 97 Extra theme packages for plymouth. 98 ''; 99 }; 100 101 theme = mkOption { 102 default = "bgrt"; 103 type = types.str; 104 description = '' 105 Splash screen theme. 106 ''; 107 }; 108 109 logo = mkOption { 110 type = types.path; 111 # Dimensions are 48x48 to match GDM logo 112 default = "${pkgs.nixos-icons}/share/icons/hicolor/48x48/apps/nix-snowflake-white.png"; 113 defaultText = literalExpression ''"''${pkgs.nixos-icons}/share/icons/hicolor/48x48/apps/nix-snowflake-white.png"''; 114 example = literalExpression '' 115 pkgs.fetchurl { 116 url = "https://nixos.org/logo/nixos-hires.png"; 117 sha256 = "1ivzgd7iz0i06y36p8m5w48fd8pjqwxhdaavc0pxs7w1g7mcy5si"; 118 } 119 ''; 120 description = '' 121 Logo which is displayed on the splash screen. 122 Currently supports PNG file format only. 123 ''; 124 }; 125 126 extraConfig = mkOption { 127 type = types.lines; 128 default = ""; 129 description = '' 130 Literal string to append to `configFile` 131 and the config file generated by the plymouth module. 132 ''; 133 }; 134 135 }; 136 137 }; 138 139 config = mkIf cfg.enable { 140 141 boot.kernelParams = [ "splash" ]; 142 143 # To be discoverable by systemd. 144 environment.systemPackages = [ plymouth ]; 145 146 environment.etc."plymouth/plymouthd.conf".source = configFile; 147 environment.etc."plymouth/plymouthd.defaults".source = 148 "${plymouth}/share/plymouth/plymouthd.defaults"; 149 environment.etc."plymouth/logo.png".source = cfg.logo; 150 environment.etc."plymouth/themes".source = "${themesEnv}/share/plymouth/themes"; 151 # XXX: Needed because we supply a different set of plugins in initrd. 152 environment.etc."plymouth/plugins".source = "${plymouth}/lib/plymouth"; 153 154 systemd.tmpfiles.rules = [ 155 "d /run/plymouth 0755 root root 0 -" 156 "L+ /run/plymouth/plymouthd.defaults - - - - /etc/plymouth/plymouthd.defaults" 157 "L+ /run/plymouth/themes - - - - /etc/plymouth/themes" 158 "L+ /run/plymouth/plugins - - - - /etc/plymouth/plugins" 159 ]; 160 161 systemd.packages = [ plymouth ]; 162 163 systemd.services.plymouth-kexec.wantedBy = [ "kexec.target" ]; 164 systemd.services.plymouth-halt.wantedBy = [ "halt.target" ]; 165 systemd.services.plymouth-quit-wait.wantedBy = [ "multi-user.target" ]; 166 systemd.services.plymouth-quit.wantedBy = [ "multi-user.target" ]; 167 systemd.services.plymouth-poweroff.wantedBy = [ "poweroff.target" ]; 168 systemd.services.plymouth-reboot.wantedBy = [ "reboot.target" ]; 169 systemd.services.plymouth-read-write.wantedBy = [ "sysinit.target" ]; 170 systemd.services.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ]; 171 systemd.paths.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ]; 172 173 # Prevent Plymouth taking over the screen during system updates. 174 systemd.services.plymouth-start.restartIfChanged = false; 175 176 boot.initrd.systemd = { 177 extraBin.plymouth = "${plymouth}/bin/plymouth"; # for the recovery shell 178 storePaths = [ 179 "${lib.getBin config.boot.initrd.systemd.package}/bin/systemd-tty-ask-password-agent" 180 "${plymouth}/bin/plymouthd" 181 "${plymouth}/sbin/plymouthd" 182 ]; 183 packages = [ plymouth ]; # systemd units 184 contents = { 185 # Files 186 "/etc/plymouth/plymouthd.conf".source = configFile; 187 "/etc/plymouth/logo.png".source = cfg.logo; 188 "/etc/plymouth/plymouthd.defaults".source = "${plymouth}/share/plymouth/plymouthd.defaults"; 189 # Directories 190 "/etc/plymouth/plugins".source = pkgs.runCommand "plymouth-initrd-plugins" { } '' 191 # Check if the actual requested theme is here 192 if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then 193 echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages" 194 exit 1 195 fi 196 197 moduleName="$(sed -n 's,ModuleName *= *,,p' ${themesEnv}/share/plymouth/themes/${cfg.theme}/${cfg.theme}.plymouth)" 198 199 mkdir -p $out/renderers 200 # module might come from a theme 201 cp ${themesEnv}/lib/plymouth/*.so $out 202 cp ${plymouth}/lib/plymouth/renderers/*.so $out/renderers 203 # useless in the initrd, and adds several megabytes to the closure 204 rm $out/renderers/x11.so 205 ''; 206 "/etc/plymouth/themes".source = pkgs.runCommand "plymouth-initrd-themes" { } '' 207 # Check if the actual requested theme is here 208 if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then 209 echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages" 210 exit 1 211 fi 212 213 mkdir -p $out/${cfg.theme} 214 cp -r ${themesEnv}/share/plymouth/themes/${cfg.theme}/* $out/${cfg.theme} 215 # Copy more themes if the theme depends on others 216 for theme in $(grep -hRo '/share/plymouth/themes/.*$' $out | xargs -n1 basename); do 217 if [[ -d "${themesEnv}/share/plymouth/themes/$theme" ]]; then 218 if [[ ! -d "$out/$theme" ]]; then 219 echo "Adding dependent theme: $theme" 220 mkdir -p "$out/$theme" 221 cp -r "${themesEnv}/share/plymouth/themes/$theme"/* "$out/$theme" 222 fi 223 else 224 echo "Missing theme dependency: $theme" 225 fi 226 done 227 # Fixup references 228 for theme in $out/*/*.plymouth; do 229 sed -i "s,${builtins.storeDir}/.*/share/plymouth/themes,$out," "$theme" 230 done 231 ''; 232 233 # Fonts 234 "/etc/plymouth/fonts".source = pkgs.runCommand "plymouth-initrd-fonts" { } '' 235 mkdir -p $out 236 cp ${escapeShellArg cfg.font} $out 237 ''; 238 "/etc/fonts/fonts.conf".text = '' 239 <?xml version="1.0"?> 240 <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> 241 <fontconfig> 242 <dir>/etc/plymouth/fonts</dir> 243 </fontconfig> 244 ''; 245 }; 246 # Properly enable units. These are the units that arch copies 247 services = { 248 plymouth-halt.wantedBy = [ "halt.target" ]; 249 plymouth-kexec.wantedBy = [ "kexec.target" ]; 250 plymouth-poweroff.wantedBy = [ "poweroff.target" ]; 251 plymouth-quit-wait.wantedBy = [ "multi-user.target" ]; 252 plymouth-quit.wantedBy = [ "multi-user.target" ]; 253 plymouth-read-write.wantedBy = [ "sysinit.target" ]; 254 plymouth-reboot.wantedBy = [ "reboot.target" ]; 255 plymouth-start.wantedBy = [ 256 "initrd-switch-root.target" 257 "sysinit.target" 258 ]; 259 plymouth-switch-root-initramfs.wantedBy = [ 260 "halt.target" 261 "kexec.target" 262 "plymouth-switch-root-initramfs.service" 263 "poweroff.target" 264 "reboot.target" 265 ]; 266 plymouth-switch-root.wantedBy = [ "initrd-switch-root.target" ]; 267 }; 268 # Link in runtime files before starting 269 services.plymouth-start.preStart = '' 270 mkdir -p /run/plymouth 271 ln -sf /etc/plymouth/{plymouthd.defaults,themes,plugins} /run/plymouth/ 272 ''; 273 }; 274 275 # Insert required udev rules. We take stage 2 systemd because the udev 276 # rules are only generated when building with logind. 277 boot.initrd.services.udev.packages = [ 278 (pkgs.runCommand "initrd-plymouth-udev-rules" { } '' 279 mkdir -p $out/etc/udev/rules.d 280 cp ${config.systemd.package.out}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out/etc/udev/rules.d 281 sed -i '/loginctl/d' $out/etc/udev/rules.d/71-seat.rules 282 '') 283 ]; 284 285 boot.initrd.extraUtilsCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' 286 copy_bin_and_libs ${plymouth}/bin/plymouth 287 copy_bin_and_libs ${plymouth}/bin/plymouthd 288 289 # Check if the actual requested theme is here 290 if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then 291 echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages" 292 exit 1 293 fi 294 295 moduleName="$(sed -n 's,ModuleName *= *,,p' ${themesEnv}/share/plymouth/themes/${cfg.theme}/${cfg.theme}.plymouth)" 296 297 mkdir -p $out/lib/plymouth/renderers 298 # module might come from a theme 299 cp ${themesEnv}/lib/plymouth/*.so $out/lib/plymouth 300 cp ${plymouth}/lib/plymouth/renderers/*.so $out/lib/plymouth/renderers 301 # useless in the initrd, and adds several megabytes to the closure 302 rm $out/lib/plymouth/renderers/x11.so 303 304 mkdir -p $out/share/plymouth/themes 305 cp ${plymouth}/share/plymouth/plymouthd.defaults $out/share/plymouth 306 307 # Copy themes into working directory for patching 308 mkdir themes 309 310 # Use -L to copy the directories proper, not the symlinks to them. 311 # Copy all themes because they're not large assets, and bgrt depends on the ImageDir of 312 # the spinner theme. 313 cp -r -L ${themesEnv}/share/plymouth/themes/* themes 314 315 # Patch out any attempted references to the theme or plymouth's themes directory 316 chmod -R +w themes 317 find themes -type f | while read file 318 do 319 sed -i "s,${builtins.storeDir}/.*/share/plymouth/themes,$out/share/plymouth/themes,g" $file 320 done 321 322 # Install themes 323 cp -r themes/* $out/share/plymouth/themes 324 325 # Install logo 326 mkdir -p $out/etc/plymouth 327 cp -r -L ${themesEnv}/etc/plymouth $out/etc 328 329 # Setup font 330 mkdir -p $out/share/fonts 331 cp ${cfg.font} $out/share/fonts 332 mkdir -p $out/etc/fonts 333 cat > $out/etc/fonts/fonts.conf <<EOF 334 <?xml version="1.0"?> 335 <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> 336 <fontconfig> 337 <dir>$out/share/fonts</dir> 338 </fontconfig> 339 EOF 340 ''; 341 342 boot.initrd.extraUtilsCommandsTest = mkIf (!config.boot.initrd.systemd.enable) '' 343 $out/bin/plymouthd --help >/dev/null 344 $out/bin/plymouth --help >/dev/null 345 ''; 346 347 boot.initrd.extraUdevRulesCommands = mkIf (!config.boot.initrd.systemd.enable) '' 348 cp ${config.systemd.package}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out 349 sed -i '/loginctl/d' $out/71-seat.rules 350 ''; 351 352 # We use `mkAfter` to ensure that LUKS password prompt would be shown earlier than the splash screen. 353 boot.initrd.preLVMCommands = mkIf (!config.boot.initrd.systemd.enable) (mkAfter '' 354 plymouth_enabled=1 355 for o in $(cat /proc/cmdline); do 356 case $o in 357 plymouth.enable=0) 358 plymouth_enabled=0 359 ;; 360 esac 361 done 362 363 if [ "$plymouth_enabled" != 0 ]; then 364 mkdir -p /etc/plymouth 365 mkdir -p /run/plymouth 366 ln -s $extraUtils/etc/plymouth/logo.png /etc/plymouth/logo.png 367 ln -s ${configFile} /etc/plymouth/plymouthd.conf 368 ln -s $extraUtils/share/plymouth/plymouthd.defaults /run/plymouth/plymouthd.defaults 369 ln -s $extraUtils/share/plymouth/themes /run/plymouth/themes 370 ln -s $extraUtils/lib/plymouth /run/plymouth/plugins 371 ln -s $extraUtils/etc/fonts /etc/fonts 372 373 plymouthd --mode=boot --pid-file=/run/plymouth/pid --attach-to-session 374 plymouth show-splash 375 fi 376 ''); 377 378 boot.initrd.postMountCommands = mkIf (!config.boot.initrd.systemd.enable) '' 379 if [ "$plymouth_enabled" != 0 ]; then 380 plymouth update-root-fs --new-root-dir="$targetRoot" 381 fi 382 ''; 383 384 # `mkBefore` to ensure that any custom prompts would be visible. 385 boot.initrd.preFailCommands = mkIf (!config.boot.initrd.systemd.enable) (mkBefore '' 386 if [ "$plymouth_enabled" != 0 ]; then 387 plymouth quit --wait 388 fi 389 ''); 390 391 }; 392 393}