Changeset View
Changeset View
Standalone View
Standalone View
head/sys/boot/efi/libefi/efipart.c
Show First 20 Lines • Show All 828 Lines • ▼ Show 20 Lines | if (blkio->Media->ReadOnly) | ||||
return (EROFS); | return (EROFS); | ||||
status = blkio->WriteBlocks(blkio, blkio->Media->MediaId, blk, | status = blkio->WriteBlocks(blkio, blkio->Media->MediaId, blk, | ||||
nblks * blkio->Media->BlockSize, buf); | nblks * blkio->Media->BlockSize, buf); | ||||
break; | break; | ||||
default: | default: | ||||
return (ENOSYS); | return (ENOSYS); | ||||
} | } | ||||
if (EFI_ERROR(status)) | if (EFI_ERROR(status)) { | ||||
printf("%s: rw=%d, status=%lu\n", __func__, rw, (u_long)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)); | return (efi_status_to_errno(status)); | ||||
} | } | ||||
static int | static int | ||||
efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size, | efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size, | ||||
char *buf, size_t *rsize) | char *buf, size_t *rsize) | ||||
{ | { | ||||
struct bcache_devdata bcd; | struct bcache_devdata bcd; | ||||
struct disk_devdesc *dev; | struct disk_devdesc *dev; | ||||
pdinfo_list_t *pdi; | pdinfo_list_t *pdi; | ||||
pdinfo_t *pd; | pdinfo_t *pd; | ||||
dev = (struct disk_devdesc *)devdata; | dev = (struct disk_devdesc *)devdata; | ||||
if (dev == NULL) | if (dev == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
pdi = efiblk_get_pdinfo_list(dev->d_dev); | pdi = efiblk_get_pdinfo_list(dev->d_dev); | ||||
if (pdi == NULL) | if (pdi == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
pd = efiblk_get_pdinfo(pdi, dev->d_unit); | pd = efiblk_get_pdinfo(pdi, dev->d_unit); | ||||
if (pd == NULL) | if (pd == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (pd->pd_blkio->Media->RemovableMedia && | |||||
!pd->pd_blkio->Media->MediaPresent) | |||||
return (EIO); | |||||
bcd.dv_strategy = efipart_realstrategy; | bcd.dv_strategy = efipart_realstrategy; | ||||
bcd.dv_devdata = devdata; | bcd.dv_devdata = devdata; | ||||
bcd.dv_cache = pd->pd_bcache; | bcd.dv_cache = pd->pd_bcache; | ||||
if (dev->d_dev->dv_type == DEVT_DISK) { | if (dev->d_dev->dv_type == DEVT_DISK) { | ||||
return (bcache_strategy(&bcd, rw, blk + dev->d_offset, | return (bcache_strategy(&bcd, rw, blk + dev->d_offset, | ||||
size, buf, rsize)); | size, buf, rsize)); | ||||
} | } | ||||
return (bcache_strategy(&bcd, rw, blk, size, buf, rsize)); | return (bcache_strategy(&bcd, rw, blk, size, buf, rsize)); | ||||
} | } | ||||
static int | static int | ||||
efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t size, | efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t size, | ||||
char *buf, size_t *rsize) | char *buf, size_t *rsize) | ||||
{ | { | ||||
struct disk_devdesc *dev = (struct disk_devdesc *)devdata; | struct disk_devdesc *dev = (struct disk_devdesc *)devdata; | ||||
pdinfo_list_t *pdi; | pdinfo_list_t *pdi; | ||||
pdinfo_t *pd; | pdinfo_t *pd; | ||||
EFI_BLOCK_IO *blkio; | EFI_BLOCK_IO *blkio; | ||||
off_t off; | uint64_t off, disk_blocks, d_offset = 0; | ||||
char *blkbuf; | char *blkbuf; | ||||
size_t blkoff, blksz; | size_t blkoff, blksz; | ||||
int error; | int error; | ||||
if (dev == NULL || blk < 0) | if (dev == NULL || blk < 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
pdi = efiblk_get_pdinfo_list(dev->d_dev); | pdi = efiblk_get_pdinfo_list(dev->d_dev); | ||||
if (pdi == NULL) | if (pdi == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
pd = efiblk_get_pdinfo(pdi, dev->d_unit); | pd = efiblk_get_pdinfo(pdi, dev->d_unit); | ||||
if (pd == NULL) | if (pd == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
blkio = pd->pd_blkio; | blkio = pd->pd_blkio; | ||||
if (blkio == NULL) | if (blkio == NULL) | ||||
return (ENXIO); | return (ENXIO); | ||||
if (size == 0 || (size % 512) != 0) | if (size == 0 || (size % 512) != 0) | ||||
return (EIO); | return (EIO); | ||||
off = blk * 512; | 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 */ | /* make sure we don't read past disk end */ | ||||
if ((off + size) / blkio->Media->BlockSize - 1 > | if ((off + size) / blkio->Media->BlockSize > d_offset + disk_blocks) { | ||||
blkio->Media->LastBlock) { | size = d_offset + disk_blocks - off / blkio->Media->BlockSize; | ||||
size = blkio->Media->LastBlock + 1 - | |||||
off / blkio->Media->BlockSize; | |||||
size = size * blkio->Media->BlockSize; | size = size * blkio->Media->BlockSize; | ||||
} | } | ||||
if (rsize != NULL) | if (rsize != NULL) | ||||
*rsize = size; | *rsize = size; | ||||
if ((size % blkio->Media->BlockSize == 0) && | if ((size % blkio->Media->BlockSize == 0) && | ||||
((blk * 512) % blkio->Media->BlockSize == 0)) | (off % blkio->Media->BlockSize == 0)) | ||||
return (efipart_readwrite(blkio, rw, | return (efipart_readwrite(blkio, rw, | ||||
blk * 512 / blkio->Media->BlockSize, | off / blkio->Media->BlockSize, | ||||
size / blkio->Media->BlockSize, buf)); | size / blkio->Media->BlockSize, buf)); | ||||
/* | /* | ||||
* The block size of the media is not a multiple of I/O. | * The block size of the media is not a multiple of I/O. | ||||
*/ | */ | ||||
blkbuf = malloc(blkio->Media->BlockSize); | blkbuf = malloc(blkio->Media->BlockSize); | ||||
if (blkbuf == NULL) | if (blkbuf == NULL) | ||||
return (ENOMEM); | return (ENOMEM); | ||||
Show All 22 Lines |