1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 makeColor = n: value: "COLOR_${toString n}=${value}";
8 makeColorCS =
9 let positions = [ "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F" ];
10 in n: value: "\\033]P${elemAt positions (n - 1)}${value}";
11 colors = concatImapStringsSep "\n" makeColor config.i18n.consoleColors;
12
13 isUnicode = hasSuffix "UTF-8" (toUpper config.i18n.defaultLocale);
14
15 optimizedKeymap = pkgs.runCommand "keymap" {
16 nativeBuildInputs = [ pkgs.kbd ];
17 LOADKEYS_KEYMAP_PATH = "${kbdEnv}/share/keymaps/**";
18 } ''
19 loadkeys -b ${optionalString isUnicode "-u"} "${config.i18n.consoleKeyMap}" > $out
20 '';
21
22 # Sadly, systemd-vconsole-setup doesn't support binary keymaps.
23 vconsoleConf = pkgs.writeText "vconsole.conf" ''
24 KEYMAP=${config.i18n.consoleKeyMap}
25 FONT=${config.i18n.consoleFont}
26 ${colors}
27 '';
28
29 kbdEnv = pkgs.buildEnv {
30 name = "kbd-env";
31 paths = [ pkgs.kbd ] ++ config.i18n.consolePackages;
32 pathsToLink = [ "/share/consolefonts" "/share/consoletrans" "/share/keymaps" "/share/unimaps" ];
33 };
34
35 setVconsole = !config.boot.isContainer;
36in
37
38{
39 ###### interface
40
41 options = {
42
43 # most options are defined in i18n.nix
44
45 # FIXME: still needed?
46 boot.extraTTYs = mkOption {
47 default = [];
48 type = types.listOf types.str;
49 example = ["tty8" "tty9"];
50 description = ''
51 Tty (virtual console) devices, in addition to the consoles on
52 which mingetty and syslogd run, that must be initialised.
53 Only useful if you have some program that you want to run on
54 some fixed console. For example, the NixOS installation CD
55 opens the manual in a web browser on console 7, so it sets
56 <option>boot.extraTTYs</option> to <literal>["tty7"]</literal>.
57 '';
58 };
59
60 boot.earlyVconsoleSetup = mkOption {
61 default = false;
62 type = types.bool;
63 description = ''
64 Enable setting font as early as possible (in initrd).
65 '';
66 };
67
68 };
69
70
71 ###### implementation
72
73 config = mkMerge [
74 (mkIf (!setVconsole || (setVconsole && config.boot.earlyVconsoleSetup)) {
75 systemd.services."systemd-vconsole-setup".enable = false;
76 })
77
78 (mkIf setVconsole (mkMerge [
79 { environment.systemPackages = [ pkgs.kbd ];
80
81 # Let systemd-vconsole-setup.service do the work of setting up the
82 # virtual consoles.
83 environment.etc."vconsole.conf".source = vconsoleConf;
84 # Provide kbd with additional packages.
85 environment.etc."kbd".source = "${kbdEnv}/share";
86
87 boot.initrd.preLVMCommands = mkBefore ''
88 kbd_mode ${if isUnicode then "-u" else "-a"} -C /dev/console
89 printf "\033%%${if isUnicode then "G" else "@"}" >> /dev/console
90 loadkmap < ${optimizedKeymap}
91
92 ${optionalString config.boot.earlyVconsoleSetup ''
93 setfont -C /dev/console $extraUtils/share/consolefonts/font.psf
94 ''}
95
96 ${concatImapStringsSep "\n" (n: color: ''
97 printf "${makeColorCS n color}" >> /dev/console
98 '') config.i18n.consoleColors}
99 '';
100 }
101
102 (mkIf (!config.boot.earlyVconsoleSetup) {
103 # This is identical to the systemd-vconsole-setup.service unit
104 # shipped with systemd, except that it uses /dev/tty1 instead of
105 # /dev/tty0 to prevent putting the X server in non-raw mode, and
106 # it has a restart trigger.
107 systemd.services."systemd-vconsole-setup" =
108 { wantedBy = [ "sysinit.target" ];
109 before = [ "display-manager.service" ];
110 after = [ "systemd-udev-settle.service" ];
111 restartTriggers = [ vconsoleConf kbdEnv ];
112 };
113 })
114
115 (mkIf config.boot.earlyVconsoleSetup {
116 boot.initrd.extraUtilsCommands = ''
117 mkdir -p $out/share/consolefonts
118 ${if substring 0 1 config.i18n.consoleFont == "/" then ''
119 font="${config.i18n.consoleFont}"
120 '' else ''
121 font="$(echo ${kbdEnv}/share/consolefonts/${config.i18n.consoleFont}.*)"
122 ''}
123 if [[ $font == *.gz ]]; then
124 gzip -cd $font > $out/share/consolefonts/font.psf
125 else
126 cp -L $font $out/share/consolefonts/font.psf
127 fi
128 '';
129 })
130 ]))
131 ];
132
133}