Changeset View
Changeset View
Standalone View
Standalone View
sys/boot/efi/libefi/efipart.c
Show All 36 Lines | |||||
#include <bootstrap.h> | #include <bootstrap.h> | ||||
#include <efi.h> | #include <efi.h> | ||||
#include <efilib.h> | #include <efilib.h> | ||||
#include <efiprot.h> | #include <efiprot.h> | ||||
#include <disk.h> | #include <disk.h> | ||||
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; | static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; | ||||
static EFI_GUID FreeBSDGELIGUID = FREEBSD_GELI_GUID; | |||||
static int efipart_initfd(void); | static int efipart_initfd(void); | ||||
static int efipart_initcd(void); | static int efipart_initcd(void); | ||||
static int efipart_inithd(void); | static int efipart_inithd(void); | ||||
static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *); | static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *); | ||||
static int efipart_realstrategy(void *, int, daddr_t, size_t, char *, size_t *); | static int efipart_realstrategy(void *, int, daddr_t, size_t, char *, size_t *); | ||||
▲ Show 20 Lines • Show All 293 Lines • ▼ Show 20 Lines | efipart_initcd(void) | ||||
STAILQ_INIT(&cdinfo); | STAILQ_INIT(&cdinfo); | ||||
efipart_updatecd(); | efipart_updatecd(); | ||||
bcache_add_dev(efiblk_pdinfo_count(&cdinfo)); | bcache_add_dev(efiblk_pdinfo_count(&cdinfo)); | ||||
return (0); | return (0); | ||||
} | } | ||||
static size_t | |||||
wcslen(const CHAR16 *s) | |||||
{ | |||||
size_t len; | |||||
for(len = 0; s[len] != '\0'; len++); | |||||
return len; | |||||
} | |||||
static void | |||||
efifs_dev_print(EFI_DEVICE_PATH *devpath) | |||||
{ | |||||
CHAR16 *name16; | |||||
name16 = efi_devpath_name(devpath); | |||||
char buf[wcslen(name16) + 1]; | |||||
memset(buf, 0, sizeof buf); | |||||
cpy16to8(name16, buf, wcslen(name16)); | |||||
printf("%s\n", buf); | |||||
} | |||||
static int | static int | ||||
efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle) | efipart_hdinfo_add(EFI_HANDLE disk_handle, EFI_HANDLE part_handle) | ||||
{ | { | ||||
EFI_DEVICE_PATH *disk_devpath, *part_devpath; | EFI_DEVICE_PATH *disk_devpath, *part_devpath, *trimpath, *lastnode; | ||||
VENDOR_DEVICE_PATH *vendornode; | |||||
HARDDRIVE_DEVICE_PATH *node; | HARDDRIVE_DEVICE_PATH *node; | ||||
int unit; | int unit; | ||||
pdinfo_t *hd, *pd, *last; | pdinfo_t *hd, *pd, *pp, *last; | ||||
disk_devpath = efi_lookup_devpath(disk_handle); | disk_devpath = efi_lookup_devpath(disk_handle); | ||||
part_devpath = efi_lookup_devpath(part_handle); | part_devpath = efi_lookup_devpath(part_handle); | ||||
if (disk_devpath == NULL || part_devpath == NULL) { | if (disk_devpath == NULL || part_devpath == NULL) { | ||||
return (ENOENT); | return (ENOENT); | ||||
} | } | ||||
node = (HARDDRIVE_DEVICE_PATH *)efi_devpath_last_node(part_devpath); | |||||
if (node == NULL) | /* Get the disk partition node */ | ||||
lastnode = efi_devpath_last_node(part_devpath); | |||||
if (lastnode == NULL) | |||||
allanjude: looks like you renamed 'node' to 'lastnode', but are checking 'node' for NULL, and it is never… | |||||
return (ENOENT); /* This should not happen. */ | return (ENOENT); /* This should not happen. */ | ||||
if (DevicePathType(lastnode) == MEDIA_DEVICE_PATH) { | |||||
if (DevicePathSubType(lastnode) == MEDIA_VENDOR_DP) { | |||||
vendornode = (VENDOR_DEVICE_PATH *)lastnode; | |||||
/* We only want GELI partitions */ | |||||
if (memcmp(&(vendornode->Guid), &FreeBSDGELIGUID, | |||||
sizeof(EFI_GUID))) { | |||||
return (EINVAL); | |||||
} | |||||
/* Trim off the vendor node */ | |||||
trimpath = efi_devpath_trim(part_devpath); | |||||
if (trimpath == NULL) | |||||
return (ENOENT); | |||||
lastnode = efi_devpath_last_node(trimpath); | |||||
if (lastnode == NULL) | |||||
return (ENOENT); | |||||
node = (HARDDRIVE_DEVICE_PATH *)lastnode; | |||||
} else if (DevicePathSubType(lastnode) == MEDIA_HARDDRIVE_DP) { | |||||
node = (HARDDRIVE_DEVICE_PATH *)lastnode; | |||||
} | |||||
else | |||||
return (EINVAL); | |||||
} else { | |||||
return (EINVAL); | |||||
} | |||||
pd = malloc(sizeof(pdinfo_t)); | pd = malloc(sizeof(pdinfo_t)); | ||||
if (pd == NULL) { | if (pd == NULL) { | ||||
printf("Failed to add disk, out of memory\n"); | printf("Failed to add disk, out of memory\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
memset(pd, 0, sizeof(pdinfo_t)); | memset(pd, 0, sizeof(pdinfo_t)); | ||||
STAILQ_INIT(&pd->pd_part); | STAILQ_INIT(&pd->pd_part); | ||||
STAILQ_FOREACH(hd, &hdinfo, pd_link) { | STAILQ_FOREACH(hd, &hdinfo, pd_link) { | ||||
if (efi_devpath_match(hd->pd_devpath, disk_devpath) != 0) { | if (efi_devpath_match(hd->pd_devpath, disk_devpath) != 0) { | ||||
/* Check if there's a related device entry | |||||
* already here. | |||||
*/ | |||||
STAILQ_FOREACH(pp, &hd->pd_part, pd_link) { | |||||
/* If the new device is a subpath of | |||||
* an existing device, then the | |||||
* existing entry subsumes the new | |||||
* one. | |||||
*/ | |||||
trimpath = efi_devpath_trim(pp->pd_devpath); | |||||
if (trimpath == NULL) | |||||
return (ENOMEM); | |||||
if (efi_devpath_match(trimpath, | |||||
part_devpath) != 0) { | |||||
free(trimpath); | |||||
free(pd); | |||||
return (EBUSY); | |||||
} | |||||
/* If the existing device path is a | |||||
* subpath of the new one, then the | |||||
* new entry subsumes the existing | |||||
* one. | |||||
*/ | |||||
free(trimpath); | |||||
trimpath = efi_devpath_trim(part_devpath); | |||||
if (trimpath == NULL) | |||||
return (ENOMEM); | |||||
if (efi_devpath_match(trimpath, | |||||
pp->pd_devpath) != 0) { | |||||
pp->pd_handle = part_handle; | |||||
pp->pd_devpath = part_devpath; | |||||
free(trimpath); | |||||
free(pd); | |||||
return (0); | |||||
} | |||||
free(trimpath); | |||||
} | |||||
/* Add the partition. */ | /* Add the partition. */ | ||||
pd->pd_handle = part_handle; | pd->pd_handle = part_handle; | ||||
pd->pd_unit = node->PartitionNumber; | pd->pd_unit = node->PartitionNumber; | ||||
pd->pd_devpath = part_devpath; | pd->pd_devpath = part_devpath; | ||||
STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link); | STAILQ_INSERT_TAIL(&hd->pd_part, pd, pd_link); | ||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | efipart_updatehd(void) | ||||
EFI_BLOCK_IO *blkio; | EFI_BLOCK_IO *blkio; | ||||
EFI_STATUS status; | EFI_STATUS status; | ||||
nin = efipart_nhandles / sizeof (*efipart_handles); | nin = efipart_nhandles / sizeof (*efipart_handles); | ||||
for (i = 0; i < nin; i++) { | for (i = 0; i < nin; i++) { | ||||
devpath = efi_lookup_devpath(efipart_handles[i]); | devpath = efi_lookup_devpath(efipart_handles[i]); | ||||
if (devpath == NULL) | if (devpath == NULL) | ||||
continue; | continue; | ||||
if ((node = efi_devpath_last_node(devpath)) == NULL) | if ((node = efi_devpath_last_node(devpath)) == NULL) | ||||
continue; | continue; | ||||
if (efipart_floppy(node) != NULL) | if (efipart_floppy(node) != NULL) | ||||
continue; | continue; | ||||
status = BS->HandleProtocol(efipart_handles[i], | status = BS->HandleProtocol(efipart_handles[i], | ||||
&blkio_guid, (void **)&blkio); | &blkio_guid, (void **)&blkio); | ||||
if (EFI_ERROR(status)) | if (EFI_ERROR(status)) | ||||
continue; | continue; | ||||
/* Handle GELI volumes */ | |||||
if (DevicePathType(node) == MEDIA_DEVICE_PATH && | if (DevicePathType(node) == MEDIA_DEVICE_PATH && | ||||
DevicePathSubType(node) == MEDIA_VENDOR_DP) { | |||||
VENDOR_DEVICE_PATH *vendornode; | |||||
vendornode = (VENDOR_DEVICE_PATH *)node; | |||||
/* We only want GELI partitions */ | |||||
if (memcmp(&(vendornode->Guid), &FreeBSDGELIGUID, | |||||
sizeof(EFI_GUID))) { | |||||
continue; | |||||
} | |||||
/* Trim off the vendor node */ | |||||
devpathcpy = efi_devpath_trim(devpath); | |||||
if (devpathcpy == NULL) | |||||
continue; | |||||
if ((node = efi_devpath_last_node(devpathcpy)) == NULL) | |||||
continue; | |||||
devpath = devpathcpy; | |||||
} | |||||
if (DevicePathType(node) == MEDIA_DEVICE_PATH && | |||||
DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) { | DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) { | ||||
devpathcpy = efi_devpath_trim(devpath); | devpathcpy = efi_devpath_trim(devpath); | ||||
if (devpathcpy == NULL) | if (devpathcpy == NULL) | ||||
continue; | continue; | ||||
tmpdevpath = devpathcpy; | tmpdevpath = devpathcpy; | ||||
status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath, | status = BS->LocateDevicePath(&blkio_guid, &tmpdevpath, | ||||
&handle); | &handle); | ||||
free(devpathcpy); | free(devpathcpy); | ||||
if (EFI_ERROR(status)) | if (EFI_ERROR(status)) | ||||
continue; | continue; | ||||
/* | /* | ||||
* We do not support nested partitions. | * We do not support nested partitions. | ||||
*/ | */ | ||||
devpathcpy = efi_lookup_devpath(handle); | devpathcpy = efi_lookup_devpath(handle); | ||||
if (devpathcpy == NULL) | if (devpathcpy == NULL) | ||||
continue; | continue; | ||||
if ((node = efi_devpath_last_node(devpathcpy)) == NULL) | if ((node = efi_devpath_last_node(devpathcpy)) == NULL) | ||||
continue; | continue; | ||||
if (DevicePathType(node) == MEDIA_DEVICE_PATH && | if (DevicePathType(node) == MEDIA_DEVICE_PATH && | ||||
DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) | DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) | ||||
continue; | continue; | ||||
efipart_hdinfo_add(handle, efipart_handles[i]); | efipart_hdinfo_add(handle, efipart_handles[i]); | ||||
continue; | continue; | ||||
} | } | ||||
if (DevicePathType(node) == MEDIA_DEVICE_PATH && | if (DevicePathType(node) == MEDIA_DEVICE_PATH && | ||||
DevicePathSubType(node) == MEDIA_FILEPATH_DP) { | DevicePathSubType(node) == MEDIA_FILEPATH_DP) { | ||||
efipart_hdinfo_add_filepath(efipart_handles[i]); | efipart_hdinfo_add_filepath(efipart_handles[i]); | ||||
continue; | continue; | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | if (!EFI_ERROR(status)) { | ||||
continue; | continue; | ||||
pd->pd_blkio = blkio; | pd->pd_blkio = blkio; | ||||
pd_dev.d_dev = dev; | pd_dev.d_dev = dev; | ||||
pd_dev.d_unit = pd->pd_unit; | pd_dev.d_unit = pd->pd_unit; | ||||
pd_dev.d_slice = -1; | pd_dev.d_slice = -1; | ||||
pd_dev.d_partition = -1; | pd_dev.d_partition = -1; | ||||
pd_dev.d_opendata = blkio; | pd_dev.d_opendata = blkio; | ||||
ret = disk_open(&pd_dev, blkio->Media->BlockSize * | |||||
(blkio->Media->LastBlock + 1), | |||||
blkio->Media->BlockSize); | |||||
if (ret == 0) { | |||||
ret = disk_print(&pd_dev, line, verbose); | |||||
disk_close(&pd_dev); | |||||
if (ret != 0) | |||||
return (ret); | |||||
} else { | } else { | ||||
/* Do not fail from disk_open() */ | |||||
ret = 0; | |||||
} | |||||
} else { | |||||
if ((ret = pager_output("\n")) != 0) | if ((ret = pager_output("\n")) != 0) | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
return (ret); | return (ret); | ||||
} | } | ||||
static int | static int | ||||
Show All 12 Lines | |||||
efipart_printhd(int verbose) | efipart_printhd(int verbose) | ||||
{ | { | ||||
return (efipart_print_common(&efipart_hddev, &hdinfo, verbose)); | return (efipart_print_common(&efipart_hddev, &hdinfo, verbose)); | ||||
} | } | ||||
pdinfo_list_t * | pdinfo_list_t * | ||||
efiblk_get_pdinfo_list(struct devsw *dev) | efiblk_get_pdinfo_list(struct devsw *dev) | ||||
{ | { | ||||
if (dev->dv_type == DEVT_DISK) | if (dev->dv_type == DEVT_DISK) | ||||
return (&hdinfo); | return (&hdinfo); | ||||
if (dev->dv_type == DEVT_CD) | if (dev->dv_type == DEVT_CD) | ||||
return (&cdinfo); | return (&cdinfo); | ||||
if (dev->dv_type == DEVT_FD) | if (dev->dv_type == DEVT_FD) | ||||
return (&fdinfo); | return (&fdinfo); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
static int | static int | ||||
efipart_lookupdev(struct disk_devdesc *dev, pdinfo_t **pp) | |||||
{ | |||||
pdinfo_list_t *pdi; | |||||
pdinfo_t *pd; | |||||
if (dev == NULL) { | |||||
return (EINVAL); | |||||
} | |||||
pdi = efiblk_get_pdinfo_list(dev->d_dev); | |||||
if (pdi == NULL) { | |||||
return (EINVAL); | |||||
} | |||||
pd = efiblk_get_pdinfo(pdi, dev->d_unit); | |||||
if (pd == NULL) { | |||||
return (EIO); | |||||
} | |||||
/* If we're looking up a specific partition, get the | |||||
* IO interface from that devide handle. | |||||
*/ | |||||
if (dev->d_slice != -1) { | |||||
pd = efiblk_get_pdinfo(&pd->pd_part, dev->d_slice); | |||||
} | |||||
*pp = pd; | |||||
return (0); | |||||
} | |||||
static int | |||||
efipart_open(struct open_file *f, ...) | efipart_open(struct open_file *f, ...) | ||||
{ | { | ||||
va_list args; | va_list args; | ||||
struct disk_devdesc *dev; | struct disk_devdesc *dev; | ||||
pdinfo_list_t *pdi; | |||||
pdinfo_t *pd; | pdinfo_t *pd; | ||||
EFI_BLOCK_IO *blkio; | EFI_BLOCK_IO *blkio; | ||||
EFI_STATUS status; | EFI_STATUS status; | ||||
int err; | |||||
va_start(args, f); | va_start(args, f); | ||||
dev = va_arg(args, struct disk_devdesc*); | dev = va_arg(args, struct disk_devdesc*); | ||||
va_end(args); | va_end(args); | ||||
if (dev == NULL) | |||||
return (EINVAL); | |||||
pdi = efiblk_get_pdinfo_list(dev->d_dev); | if ((err = efipart_lookupdev(dev, &pd)) != 0) { | ||||
if (pdi == NULL) | return (err); | ||||
return (EINVAL); | } | ||||
pd = efiblk_get_pdinfo(pdi, dev->d_unit); | |||||
if (pd == NULL) | |||||
return (EIO); | |||||
if (pd->pd_blkio == NULL) { | if (pd->pd_blkio == NULL) { | ||||
status = BS->HandleProtocol(pd->pd_handle, &blkio_guid, | status = BS->HandleProtocol(pd->pd_handle, &blkio_guid, | ||||
(void **)&pd->pd_blkio); | (void **)&pd->pd_blkio); | ||||
if (EFI_ERROR(status)) | if (EFI_ERROR(status)) | ||||
return (efi_status_to_errno(status)); | return (efi_status_to_errno(status)); | ||||
} | } | ||||
blkio = pd->pd_blkio; | blkio = pd->pd_blkio; | ||||
if (!blkio->Media->MediaPresent) | if (!blkio->Media->MediaPresent) { | ||||
return (EAGAIN); | return (EAGAIN); | ||||
} | |||||
pd->pd_open++; | pd->pd_open++; | ||||
if (pd->pd_bcache == NULL) | if (pd->pd_bcache == NULL) | ||||
pd->pd_bcache = bcache_allocate(); | pd->pd_bcache = bcache_allocate(); | ||||
if (dev->d_dev->dv_type == DEVT_DISK) { | dev->d_offset = 0; | ||||
return (disk_open(dev, | |||||
blkio->Media->BlockSize * (blkio->Media->LastBlock + 1), | |||||
blkio->Media->BlockSize)); | |||||
} | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
efipart_close(struct open_file *f) | efipart_close(struct open_file *f) | ||||
{ | { | ||||
struct disk_devdesc *dev; | struct disk_devdesc *dev; | ||||
pdinfo_list_t *pdi; | |||||
pdinfo_t *pd; | pdinfo_t *pd; | ||||
int err; | |||||
dev = (struct disk_devdesc *)(f->f_devdata); | dev = (struct disk_devdesc *)(f->f_devdata); | ||||
if (dev == NULL) | if ((err = efipart_lookupdev(dev, &pd)) != 0) { | ||||
return (EINVAL); | return (err); | ||||
pdi = efiblk_get_pdinfo_list(dev->d_dev); | } | ||||
if (pdi == NULL) | |||||
return (EINVAL); | |||||
pd = efiblk_get_pdinfo(pdi, dev->d_unit); | |||||
if (pd == NULL) | |||||
return (EINVAL); | |||||
pd->pd_open--; | pd->pd_open--; | ||||
if (pd->pd_open == 0) { | if (pd->pd_open == 0) { | ||||
pd->pd_blkio = NULL; | pd->pd_blkio = NULL; | ||||
bcache_free(pd->pd_bcache); | bcache_free(pd->pd_bcache); | ||||
pd->pd_bcache = NULL; | pd->pd_bcache = NULL; | ||||
} | } | ||||
if (dev->d_dev->dv_type == DEVT_DISK) | |||||
return (disk_close(dev)); | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
efipart_ioctl(struct open_file *f, u_long cmd, void *data) | efipart_ioctl(struct open_file *f, u_long cmd, void *data) | ||||
{ | { | ||||
struct disk_devdesc *dev; | struct disk_devdesc *dev; | ||||
pdinfo_list_t *pdi; | |||||
pdinfo_t *pd; | pdinfo_t *pd; | ||||
int rc; | int err; | ||||
dev = (struct disk_devdesc *)(f->f_devdata); | dev = (struct disk_devdesc *)(f->f_devdata); | ||||
if (dev == NULL) | if ((err = efipart_lookupdev(dev, &pd)) != 0) { | ||||
return (EINVAL); | return (err); | ||||
pdi = efiblk_get_pdinfo_list(dev->d_dev); | |||||
if (pdi == NULL) | |||||
return (EINVAL); | |||||
pd = efiblk_get_pdinfo(pdi, dev->d_unit); | |||||
if (pd == NULL) | |||||
return (EINVAL); | |||||
if (dev->d_dev->dv_type == DEVT_DISK) { | |||||
rc = disk_ioctl(dev, cmd, data); | |||||
if (rc != ENOTTY) | |||||
return (rc); | |||||
} | } | ||||
switch (cmd) { | switch (cmd) { | ||||
case DIOCGSECTORSIZE: | case DIOCGSECTORSIZE: | ||||
*(u_int *)data = pd->pd_blkio->Media->BlockSize; | *(u_int *)data = pd->pd_blkio->Media->BlockSize; | ||||
break; | break; | ||||
case DIOCGMEDIASIZE: | case DIOCGMEDIASIZE: | ||||
*(uint64_t *)data = pd->pd_blkio->Media->BlockSize * | *(uint64_t *)data = pd->pd_blkio->Media->BlockSize * | ||||
(pd->pd_blkio->Media->LastBlock + 1); | (pd->pd_blkio->Media->LastBlock + 1); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
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_t *pd; | pdinfo_t *pd; | ||||
int err; | |||||
dev = (struct disk_devdesc *)devdata; | dev = (struct disk_devdesc *)devdata; | ||||
if (dev == NULL) | if ((err = efipart_lookupdev(dev, &pd)) != 0) { | ||||
return (EINVAL); | return (err); | ||||
pdi = efiblk_get_pdinfo_list(dev->d_dev); | } | ||||
if (pdi == NULL) | |||||
return (EINVAL); | |||||
pd = efiblk_get_pdinfo(pdi, dev->d_unit); | |||||
if (pd == NULL) | |||||
return (EINVAL); | |||||
if (pd->pd_blkio->Media->RemovableMedia && | if (pd->pd_blkio->Media->RemovableMedia && | ||||
!pd->pd_blkio->Media->MediaPresent) | !pd->pd_blkio->Media->MediaPresent) | ||||
return (EIO); | 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_t *pd; | pdinfo_t *pd; | ||||
EFI_BLOCK_IO *blkio; | EFI_BLOCK_IO *blkio; | ||||
uint64_t off, disk_blocks, d_offset = 0; | uint64_t off, disk_blocks, d_offset = 0; | ||||
char *blkbuf; | char *blkbuf; | ||||
size_t blkoff, blksz; | size_t blkoff, blksz; | ||||
int error; | int error; | ||||
size_t diskend, readstart; | size_t diskend, readstart; | ||||
if (dev == NULL || blk < 0) | if (blk < 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
pdi = efiblk_get_pdinfo_list(dev->d_dev); | if ((error = efipart_lookupdev(dev, &pd)) != 0) { | ||||
if (pdi == NULL) | return (error); | ||||
return (EINVAL); | } | ||||
pd = efiblk_get_pdinfo(pdi, dev->d_unit); | |||||
if (pd == NULL) | |||||
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; | 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 > d_offset + disk_blocks) { | if ((off + size) / blkio->Media->BlockSize > d_offset + disk_blocks) { | ||||
diskend = d_offset + disk_blocks; | diskend = d_offset + disk_blocks; | ||||
readstart = off / blkio->Media->BlockSize; | readstart = off / blkio->Media->BlockSize; | ||||
if (diskend <= readstart) { | if (diskend <= readstart) { | ||||
*rsize = 0; | *rsize = 0; | ||||
▲ Show 20 Lines • Show All 44 Lines • Show Last 20 Lines |
looks like you renamed 'node' to 'lastnode', but are checking 'node' for NULL, and it is never set.