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) {
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 /* XXX: systemd-vconsole-setup needs a "main" terminal. By default
102 * /dev/tty0 is used which wouldn't work when the service is restarted
103 * from X11. We set this to /dev/tty1; not ideal because it may also be
104 * owned by X11 or something else.
105 *
106 * See #22470.
107 */
108 systemd.services."systemd-vconsole-setup" =
109 { wantedBy = [ "sysinit.target" ];
110 before = [ "display-manager.service" ];
111 after = [ "systemd-udev-settle.service" ];
112 restartTriggers = [ vconsoleConf kbdEnv ];
113 serviceConfig.ExecStart = [
114 ""
115 "${pkgs.systemd}/lib/systemd/systemd-vconsole-setup /dev/tty1"
116 ];
117 };
118 }
119
120 (mkIf config.boot.earlyVconsoleSetup {
121 boot.initrd.extraUtilsCommands = ''
122 mkdir -p $out/share/consolefonts
123 ${if substring 0 1 config.i18n.consoleFont == "/" then ''
124 font="${config.i18n.consoleFont}"
125 '' else ''
126 font="$(echo ${kbdEnv}/share/consolefonts/${config.i18n.consoleFont}.*)"
127 ''}
128 if [[ $font == *.gz ]]; then
129 gzip -cd $font > $out/share/consolefonts/font.psf
130 else
131 cp -L $font $out/share/consolefonts/font.psf
132 fi
133 '';
134 })
135 ]))
136 ];
137
138}