Changeset View
Changeset View
Standalone View
Standalone View
head/sys/boot/efi/libefi/efipart.c
Show All 36 Lines | |||||
#include <efi.h> | #include <efi.h> | ||||
#include <efilib.h> | #include <efilib.h> | ||||
#include <efiprot.h> | #include <efiprot.h> | ||||
static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; | static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL; | ||||
static EFI_GUID devpath_guid = DEVICE_PATH_PROTOCOL; | static EFI_GUID devpath_guid = DEVICE_PATH_PROTOCOL; | ||||
static int efipart_init(void); | static int efipart_init(void); | ||||
static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *); | static int efipart_strategy(void *, int, daddr_t, size_t, size_t, char *, | ||||
size_t *); | |||||
static int efipart_realstrategy(void *, int, daddr_t, size_t, size_t, char *, | |||||
size_t *); | |||||
static int efipart_open(struct open_file *, ...); | static int efipart_open(struct open_file *, ...); | ||||
static int efipart_close(struct open_file *); | static int efipart_close(struct open_file *); | ||||
static void efipart_print(int); | static void efipart_print(int); | ||||
struct devsw efipart_dev = { | struct devsw efipart_dev = { | ||||
.dv_name = "part", | .dv_name = "part", | ||||
.dv_type = DEVT_DISK, | .dv_type = DEVT_DISK, | ||||
.dv_init = efipart_init, | .dv_init = efipart_init, | ||||
.dv_strategy = efipart_strategy, | .dv_strategy = efipart_strategy, | ||||
.dv_open = efipart_open, | .dv_open = efipart_open, | ||||
.dv_close = efipart_close, | .dv_close = efipart_close, | ||||
.dv_ioctl = noioctl, | .dv_ioctl = noioctl, | ||||
.dv_print = efipart_print, | .dv_print = efipart_print, | ||||
.dv_cleanup = NULL | .dv_cleanup = NULL | ||||
}; | }; | ||||
/* | |||||
* info structure to support bcache | |||||
*/ | |||||
#define MAXPDDEV 31 /* see MAXDEV in libi386.h */ | |||||
static struct pdinfo | |||||
{ | |||||
int pd_unit; /* unit number */ | |||||
int pd_open; /* reference counter */ | |||||
void *pd_bcache; /* buffer cache data */ | |||||
} pdinfo [MAXPDDEV]; | |||||
static int npdinfo = 0; | |||||
#define PD(dev) (pdinfo[(dev)->d_unit]) | |||||
static int | static int | ||||
efipart_init(void) | efipart_init(void) | ||||
{ | { | ||||
EFI_BLOCK_IO *blkio; | EFI_BLOCK_IO *blkio; | ||||
EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node; | EFI_DEVICE_PATH *devpath, *devpathcpy, *tmpdevpath, *node; | ||||
EFI_HANDLE *hin, *hout, *aliases, handle; | EFI_HANDLE *hin, *hout, *aliases, handle; | ||||
EFI_STATUS status; | EFI_STATUS status; | ||||
UINTN sz; | UINTN sz; | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | if (DevicePathType(node) == MEDIA_DEVICE_PATH && | ||||
free(devpathcpy); | free(devpathcpy); | ||||
if (EFI_ERROR(status)) | if (EFI_ERROR(status)) | ||||
continue; | continue; | ||||
hout[nout] = handle; | hout[nout] = handle; | ||||
aliases[nout] = hin[n]; | aliases[nout] = hin[n]; | ||||
} else | } else | ||||
hout[nout] = hin[n]; | hout[nout] = hin[n]; | ||||
nout++; | nout++; | ||||
pdinfo[npdinfo].pd_open = 0; | |||||
pdinfo[npdinfo].pd_bcache = NULL; | |||||
pdinfo[npdinfo].pd_unit = npdinfo; | |||||
npdinfo++; | |||||
} | } | ||||
bcache_add_dev(npdinfo); | |||||
err = efi_register_handles(&efipart_dev, hout, aliases, nout); | err = efi_register_handles(&efipart_dev, hout, aliases, nout); | ||||
free(hin); | free(hin); | ||||
return (err); | return (err); | ||||
} | } | ||||
static void | static void | ||||
efipart_print(int verbose) | efipart_print(int verbose) | ||||
{ | { | ||||
Show All 15 Lines | if (!EFI_ERROR(status)) { | ||||
pager_output(line); | pager_output(line); | ||||
if (blkio->Media->RemovableMedia) | if (blkio->Media->RemovableMedia) | ||||
pager_output(" (removable)"); | pager_output(" (removable)"); | ||||
} | } | ||||
pager_output("\n"); | pager_output("\n"); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
efipart_open(struct open_file *f, ...) | efipart_open(struct open_file *f, ...) | ||||
{ | { | ||||
va_list args; | va_list args; | ||||
struct devdesc *dev; | struct devdesc *dev; | ||||
EFI_BLOCK_IO *blkio; | EFI_BLOCK_IO *blkio; | ||||
EFI_HANDLE h; | EFI_HANDLE h; | ||||
EFI_STATUS status; | EFI_STATUS status; | ||||
va_start(args, f); | va_start(args, f); | ||||
dev = va_arg(args, struct devdesc*); | dev = va_arg(args, struct devdesc*); | ||||
va_end(args); | va_end(args); | ||||
h = efi_find_handle(&efipart_dev, dev->d_unit); | h = efi_find_handle(&efipart_dev, dev->d_unit); | ||||
if (h == NULL) | if (h == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio); | status = BS->HandleProtocol(h, &blkio_guid, (void **)&blkio); | ||||
if (EFI_ERROR(status)) | if (EFI_ERROR(status)) | ||||
return (efi_status_to_errno(status)); | return (efi_status_to_errno(status)); | ||||
if (!blkio->Media->MediaPresent) | if (!blkio->Media->MediaPresent) | ||||
return (EAGAIN); | return (EAGAIN); | ||||
dev->d_opendata = blkio; | dev->d_opendata = blkio; | ||||
PD(dev).pd_open++; | |||||
if (PD(dev).pd_bcache == NULL) | |||||
PD(dev).pd_bcache = bcache_allocate(); | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
efipart_close(struct open_file *f) | efipart_close(struct open_file *f) | ||||
{ | { | ||||
struct devdesc *dev; | struct devdesc *dev; | ||||
dev = (struct devdesc *)(f->f_devdata); | dev = (struct devdesc *)(f->f_devdata); | ||||
if (dev->d_opendata == NULL) | if (dev->d_opendata == NULL) | ||||
return (EINVAL); | return (EINVAL); | ||||
dev->d_opendata = NULL; | dev->d_opendata = NULL; | ||||
PD(dev).pd_open--; | |||||
if (PD(dev).pd_open == 0) { | |||||
bcache_free(PD(dev).pd_bcache); | |||||
PD(dev).pd_bcache = NULL; | |||||
} | |||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* efipart_readwrite() | * efipart_readwrite() | ||||
* Internal equivalent of efipart_strategy(), which operates on the | * Internal equivalent of efipart_strategy(), which operates on the | ||||
* media-native block size. This function expects all I/O requests | * media-native block size. This function expects all I/O requests | ||||
* to be within the media size and returns an error if such is not | * to be within the media size and returns an error if such is not | ||||
Show All 27 Lines | 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, status=%lu\n", __func__, rw, (u_long)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, char *buf, | efipart_strategy(void *devdata, int rw, daddr_t blk, size_t offset, | ||||
size_t *rsize) | size_t size, char *buf, size_t *rsize) | ||||
{ | |||||
struct bcache_devdata bcd; | |||||
struct devdesc *dev; | |||||
dev = (struct devdesc *)devdata; | |||||
bcd.dv_strategy = efipart_realstrategy; | |||||
bcd.dv_devdata = devdata; | |||||
bcd.dv_cache = PD(dev).pd_bcache; | |||||
return (bcache_strategy(&bcd, rw, blk, offset, size, | |||||
buf, rsize)); | |||||
} | |||||
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; | struct devdesc *dev = (struct devdesc *)devdata; | ||||
EFI_BLOCK_IO *blkio; | EFI_BLOCK_IO *blkio; | ||||
off_t off; | off_t off; | ||||
char *blkbuf; | char *blkbuf; | ||||
size_t blkoff, blksz; | size_t blkoff, blksz; | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 45 Lines • Show Last 20 Lines |