_CONSOLE_MODE_INVALID = -EINVAL,
} ConsoleMode;
+typedef enum ConsoleTransport {
+ CONSOLE_TRANSPORT_VIRTIO, /* virtio-serial (hvc0) */
+ CONSOLE_TRANSPORT_SERIAL, /* regular serial port (ttyS0/ttyAMA0) */
+ _CONSOLE_TRANSPORT_MAX,
+ _CONSOLE_TRANSPORT_INVALID = -EINVAL,
+} ConsoleTransport;
+
typedef enum SettingsMask {
SETTING_START_MODE = UINT64_C(1) << 0,
SETTING_MACHINE_ID = UINT64_C(1) << 6,
} SettingsMask;
DECLARE_STRING_TABLE_LOOKUP(console_mode, ConsoleMode);
+DECLARE_STRING_TABLE_LOOKUP(console_transport, ConsoleTransport);
DECLARE_STRING_TABLE_LOOKUP(disk_type, DiskType);
DECLARE_STRING_TABLE_LOOKUP(image_format, ImageFormat);
static char *arg_linux = NULL;
static char **arg_initrds = NULL;
static ConsoleMode arg_console_mode = CONSOLE_INTERACTIVE;
+static ConsoleTransport arg_console_transport = CONSOLE_TRANSPORT_VIRTIO;
static NetworkStack arg_network_stack = NETWORK_STACK_NONE;
static MachineCredentialContext arg_credentials = {};
static uid_t arg_uid_shift = UID_INVALID, arg_uid_range = 0x10000U;
"\n%3$sInput/Output:%4$s\n"
" --console=MODE Console mode (interactive, native, gui, read-only\n"
" or headless)\n"
+ " --console-transport=TRANSPORT\n"
+ " Console transport (virtio or serial)\n"
" --background=COLOR Set ANSI color for background\n"
"\n%3$sCredentials:%4$s\n"
" --set-credential=ID:VALUE\n"
ARG_USER,
ARG_IMAGE_FORMAT,
ARG_IMAGE_DISK_TYPE,
+ ARG_CONSOLE_TRANSPORT,
};
static const struct option options[] = {
{ "linux", required_argument, NULL, ARG_LINUX },
{ "initrd", required_argument, NULL, ARG_INITRD },
{ "console", required_argument, NULL, ARG_CONSOLE },
+ { "console-transport", required_argument, NULL, ARG_CONSOLE_TRANSPORT },
{ "qemu-gui", no_argument, NULL, ARG_QEMU_GUI }, /* compat option */
{ "network-tap", no_argument, NULL, 'n' },
{ "network-user-mode", no_argument, NULL, ARG_NETWORK_USER_MODE },
break;
+ case ARG_CONSOLE_TRANSPORT:
+ arg_console_transport = console_transport_from_string(optarg);
+ if (arg_console_transport < 0)
+ return log_error_errno(arg_console_transport, "Failed to parse specified console transport: %s", optarg);
+
+ break;
+
case ARG_QEMU_GUI:
arg_console_mode = CONSOLE_GUI;
break;
if (r < 0)
return log_oom();
- r = qemu_config_section(config_file, "device", "vmspawn-virtio-serial-pci",
- "driver", "virtio-serial-pci");
- if (r < 0)
- return r;
-
/* Enable mux for native console so the QEMU monitor is accessible via Ctrl-a c */
r = qemu_config_section(config_file, "chardev", "console",
"backend", "serial",
if (r < 0)
return r;
- r = qemu_config_section(config_file, "device", "virtconsole0",
- "driver", "virtconsole",
- "chardev", "console");
- if (r < 0)
- return r;
-
if (arg_console_mode == CONSOLE_NATIVE) {
r = qemu_config_section(config_file, "mon", "mon0",
"chardev", "console");
assert_not_reached();
}
+ if (!IN_SET(arg_console_mode, CONSOLE_GUI, CONSOLE_HEADLESS)) {
+ if (arg_console_transport == CONSOLE_TRANSPORT_SERIAL) {
+ /* Use -serial to connect the chardev to the platform's default serial
+ * device (e.g. isa-serial on x86, PL011 on ARM). On some platforms the
+ * serial device is a sysbus device that can only be connected via
+ * serial_hd() which is populated by -serial, not via the config file. */
+ r = strv_extend_many(&cmdline, "-serial", "chardev:console");
+ if (r < 0)
+ return log_oom();
+ } else {
+ r = qemu_config_section(config_file, "device", "vmspawn-virtio-serial-pci",
+ "driver", "virtio-serial-pci");
+ if (r < 0)
+ return r;
+
+ r = qemu_config_section(config_file, "device", "virtconsole0",
+ "driver", "virtconsole",
+ "chardev", "console");
+ if (r < 0)
+ return r;
+ }
+ }
+
r = qemu_config_section(config_file, "drive", "ovmf-code",
"if", "pflash",
"format", ovmf_config_format(ovmf_config),
}
if (!IN_SET(arg_console_mode, CONSOLE_GUI, CONSOLE_HEADLESS)) {
- r = strv_prepend(&arg_kernel_cmdline_extra, "console=hvc0");
+ r = strv_prepend(&arg_kernel_cmdline_extra,
+ arg_console_transport == CONSOLE_TRANSPORT_SERIAL ?
+ "console=" QEMU_SERIAL_CONSOLE_NAME : "console=hvc0");
if (r < 0)
return log_oom();