More s390x patches, this time boot related:
- LOADPARM machine property, exposed to the guest via SCLP and diagnose 308 - Use LOADPARM in the s390-ccw bios to select a boot entry - Fix a crash in the ipl device code when a virtio-scsi-pci device has been specified -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZCIm2AAoJEN7Pa5PG8C+v/ckP/3doTOMyiYWQZ91MOKk2UP4W paX4+hqEmuy68Jpk6/owk9t3Mzlx2c0xLuDQX7QWuifi3Vk1y5kD1DbRNx14t6oy icqzWh9wSGMT8Suacf44WjFR+V5TDX9DxrB2c/YDSI1UWg6cEJDM6//hZrbkSH+s Ig4O5rpmhpMNycnDYwSAQXCOZgyqDG8pVdVk0H+nWU/1+9uxVNYEnB8yMpCRSB9a IaDU7LNqkMNBRjCYWLCfMn+UNuRV7bB33iaM3KmaDkAu+XuCZTQuT4H3r5bV5Ata UUCmJtfiWUsGJAOaoxbBrNVNWEUW4yZxsjbVceBkYrUHw0xU6ZKCtyA/AhMCDraF yDwxUbHRQ4rmvqfeyyUGZRMErn7WfdXoPjwWzN3/Cj4DSXSpgz/FTlRmap2B3yqK 1u6lyQFyfTvHgvLVvtfPSQSYGPSGA0/qotzE3C1DoUHZAJtpnYtCRW2mlAd/RxWy 5xUfW6W9p+mE2OHI/zEs47pWe8U4uiG7A+jfEzqKSlMe7g8EGDVvoVFmwL6nPwbD xhzZAsiw3yK3YSeVcYN0bsrvvP6PUBLpnumU0u1QlZlSOoTv79KlJQSXksvrsqqr t/fSsXrW+ZUGDuMnK8qr7Fg1gCPmzfA6bo8o5rmWCE+zM2oDln5UMlZy+QhA1J05 HqG+2eHpaCyLCBKZyF9u =fFQl -----END PGP SIGNATURE----- Merge remote-tracking branch 'cohuck/tags/s390x-20170502' into staging More s390x patches, this time boot related: - LOADPARM machine property, exposed to the guest via SCLP and diagnose 308 - Use LOADPARM in the s390-ccw bios to select a boot entry - Fix a crash in the ipl device code when a virtio-scsi-pci device has been specified # gpg: Signature made Tue 02 May 2017 02:29:26 PM BST # gpg: using RSA key 0xDECF6B93C6F02FAF # gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>" # gpg: aka "Cornelia Huck <cohuck@kernel.org>" # gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>" # gpg: aka "Cornelia Huck <huckc@linux.vnet.ibm.com>" # Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0 18CE DECF 6B93 C6F0 2FAF * cohuck/tags/s390x-20170502: hw/s390x/ipl: Fix crash with virtio-scsi-pci device pc-bios/s390-ccw.img: update image pc-bios/s390-ccw: add boot entry selection to El Torito routine pc-bios/s390-ccw: add boot entry selection for ECKD DASD pc-bios/s390-ccw: provide entry selection on LOADPARM for SCSI disk pc-bios/s390-ccw: provide a function to interpret LOADPARM value pc-bios/s390-ccw: get LOADPARM stored in SCP Read Info pc-bios/s390-ccw: Make ebcdic/ascii conversion public util/qemu-config: Add loadparm to qemu machine_opts hw/s390x/sclp: update LOADPARM in SCP Info hw/s390x/ipl: enable LOADPARM in IPIB for a boot device hw/s390x: provide loadparm property for the machine Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
4f225f343a
@ -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,12 +245,17 @@ 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);
|
||||
VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev);
|
||||
CcwDevice *ccw_dev = CCW_DEVICE(scsi_ccw);
|
||||
CcwDevice *ccw_dev;
|
||||
|
||||
ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw),
|
||||
TYPE_CCW_DEVICE);
|
||||
if (!ccw_dev) { /* It might be a PCI device instead */
|
||||
return false;
|
||||
}
|
||||
|
||||
ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN);
|
||||
ipl->iplb.blk0_len =
|
||||
@ -259,13 +266,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();
|
||||
|
@ -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);
|
||||
|
@ -274,6 +274,36 @@ bool cpu_model_allowed(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *machine_get_loadparm(Object *obj, Error **errp)
|
||||
{
|
||||
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
|
||||
|
||||
return g_memdup(ms->loadparm, sizeof(ms->loadparm));
|
||||
}
|
||||
|
||||
static void machine_set_loadparm(Object *obj, const char *val, Error **errp)
|
||||
{
|
||||
S390CcwMachineState *ms = S390_CCW_MACHINE(obj);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof(ms->loadparm) && val[i]; i++) {
|
||||
uint8_t c = toupper(val[i]); /* mimic HMC */
|
||||
|
||||
if (('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || (c == '.') ||
|
||||
(c == ' ')) {
|
||||
ms->loadparm[i] = c;
|
||||
} else {
|
||||
error_setg(errp, "LOADPARM: invalid character '%c' (ASCII 0x%02x)",
|
||||
c, c);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < sizeof(ms->loadparm); i++) {
|
||||
ms->loadparm[i] = ' '; /* pad right with spaces */
|
||||
}
|
||||
}
|
||||
|
||||
static inline void s390_machine_initfn(Object *obj)
|
||||
{
|
||||
object_property_add_bool(obj, "aes-key-wrap",
|
||||
@ -291,6 +321,13 @@ static inline void s390_machine_initfn(Object *obj)
|
||||
"enable/disable DEA key wrapping using the CPACF wrapping key",
|
||||
NULL);
|
||||
object_property_set_bool(obj, true, "dea-key-wrap", NULL);
|
||||
object_property_add_str(obj, "loadparm",
|
||||
machine_get_loadparm, machine_set_loadparm, NULL);
|
||||
object_property_set_description(obj, "loadparm",
|
||||
"Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted"
|
||||
" to upper case) to pass to machine loader, boot manager,"
|
||||
" and guest kernel",
|
||||
NULL);
|
||||
}
|
||||
|
||||
static const TypeInfo ccw_machine_info = {
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "hw/s390x/sclp.h"
|
||||
#include "hw/s390x/event-facility.h"
|
||||
#include "hw/s390x/s390-pci-bus.h"
|
||||
#include "hw/s390x/ipl.h"
|
||||
|
||||
static inline SCLPDevice *get_sclp_device(void)
|
||||
{
|
||||
@ -57,6 +58,7 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
||||
int cpu_count = 0;
|
||||
int rnsize, rnmax;
|
||||
int slots = MIN(machine->ram_slots, s390_get_memslot_count(kvm_state));
|
||||
IplParameterBlock *ipib = s390_ipl_get_iplb();
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
cpu_count++;
|
||||
@ -129,6 +131,13 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
|
||||
read_info->rnmax2 = cpu_to_be64(rnmax);
|
||||
}
|
||||
|
||||
if (ipib && ipib->flags & DIAG308_FLAGS_LP_VALID) {
|
||||
memcpy(&read_info->loadparm, &ipib->loadparm,
|
||||
sizeof(read_info->loadparm));
|
||||
} else {
|
||||
s390_ipl_set_loadparm(read_info->loadparm);
|
||||
}
|
||||
|
||||
sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_READ_COMPLETION);
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@ typedef struct S390CcwMachineState {
|
||||
/*< public >*/
|
||||
bool aes_key_wrap;
|
||||
bool dea_key_wrap;
|
||||
uint8_t loadparm[8];
|
||||
} S390CcwMachineState;
|
||||
|
||||
typedef struct S390CcwMachineClass {
|
||||
|
Binary file not shown.
@ -9,7 +9,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw)
|
||||
|
||||
.PHONY : all clean build-all
|
||||
|
||||
OBJECTS = start.o main.o bootmap.o sclp-ascii.o virtio.o virtio-scsi.o
|
||||
OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o
|
||||
QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS))
|
||||
QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float
|
||||
QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing
|
||||
|
@ -183,15 +183,21 @@ static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address)
|
||||
static void run_eckd_boot_script(block_number_t mbr_block_nr)
|
||||
{
|
||||
int i;
|
||||
unsigned int loadparm = get_loadparm_index();
|
||||
block_number_t block_nr;
|
||||
uint64_t address;
|
||||
ScsiMbr *scsi_mbr = (void *)sec;
|
||||
ScsiMbr *bte = (void *)sec; /* Eckd bootmap table entry */
|
||||
BootMapScript *bms = (void *)sec;
|
||||
|
||||
debug_print_int("loadparm", loadparm);
|
||||
IPL_assert(loadparm < 31, "loadparm value greater than"
|
||||
" maximum number of boot entries allowed");
|
||||
|
||||
memset(sec, FREE_SPACE_FILLER, sizeof(sec));
|
||||
read_block(mbr_block_nr, sec, "Cannot read MBR");
|
||||
|
||||
block_nr = eckd_block_num((void *)&(scsi_mbr->blockptr));
|
||||
block_nr = eckd_block_num((void *)&(bte->blockptr[loadparm]));
|
||||
IPL_assert(block_nr != -1, "No Boot Map");
|
||||
|
||||
memset(sec, FREE_SPACE_FILLER, sizeof(sec));
|
||||
read_block(block_nr, sec, "Cannot read Boot Map Script");
|
||||
@ -444,7 +450,8 @@ static void ipl_scsi(void)
|
||||
uint8_t *ns, *ns_end;
|
||||
int program_table_entries = 0;
|
||||
const int pte_len = sizeof(ScsiBlockPtr);
|
||||
ScsiBlockPtr *prog_table_entry;
|
||||
ScsiBlockPtr *prog_table_entry = NULL;
|
||||
unsigned int loadparm = get_loadparm_index();
|
||||
|
||||
/* Grab the MBR */
|
||||
memset(sec, FREE_SPACE_FILLER, sizeof(sec));
|
||||
@ -458,15 +465,16 @@ static void ipl_scsi(void)
|
||||
debug_print_int("MBR Version", mbr->version_id);
|
||||
IPL_check(mbr->version_id == 1,
|
||||
"Unknown MBR layout version, assuming version 1");
|
||||
debug_print_int("program table", mbr->blockptr.blockno);
|
||||
IPL_assert(mbr->blockptr.blockno, "No Program Table");
|
||||
debug_print_int("program table", mbr->blockptr[0].blockno);
|
||||
IPL_assert(mbr->blockptr[0].blockno, "No Program Table");
|
||||
|
||||
/* Parse the program table */
|
||||
read_block(mbr->blockptr.blockno, sec,
|
||||
read_block(mbr->blockptr[0].blockno, sec,
|
||||
"Error reading Program Table");
|
||||
|
||||
IPL_assert(magic_match(sec, ZIPL_MAGIC), "No zIPL magic in PT");
|
||||
|
||||
debug_print_int("loadparm index", loadparm);
|
||||
ns_end = sec + virtio_get_block_size();
|
||||
for (ns = (sec + pte_len); (ns + pte_len) < ns_end; ns += pte_len) {
|
||||
prog_table_entry = (ScsiBlockPtr *)ns;
|
||||
@ -475,16 +483,15 @@ static void ipl_scsi(void)
|
||||
}
|
||||
|
||||
program_table_entries++;
|
||||
if (program_table_entries == loadparm + 1) {
|
||||
break; /* selected entry found */
|
||||
}
|
||||
}
|
||||
|
||||
debug_print_int("program table entries", program_table_entries);
|
||||
|
||||
IPL_assert(program_table_entries != 0, "Empty Program Table");
|
||||
|
||||
/* Run the default entry */
|
||||
|
||||
prog_table_entry = (ScsiBlockPtr *)(sec + pte_len);
|
||||
|
||||
zipl_run(prog_table_entry); /* no return */
|
||||
}
|
||||
|
||||
@ -648,6 +655,7 @@ static IsoBcSection *find_iso_bc_entry(void)
|
||||
IsoBcEntry *e = (IsoBcEntry *)sec;
|
||||
uint32_t offset = find_iso_bc();
|
||||
int i;
|
||||
unsigned int loadparm = get_loadparm_index();
|
||||
|
||||
if (!offset) {
|
||||
return NULL;
|
||||
@ -668,7 +676,11 @@ static IsoBcSection *find_iso_bc_entry(void)
|
||||
for (i = 1; i < ISO_BC_ENTRY_PER_SECTOR; i++) {
|
||||
if (e[i].id == ISO_BC_BOOTABLE_SECTION) {
|
||||
if (is_iso_bc_entry_compatible(&e[i].body.sect)) {
|
||||
return &e[i].body.sect;
|
||||
if (loadparm <= 1) {
|
||||
/* found, default, or unspecified */
|
||||
return &e[i].body.sect;
|
||||
}
|
||||
loadparm--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ typedef struct ScsiMbr {
|
||||
uint8_t magic[4];
|
||||
uint32_t version_id;
|
||||
uint8_t reserved[8];
|
||||
ScsiBlockPtr blockptr;
|
||||
ScsiBlockPtr blockptr[];
|
||||
} __attribute__ ((packed)) ScsiMbr;
|
||||
|
||||
#define ZIPL_MAGIC "zIPL"
|
||||
@ -264,28 +264,6 @@ typedef enum {
|
||||
|
||||
/* utility code below */
|
||||
|
||||
static const unsigned char ebc2asc[256] =
|
||||
/* 0123456789abcdef0123456789abcdef */
|
||||
"................................" /* 1F */
|
||||
"................................" /* 3F */
|
||||
" ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */
|
||||
"-/.........,%_>?.........`:#@'=\""/* 7F */
|
||||
".abcdefghi.......jklmnopqr......" /* 9F */
|
||||
"..stuvwxyz......................" /* BF */
|
||||
".ABCDEFGHI.......JKLMNOPQR......" /* DF */
|
||||
"..STUVWXYZ......0123456789......";/* FF */
|
||||
|
||||
static inline void ebcdic_to_ascii(const char *src,
|
||||
char *dst,
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
unsigned c = src[i];
|
||||
dst[i] = ebc2asc[c];
|
||||
}
|
||||
}
|
||||
|
||||
static inline void print_volser(const void *volser)
|
||||
{
|
||||
char ascii[8];
|
||||
|
@ -14,6 +14,18 @@
|
||||
char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
|
||||
static SubChannelId blk_schid = { .one = 1 };
|
||||
IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE)));
|
||||
static char loadparm[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
const unsigned char ebc2asc[256] =
|
||||
/* 0123456789abcdef0123456789abcdef */
|
||||
"................................" /* 1F */
|
||||
"................................" /* 3F */
|
||||
" ...........<(+|&.........!$*);." /* 5F first.chr.here.is.real.space */
|
||||
"-/.........,%_>?.........`:#@'=\""/* 7F */
|
||||
".abcdefghi.......jklmnopqr......" /* 9F */
|
||||
"..stuvwxyz......................" /* BF */
|
||||
".ABCDEFGHI.......JKLMNOPQR......" /* DF */
|
||||
"..STUVWXYZ......0123456789......";/* FF */
|
||||
|
||||
/*
|
||||
* Priniciples of Operations (SA22-7832-09) chapter 17 requires that
|
||||
@ -29,7 +41,6 @@ void write_subsystem_identification(void)
|
||||
*zeroes = 0;
|
||||
}
|
||||
|
||||
|
||||
void panic(const char *string)
|
||||
{
|
||||
sclp_print(string);
|
||||
@ -37,6 +48,26 @@ void panic(const char *string)
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
unsigned int get_loadparm_index(void)
|
||||
{
|
||||
const char *lp = loadparm;
|
||||
int i;
|
||||
unsigned int idx = 0;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
char c = lp[i];
|
||||
|
||||
if (c < '0' || c > '9') {
|
||||
break;
|
||||
}
|
||||
|
||||
idx *= 10;
|
||||
idx += c - '0';
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static bool find_dev(Schib *schib, int dev_no)
|
||||
{
|
||||
int i, r;
|
||||
@ -73,6 +104,7 @@ static void virtio_setup(void)
|
||||
int ssid;
|
||||
bool found = false;
|
||||
uint16_t dev_no;
|
||||
char ldp[] = "LOADPARM=[________]\n";
|
||||
VDev *vdev = virtio_get_device();
|
||||
|
||||
/*
|
||||
@ -82,6 +114,10 @@ static void virtio_setup(void)
|
||||
*/
|
||||
enable_mss_facility();
|
||||
|
||||
sclp_get_loadparm_ascii(loadparm);
|
||||
memcpy(ldp + 10, loadparm, 8);
|
||||
sclp_print(ldp);
|
||||
|
||||
if (store_iplb(&iplb)) {
|
||||
switch (iplb.pbt) {
|
||||
case S390_IPL_TYPE_CCW:
|
||||
|
@ -62,10 +62,12 @@ void consume_sclp_int(void);
|
||||
void panic(const char *string);
|
||||
void write_subsystem_identification(void);
|
||||
extern char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE)));
|
||||
unsigned int get_loadparm_index(void);
|
||||
|
||||
/* sclp-ascii.c */
|
||||
/* sclp.c */
|
||||
void sclp_print(const char *string);
|
||||
void sclp_setup(void);
|
||||
void sclp_get_loadparm_ascii(char *loadparm);
|
||||
|
||||
/* virtio.c */
|
||||
unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2,
|
||||
@ -189,4 +191,17 @@ static inline void IPL_check(bool term, const char *message)
|
||||
}
|
||||
}
|
||||
|
||||
extern const unsigned char ebc2asc[256];
|
||||
static inline void ebcdic_to_ascii(const char *src,
|
||||
char *dst,
|
||||
unsigned int size)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
unsigned c = src[i];
|
||||
dst[i] = ebc2asc[c];
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* S390_CCW_H */
|
||||
|
@ -80,3 +80,15 @@ void sclp_print(const char *str)
|
||||
|
||||
sclp_service_call(SCLP_CMD_WRITE_EVENT_DATA, sccb);
|
||||
}
|
||||
|
||||
void sclp_get_loadparm_ascii(char *loadparm)
|
||||
{
|
||||
|
||||
ReadInfo *sccb = (void *)_sccb;
|
||||
|
||||
memset((char *)_sccb, 0, sizeof(ReadInfo));
|
||||
sccb->h.length = sizeof(ReadInfo);
|
||||
if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) {
|
||||
ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8);
|
||||
}
|
||||
}
|
@ -55,6 +55,8 @@ typedef struct ReadInfo {
|
||||
SCCBHeader h;
|
||||
uint16_t rnmax;
|
||||
uint8_t rnsize;
|
||||
uint8_t reserved[13];
|
||||
uint8_t loadparm[8];
|
||||
} __attribute__((packed)) ReadInfo;
|
||||
|
||||
typedef struct SCCB {
|
||||
|
@ -227,6 +227,12 @@ static QemuOptsList machine_opts = {
|
||||
.name = "dea-key-wrap",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "enable/disable DEA key wrapping using the CPACF wrapping key",
|
||||
},{
|
||||
.name = "loadparm",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Up to 8 chars in set of [A-Za-z0-9. ](lower case chars"
|
||||
" converted to upper case) to pass to machine"
|
||||
" loader, boot manager, and guest kernel",
|
||||
},
|
||||
{ /* End of list */ }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user