[PATCH] vt: Add boot param for setting default vt console
From: Adam Saponara
Date: Sun Mar 01 2026 - 17:03:48 EST
Presently the default console is hard-coded to vt1.
The param allows for setting a different default. The param defaults to 0
(vt1), preserving the current behavior. It is clamped by the constants
`(MIN|MAX)_NR_CONSOLES`. If set `>= MIN`, `con_init` will initialize that
vt as well (a couple extra kilobytes heap for the `vc_data` and
`vc_screenbuf` structs).
Without this feature, users achieve the same effect with an init
script[0][1][2][3]. This works but requires an extra `chvt(1)` which can
race with user interaction and flicker the screen at login.
[0]: https://bbs.archlinux.org/viewtopic.php?id=232058
[1]: https://unix.stackexchange.com/questions/399986
[2]: https://github.com/systemd/systemd/issues/7247
[3]: https://www.linuxquestions.org/questions/linux-general-1/x-4175722418
Signed-off-by: Adam Saponara <as@xxxxxxx>
---
.../admin-guide/kernel-parameters.txt | 5 +++
drivers/tty/vt/vt.c | 44 +++++++++++++------
2 files changed, 36 insertions(+), 13 deletions(-)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index cb850e5290c2..6694b2edcfd6 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -8429,6 +8429,11 @@ Kernel parameters
overridden by individual drivers. 0 will hide
cursors, 1 will display them.
+ vt.default_console=
+ [VT]
+ Set default console; 0-62.
+ Default: 0 (vt1)
+
vt.italic= [VT] Default color for italic text; 0-15.
Default: 2 = green.
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index c1f152d8b03b..e566942c380f 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -140,6 +140,7 @@ EXPORT_SYMBOL(vc_cons);
static const struct consw *con_driver_map[MAX_NR_CONSOLES];
static int con_open(struct tty_struct *, struct file *);
+static void con_init_vc(int console_idx);
static void vc_init(struct vc_data *vc, int do_clear);
static void gotoxy(struct vc_data *vc, int new_x, int new_y);
static void restore_cur(struct vc_data *vc);
@@ -159,10 +160,14 @@ static void unblank_screen(void);
int default_utf8 = true;
module_param(default_utf8, int, S_IRUGO | S_IWUSR);
+
int global_cursor_default = -1;
module_param(global_cursor_default, int, S_IRUGO | S_IWUSR);
EXPORT_SYMBOL(global_cursor_default);
+int default_console;
+module_param(default_console, int, S_IRUGO | S_IWUSR);
+
static int cur_default = CUR_UNDERLINE;
module_param(cur_default, int, S_IRUGO | S_IWUSR);
@@ -3742,7 +3747,7 @@ static int __init con_init(void)
{
const char *display_desc = NULL;
struct vc_data *vc;
- unsigned int currcons = 0, i;
+ unsigned int i, di;
console_lock();
@@ -3776,18 +3781,18 @@ static int __init con_init(void)
mod_timer(&console_timer, jiffies + (blankinterval * HZ));
}
- for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
- vc_cons[currcons].d = vc = kzalloc_obj(struct vc_data,
- GFP_NOWAIT);
- INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
- tty_port_init(&vc->port);
- visual_init(vc, currcons, true);
- /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */
- vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
- vc_init(vc, currcons || !vc->vc_sw->con_save_screen);
- }
- currcons = fg_console = 0;
- master_display_fg = vc = vc_cons[currcons].d;
+ for (i = 0; i < MIN_NR_CONSOLES; i++)
+ con_init_vc(i);
+
+ /* Init default_console if we didn't already do that above */
+ di = clamp(default_console, 0, MAX_NR_CONSOLES - 1);
+ if (di >= MIN_NR_CONSOLES)
+ con_init_vc(di);
+
+ fg_console = di;
+
+ vc = vc_cons[fg_console].d;
+ master_display_fg = vc;
set_origin(vc);
save_screen(vc);
gotoxy(vc, vc->state.x, vc->state.y);
@@ -3806,6 +3811,19 @@ static int __init con_init(void)
}
console_initcall(con_init);
+static void con_init_vc(int console_idx)
+{
+ struct vc_data *vc = kzalloc_obj(struct vc_data, GFP_NOWAIT);
+
+ vc_cons[console_idx].d = vc;
+ INIT_WORK(&vc_cons[console_idx].SAK_work, vc_SAK);
+ tty_port_init(&vc->port);
+ visual_init(vc, console_idx, true);
+ /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */
+ vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
+ vc_init(vc, console_idx || !vc->vc_sw->con_save_screen);
+}
+
static const struct tty_operations con_ops = {
.install = con_install,
.open = con_open,
--
2.51.0