diff options
author | Cornelia Huck <cohuck@redhat.com> | 2018-02-27 13:54:37 +0100 |
---|---|---|
committer | Cornelia Huck <cohuck@redhat.com> | 2018-02-27 13:54:37 +0100 |
commit | eae9f29130f3ed40ad77f40a3bae4b9ebff28907 (patch) | |
tree | d8940c54cabf258daba77ae2e71b59ede05dd1ee /hw | |
parent | 3e65a3c283ae36c1f27141f71d2bb040737b1390 (diff) | |
parent | 9c050f3d15697c4c84c9d6aa7af779a273b71d87 (diff) |
Merge tag 'tags/s390-ccw-bios-2018-02-26' into s390-next
Boot menu patches by Collin L. Walling
# gpg: Signature made Mon 26 Feb 2018 11:24:21 AM CET
# gpg: using RSA key 2ED9D774FE702DB5
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full]
# gpg: aka "Thomas Huth <thuth@redhat.com>" [undefined]
# gpg: aka "Thomas Huth <huth@tuxfamily.org>" [undefined]
# gpg: aka "Thomas Huth <th.huth@posteo.de>" [unknown]
* tag 'tags/s390-ccw-bios-2018-02-26':
pc-bios/s390: Rebuild the s390x firmware images with the boot menu changes
s390-ccw: interactive boot menu for scsi
s390-ccw: use zipl values when no boot menu options are present
s390-ccw: set cp_receive mask only when needed and consume pending service irqs
s390-ccw: read user input for boot index via the SCLP console
s390-ccw: print zipl boot menu
s390-ccw: read stage2 boot loader data to find menu
s390-ccw: set up interactive boot menu parameters
s390-ccw: parse and set boot menu options
s390-ccw: move auxiliary IPL data to separate location
s390-ccw: update libc
s390-ccw: refactor IPL structs
s390-ccw: refactor eckd_block_num to use CHS
s390-ccw: refactor boot map table code
Diffstat (limited to 'hw')
-rw-r--r-- | hw/s390x/ipl.c | 77 | ||||
-rw-r--r-- | hw/s390x/ipl.h | 31 |
2 files changed, 105 insertions, 3 deletions
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index 0d06fc12b6..798e99aadf 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -23,6 +23,9 @@ #include "hw/s390x/ebcdic.h" #include "ipl.h" #include "qemu/error-report.h" +#include "qemu/config-file.h" +#include "qemu/cutils.h" +#include "qemu/option.h" #define KERN_IMAGE_START 0x010000UL #define KERN_PARM_AREA 0x010480UL @@ -219,6 +222,61 @@ static Property s390_ipl_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static void s390_ipl_set_boot_menu(S390IPLState *ipl) +{ + QemuOptsList *plist = qemu_find_opts("boot-opts"); + QemuOpts *opts = QTAILQ_FIRST(&plist->head); + uint8_t *flags = &ipl->qipl.qipl_flags; + uint32_t *timeout = &ipl->qipl.boot_menu_timeout; + const char *tmp; + unsigned long splash_time = 0; + + if (!get_boot_device(0)) { + if (boot_menu) { + error_report("boot menu requires a bootindex to be specified for " + "the IPL device."); + } + return; + } + + switch (ipl->iplb.pbt) { + case S390_IPL_TYPE_CCW: + /* In the absence of -boot menu, use zipl parameters */ + if (!qemu_opt_get(opts, "menu")) { + *flags |= QIPL_FLAG_BM_OPTS_ZIPL; + return; + } + break; + case S390_IPL_TYPE_QEMU_SCSI: + break; + default: + error_report("boot menu is not supported for this device type."); + return; + } + + if (!boot_menu) { + return; + } + + *flags |= QIPL_FLAG_BM_OPTS_CMD; + + tmp = qemu_opt_get(opts, "splash-time"); + + if (tmp && qemu_strtoul(tmp, NULL, 10, &splash_time)) { + error_report("splash-time is invalid, forcing it to 0."); + *timeout = 0; + return; + } + + if (splash_time > 0xffffffff) { + error_report("splash-time is too large, forcing it to max value."); + *timeout = 0xffffffff; + return; + } + + *timeout = cpu_to_be32(splash_time); +} + static bool s390_gen_initial_iplb(S390IPLState *ipl) { DeviceState *dev_st; @@ -399,6 +457,21 @@ void s390_reipl_request(void) qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); } +static void s390_ipl_prepare_qipl(S390CPU *cpu) +{ + S390IPLState *ipl = get_ipl_device(); + uint8_t *addr; + uint64_t len = 4096; + + addr = cpu_physical_memory_map(cpu->env.psa, &len, 1); + if (!addr || len < QIPL_ADDRESS + sizeof(QemuIplParameters)) { + error_report("Cannot set QEMU IPL parameters"); + return; + } + memcpy(addr + QIPL_ADDRESS, &ipl->qipl, sizeof(QemuIplParameters)); + cpu_physical_memory_unmap(addr, len, 1, len); +} + void s390_ipl_prepare_cpu(S390CPU *cpu) { S390IPLState *ipl = get_ipl_device(); @@ -418,8 +491,10 @@ void s390_ipl_prepare_cpu(S390CPU *cpu) error_report_err(err); vm_stop(RUN_STATE_INTERNAL_ERROR); } - ipl->iplb.ccw.netboot_start_addr = cpu_to_be64(ipl->start_addr); + ipl->qipl.netboot_start_addr = cpu_to_be64(ipl->start_addr); } + s390_ipl_set_boot_menu(ipl); + s390_ipl_prepare_qipl(cpu); } static void s390_ipl_reset(DeviceState *dev) diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h index 8a705e0428..0570d0ad75 100644 --- a/hw/s390x/ipl.h +++ b/hw/s390x/ipl.h @@ -16,8 +16,7 @@ #include "cpu.h" struct IplBlockCcw { - uint64_t netboot_start_addr; - uint8_t reserved0[77]; + uint8_t reserved0[85]; uint8_t ssid; uint16_t devno; uint8_t vm_flags; @@ -90,6 +89,33 @@ void s390_ipl_prepare_cpu(S390CPU *cpu); IplParameterBlock *s390_ipl_get_iplb(void); void s390_reipl_request(void); +#define QIPL_ADDRESS 0xcc + +/* Boot Menu flags */ +#define QIPL_FLAG_BM_OPTS_CMD 0x80 +#define QIPL_FLAG_BM_OPTS_ZIPL 0x40 + +/* + * The QEMU IPL Parameters will be stored at absolute address + * 204 (0xcc) which means it is 32-bit word aligned but not + * double-word aligned. + * Placement of data fields in this area must account for + * their alignment needs. E.g., netboot_start_address must + * have an offset of 4 + n * 8 bytes within the struct in order + * to keep it double-word aligned. + * The total size of the struct must never exceed 28 bytes. + * This definition must be kept in sync with the defininition + * in pc-bios/s390-ccw/iplb.h. + */ +struct QemuIplParameters { + uint8_t qipl_flags; + uint8_t reserved1[3]; + uint64_t netboot_start_addr; + uint32_t boot_menu_timeout; + uint8_t reserved2[12]; +} QEMU_PACKED; +typedef struct QemuIplParameters QemuIplParameters; + #define TYPE_S390_IPL "s390-ipl" #define S390_IPL(obj) OBJECT_CHECK(S390IPLState, (obj), TYPE_S390_IPL) @@ -105,6 +131,7 @@ struct S390IPLState { bool iplb_valid; bool reipl_requested; bool netboot; + QemuIplParameters qipl; /*< public >*/ char *kernel; |