From f04db28b86654d1c7ff805b40eff27bba6b0f686 Mon Sep 17 00:00:00 2001 From: "Eugene (jno) Dvurechenski" Date: Fri, 29 Aug 2014 11:01:39 +0200 Subject: pc-bios/s390-ccw Really big EAV ECKD DASD handling For EAV ECKD DASD, the cylinder count will have the magic value 0xfffeU. Therefore, use the block number to test for valid eckd addresses instead. Signed-off-by: Eugene (jno) Dvurechenski Acked-by: Cornelia Huck Acked-by: Christian Borntraeger Reviewed-by: David Hildenbrand Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- pc-bios/s390-ccw/bootmap.c | 31 +++++++++++++++---------------- pc-bios/s390-ccw/virtio.c | 11 ++++++----- pc-bios/s390-ccw/virtio.h | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'pc-bios') diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index e4352b1..d4c579c 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -93,11 +93,23 @@ static inline void verify_boot_info(BootInfo *bip) "Bad block size in zIPL section of the 1st record."); } -static bool eckd_valid_address(BootMapPointer *p) +static block_number_t eckd_block_num(BootMapPointer *p) { + const uint64_t sectors = virtio_get_sectors(); + const uint64_t heads = virtio_get_heads(); const uint64_t cylinder = p->eckd.cylinder + ((p->eckd.head & 0xfff0) << 12); const uint64_t head = p->eckd.head & 0x000f; + const block_number_t block = sectors * heads * cylinder + + sectors * head + + p->eckd.sector + - 1; /* block nr starts with zero */ + return block; +} + +static bool eckd_valid_address(BootMapPointer *p) +{ + const uint64_t head = p->eckd.head & 0x000f; if (head >= virtio_get_heads() || p->eckd.sector > virtio_get_sectors() @@ -105,27 +117,14 @@ static bool eckd_valid_address(BootMapPointer *p) return false; } - if (!virtio_guessed_disk_nature() && cylinder >= virtio_get_cylinders()) { + if (!virtio_guessed_disk_nature() && + eckd_block_num(p) >= virtio_get_blocks()) { return false; } return true; } -static block_number_t eckd_block_num(BootMapPointer *p) -{ - const uint64_t sectors = virtio_get_sectors(); - const uint64_t heads = virtio_get_heads(); - const uint64_t cylinder = p->eckd.cylinder - + ((p->eckd.head & 0xfff0) << 12); - const uint64_t head = p->eckd.head & 0x000f; - const block_number_t block = sectors * heads * cylinder - + sectors * head - + p->eckd.sector - - 1; /* block nr starts with zero */ - return block; -} - static block_number_t load_eckd_segments(block_number_t blk, uint64_t *address) { block_number_t block_nr; diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c index 6ed3dc9..c0540d1 100644 --- a/pc-bios/s390-ccw/virtio.c +++ b/pc-bios/s390-ccw/virtio.c @@ -340,11 +340,6 @@ int virtio_get_block_size(void) return blk_cfg.blk_size << blk_cfg.physical_block_exp; } -uint16_t virtio_get_cylinders(void) -{ - return blk_cfg.geometry.cylinders; -} - uint8_t virtio_get_heads(void) { return blk_cfg.geometry.heads; @@ -355,6 +350,12 @@ uint8_t virtio_get_sectors(void) return blk_cfg.geometry.sectors; } +uint64_t virtio_get_blocks(void) +{ + return blk_cfg.capacity / + (virtio_get_block_size() / VIRTIO_SECTOR_SIZE); +} + void virtio_setup_block(struct subchannel_id schid) { struct vq_info_block info; diff --git a/pc-bios/s390-ccw/virtio.h b/pc-bios/s390-ccw/virtio.h index f1fb1b0..c23466b 100644 --- a/pc-bios/s390-ccw/virtio.h +++ b/pc-bios/s390-ccw/virtio.h @@ -192,9 +192,9 @@ extern bool virtio_disk_is_scsi(void); extern bool virtio_disk_is_eckd(void); extern bool virtio_ipl_disk_is_valid(void); extern int virtio_get_block_size(void); -extern uint16_t virtio_get_cylinders(void); extern uint8_t virtio_get_heads(void); extern uint8_t virtio_get_sectors(void); +extern uint64_t virtio_get_blocks(void); extern int virtio_read_many(ulong sector, void *load_addr, int sec_num); #define VIRTIO_SECTOR_SIZE 512 -- cgit v1.1