diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 52119f0a0a8fea8009ac4cd58d4fd2cf533df0a8..a55a9e13920d5e65a2f51f5b909f99de2111fa1a 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -3027,8 +3027,13 @@
boot
Specifies that the disk is bootable. The order
attribute determines the order in which devices will be tried during
- boot sequence. The per-device boot
elements cannot be
- used together with general boot elements in
+ boot sequence. On the S390 architecture only the first boot device is
+ used. The optional loadparm
attribute is an 8 character
+ string which can be queried by guests on S390 via sclp or diag 308.
+ Linux guests on S390 can use loadparm
to select a boot
+ entry. Since 3.5.0
+ The per-device boot
elements cannot be used together
+ with general boot elements in
BIOS bootloader section.
Since 0.8.8
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 4950ddc10915c7fd3f5e04cf3831988a42268896..e259e3ee2583ea74b9a97594bedacaf12ae401dd 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -5071,6 +5071,13 @@
+
+
+
+ [a-zA-Z0-9.\s]{1,8}
+
+
+
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index a20de853f8728d1c290b36afaeb72af1bad3d4a1..48782be95e5001bce989bf918778ff24e75953c8 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -167,6 +167,7 @@ struct _virDomainDeviceInfo {
* assignment, never saved and never reported.
*/
int pciConnectFlags; /* enum virDomainPCIConnectFlags */
+ char *loadparm;
};
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4f79d38251740ae4d34a13b01857519cdbcf41c3..0409c62eff26781851d6dd1704cefa1927cb34b3 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3589,6 +3589,7 @@ void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info)
memset(&info->addr, 0, sizeof(info->addr));
info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE;
VIR_FREE(info->romfile);
+ VIR_FREE(info->loadparm);
}
@@ -5316,6 +5317,50 @@ virDomainDefValidate(virDomainDefPtr def,
}
+/**
+ * virDomainDeviceLoadparmIsValid
+ * @loadparm : The string to validate
+ *
+ * The valid set of values for loadparm are [a-zA-Z0-9.]
+ * and blank spaces.
+ * The maximum allowed length is 8 characters.
+ * An empty string is considered invalid
+ */
+static bool
+virDomainDeviceLoadparmIsValid(const char *loadparm)
+{
+ size_t i;
+
+ if (virStringIsEmpty(loadparm)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("loadparm cannot be an empty string"));
+ return false;
+ }
+
+ if (strlen(loadparm) > 8) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("loadparm '%s' exceeds 8 characters"), loadparm);
+ return false;
+ }
+
+ for (i = 0; i < strlen(loadparm); i++) {
+ uint8_t c = loadparm[i];
+
+ if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') ||
+ (c == '.') || (c == ' ')) {
+ continue;
+ } else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("invalid loadparm char '%c', expecting chars"
+ " in set of [a-zA-Z0-9.] and blank spaces"), c);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
static void
virDomainVirtioOptionsFormat(virBufferPtr buf,
virDomainVirtioOptionsPtr virtio)
@@ -5342,9 +5387,14 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
virDomainDeviceInfoPtr info,
unsigned int flags)
{
- if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex)
- virBufferAsprintf(buf, " \n", info->bootIndex);
+ if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex) {
+ virBufferAsprintf(buf, "bootIndex);
+ if (info->loadparm)
+ virBufferAsprintf(buf, " loadparm='%s'", info->loadparm);
+
+ virBufferAddLit(buf, "/>\n");
+ }
if (info->alias &&
!(flags & VIR_DOMAIN_DEF_FORMAT_INACTIVE)) {
virBufferAsprintf(buf, " \n", info->alias);
@@ -5770,6 +5820,7 @@ virDomainDeviceBootParseXML(xmlNodePtr node,
virHashTablePtr bootHash)
{
char *order;
+ char *loadparm;
int ret = -1;
if (!(order = virXMLPropString(node, "order"))) {
@@ -5798,10 +5849,26 @@ virDomainDeviceBootParseXML(xmlNodePtr node,
goto cleanup;
}
+ loadparm = virXMLPropString(node, "loadparm");
+ if (loadparm) {
+ if (virStringToUpper(&info->loadparm, loadparm) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to convert loadparm '%s' to upper case"),
+ loadparm);
+ goto cleanup;
+ }
+
+ if (!virDomainDeviceLoadparmIsValid(info->loadparm)) {
+ VIR_FREE(info->loadparm);
+ goto cleanup;
+ }
+ }
+
ret = 0;
cleanup:
VIR_FREE(order);
+ VIR_FREE(loadparm);
return ret;
}
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-machine-loadparm-multiple-disks-nets-s390.xml b/tests/qemuxml2argvdata/qemuxml2argv-machine-loadparm-multiple-disks-nets-s390.xml
new file mode 100644
index 0000000000000000000000000000000000000000..df442e95e44d19fff16c533e157343a3e88817c4
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-machine-loadparm-multiple-disks-nets-s390.xml
@@ -0,0 +1,43 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-s390x
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-machine-loadparm-multiple-disks-nets-s390.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-machine-loadparm-multiple-disks-nets-s390.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2f0bb831070551182484294db9569ae462d21150
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-machine-loadparm-multiple-disks-nets-s390.xml
@@ -0,0 +1,44 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu-system-s390x
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 1bdd383a59e7f7491aecc931d834d385fa97ccb4..13072996c254ded0d9f65128f3a9c158c0055291 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -362,6 +362,7 @@ mymain(void)
DO_TEST("minimal", NONE);
DO_TEST("machine-core-on", NONE);
DO_TEST("machine-core-off", NONE);
+ DO_TEST("machine-loadparm-multiple-disks-nets-s390", NONE);
DO_TEST("default-kvm-host-arch", NONE);
DO_TEST("default-qemu-host-arch", NONE);
DO_TEST("boot-cdrom", NONE);