FreeBSD/sys/boot/i386/zfsboot/zfsboot.c
/*
 * A wrapper for dskread that doesn't have to worry about whether the
 * buffer pointer crosses a 64k boundary.
 */
A wrapper for dskread that doesn't have to worry about whether the
buffer pointer crosses a 64k boundary.
A wrapper for dskread that doesn ' t have to worry about whether the buffer pointer crosses a 64k boundary .
static int
vdev_read(vdev_t *vdev, void *priv, off_t off, void *buf, size_t bytes)
{
	char *p;
	daddr_t lba, alignlba;
	off_t diff;
	unsigned int nb, alignnb;
	struct dsk *dsk = (struct dsk *) priv;
	if ((off & (DEV_BSIZE - 1)) || (bytes & (DEV_BSIZE - 1)))
		return -1;
	p = buf;
	lba = off / DEV_BSIZE;
	lba += dsk->start;
	alignlba = rounddown2(off, DEV_GELIBOOT_BSIZE) / DEV_BSIZE;
	alignlba += dsk->start;
	diff = (lba - alignlba) * DEV_BSIZE;
	while (bytes > 0) {
		nb = bytes / DEV_BSIZE;
		if (nb > (READ_BUF_SIZE - diff) / DEV_BSIZE)
			nb = (READ_BUF_SIZE - diff) / DEV_BSIZE;
		alignnb = roundup2(nb * DEV_BSIZE + diff, DEV_GELIBOOT_BSIZE)
		    / DEV_BSIZE;
		if (drvread(dsk, dmadat->rdbuf, alignlba, alignnb))
			return -1;
#ifdef LOADER_GELI_SUPPORT
		if (is_geli(dsk) == 0) {
			if (geli_read(dsk, ((alignlba - dsk->start) *
			    DEV_BSIZE), dmadat->rdbuf, alignnb * DEV_BSIZE))
				return (-1);
		}
#endif
		memcpy(p, dmadat->rdbuf + diff, nb * DEV_BSIZE);
		p += nb * DEV_BSIZE;
		lba += nb;
		alignlba += alignnb;
		bytes -= nb * DEV_BSIZE;
		diff = 0;
	}
	return 0;
}
static int vdev_read ( vdev_t * vdev , void * priv , off_t off , void * buf , size_t bytes ) { char * p ; daddr_t lba , alignlba ; off_t diff ; unsigned int nb , alignnb ; struct dsk * dsk = ( struct dsk * ) priv ; if ( ( off & ( DEV_BSIZE - 1 ) ) || ( bytes & ( DEV_BSIZE - 1 ) ) ) return -1 ; p = buf ; lba = off / DEV_BSIZE ; lba += dsk -> start ; alignlba = rounddown2 ( off , DEV_GELIBOOT_BSIZE ) / DEV_BSIZE ; alignlba += dsk -> start ; diff = ( lba - alignlba ) * DEV_BSIZE ; while ( bytes > 0 ) { nb = bytes / DEV_BSIZE ; if ( nb > ( READ_BUF_SIZE - diff ) / DEV_BSIZE ) nb = ( READ_BUF_SIZE - diff ) / DEV_BSIZE ; alignnb = roundup2 ( nb * DEV_BSIZE + diff , DEV_GELIBOOT_BSIZE ) / DEV_BSIZE ; if ( drvread ( dsk , dmadat -> rdbuf , alignlba , alignnb ) ) return -1 ; #ifdef LOADER_GELI_SUPPORT if ( is_geli ( dsk ) == 0 ) { if ( geli_read ( dsk , ( ( alignlba - dsk -> start ) * DEV_BSIZE ) , dmadat -> rdbuf , alignnb * DEV_BSIZE ) ) return ( -1 ) ; } #endif memcpy ( p , dmadat -> rdbuf + diff , nb * DEV_BSIZE ) ; p += nb * DEV_BSIZE ; lba += nb ; alignlba += alignnb ; bytes -= nb * DEV_BSIZE ; diff = 0 ; } return 0 ; }
A wrapper for dskread that doesn't have to worry about whether the
 buffer pointer crosses a 64k boundary.
A wrapper for dskread that doesn ' t have to worry about whether the buffer pointer crosses a 64k boundary .
/*
	 * Align reads to 4k else 4k sector GELIs will not decrypt.
	 * Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes.
	 */ /*
	 * The read must be aligned to DEV_GELIBOOT_BSIZE bytes relative to the
	 * start of the GELI partition, not the start of the actual disk.
	 */ /*
		 * Ensure that the read size plus the leading offset does not
		 * exceed the size of the read buffer.
		 */ /*
		 * Round the number of blocks to read up to the nearest multiple
		 * of DEV_GELIBOOT_BSIZE.
		 */ /* decrypt */ /* Don't need the leading offset after the first block. */