at 23.11-pre 12 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 ''pkgs.fetchurl { 102 url = "https://nixos.org/logo/nixos-hires.png"; 103 sha256 = "1ivzgd7iz0i06y36p8m5w48fd8pjqwxhdaavc0pxs7w1g7mcy5si"; 104 }''; 105 description = lib.mdDoc '' 106 Logo which is displayed on the splash screen. 107 ''; 108 }; 109 110 extraConfig = mkOption { 111 type = types.lines; 112 default = ""; 113 description = lib.mdDoc '' 114 Literal string to append to `configFile` 115 and the config file generated by the plymouth module. 116 ''; 117 }; 118 119 }; 120 121 }; 122 123 config = mkIf cfg.enable { 124 125 boot.kernelParams = [ "splash" ]; 126 127 # To be discoverable by systemd. 128 environment.systemPackages = [ plymouth ]; 129 130 environment.etc."plymouth/plymouthd.conf".source = configFile; 131 environment.etc."plymouth/plymouthd.defaults".source = "${plymouth}/share/plymouth/plymouthd.defaults"; 132 environment.etc."plymouth/logo.png".source = cfg.logo; 133 environment.etc."plymouth/themes".source = "${themesEnv}/share/plymouth/themes"; 134 # XXX: Needed because we supply a different set of plugins in initrd. 135 environment.etc."plymouth/plugins".source = "${plymouth}/lib/plymouth"; 136 137 systemd.packages = [ plymouth ]; 138 139 systemd.services.plymouth-kexec.wantedBy = [ "kexec.target" ]; 140 systemd.services.plymouth-halt.wantedBy = [ "halt.target" ]; 141 systemd.services.plymouth-quit-wait.wantedBy = [ "multi-user.target" ]; 142 systemd.services.plymouth-quit.wantedBy = [ "multi-user.target" ]; 143 systemd.services.plymouth-poweroff.wantedBy = [ "poweroff.target" ]; 144 systemd.services.plymouth-reboot.wantedBy = [ "reboot.target" ]; 145 systemd.services.plymouth-read-write.wantedBy = [ "sysinit.target" ]; 146 systemd.services.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ]; 147 systemd.paths.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ]; 148 149 # Prevent Plymouth taking over the screen during system updates. 150 systemd.services.plymouth-start.restartIfChanged = false; 151 152 boot.initrd.systemd = { 153 extraBin.plymouth = "${plymouth}/bin/plymouth"; # for the recovery shell 154 storePaths = [ 155 "${lib.getBin config.boot.initrd.systemd.package}/bin/systemd-tty-ask-password-agent" 156 "${plymouth}/bin/plymouthd" 157 "${plymouth}/sbin/plymouthd" 158 ]; 159 packages = [ plymouth ]; # systemd units 160 contents = { 161 # Files 162 "/etc/plymouth/plymouthd.conf".source = configFile; 163 "/etc/plymouth/plymouthd.defaults".source = "${plymouth}/share/plymouth/plymouthd.defaults"; 164 "/etc/plymouth/logo.png".source = cfg.logo; 165 # Directories 166 "/etc/plymouth/plugins".source = pkgs.runCommand "plymouth-initrd-plugins" {} '' 167 # Check if the actual requested theme is here 168 if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then 169 echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages" 170 exit 1 171 fi 172 173 moduleName="$(sed -n 's,ModuleName *= *,,p' ${themesEnv}/share/plymouth/themes/${cfg.theme}/${cfg.theme}.plymouth)" 174 175 mkdir -p $out/renderers 176 # module might come from a theme 177 cp ${themesEnv}/lib/plymouth/{text,details,label,$moduleName}.so $out 178 cp ${plymouth}/lib/plymouth/renderers/{drm,frame-buffer}.so $out/renderers 179 ''; 180 "/etc/plymouth/themes".source = pkgs.runCommand "plymouth-initrd-themes" {} '' 181 # Check if the actual requested theme is here 182 if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then 183 echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages" 184 exit 1 185 fi 186 187 mkdir $out 188 cp -r ${themesEnv}/share/plymouth/themes/${cfg.theme} $out 189 # Copy more themes if the theme depends on others 190 for theme in $(grep -hRo '/etc/plymouth/themes/.*$' $out | xargs -n1 basename); do 191 if [[ -d "${themesEnv}/share/plymouth/themes/$theme" ]]; then 192 if [[ ! -d "$out/$theme" ]]; then 193 echo "Adding dependent theme: $theme" 194 cp -r "${themesEnv}/share/plymouth/themes/$theme" $out 195 fi 196 else 197 echo "Missing theme dependency: $theme" 198 fi 199 done 200 ''; 201 202 # Fonts 203 "/etc/plymouth/fonts".source = pkgs.runCommand "plymouth-initrd-fonts" {} '' 204 mkdir -p $out 205 cp ${cfg.font} $out 206 ''; 207 "/etc/fonts/fonts.conf".text = '' 208 <?xml version="1.0"?> 209 <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> 210 <fontconfig> 211 <dir>/etc/plymouth/fonts</dir> 212 </fontconfig> 213 ''; 214 }; 215 # Properly enable units. These are the units that arch copies 216 services = { 217 plymouth-halt.wantedBy = [ "halt.target" ]; 218 plymouth-kexec.wantedBy = [ "kexec.target" ]; 219 plymouth-poweroff.wantedBy = [ "poweroff.target" ]; 220 plymouth-quit-wait.wantedBy = [ "multi-user.target" ]; 221 plymouth-quit.wantedBy = [ "multi-user.target" ]; 222 plymouth-read-write.wantedBy = [ "sysinit.target" ]; 223 plymouth-reboot.wantedBy = [ "reboot.target" ]; 224 plymouth-start.wantedBy = [ "initrd-switch-root.target" "sysinit.target" ]; 225 plymouth-switch-root-initramfs.wantedBy = [ "halt.target" "kexec.target" "plymouth-switch-root-initramfs.service" "poweroff.target" "reboot.target" ]; 226 plymouth-switch-root.wantedBy = [ "initrd-switch-root.target" ]; 227 }; 228 }; 229 230 # Insert required udev rules. We take stage 2 systemd because the udev 231 # rules are only generated when building with logind. 232 boot.initrd.services.udev.packages = [ (pkgs.runCommand "initrd-plymouth-udev-rules" {} '' 233 mkdir -p $out/etc/udev/rules.d 234 cp ${config.systemd.package.out}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out/etc/udev/rules.d 235 sed -i '/loginctl/d' $out/etc/udev/rules.d/71-seat.rules 236 '') ]; 237 238 boot.initrd.extraUtilsCommands = lib.mkIf (!config.boot.initrd.systemd.enable) '' 239 copy_bin_and_libs ${plymouth}/bin/plymouth 240 copy_bin_and_libs ${plymouth}/bin/plymouthd 241 242 # Check if the actual requested theme is here 243 if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then 244 echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages" 245 exit 1 246 fi 247 248 moduleName="$(sed -n 's,ModuleName *= *,,p' ${themesEnv}/share/plymouth/themes/${cfg.theme}/${cfg.theme}.plymouth)" 249 250 mkdir -p $out/lib/plymouth/renderers 251 # module might come from a theme 252 cp ${themesEnv}/lib/plymouth/{text,details,label,$moduleName}.so $out/lib/plymouth 253 cp ${plymouth}/lib/plymouth/renderers/{drm,frame-buffer}.so $out/lib/plymouth/renderers 254 255 mkdir -p $out/share/plymouth/themes 256 cp ${plymouth}/share/plymouth/plymouthd.defaults $out/share/plymouth 257 258 # Copy themes into working directory for patching 259 mkdir themes 260 261 # Use -L to copy the directories proper, not the symlinks to them. 262 # Copy all themes because they're not large assets, and bgrt depends on the ImageDir of 263 # the spinner theme. 264 cp -r -L ${themesEnv}/share/plymouth/themes/* themes 265 266 # Patch out any attempted references to the theme or plymouth's themes directory 267 chmod -R +w themes 268 find themes -type f | while read file 269 do 270 sed -i "s,/nix/.*/share/plymouth/themes,$out/share/plymouth/themes,g" $file 271 done 272 273 # Install themes 274 cp -r themes/* $out/share/plymouth/themes 275 276 # Install logo 277 mkdir -p $out/etc/plymouth 278 cp -r -L ${themesEnv}/etc/plymouth $out 279 280 # Setup font 281 mkdir -p $out/share/fonts 282 cp ${cfg.font} $out/share/fonts 283 mkdir -p $out/etc/fonts 284 cat > $out/etc/fonts/fonts.conf <<EOF 285 <?xml version="1.0"?> 286 <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd"> 287 <fontconfig> 288 <dir>$out/share/fonts</dir> 289 </fontconfig> 290 EOF 291 ''; 292 293 boot.initrd.extraUtilsCommandsTest = mkIf (!config.boot.initrd.systemd.enable) '' 294 $out/bin/plymouthd --help >/dev/null 295 $out/bin/plymouth --help >/dev/null 296 ''; 297 298 boot.initrd.extraUdevRulesCommands = mkIf (!config.boot.initrd.systemd.enable) '' 299 cp ${config.systemd.package}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out 300 sed -i '/loginctl/d' $out/71-seat.rules 301 ''; 302 303 # We use `mkAfter` to ensure that LUKS password prompt would be shown earlier than the splash screen. 304 boot.initrd.preLVMCommands = mkIf (!config.boot.initrd.systemd.enable) (mkAfter '' 305 mkdir -p /etc/plymouth 306 mkdir -p /run/plymouth 307 ln -s ${configFile} /etc/plymouth/plymouthd.conf 308 ln -s $extraUtils/share/plymouth/plymouthd.defaults /etc/plymouth/plymouthd.defaults 309 ln -s $extraUtils/share/plymouth/logo.png /etc/plymouth/logo.png 310 ln -s $extraUtils/share/plymouth/themes /etc/plymouth/themes 311 ln -s $extraUtils/lib/plymouth /etc/plymouth/plugins 312 ln -s $extraUtils/etc/fonts /etc/fonts 313 314 plymouthd --mode=boot --pid-file=/run/plymouth/pid --attach-to-session 315 plymouth show-splash 316 ''); 317 318 boot.initrd.postMountCommands = mkIf (!config.boot.initrd.systemd.enable) '' 319 plymouth update-root-fs --new-root-dir="$targetRoot" 320 ''; 321 322 # `mkBefore` to ensure that any custom prompts would be visible. 323 boot.initrd.preFailCommands = mkIf (!config.boot.initrd.systemd.enable) (mkBefore '' 324 plymouth quit --wait 325 ''); 326 327 }; 328 329}