about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--nixos/modules/tasks/kbd.nix94
-rw-r--r--pkgs/os-specific/linux/busybox/default.nix3
2 files changed, 76 insertions, 21 deletions
diff --git a/nixos/modules/tasks/kbd.nix b/nixos/modules/tasks/kbd.nix
index dd89804d43a7..8cdd34ef174c 100644
--- a/nixos/modules/tasks/kbd.nix
+++ b/nixos/modules/tasks/kbd.nix
@@ -5,8 +5,21 @@ 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;
 
+  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}
@@ -44,36 +57,75 @@ 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;
+        # Provide kbd with additional packages.
+        environment.etc."kbd".source = "${kbdEnv}/share";
+      }
+
+      (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 kbdEnv ];
+          };
+      })
+
+      (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}
+        '';
+      })
+    ]))
   ];
 
 }
diff --git a/pkgs/os-specific/linux/busybox/default.nix b/pkgs/os-specific/linux/busybox/default.nix
index fa6591701a69..b04f7855fefa 100644
--- a/pkgs/os-specific/linux/busybox/default.nix
+++ b/pkgs/os-specific/linux/busybox/default.nix
@@ -56,6 +56,9 @@ stdenv.mkDerivation rec {
     CONFIG_FEATURE_MOUNT_CIFS n
     CONFIG_FEATURE_MOUNT_HELPERS y
 
+    # Set paths for console fonts.
+    CONFIG_DEFAULT_SETFONT_DIR "/etc/kbd"
+
     ${extraConfig}
     $extraCrossConfig
     EOF