static int efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf, size_t *rsize) { struct devdesc *dev = (struct devdesc *)devdata; EFI_BLOCK_IO *blkio; off_t off; char *blkbuf; size_t blkoff, blksz; int error; if (dev == NULL || blk < 0) return (EINVAL); blkio = dev->d_opendata; if (blkio == NULL) return (ENXIO); if (size == 0 || (size % 512) != 0) return (EIO); if (rsize != NULL) *rsize = size; if (blkio->Media->BlockSize == 512) return (efipart_readwrite(blkio, rw, blk, size / 512, buf)); /* * The block size of the media is not 512B per sector. */ blkbuf = malloc(blkio->Media->BlockSize); if (blkbuf == NULL) return (ENOMEM); error = 0; off = blk * 512; blk = off / blkio->Media->BlockSize; blkoff = off % blkio->Media->BlockSize; blksz = blkio->Media->BlockSize - blkoff; while (size > 0) { error = efipart_readwrite(blkio, rw, blk, 1, blkbuf); if (error) break; if (size < blksz) blksz = size; bcopy(blkbuf + blkoff, buf, blksz); buf += blksz; size -= blksz; blk++; blkoff = 0; blksz = blkio->Media->BlockSize; } free(blkbuf); return (error); }
static int efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t offset, size_t size, char *buf, size_t *rsize) { struct devdesc *dev = (struct devdesc *)devdata; EFI_BLOCK_IO *blkio; off_t off; char *blkbuf; size_t blkoff, blksz; int error; if (dev == NULL || blk < 0) return (EINVAL); blkio = dev->d_opendata; if (blkio == NULL) return (ENXIO); if (size == 0 || (size % 512) != 0) return (EIO); off = blk * 512; /* 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; size = size * blkio->Media->BlockSize; } if (rsize != NULL) *rsize = size; if ((size % blkio->Media->BlockSize == 0) && ((blk * 512) % blkio->Media->BlockSize == 0)) return (efipart_readwrite(blkio, rw, blk * 512 / blkio->Media->BlockSize, size / blkio->Media->BlockSize, buf)); /* * The block size of the media is not a multiple of I/O. */ blkbuf = malloc(blkio->Media->BlockSize); if (blkbuf == NULL) return (ENOMEM); error = 0; blk = off / blkio->Media->BlockSize; blkoff = off % blkio->Media->BlockSize; blksz = blkio->Media->BlockSize - blkoff; while (size > 0) { error = efipart_readwrite(blkio, rw, blk, 1, blkbuf); if (error) break; if (size < blksz) blksz = size; bcopy(blkbuf + blkoff, buf, blksz); buf += blksz; size -= blksz; blk++; blkoff = 0; blksz = blkio->Media->BlockSize; } free(blkbuf); return (error); }