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>