summary refs log blame commit diff
path: root/nixos/modules/system/boot/plymouth.nix
blob: 78ae8e9d20b77aa4aafcb312e687f201796faf01 (plain) (tree)
1
2
3
4
5
6
7
8
9
                                    




         
                                      

                             
                              
 
                                                                       



                                            

    


















                                                                                   

                             



                           




                                                 
                   
                      
                      











                                                            

                                                                                     
                                                                                                                 





                                                                            
                                
                                                                           




                                                                       






                                            
                         







                              

                                                                                          
                                                         


                                                                          




                                                       








                                                                   











                                                                  
                                                                                                           








                                                                                    
                                                                           
                                                                      


                                                                         

                                                                                      

                                       

                                                 
 





                                                                                                                        


                                                                                                                         
                                      
                                                                                        



                                                                                             
 
                                                       
                  
 





                                                                                             





                                                                                   
                      
                                               
 




                                             









                                                             











                                                                                   
                                                                                                         

                                           
                            




                                                                                          
                                            

                                                                            
                          

       



                                                          




                                                                    


    
{ config, lib, options, pkgs, ... }:

with lib;

let

  inherit (pkgs) plymouth nixos-icons;

  cfg = config.boot.plymouth;
  opt = options.boot.plymouth;

  nixosBreezePlymouth = pkgs.plasma5Packages.breeze-plymouth.override {
    logoFile = cfg.logo;
    logoName = "nixos";
    osName = "NixOS";
    osVersion = config.system.nixos.release;
  };

  plymouthLogos = pkgs.runCommand "plymouth-logos" { inherit (cfg) logo; } ''
    mkdir -p $out

    # For themes that are compiled with PLYMOUTH_LOGO_FILE
    mkdir -p $out/etc/plymouth
    ln -s $logo $out/etc/plymouth/logo.png

    # Logo for bgrt theme
    # Note this is technically an abuse of watermark for the bgrt theme
    # See: https://gitlab.freedesktop.org/plymouth/plymouth/-/issues/95#note_813768
    mkdir -p $out/share/plymouth/themes/spinner
    ln -s $logo $out/share/plymouth/themes/spinner/watermark.png

    # Logo for spinfinity theme
    # See: https://gitlab.freedesktop.org/plymouth/plymouth/-/issues/106
    mkdir -p $out/share/plymouth/themes/spinfinity
    ln -s $logo $out/share/plymouth/themes/spinfinity/header-image.png
  '';

  themesEnv = pkgs.buildEnv {
    name = "plymouth-themes";
    paths = [
      plymouth
      plymouthLogos
    ] ++ cfg.themePackages;
  };

  configFile = pkgs.writeText "plymouthd.conf" ''
    [Daemon]
    ShowDelay=0
    DeviceTimeout=8
    Theme=${cfg.theme}
    ${cfg.extraConfig}
  '';

in

{

  options = {

    boot.plymouth = {

      enable = mkEnableOption "Plymouth boot splash screen";

      font = mkOption {
        default = "${pkgs.dejavu_fonts.minimal}/share/fonts/truetype/DejaVuSans.ttf";
        defaultText = literalExpression ''"''${pkgs.dejavu_fonts.minimal}/share/fonts/truetype/DejaVuSans.ttf"'';
        type = types.path;
        description = ''
          Font file made available for displaying text on the splash screen.
        '';
      };

      themePackages = mkOption {
        default = lib.optional (cfg.theme == "breeze") nixosBreezePlymouth;
        defaultText = literalDocBook ''
          A NixOS branded variant of the breeze theme when
          <literal>config.${opt.theme} == "breeze"</literal>, otherwise
          <literal>[ ]</literal>.
        '';
        type = types.listOf types.package;
        description = ''
          Extra theme packages for plymouth.
        '';
      };

      theme = mkOption {
        default = "bgrt";
        type = types.str;
        description = ''
          Splash screen theme.
        '';
      };

      logo = mkOption {
        type = types.path;
        # Dimensions are 48x48 to match GDM logo
        default = "${nixos-icons}/share/icons/hicolor/48x48/apps/nix-snowflake-white.png";
        defaultText = literalExpression ''pkgs.fetchurl {
          url = "https://nixos.org/logo/nixos-hires.png";
          sha256 = "1ivzgd7iz0i06y36p8m5w48fd8pjqwxhdaavc0pxs7w1g7mcy5si";
        }'';
        description = ''
          Logo which is displayed on the splash screen.
        '';
      };

      extraConfig = mkOption {
        type = types.lines;
        default = "";
        description = ''
          Literal string to append to <literal>configFile</literal>
          and the config file generated by the plymouth module.
        '';
      };

    };

  };

  config = mkIf cfg.enable {

    boot.kernelParams = [ "splash" ];

    # To be discoverable by systemd.
    environment.systemPackages = [ plymouth ];

    environment.etc."plymouth/plymouthd.conf".source = configFile;
    environment.etc."plymouth/plymouthd.defaults".source = "${plymouth}/share/plymouth/plymouthd.defaults";
    environment.etc."plymouth/logo.png".source = cfg.logo;
    environment.etc."plymouth/themes".source = "${themesEnv}/share/plymouth/themes";
    # XXX: Needed because we supply a different set of plugins in initrd.
    environment.etc."plymouth/plugins".source = "${plymouth}/lib/plymouth";

    systemd.packages = [ plymouth ];

    systemd.services.plymouth-kexec.wantedBy = [ "kexec.target" ];
    systemd.services.plymouth-halt.wantedBy = [ "halt.target" ];
    systemd.services.plymouth-quit-wait.wantedBy = [ "multi-user.target" ];
    systemd.services.plymouth-quit.wantedBy = [ "multi-user.target" ];
    systemd.services.plymouth-poweroff.wantedBy = [ "poweroff.target" ];
    systemd.services.plymouth-reboot.wantedBy = [ "reboot.target" ];
    systemd.services.plymouth-read-write.wantedBy = [ "sysinit.target" ];
    systemd.services.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ];
    systemd.paths.systemd-ask-password-plymouth.wantedBy = [ "multi-user.target" ];

    boot.initrd.extraUtilsCommands = ''
      copy_bin_and_libs ${plymouth}/bin/plymouth
      copy_bin_and_libs ${plymouth}/bin/plymouthd

      # Check if the actual requested theme is here
      if [[ ! -d ${themesEnv}/share/plymouth/themes/${cfg.theme} ]]; then
          echo "The requested theme: ${cfg.theme} is not provided by any of the packages in boot.plymouth.themePackages"
          exit 1
      fi

      moduleName="$(sed -n 's,ModuleName *= *,,p' ${themesEnv}/share/plymouth/themes/${cfg.theme}/${cfg.theme}.plymouth)"

      mkdir -p $out/lib/plymouth/renderers
      # module might come from a theme
      cp ${themesEnv}/lib/plymouth/{text,details,label,$moduleName}.so $out/lib/plymouth
      cp ${plymouth}/lib/plymouth/renderers/{drm,frame-buffer}.so $out/lib/plymouth/renderers

      mkdir -p $out/share/plymouth/themes
      cp ${plymouth}/share/plymouth/plymouthd.defaults $out/share/plymouth

      # Copy themes into working directory for patching
      mkdir themes

      # Use -L to copy the directories proper, not the symlinks to them.
      # Copy all themes because they're not large assets, and bgrt depends on the ImageDir of
      # the spinner theme.
      cp -r -L ${themesEnv}/share/plymouth/themes/* themes

      # Patch out any attempted references to the theme or plymouth's themes directory
      chmod -R +w themes
      find themes -type f | while read file
      do
        sed -i "s,/nix/.*/share/plymouth/themes,$out/share/plymouth/themes,g" $file
      done

      # Install themes
      cp -r themes/* $out/share/plymouth/themes

      # Install logo
      mkdir -p $out/etc/plymouth
      cp -r -L ${themesEnv}/etc/plymouth $out

      # Setup font
      mkdir -p $out/share/fonts
      cp ${cfg.font} $out/share/fonts
      mkdir -p $out/etc/fonts
      cat > $out/etc/fonts/fonts.conf <<EOF
      <?xml version="1.0"?>
      <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
      <fontconfig>
          <dir>$out/share/fonts</dir>
      </fontconfig>
      EOF
    '';

    boot.initrd.extraUtilsCommandsTest = ''
      $out/bin/plymouthd --help >/dev/null
      $out/bin/plymouth --help >/dev/null
    '';

    boot.initrd.extraUdevRulesCommands = ''
      cp ${config.systemd.package}/lib/udev/rules.d/{70-uaccess,71-seat}.rules $out
      sed -i '/loginctl/d' $out/71-seat.rules
    '';

    # We use `mkAfter` to ensure that LUKS password prompt would be shown earlier than the splash screen.
    boot.initrd.preLVMCommands = mkAfter ''
      mkdir -p /etc/plymouth
      mkdir -p /run/plymouth
      ln -s ${configFile} /etc/plymouth/plymouthd.conf
      ln -s $extraUtils/share/plymouth/plymouthd.defaults /etc/plymouth/plymouthd.defaults
      ln -s $extraUtils/share/plymouth/logo.png /etc/plymouth/logo.png
      ln -s $extraUtils/share/plymouth/themes /etc/plymouth/themes
      ln -s $extraUtils/lib/plymouth /etc/plymouth/plugins
      ln -s $extraUtils/etc/fonts /etc/fonts

      plymouthd --mode=boot --pid-file=/run/plymouth/pid --attach-to-session
      plymouth show-splash
    '';

    boot.initrd.postMountCommands = ''
      plymouth update-root-fs --new-root-dir="$targetRoot"
    '';

    # `mkBefore` to ensure that any custom prompts would be visible.
    boot.initrd.preFailCommands = mkBefore ''
      plymouth quit --wait
    '';

  };

}