Index: sys/boot/i386/libi386/biosdisk.c =================================================================== --- sys/boot/i386/libi386/biosdisk.c +++ sys/boot/i386/libi386/biosdisk.c @@ -746,21 +746,29 @@ * sectors cannot be decrypted. Round the requested LBA down to * nearest multiple of DEV_GELIBOOT_BSIZE bytes. */ - alignlba = dblk & - ~(daddr_t)((DEV_GELIBOOT_BSIZE / BIOSDISK_SECSIZE) - 1); + alignlba = rounddown2(dblk * BIOSDISK_SECSIZE, + DEV_GELIBOOT_BSIZE) / BIOSDISK_SECSIZE; /* * Round number of blocks to read up to nearest multiple of * DEV_GELIBOOT_BSIZE */ - alignblks = blks + (dblk - alignlba) + - ((DEV_GELIBOOT_BSIZE / BIOSDISK_SECSIZE) - 1) & - ~(int)((DEV_GELIBOOT_BSIZE / BIOSDISK_SECSIZE) - 1); diff = (dblk - alignlba) * BIOSDISK_SECSIZE; + alignblks = roundup2(blks * BIOSDISK_SECSIZE + diff, + DEV_GELIBOOT_BSIZE) / BIOSDISK_SECSIZE; + /* - * Use a temporary buffer here because the buffer provided by - * the caller may be too small. + * If the read is rounded up to a larger size, use a temporary + * buffer here because the buffer provided by the caller may be + * too small. */ - tmpbuf = alloca(alignblks * BIOSDISK_SECSIZE); + if (diff == 0) { + tmpbuf = dest; + } else { + tmpbuf = malloc(alignblks * BIOSDISK_SECSIZE); + if (tmpbuf == NULL) { + return (1); + } + } err = bd_io(dev, alignlba, alignblks, tmpbuf, 0); if (err) @@ -781,7 +789,10 @@ if (err) return (err); - bcopy(tmpbuf + diff, dest, blks * BIOSDISK_SECSIZE); + if (tmpbuf != dest) { + bcopy(tmpbuf + diff, dest, blks * BIOSDISK_SECSIZE); + free(tmpbuf); + } return (0); } #endif /* LOADER_GELI_SUPPORT */ Index: sys/boot/i386/zfsboot/zfsboot.c =================================================================== --- sys/boot/i386/zfsboot/zfsboot.c +++ sys/boot/i386/zfsboot/zfsboot.c @@ -201,7 +201,7 @@ { char *p; daddr_t lba, alignlba; - off_t alignoff, diff; + off_t diff; unsigned int nb, alignnb; struct dsk *dsk = (struct dsk *) priv; @@ -211,10 +211,11 @@ p = buf; lba = off / DEV_BSIZE; lba += dsk->start; - /* Align reads to 4k else 4k sector GELIs will not decrypt. */ - alignoff = off & ~ (off_t)(DEV_GELIBOOT_BSIZE - 1); - /* Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes. */ - alignlba = alignoff / DEV_BSIZE; + /* + * Align reads to 4k else 4k sector GELIs will not decrypt. + * Round LBA down to nearest multiple of DEV_GELIBOOT_BSIZE bytes. + */ + alignlba = rounddown2(off, DEV_GELIBOOT_BSIZE) / DEV_BSIZE; /* * 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.