aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFarhan Ali <alifm@linux.vnet.ibm.com>2016-03-29 16:28:40 +0200
committerCornelia Huck <cornelia.huck@de.ibm.com>2017-05-02 15:08:54 +0200
commitbd1badf45788930473d271f44f1268a63f2ddbdd (patch)
treeed1fdf1e7ae59b3d97c561b4e6fce4a4daed9c61
parent7104bae9de560e7f9f00b2bef4b8c791cdd59c7f (diff)
hw/s390x/ipl: enable LOADPARM in IPIB for a boot device
Insert the LOADPARM value to the IPL Information Parameter Block. An IPL Information Parameter Block is created when "bootindex" is specified for a device. If a user specifies "loadparm=", then we store the loadparm value in the created IPIB for that boot device. Initial patch from Eugene (jno) Dvurechenski. Signed-off-by: Eugene (jno) Dvurechenski <jno@linux.vnet.ibm.com> Signed-off-by: Farhan Ali <alifm@linux.vnet.ibm.com> Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
-rw-r--r--hw/s390x/ipl.c31
-rw-r--r--hw/s390x/ipl.h3
2 files changed, 32 insertions, 2 deletions
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 7978c7d52a..0711ee927a 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -17,8 +17,10 @@
#include "cpu.h"
#include "elf.h"
#include "hw/loader.h"
+#include "hw/boards.h"
#include "hw/s390x/virtio-ccw.h"
#include "hw/s390x/css.h"
+#include "hw/s390x/ebcdic.h"
#include "ipl.h"
#include "qemu/error-report.h"
@@ -243,7 +245,6 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
ipl->iplb.pbt = S390_IPL_TYPE_CCW;
ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3;
- return true;
} else if (sd) {
SCSIBus *bus = scsi_bus_from_device(sd);
VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus);
@@ -259,13 +260,39 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl)
ipl->iplb.scsi.channel = cpu_to_be16(sd->channel);
ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno);
ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3;
- return true;
+ } else {
+ return false; /* unknown device */
+ }
+
+ if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) {
+ ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID;
}
+ return true;
}
return false;
}
+int s390_ipl_set_loadparm(uint8_t *loadparm)
+{
+ MachineState *machine = MACHINE(qdev_get_machine());
+ char *lp = object_property_get_str(OBJECT(machine), "loadparm", NULL);
+
+ if (lp) {
+ int i;
+
+ /* lp is an uppercase string without leading/embedded spaces */
+ for (i = 0; i < 8 && lp[i]; i++) {
+ loadparm[i] = ascii2ebcdic[(uint8_t) lp[i]];
+ }
+
+ g_free(lp);
+ return 0;
+ }
+
+ return -1;
+}
+
static int load_netboot_image(Error **errp)
{
S390IPLState *ipl = get_ipl_device();
diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h
index 46930e4c64..8a705e0428 100644
--- a/hw/s390x/ipl.h
+++ b/hw/s390x/ipl.h
@@ -57,6 +57,8 @@ struct IplBlockQemuScsi {
} QEMU_PACKED;
typedef struct IplBlockQemuScsi IplBlockQemuScsi;
+#define DIAG308_FLAGS_LP_VALID 0x80
+
union IplParameterBlock {
struct {
uint32_t len;
@@ -82,6 +84,7 @@ union IplParameterBlock {
} QEMU_PACKED;
typedef union IplParameterBlock IplParameterBlock;
+int s390_ipl_set_loadparm(uint8_t *loadparm);
void s390_ipl_update_diag308(IplParameterBlock *iplb);
void s390_ipl_prepare_cpu(S390CPU *cpu);
IplParameterBlock *s390_ipl_get_iplb(void);