diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index fa4e0c23b7..269fc30c6e 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -86,6 +86,7 @@
<boot dev='cdrom'/>
<bootmenu enable='yes'/>
<smbios mode='sysinfo'/>
+ <bios useserial='yes'/>
</os>
...
@@ -137,6 +138,14 @@
specified, the hypervisor default is used.
Since 0.8.7
+
bios
+ This element has attribute useserial
with possible
+ values yes
or no
. It enables or disables
+ Serial Graphics Adapter which allows users to see BIOS messages
+ on a serial port. Therefore, one needs to have
+ serial port defined.
+ Since 0.9.4
+
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index c01801e4cd..ba31263a08 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -151,6 +151,9 @@
+
+
+
@@ -2277,6 +2280,17 @@
+
+
+
+
+ yes
+ no
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a680b114e8..2315c98028 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -5662,9 +5662,9 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
{
xmlNodePtr *nodes = NULL;
int i, n;
- char *bootstr;
+ char *bootstr, *useserial;
int ret = -1;
- unsigned long deviceBoot;
+ unsigned long deviceBoot, serialPorts;
if (virXPathULong("count(./devices/disk[boot]"
"|./devices/interface[boot]"
@@ -5718,6 +5718,22 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
VIR_FREE(bootstr);
}
+ useserial = virXPathString("string(./os/bios[1]/@useserial)", ctxt);
+ if (useserial) {
+ if (STREQ(useserial, "yes")) {
+ if (virXPathULong("count(./devices/serial)",
+ ctxt, &serialPorts) < 0) {
+ virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("need at least one serial port "
+ "for useserial"));
+ goto cleanup;
+ }
+ def->os.bios.useserial = VIR_DOMAIN_BIOS_USESERIAL_YES;
+ } else {
+ def->os.bios.useserial = VIR_DOMAIN_BIOS_USESERIAL_NO;
+ }
+ }
+
*bootCount = deviceBoot;
ret = 0;
@@ -9758,6 +9774,13 @@ char *virDomainDefFormat(virDomainDefPtr def,
: "no");
virBufferAsprintf(&buf, " \n", enabled);
}
+
+ if (def->os.bios.useserial) {
+ const char *useserial = (def->os.bios.useserial ==
+ VIR_DOMAIN_BIOS_USESERIAL_YES ? "yes"
+ : "no");
+ virBufferAsprintf(&buf, " \n", useserial);
+ }
}
if (def->os.smbios_mode) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 15adc70b88..0af6d5b093 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -933,6 +933,18 @@ enum virDomainLifecycleCrashAction {
VIR_DOMAIN_LIFECYCLE_CRASH_LAST
};
+enum virDomainBIOSUseserial {
+ VIR_DOMAIN_BIOS_USESERIAL_DEFAULT = 0,
+ VIR_DOMAIN_BIOS_USESERIAL_YES,
+ VIR_DOMAIN_BIOS_USESERIAL_NO
+};
+
+typedef struct _virDomainBIOSDef virDomainBIOSDef;
+typedef virDomainBIOSDef *virDomainBIOSDefPtr;
+struct _virDomainBIOSDef {
+ int useserial;
+};
+
/* Operating system configuration data & machine / arch */
typedef struct _virDomainOSDef virDomainOSDef;
typedef virDomainOSDef *virDomainOSDefPtr;
@@ -952,6 +964,7 @@ struct _virDomainOSDef {
char *bootloader;
char *bootloaderArgs;
int smbios_mode;
+ virDomainBIOSDef bios;
};
enum virDomainSeclabelType {
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 2c037ce64c..1421a5e003 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -122,6 +122,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"pci-multifunction", /* 60 */
"virtio-blk-pci.ioeventfd",
+ "sga",
);
struct qemu_feature_flags {
@@ -1212,6 +1213,8 @@ qemuCapsParseDeviceStr(const char *str, virBitmapPtr flags)
qemuCapsSet(flags, QEMU_CAPS_DEVICE_QXL_VGA);
if (strstr(str, "virtio-blk-pci.ioeventfd"))
qemuCapsSet(flags, QEMU_CAPS_VIRTIO_IOEVENTFD);
+ if (strstr(str, "name \"sga\""))
+ qemuCapsSet(flags, QEMU_CAPS_SGA);
return 0;
}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 0b9c8be754..d251262362 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -97,6 +97,7 @@ enum qemuCapsFlags {
QEMU_CAPS_DEVICE_QXL_VGA = 59, /* Is the primary and vga campatible qxl device named qxl-vga? */
QEMU_CAPS_PCI_MULTIFUNCTION = 60, /* -device multifunction=on|off */
QEMU_CAPS_VIRTIO_IOEVENTFD = 61, /* IOeventFD feature: virtio-{net|blk}-pci.ioeventfd=on/off */
+ QEMU_CAPS_SGA = 62, /* Serial Graphics Adapter */
QEMU_CAPS_LAST, /* this must always be the last item */
};
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 19151ce03f..b131ce7cb4 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3060,6 +3060,26 @@ qemuBuildCommandLine(virConnectPtr conn,
"-nodefaults"); /* Disable default guest devices */
}
+ /* Serial graphics adapter */
+ if (def->os.bios.useserial == VIR_DOMAIN_BIOS_USESERIAL_YES) {
+ if (!qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qemu does not support -device"));
+ goto error;
+ }
+ if (!qemuCapsGet(qemuCaps, QEMU_CAPS_SGA)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("qemu does not support SGA"));
+ goto error;
+ }
+ if (!def->nserials) {
+ qemuReportError(VIR_ERR_XML_ERROR, "%s",
+ _("need at least one serial port to use SGA"));
+ goto error;
+ }
+ virCommandAddArgList(cmd, "-device", "sga", NULL);
+ }
+
if (monitor_chr) {
char *chrdev;
/* Use -chardev if it's available */
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bios.args b/tests/qemuxml2argvdata/qemuxml2argv-bios.args
new file mode 100644
index 0000000000..f9727c436d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-bios.args
@@ -0,0 +1,6 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M pc -m 1024 -smp 1 -nodefaults -device sga \
+-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-hda /dev/HostVG/QEMUGuest1 -serial pty \
+-usb -device usb-tablet,id=input0 -vnc 127.0.0.1:0 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-bios.xml b/tests/qemuxml2argvdata/qemuxml2argv-bios.xml
new file mode 100644
index 0000000000..5ce3e24c3f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-bios.xml
@@ -0,0 +1,39 @@
+
+ test-bios
+ 362d1fc1-df7d-193e-5c18-49a71bd1da66
+ 1048576
+ 1048576
+ 1
+
+ hvm
+
+
+
+
+
+ destroy
+ restart
+ restart
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index f12d81577e..56f928812e 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -287,6 +287,7 @@ mymain(void)
QEMU_CAPS_DEVICE, QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_BOOT,
QEMU_CAPS_BOOTINDEX);
DO_TEST("bootloader", true, QEMU_CAPS_DOMID);
+ DO_TEST("bios", false, QEMU_CAPS_DEVICE, QEMU_CAPS_SGA);
DO_TEST("clock-utc", false, NONE);
DO_TEST("clock-localtime", false, NONE);
/*