about summary refs log tree commit diff
path: root/nixos/modules/tasks/kbd.nix
diff options
context:
space:
mode:
authorNikolay Amiantov <ab@fmap.me>2016-07-08 20:01:42 +0300
committerNikolay Amiantov <ab@fmap.me>2016-07-08 20:44:01 +0300
commit9e48baa716f17385b4850377f11e16c33d75cac1 (patch)
tree5595dc50b35ba166acf5978062c53ef780c96ec8 /nixos/modules/tasks/kbd.nix
parent803b1eedd65337e18c54d413f4bbbcbcba772e53 (diff)
downloadnixlib-9e48baa716f17385b4850377f11e16c33d75cac1.tar
nixlib-9e48baa716f17385b4850377f11e16c33d75cac1.tar.gz
nixlib-9e48baa716f17385b4850377f11e16c33d75cac1.tar.bz2
nixlib-9e48baa716f17385b4850377f11e16c33d75cac1.tar.lz
nixlib-9e48baa716f17385b4850377f11e16c33d75cac1.tar.xz
nixlib-9e48baa716f17385b4850377f11e16c33d75cac1.tar.zst
nixlib-9e48baa716f17385b4850377f11e16c33d75cac1.zip
kbd service: add support for early loading of fonts and keymaps
Diffstat (limited to 'nixos/modules/tasks/kbd.nix')
-rw-r--r--nixos/modules/tasks/kbd.nix104
1 files changed, 77 insertions, 27 deletions
diff --git a/nixos/modules/tasks/kbd.nix b/nixos/modules/tasks/kbd.nix
index dd89804d43a7..5a49b09d6356 100644
--- a/nixos/modules/tasks/kbd.nix
+++ b/nixos/modules/tasks/kbd.nix
@@ -5,20 +5,33 @@ with lib;
 let
 
   makeColor = n: value: "COLOR_${toString n}=${value}";
+  makeColorCS =
+    let positions = [ "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F" ];
+    in n: value: "\033]P${elemAt position n}${value}";
   colors = concatImapStringsSep "\n" makeColor config.i18n.consoleColors;
 
-  vconsoleConf = pkgs.writeText "vconsole.conf" ''
-    KEYMAP=${config.i18n.consoleKeyMap}
-    FONT=${config.i18n.consoleFont}
-    ${colors}
-  '';
-
   kbdEnv = pkgs.buildEnv {
     name = "kbd-env";
     paths = [ pkgs.kbd ] ++ config.i18n.consolePackages;
     pathsToLink = [ "/share/consolefonts" "/share/consoletrans" "/share/keymaps" "/share/unimaps" ];
   };
 
+  isUnicode = hasSuffix "UTF-8" (toUpper config.i18n.defaultLocale);
+
+  optimizedKeymap = pkgs.runCommand "keymap" {
+    nativeBuildInputs = [ pkgs.kbd ];
+  } ''
+    cd ${kbdEnv}/share/keymaps
+    loadkeys -b ${optionalString isUnicode "-u"} "${config.i18n.consoleKeyMap}" > $out
+  '';
+
+  # Sadly, systemd-vconsole-setup doesn't support binary keymaps.
+  vconsoleConf = pkgs.writeText "vconsole.conf" ''
+    KEYMAP=${config.i18n.consoleKeyMap}
+    FONT=${config.i18n.consoleFont}
+    ${colors}
+  '';
+
   setVconsole = !config.boot.isContainer;
 in
 
@@ -44,36 +57,73 @@ in
       '';
     };
 
+    boot.earlyVconsoleSetup = mkOption {
+      default = false;
+      type = types.bool;
+      description = ''
+        Enable setting font and keymap as early as possible (in initrd).
+      '';
+    };
+
   };
 
 
   ###### implementation
 
   config = mkMerge [
-    (mkIf (!setVconsole) {
+    (mkIf (!setVconsole || (setVconsole && config.boot.earlyVconsoleSetup)) {
       systemd.services."systemd-vconsole-setup".enable = false;
     })
 
-    (mkIf setVconsole {
-      environment.systemPackages = [ pkgs.kbd ];
-
-      # Let systemd-vconsole-setup.service do the work of setting up the
-      # virtual consoles.
-      environment.etc."vconsole.conf".source = vconsoleConf;
-      # Provide kbd with additional packages.
-      environment.etc."kbd".source = "${kbdEnv}/share";
-
-      # This is identical to the systemd-vconsole-setup.service unit
-      # shipped with systemd, except that it uses /dev/tty1 instead of
-      # /dev/tty0 to prevent putting the X server in non-raw mode, and
-      # it has a restart trigger.
-      systemd.services."systemd-vconsole-setup" =
-        { wantedBy = [ "multi-user.target" ];
-          before = [ "display-manager.service" ];
-          after = [ "systemd-udev-settle.service" ];
-          restartTriggers = [ vconsoleConf kbdEnv ];
-        };
-    })
+    (mkIf setVconsole (mkMerge [
+      { environment.systemPackages = [ pkgs.kbd ];
+
+        # Let systemd-vconsole-setup.service do the work of setting up the
+        # virtual consoles.
+        environment.etc."vconsole.conf".source = vconsoleConf;
+      }
+
+      (mkIf (!config.boot.earlyVconsoleSetup) {
+        # This is identical to the systemd-vconsole-setup.service unit
+        # shipped with systemd, except that it uses /dev/tty1 instead of
+        # /dev/tty0 to prevent putting the X server in non-raw mode, and
+        # it has a restart trigger.
+        systemd.services."systemd-vconsole-setup" =
+          { wantedBy = [ "sysinit.target" ];
+            before = [ "display-manager.service" ];
+            after = [ "systemd-udev-settle.service" ];
+            restartTriggers = [ vconsoleConf ];
+          };
+      })
+
+      (mkIf config.boot.earlyVconsoleSetup {
+        boot.initrd.extraUtilsCommands = ''
+          mkdir -p $out/share/consolefonts
+          ${if substring 0 1 config.i18n.consoleFont == "/" then ''
+            font="${config.i18n.consoleFont}"
+          '' else ''
+            font="$(echo ${kbdEnv}/share/consolefonts/${config.i18n.consoleFont}.*)"
+          ''}
+          if [[ $font == *.gz ]]; then
+            gzip -cd $font > $out/share/consolefonts/font.psf
+          else
+            cp -L $font $out/share/consolefonts/font.psf
+          fi
+        '';
+
+        boot.initrd.preLVMCommands = mkBefore ''
+          kbd_mode ${if isUnicode then "-u" else "-a"} -C /dev/console
+          printf "\033%%${if isUnicode then "G" else "@"}" >> /dev/console
+          loadkmap < ${optimizedKeymap}
+
+          setfont -C /dev/console $extraUtils/share/consolefonts/font.psf
+
+          ${concatImapStringsSep "\n" (n: color: ''
+            printf "${makeColorCS n color}" >> /dev/console
+          '') config.i18n.consoleColors}
+        '';
+      })
+    ]))
   ];
 
 }