aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/conf/domain_conf.c16
-rw-r--r--src/conf/domain_conf.h5
-rw-r--r--src/libvirt_private.syms2
-rw-r--r--src/qemu/qemu_command.c93
4 files changed, 88 insertions, 28 deletions
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 15b360a76..35814fb02 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -102,6 +102,11 @@ VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST,
"hd",
"network")
+VIR_ENUM_IMPL(virDomainBootMenu, VIR_DOMAIN_BOOT_MENU_LAST,
+ "default",
+ "yes",
+ "no")
+
VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
"acpi",
"apic",
@@ -8181,10 +8186,15 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt,
bootstr = virXPathString("string(./os/bootmenu[1]/@enable)", ctxt);
if (bootstr) {
- if (STREQ(bootstr, "yes"))
- def->os.bootmenu = VIR_DOMAIN_BOOT_MENU_ENABLED;
- else
+ def->os.bootmenu = virDomainBootMenuTypeFromString(bootstr);
+ if (def->os.bootmenu <= 0) {
+ /* In order not to break misconfigured machines, this
+ * should not emit an error, but rather set the bootmenu
+ * to disabled */
+ VIR_WARN("disabling bootmenu due to unknown option '%s'",
+ bootstr);
def->os.bootmenu = VIR_DOMAIN_BOOT_MENU_DISABLED;
+ }
VIR_FREE(bootstr);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f0dea48bf..4801c27be 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1359,6 +1359,8 @@ enum virDomainBootMenu {
VIR_DOMAIN_BOOT_MENU_DEFAULT = 0,
VIR_DOMAIN_BOOT_MENU_ENABLED,
VIR_DOMAIN_BOOT_MENU_DISABLED,
+
+ VIR_DOMAIN_BOOT_MENU_LAST
};
enum virDomainFeature {
@@ -1429,6 +1431,7 @@ struct _virDomainOSDef {
char *machine;
int nBootDevs;
int bootDevs[VIR_DOMAIN_BOOT_LAST];
+ /* enum virDomainBootMenu */
int bootmenu;
char *init;
char **initargv;
@@ -1440,6 +1443,7 @@ struct _virDomainOSDef {
char *bootloader;
char *bootloaderArgs;
int smbios_mode;
+
virDomainBIOSDef bios;
};
@@ -2129,6 +2133,7 @@ VIR_ENUM_DECL(virDomainTaint)
VIR_ENUM_DECL(virDomainVirt)
VIR_ENUM_DECL(virDomainBoot)
+VIR_ENUM_DECL(virDomainBootMenu)
VIR_ENUM_DECL(virDomainFeature)
VIR_ENUM_DECL(virDomainApicEoi)
VIR_ENUM_DECL(virDomainLifecycle)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index e75e489cc..0b538950e 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -280,6 +280,8 @@ virDomainApicEoiTypeToString;
virDomainAssignDef;
virDomainBlockedReasonTypeFromString;
virDomainBlockedReasonTypeToString;
+virDomainBootMenuTypeFromString;
+virDomainBootMenuTypeToString;
virDomainChrConsoleTargetTypeFromString;
virDomainChrConsoleTargetTypeToString;
virDomainChrDefForeach;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index cbf4aeec7..f8012ec16 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4879,6 +4879,8 @@ qemuBuildCommandLine(virConnectPtr conn,
}
if (!def->os.bootloader) {
+ int boot_nparams = 0;
+ virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
/*
* We prefer using explicit bootindex=N parameters for predictable
* results even though domain XML doesn't use per device boot elements.
@@ -4901,7 +4903,6 @@ qemuBuildCommandLine(virConnectPtr conn,
}
if (!emitBootindex) {
- virBuffer boot_buf = VIR_BUFFER_INITIALIZER;
char boot[VIR_DOMAIN_BOOT_LAST+1];
for (i = 0 ; i < def->os.nBootDevs ; i++) {
@@ -4925,19 +4926,38 @@ qemuBuildCommandLine(virConnectPtr conn,
}
boot[def->os.nBootDevs] = '\0';
- virCommandAddArg(cmd, "-boot");
+ virBufferAsprintf(&boot_buf, "%s", boot);
+ boot_nparams++;
+ }
+
+ if (def->os.bootmenu) {
+ if (qemuCapsGet(caps, QEMU_CAPS_BOOT_MENU)) {
+ if (boot_nparams++)
+ virBufferAddChar(&boot_buf, ',');
- if (qemuCapsGet(caps, QEMU_CAPS_BOOT_MENU) &&
- def->os.bootmenu != VIR_DOMAIN_BOOT_MENU_DEFAULT) {
if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_ENABLED)
- virBufferAsprintf(&boot_buf, "order=%s,menu=on", boot);
- else if (def->os.bootmenu == VIR_DOMAIN_BOOT_MENU_DISABLED)
- virBufferAsprintf(&boot_buf, "order=%s,menu=off", boot);
+ virBufferAsprintf(&boot_buf, "menu=on");
+ else
+ virBufferAsprintf(&boot_buf, "menu=off");
} else {
- virBufferAdd(&boot_buf, boot, -1);
+ /* We cannot emit an error when bootmenu is enabled but
+ * unsupported because of backward compatibility */
+ VIR_WARN("bootmenu is enabled but not "
+ "supported by this QEMU binary");
}
- virCommandAddArgBuffer(cmd, &boot_buf);
+ }
+
+ if (boot_nparams > 0) {
+ virCommandAddArg(cmd, "-boot");
+
+ if (boot_nparams < 2 || emitBootindex) {
+ virCommandAddArgBuffer(cmd, &boot_buf);
+ } else {
+ virCommandAddArgFormat(cmd,
+ "order=%s",
+ virBufferContentAndReset(&boot_buf));
+ }
}
if (def->os.kernel)
@@ -7861,6 +7881,26 @@ error:
}
+static void
+qemuParseCommandLineBootDevs(virDomainDefPtr def, const char *str) {
+ int n, b = 0;
+
+ for (n = 0 ; str[n] && b < VIR_DOMAIN_BOOT_LAST ; n++) {
+ if (str[n] == 'a')
+ def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_FLOPPY;
+ else if (str[n] == 'c')
+ def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_DISK;
+ else if (str[n] == 'd')
+ def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_CDROM;
+ else if (str[n] == 'n')
+ def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_NET;
+ else if (str[n] == ',')
+ break;
+ }
+ def->os.nBootDevs = b;
+}
+
+
/*
* Analyse the env and argv settings and reconstruct a
* virDomainDefPtr representing these settings as closely
@@ -8218,24 +8258,27 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
if (!(def->os.cmdline = strdup(val)))
goto no_memory;
} else if (STREQ(arg, "-boot")) {
- int n, b = 0;
+ const char *token = NULL;
WANT_VALUE();
- for (n = 0 ; val[n] && b < VIR_DOMAIN_BOOT_LAST ; n++) {
- if (val[n] == 'a')
- def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_FLOPPY;
- else if (val[n] == 'c')
- def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_DISK;
- else if (val[n] == 'd')
- def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_CDROM;
- else if (val[n] == 'n')
- def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_NET;
- else if (val[n] == ',')
- break;
- }
- def->os.nBootDevs = b;
- if (strstr(val, "menu=on"))
- def->os.bootmenu = 1;
+ if (!strchr(val, ','))
+ qemuParseCommandLineBootDevs(def, val);
+ else {
+ token = val;
+ while (token && *token) {
+ if (STRPREFIX(token, "order=")) {
+ token += strlen("order=");
+ qemuParseCommandLineBootDevs(def, token);
+ } else if (STRPREFIX(token, "menu=on")) {
+ def->os.bootmenu = 1;
+ }
+ token = strchr(token, ',');
+ /* This incrementation has to be done here in order to make it
+ * possible to pass the token pointer properly into the loop */
+ if (token)
+ token++;
+ }
+ }
} else if (STREQ(arg, "-name")) {
char *process;
WANT_VALUE();