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