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