Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Mar 2017 16:23:31 +0000 (UTC)
From:      Toomas Soome <tsoome@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r316279 - head/sys/boot/efi/libefi
Message-ID:  <201703301623.v2UGNVuM056787@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tsoome
Date: Thu Mar 30 16:23:31 2017
New Revision: 316279
URL: https://svnweb.freebsd.org/changeset/base/316279

Log:
  loader: efipart should check disk size from partition table
  
  While testing 32bit UEFI OVMF (which has bug about how the disk size
  is presented), I did witness the errors from blkio->ReadBlocks().
  
  It became apparent we can not entirely trust UEFI interfaces either,
  so additional checks are needed.
  
  So we use disk_ioctl(DIOCGMEDIASIZE) for disks, with fallback of
  Media->LastBlock for other media.
  
  In addition, we need to check if there is media present.
  
  + small fixes for error printout, and avoiding multiple blk * 512.
  
  Reviewed by:	allanjude
  Approved by:	allanjude (mentor)
  Differential Revision:	https://reviews.freebsd.org/D10197

Modified:
  head/sys/boot/efi/libefi/efipart.c

Modified: head/sys/boot/efi/libefi/efipart.c
==============================================================================
--- head/sys/boot/efi/libefi/efipart.c	Thu Mar 30 16:03:51 2017	(r316278)
+++ head/sys/boot/efi/libefi/efipart.c	Thu Mar 30 16:23:31 2017	(r316279)
@@ -834,8 +834,10 @@ efipart_readwrite(EFI_BLOCK_IO *blkio, i
 		return (ENOSYS);
 	}
 
-	if (EFI_ERROR(status))
-		printf("%s: rw=%d, status=%lu\n", __func__, rw, (u_long)status);
+	if (EFI_ERROR(status)) {
+		printf("%s: rw=%d, blk=%ju size=%ju status=%lu\n", __func__, rw,
+		    blk, nblks, EFI_ERROR_CODE(status));
+	}
 	return (efi_status_to_errno(status));
 }
 
@@ -859,6 +861,10 @@ efipart_strategy(void *devdata, int rw, 
 	if (pd == NULL)
 		return (EINVAL);
 
+	if (pd->pd_blkio->Media->RemovableMedia &&
+	    !pd->pd_blkio->Media->MediaPresent)
+		return (EIO);
+
 	bcd.dv_strategy = efipart_realstrategy;
 	bcd.dv_devdata = devdata;
 	bcd.dv_cache = pd->pd_bcache;
@@ -878,7 +884,7 @@ efipart_realstrategy(void *devdata, int 
 	pdinfo_list_t *pdi;
 	pdinfo_t *pd;
 	EFI_BLOCK_IO *blkio;
-	off_t off;
+	uint64_t off, disk_blocks, d_offset = 0;
 	char *blkbuf;
 	size_t blkoff, blksz;
 	int error;
@@ -902,11 +908,24 @@ efipart_realstrategy(void *devdata, int 
 		return (EIO);
 
 	off = blk * 512;
+	/*
+	 * Get disk blocks, this value is either for whole disk or for
+	 * partition.
+	 */
+	disk_blocks = 0;
+	if (dev->d_dev->dv_type == DEVT_DISK) {
+		if (disk_ioctl(dev, DIOCGMEDIASIZE, &disk_blocks) == 0) {
+			/* DIOCGMEDIASIZE does return bytes. */
+			disk_blocks /= blkio->Media->BlockSize;
+		}
+		d_offset = dev->d_offset;
+	}
+	if (disk_blocks == 0)
+		disk_blocks = blkio->Media->LastBlock + 1 - d_offset;
+
 	/* make sure we don't read past disk end */
-	if ((off + size) / blkio->Media->BlockSize - 1 >
-	    blkio->Media->LastBlock) {
-		size = blkio->Media->LastBlock + 1 -
-		    off / blkio->Media->BlockSize;
+	if ((off + size) / blkio->Media->BlockSize > d_offset + disk_blocks) {
+		size = d_offset + disk_blocks - off / blkio->Media->BlockSize;
 		size = size * blkio->Media->BlockSize;
 	}
 
@@ -914,9 +933,9 @@ efipart_realstrategy(void *devdata, int 
 		*rsize = size;
 
 	if ((size % blkio->Media->BlockSize == 0) &&
-	    ((blk * 512) % blkio->Media->BlockSize == 0))
+	    (off % blkio->Media->BlockSize == 0))
 		return (efipart_readwrite(blkio, rw,
-		    blk * 512 / blkio->Media->BlockSize,
+		    off / blkio->Media->BlockSize,
 		    size / blkio->Media->BlockSize, buf));
 
 	/*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703301623.v2UGNVuM056787>