diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-10-06 21:13:34 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-10-06 21:13:34 +0100 |
commit | 6eeea6725a70e6fcb5abba0764496bdab07ddfb3 (patch) | |
tree | ba23ee518ccfed4f6464df7a349809009746a96c | |
parent | f2687fdb7571a444b5af3509574b659d35ddd601 (diff) | |
parent | eb32abd8d931994d10327bd965a4fb12d765a0fb (diff) |
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2020-10-06' into staging
* Don't stop at the first unbootable device, continue scanning
* Fix corner cases in booting from ECKD
* s390x-ccw bios cleanup part 2
# gpg: Signature made Tue 06 Oct 2020 19:17:46 BST
# gpg: using RSA key 27B88847EEE0250118F3EAB92ED9D774FE702DB5
# gpg: issuer "thuth@redhat.com"
# gpg: Good signature from "Thomas Huth <th.huth@gmx.de>" [full]
# gpg: aka "Thomas Huth <thuth@redhat.com>" [full]
# gpg: aka "Thomas Huth <huth@tuxfamily.org>" [full]
# gpg: aka "Thomas Huth <th.huth@posteo.de>" [unknown]
# Primary key fingerprint: 27B8 8847 EEE0 2501 18F3 EAB9 2ED9 D774 FE70 2DB5
* remotes/huth-gitlab/tags/pull-request-2020-10-06:
tests/qtest/cdrom: Add more s390x-related boot tests
pc-bios/s390: Update the s390-ccw bios binaries
pc-bios: s390x: Go into disabled wait when encountering a PGM exception
pc-bios: s390x: Use reset PSW if avaliable
pc-bios: s390x: Save PSW rework
pc-bios: s390x: Fix bootmap.c zipl component entry data handling
pc-bios/s390-ccw: break loop if a null block number is reached
pc-bios/s390-ccw: fix off-by-one error
pc-bios/s390-ccw/main: Remove superfluous call to enable_subchannel()
pc-bios/s390-ccw: Allow booting in case the first virtio-blk disk is bad
pc-bios/s390-ccw: Scan through all devices if no boot device specified
pc-bios/s390-ccw: Do not bail out early if not finding a SCSI disk
pc-bios/s390-ccw: Move the inner logic of find_subch() to a separate function
pc-bios/s390-ccw: Introduce ENODEV define and remove guards of others
pc-bios/s390-ccw: Move ipl-related code from main() into a separate function
pc-bios/s390-ccw/Makefile: Compile with -std=gnu99, -fwrapv and -fno-common
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | pc-bios/s390-ccw.img | bin | 42608 -> 42608 bytes | |||
-rw-r--r-- | pc-bios/s390-ccw/Makefile | 7 | ||||
-rw-r--r-- | pc-bios/s390-ccw/bootmap.c | 47 | ||||
-rw-r--r-- | pc-bios/s390-ccw/bootmap.h | 7 | ||||
-rw-r--r-- | pc-bios/s390-ccw/jump2ipl.c | 45 | ||||
-rw-r--r-- | pc-bios/s390-ccw/main.c | 172 | ||||
-rw-r--r-- | pc-bios/s390-ccw/s390-ccw.h | 9 | ||||
-rw-r--r-- | pc-bios/s390-ccw/start.S | 5 | ||||
-rw-r--r-- | pc-bios/s390-ccw/virtio-blkdev.c | 7 | ||||
-rw-r--r-- | pc-bios/s390-ccw/virtio-scsi.c | 28 | ||||
-rw-r--r-- | pc-bios/s390-ccw/virtio-scsi.h | 2 | ||||
-rw-r--r-- | pc-bios/s390-netboot.img | bin | 67232 -> 67232 bytes | |||
-rw-r--r-- | tests/qtest/cdrom-test.c | 12 |
13 files changed, 218 insertions, 123 deletions
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img Binary files differindex 3074686a8c..5b57ea2837 100644 --- a/pc-bios/s390-ccw.img +++ b/pc-bios/s390-ccw.img diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile index 3eb785048a..29fd9019b8 100644 --- a/pc-bios/s390-ccw/Makefile +++ b/pc-bios/s390-ccw/Makefile @@ -30,10 +30,11 @@ OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o dasd-ipl.o QEMU_CFLAGS := -Wall $(filter -W%, $(QEMU_CFLAGS)) -QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float -QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing -QEMU_CFLAGS += -fno-asynchronous-unwind-tables +QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -fno-common -fPIE +QEMU_CFLAGS += -fwrapv -fno-strict-aliasing -fno-asynchronous-unwind-tables QEMU_CFLAGS += $(call cc-option, $(QEMU_CFLAGS), -fno-stack-protector) +QEMU_CFLAGS += -msoft-float -march=z900 +QEMU_CFLAGS += -std=gnu99 LDFLAGS += -Wl,-pie -nostdlib build-all: s390-ccw.img s390-netboot.img diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index 97205674e5..44df7d16af 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -10,6 +10,7 @@ #include "libc.h" #include "s390-ccw.h" +#include "s390-arch.h" #include "bootmap.h" #include "virtio.h" #include "bswap.h" @@ -163,7 +164,7 @@ static bool find_zipl_boot_menu_banner(int *offset) int i; /* Menu banner starts with "zIPL" */ - for (i = 0; i < virtio_get_block_size() - 4; i++) { + for (i = 0; i <= virtio_get_block_size() - 4; i++) { if (magic_match(s2_cur_blk + i, ZIPL_MAGIC_EBCDIC)) { *offset = i; return true; @@ -192,7 +193,7 @@ static int eckd_get_boot_menu_index(block_number_t s1b_block_nr) for (i = 0; i < STAGE2_BLK_CNT_MAX; i++) { cur_block_nr = eckd_block_num(&s1b->seek[i].chs); - if (!cur_block_nr) { + if (!cur_block_nr || is_null_block_number(cur_block_nr)) { break; } @@ -272,7 +273,8 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr, IPL_assert(bms->entry[i].type == BOOT_SCRIPT_EXEC, "Unknown script entry type"); - jump_to_IPL_code(bms->entry[i].address.load_address); /* no return */ + write_reset_psw(bms->entry[i].address.load_address); /* no return */ + jump_to_IPL_code(0); /* no return */ } static void ipl_eckd_cdl(void) @@ -289,11 +291,18 @@ static void ipl_eckd_cdl(void) read_block(1, ipl2, "Cannot read IPL2 record at block 1"); mbr = &ipl2->mbr; - IPL_assert(magic_match(mbr, ZIPL_MAGIC), "No zIPL section in IPL2 record."); - IPL_assert(block_size_ok(mbr->blockptr.xeckd.bptr.size), - "Bad block size in zIPL section of IPL2 record."); - IPL_assert(mbr->dev_type == DEV_TYPE_ECKD, - "Non-ECKD device type in zIPL section of IPL2 record."); + if (!magic_match(mbr, ZIPL_MAGIC)) { + sclp_print("No zIPL section in IPL2 record.\n"); + return; + } + if (!block_size_ok(mbr->blockptr.xeckd.bptr.size)) { + sclp_print("Bad block size in zIPL section of IPL2 record.\n"); + return; + } + if (!mbr->dev_type == DEV_TYPE_ECKD) { + sclp_print("Non-ECKD device type in zIPL section of IPL2 record.\n"); + return; + } /* save pointer to Boot Map Table */ bmt_block_nr = eckd_block_num(&mbr->blockptr.xeckd.bptr.chs); @@ -303,10 +312,14 @@ static void ipl_eckd_cdl(void) memset(sec, FREE_SPACE_FILLER, sizeof(sec)); read_block(2, vlbl, "Cannot read Volume Label at block 2"); - IPL_assert(magic_match(vlbl->key, VOL1_MAGIC), - "Invalid magic of volume label block"); - IPL_assert(magic_match(vlbl->f.key, VOL1_MAGIC), - "Invalid magic of volser block"); + if (!magic_match(vlbl->key, VOL1_MAGIC)) { + sclp_print("Invalid magic of volume label block.\n"); + return; + } + if (!magic_match(vlbl->f.key, VOL1_MAGIC)) { + sclp_print("Invalid magic of volser block.\n"); + return; + } print_volser(vlbl->f.volser); run_eckd_boot_script(bmt_block_nr, s1b_block_nr); @@ -398,7 +411,8 @@ static void ipl_eckd(void) read_block(0, mbr, "Cannot read block 0 on DASD"); if (magic_match(mbr->magic, IPL1_MAGIC)) { - ipl_eckd_cdl(); /* no return */ + ipl_eckd_cdl(); /* only returns in case of error */ + return; } /* LDL/CMS? */ @@ -436,7 +450,7 @@ static void zipl_load_segment(ComponentEntry *entry) char *blk_no = &err_msg[30]; /* where to print blockno in (those ZZs) */ blockno = entry->data.blockno; - address = entry->load_address; + address = entry->compdat.load_addr; debug_print_int("loading segment at block", blockno); debug_print_int("addr", address); @@ -514,7 +528,8 @@ static void zipl_run(ScsiBlockPtr *pte) IPL_assert(entry->component_type == ZIPL_COMP_ENTRY_EXEC, "No EXEC entry"); /* should not return */ - jump_to_IPL_code(entry->load_address); + write_reset_psw(entry->compdat.load_psw); + jump_to_IPL_code(0); } static void ipl_scsi(void) @@ -825,5 +840,5 @@ void zipl_load(void) panic("\n! Unknown IPL device type !\n"); } - panic("\n* this can never happen *\n"); + sclp_print("zIPL load failed.\n"); } diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h index 12a0166aae..3946aa3f8d 100644 --- a/pc-bios/s390-ccw/bootmap.h +++ b/pc-bios/s390-ccw/bootmap.h @@ -64,11 +64,16 @@ typedef struct BootMapTable { BootMapPointer entry[]; } __attribute__ ((packed)) BootMapTable; +typedef union ComponentEntryData { + uint64_t load_psw; + uint64_t load_addr; +} ComponentEntryData; + typedef struct ComponentEntry { ScsiBlockPtr data; uint8_t pad[7]; uint8_t component_type; - uint64_t load_address; + ComponentEntryData compdat; } __attribute((packed)) ComponentEntry; typedef struct ComponentHeader { diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c index 767012bf0c..fbae45b03c 100644 --- a/pc-bios/s390-ccw/jump2ipl.c +++ b/pc-bios/s390-ccw/jump2ipl.c @@ -12,21 +12,24 @@ #define KERN_IMAGE_START 0x010000UL #define RESET_PSW_MASK (PSW_MASK_SHORTPSW | PSW_MASK_64) +#define RESET_PSW ((uint64_t)&jump_to_IPL_addr | RESET_PSW_MASK) -typedef struct ResetInfo { - uint64_t ipl_psw; - uint32_t ipl_continue; -} ResetInfo; +static uint64_t *reset_psw = 0, save_psw, ipl_continue; -static ResetInfo save; +void write_reset_psw(uint64_t psw) +{ + *reset_psw = psw; +} -static void jump_to_IPL_2(void) +static void jump_to_IPL_addr(void) { - ResetInfo *current = 0; + __attribute__((noreturn)) void (*ipl)(void) = (void *)ipl_continue; - void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue; - *current = save; - ipl(); /* should not return */ + /* Restore reset PSW */ + write_reset_psw(save_psw); + + ipl(); + /* should not return */ } void jump_to_IPL_code(uint64_t address) @@ -46,15 +49,12 @@ void jump_to_IPL_code(uint64_t address) * content of non-BIOS memory after we loaded the guest, so we * save the original content and restore it in jump_to_IPL_2. */ - ResetInfo *current = 0; - - save = *current; - - current->ipl_psw = (uint64_t) &jump_to_IPL_2; - current->ipl_psw |= RESET_PSW_MASK; - current->ipl_continue = address & PSW_MASK_SHORT_ADDR; - - debug_print_int("set IPL addr to", current->ipl_continue); + if (address) { + save_psw = *reset_psw; + write_reset_psw(RESET_PSW); + ipl_continue = address; + } + debug_print_int("set IPL addr to", address ?: *reset_psw & PSW_MASK_SHORT_ADDR); /* Ensure the guest output starts fresh */ sclp_print("\n"); @@ -84,7 +84,12 @@ void jump_to_low_kernel(void) /* Trying to get PSW at zero address */ if (*((uint64_t *)0) & RESET_PSW_MASK) { - jump_to_IPL_code((*((uint64_t *)0)) & PSW_MASK_SHORT_ADDR); + /* + * Surely nobody will try running directly from lowcore, so + * let's use 0 as an indication that we want to load the reset + * psw at 0x0 and not jump to the entry. + */ + jump_to_IPL_code(0); } /* No other option left, so use the Linux kernel start address */ diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index 146a50760b..43c792cf95 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -51,6 +51,60 @@ unsigned int get_loadparm_index(void) return atoui(loadparm_str); } +static int is_dev_possibly_bootable(int dev_no, int sch_no) +{ + bool is_virtio; + Schib schib; + int r; + + blk_schid.sch_no = sch_no; + r = stsch_err(blk_schid, &schib); + if (r == 3 || r == -EIO) { + return -ENODEV; + } + if (!schib.pmcw.dnv) { + return false; + } + + enable_subchannel(blk_schid); + cutype = cu_type(blk_schid); + + /* + * Note: we always have to run virtio_is_supported() here to make + * sure that the vdev.senseid data gets pre-initialized correctly + */ + is_virtio = virtio_is_supported(blk_schid); + + /* No specific devno given, just return whether the device is possibly bootable */ + if (dev_no < 0) { + switch (cutype) { + case CU_TYPE_VIRTIO: + if (is_virtio) { + /* + * Skip net devices since no IPLB is created and therefore + * no network bootloader has been loaded + */ + if (virtio_get_device_type() != VIRTIO_ID_NET) { + return true; + } + } + return false; + case CU_TYPE_DASD_3990: + case CU_TYPE_DASD_2107: + return true; + default: + return false; + } + } + + /* Caller asked for a specific devno */ + if (schib.pmcw.dev == dev_no) { + return true; + } + + return false; +} + /* * Find the subchannel connected to the given device (dev_no) and fill in the * subchannel information block (schib) with the connected subchannel's info. @@ -62,53 +116,14 @@ unsigned int get_loadparm_index(void) */ static bool find_subch(int dev_no) { - Schib schib; int i, r; - bool is_virtio; for (i = 0; i < 0x10000; i++) { - blk_schid.sch_no = i; - r = stsch_err(blk_schid, &schib); - if ((r == 3) || (r == -EIO)) { + r = is_dev_possibly_bootable(dev_no, i); + if (r < 0) { break; } - if (!schib.pmcw.dnv) { - continue; - } - - enable_subchannel(blk_schid); - cutype = cu_type(blk_schid); - - /* - * Note: we always have to run virtio_is_supported() here to make - * sure that the vdev.senseid data gets pre-initialized correctly - */ - is_virtio = virtio_is_supported(blk_schid); - - /* No specific devno given, just return 1st possibly bootable device */ - if (dev_no < 0) { - switch (cutype) { - case CU_TYPE_VIRTIO: - if (is_virtio) { - /* - * Skip net devices since no IPLB is created and therefore - * no network bootloader has been loaded - */ - if (virtio_get_device_type() != VIRTIO_ID_NET) { - return true; - } - } - continue; - case CU_TYPE_DASD_3990: - case CU_TYPE_DASD_2107: - return true; - default: - continue; - } - } - - /* Caller asked for a specific devno */ - if (schib.pmcw.dev == dev_no) { + if (r == true) { return true; } } @@ -167,20 +182,8 @@ static void boot_setup(void) static void find_boot_device(void) { VDev *vdev = virtio_get_device(); - int ssid; bool found; - if (!have_iplb) { - for (ssid = 0; ssid < 0x3; ssid++) { - blk_schid.ssid = ssid; - found = find_subch(-1); - if (found) { - return; - } - } - panic("Could not find a suitable boot device (none specified)\n"); - } - switch (iplb.pbt) { case S390_IPL_TYPE_CCW: debug_print_int("device no. ", iplb.ccw.devno); @@ -203,7 +206,7 @@ static void find_boot_device(void) IPL_assert(found, "Boot device not found\n"); } -static void virtio_setup(void) +static int virtio_setup(void) { VDev *vdev = virtio_get_device(); QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; @@ -218,31 +221,68 @@ static void virtio_setup(void) sclp_print("Network boot device detected\n"); vdev->netboot_start_addr = qipl.netboot_start_addr; } else { - virtio_blk_setup_device(blk_schid); + int ret = virtio_blk_setup_device(blk_schid); + if (ret) { + return ret; + } IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); } + + return 0; } -int main(void) +static void ipl_boot_device(void) { - sclp_setup(); - css_setup(); - boot_setup(); - find_boot_device(); - enable_subchannel(blk_schid); - switch (cutype) { case CU_TYPE_DASD_3990: case CU_TYPE_DASD_2107: dasd_ipl(blk_schid, cutype); /* no return */ break; case CU_TYPE_VIRTIO: - virtio_setup(); - zipl_load(); /* no return */ + if (virtio_setup() == 0) { + zipl_load(); /* Only returns in case of errors */ + } break; default: print_int("Attempting to boot from unexpected device type", cutype); - panic(""); + panic("\nBoot failed.\n"); + } +} + +/* + * No boot device has been specified, so we have to scan through the + * channels to find one. + */ +static void probe_boot_device(void) +{ + int ssid, sch_no, ret; + + for (ssid = 0; ssid < 0x3; ssid++) { + blk_schid.ssid = ssid; + for (sch_no = 0; sch_no < 0x10000; sch_no++) { + ret = is_dev_possibly_bootable(-1, sch_no); + if (ret < 0) { + break; + } + if (ret == true) { + ipl_boot_device(); /* Only returns if unsuccessful */ + } + } + } + + sclp_print("Could not find a suitable boot device (none specified)\n"); +} + +int main(void) +{ + sclp_setup(); + css_setup(); + boot_setup(); + if (have_iplb) { + find_boot_device(); + ipl_boot_device(); + } else { + probe_boot_device(); } panic("Failed to load OS from hard disk\n"); diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h index 36b884cced..6cd92669e9 100644 --- a/pc-bios/s390-ccw/s390-ccw.h +++ b/pc-bios/s390-ccw/s390-ccw.h @@ -27,12 +27,10 @@ typedef unsigned long long __u64; #define false 0 #define PAGE_SIZE 4096 -#ifndef EIO #define EIO 1 -#endif -#ifndef EBUSY #define EBUSY 2 -#endif +#define ENODEV 3 + #ifndef NULL #define NULL 0 #endif @@ -71,13 +69,14 @@ int sclp_read(char *str, size_t count); unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, ulong subchan_id, void *load_addr); bool virtio_is_supported(SubChannelId schid); -void virtio_blk_setup_device(SubChannelId schid); +int virtio_blk_setup_device(SubChannelId schid); int virtio_read(ulong sector, void *load_addr); /* bootmap.c */ void zipl_load(void); /* jump2ipl.c */ +void write_reset_psw(uint64_t psw); void jump_to_IPL_code(uint64_t address); void jump_to_low_kernel(void); diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S index ce519300a1..4d5ad21653 100644 --- a/pc-bios/s390-ccw/start.S +++ b/pc-bios/s390-ccw/start.S @@ -34,7 +34,10 @@ remainder: larl %r2,memsetxc ex %r3,0(%r2) done: - j main /* And call C */ + /* set up a pgm exception disabled wait psw */ + larl %r2, disabled_wait_psw + mvc 0x01d0(16), 0(%r2) + j main /* And call C */ memsetxc: xc 0(1,%r1),0(%r1) diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c index 11c56261ca..7d35050292 100644 --- a/pc-bios/s390-ccw/virtio-blkdev.c +++ b/pc-bios/s390-ccw/virtio-blkdev.c @@ -263,9 +263,10 @@ uint64_t virtio_get_blocks(void) return 0; } -void virtio_blk_setup_device(SubChannelId schid) +int virtio_blk_setup_device(SubChannelId schid) { VDev *vdev = virtio_get_device(); + int ret = 0; vdev->schid = schid; virtio_setup_ccw(vdev); @@ -288,9 +289,11 @@ void virtio_blk_setup_device(SubChannelId schid) "Config: CDB size mismatch"); sclp_print("Using virtio-scsi.\n"); - virtio_scsi_setup(vdev); + ret = virtio_scsi_setup(vdev); break; default: panic("\n! No IPL device available !\n"); } + + return ret; } diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c index eddfb8a7ad..2c8d0f3097 100644 --- a/pc-bios/s390-ccw/virtio-scsi.c +++ b/pc-bios/s390-ccw/virtio-scsi.c @@ -194,7 +194,12 @@ static bool scsi_read_capacity(VDev *vdev, /* virtio-scsi routines */ -static void virtio_scsi_locate_device(VDev *vdev) +/* + * Tries to locate a SCSI device and and adds the information for the found + * device to the vdev->scsi_device structure. + * Returns 0 if SCSI device could be located, or a error code < 0 otherwise + */ +static int virtio_scsi_locate_device(VDev *vdev) { const uint16_t channel = 0; /* again, it's what QEMU does */ uint16_t target; @@ -220,7 +225,7 @@ static void virtio_scsi_locate_device(VDev *vdev) IPL_check(sdev->channel == 0, "non-zero channel requested"); IPL_check(sdev->target <= vdev->config.scsi.max_target, "target# high"); IPL_check(sdev->lun <= vdev->config.scsi.max_lun, "LUN# high"); - return; + return 0; } for (target = 0; target <= vdev->config.scsi.max_target; target++) { @@ -247,18 +252,20 @@ static void virtio_scsi_locate_device(VDev *vdev) */ sdev->lun = r->lun[0].v16[0]; /* it's returned this way */ debug_print_int("Have to use LUN", sdev->lun); - return; /* we have to use this device */ + return 0; /* we have to use this device */ } for (i = 0; i < luns; i++) { if (r->lun[i].v64) { /* Look for non-zero LUN - we have where to choose from */ sdev->lun = r->lun[i].v16[0]; debug_print_int("Will use LUN", sdev->lun); - return; /* we have found a device */ + return 0; /* we have found a device */ } } } - panic("\n! Cannot locate virtio-scsi device !\n"); + + sclp_print("Warning: Could not locate a usable virtio-scsi device\n"); + return -ENODEV; } int virtio_scsi_read_many(VDev *vdev, @@ -322,17 +329,20 @@ static void scsi_parse_capacity_report(void *data, } } -void virtio_scsi_setup(VDev *vdev) +int virtio_scsi_setup(VDev *vdev) { int retry_test_unit_ready = 3; uint8_t data[256]; uint32_t data_size = sizeof(data); ScsiInquiryEvpdPages *evpd = &scsi_inquiry_evpd_pages_response; ScsiInquiryEvpdBl *evpd_bl = &scsi_inquiry_evpd_bl_response; - int i; + int i, ret; vdev->scsi_device = &default_scsi_device; - virtio_scsi_locate_device(vdev); + ret = virtio_scsi_locate_device(vdev); + if (ret < 0) { + return ret; + } /* We have to "ping" the device before it becomes readable */ while (!scsi_test_unit_ready(vdev)) { @@ -417,4 +427,6 @@ void virtio_scsi_setup(VDev *vdev) } scsi_parse_capacity_report(data, &vdev->scsi_last_block, (uint32_t *) &vdev->scsi_block_size); + + return 0; } diff --git a/pc-bios/s390-ccw/virtio-scsi.h b/pc-bios/s390-ccw/virtio-scsi.h index 4c4f4bbc31..4b14c2c2f9 100644 --- a/pc-bios/s390-ccw/virtio-scsi.h +++ b/pc-bios/s390-ccw/virtio-scsi.h @@ -67,7 +67,7 @@ static inline bool virtio_scsi_response_ok(const VirtioScsiCmdResp *r) return r->response == VIRTIO_SCSI_S_OK && r->status == CDB_STATUS_GOOD; } -void virtio_scsi_setup(VDev *vdev); +int virtio_scsi_setup(VDev *vdev); int virtio_scsi_read_many(VDev *vdev, ulong sector, void *load_addr, int sec_num); diff --git a/pc-bios/s390-netboot.img b/pc-bios/s390-netboot.img Binary files differindex d9c319604b..3dfce693f5 100644 --- a/pc-bios/s390-netboot.img +++ b/pc-bios/s390-netboot.img diff --git a/tests/qtest/cdrom-test.c b/tests/qtest/cdrom-test.c index e9afab693c..eef242dc80 100644 --- a/tests/qtest/cdrom-test.c +++ b/tests/qtest/cdrom-test.c @@ -163,6 +163,18 @@ static void add_s390x_tests(void) qtest_add_data_func("cdrom/boot/virtio-scsi", "-device virtio-scsi -device scsi-cd,drive=cdr " "-blockdev file,node-name=cdr,filename=", test_cdboot); + qtest_add_data_func("cdrom/boot/with-bootindex", + "-device virtio-serial -device virtio-scsi " + "-device virtio-blk,drive=d1 " + "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " + "-device virtio-blk,drive=d2,bootindex=1 " + "-drive if=none,id=d2,media=cdrom,file=", test_cdboot); + qtest_add_data_func("cdrom/boot/without-bootindex", + "-device virtio-scsi -device virtio-serial " + "-device x-terminal3270 -device virtio-blk,drive=d1 " + "-drive driver=null-co,read-zeroes=on,if=none,id=d1 " + "-device virtio-blk,drive=d2 " + "-drive if=none,id=d2,media=cdrom,file=", test_cdboot); } int main(int argc, char **argv) |