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.buildPackages.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 systemd.services."systemd-vconsole-setup" =
102 { before = [ "display-manager.service" ];
103 after = [ "systemd-udev-settle.service" ];
104 restartTriggers = [ vconsoleConf kbdEnv ];
105 };
106 }
107
108 (mkIf config.boot.earlyVconsoleSetup {
109 boot.initrd.extraUtilsCommands = ''
110 mkdir -p $out/share/consolefonts
111 ${if substring 0 1 config.i18n.consoleFont == "/" then ''
112 font="${config.i18n.consoleFont}"
113 '' else ''
114 font="$(echo ${kbdEnv}/share/consolefonts/${config.i18n.consoleFont}.*)"
115 ''}
116 if [[ $font == *.gz ]]; then
117 gzip -cd $font > $out/share/consolefonts/font.psf
118 else
119 cp -L $font $out/share/consolefonts/font.psf
120 fi
121 '';
122 })
123 ]))
124 ];
125
126}