diff --git a/sys/boot/common/disk.c b/sys/boot/common/disk.c index a541cb0199aa..a8801e1b0cbb 100644 --- a/sys/boot/common/disk.c +++ b/sys/boot/common/disk.c @@ -232,6 +232,42 @@ disk_print(struct disk_devdesc *dev, char *prefix, int verbose) ptable_iterate(od->table, &pa, ptable_print); } +int +disk_read(struct disk_devdesc *dev, void *buf, off_t offset, u_int blocks) +{ + struct open_disk *od; + int ret; + + od = (struct open_disk *)dev->d_opendata; + ret = dev->d_dev->dv_strategy(dev, F_READ, dev->d_offset + offset, + blocks * od->sectorsize, buf, NULL); + + return (ret); +} + +int +disk_write(struct disk_devdesc *dev, void *buf, off_t offset, u_int blocks) +{ + struct open_disk *od; + int ret; + + od = (struct open_disk *)dev->d_opendata; + ret = dev->d_dev->dv_strategy(dev, F_WRITE, dev->d_offset + offset, + blocks * od->sectorsize, buf, NULL); + + return (ret); +} + +int +disk_ioctl(struct disk_devdesc *dev, u_long cmd, void *buf) +{ + + if (dev->d_dev->dv_ioctl) + return ((*dev->d_dev->dv_ioctl)(dev->d_opendata, cmd, buf)); + + return (ENXIO); +} + int disk_open(struct disk_devdesc *dev, off_t mediasize, u_int sectorsize, u_int flags) diff --git a/sys/boot/common/disk.h b/sys/boot/common/disk.h index 6a78fbf781dd..e95256d1993c 100644 --- a/sys/boot/common/disk.h +++ b/sys/boot/common/disk.h @@ -89,6 +89,11 @@ struct disk_devdesc off_t d_offset; }; +enum disk_ioctl { + IOCTL_GET_BLOCKS, + IOCTL_GET_BLOCK_SIZE +}; + /* * Parse disk metadata and initialise dev->d_offset. */ @@ -97,6 +102,11 @@ extern int disk_open(struct disk_devdesc *dev, off_t mediasize, #define DISK_F_NOCACHE 0x0001 /* Do not use metadata caching */ extern int disk_close(struct disk_devdesc *dev); extern void disk_cleanup(const struct devsw *d_dev); +extern int disk_ioctl(struct disk_devdesc *dev, u_long cmd, void *buf); +extern int disk_read(struct disk_devdesc *dev, void *buf, off_t offset, + u_int blocks); +extern int disk_write(struct disk_devdesc *dev, void *buf, off_t offset, + u_int blocks); /* * Print information about slices on a disk. diff --git a/sys/boot/usb/storage/umass_loader.c b/sys/boot/usb/storage/umass_loader.c index cba82ae7d772..4311b2b65ed7 100644 --- a/sys/boot/usb/storage/umass_loader.c +++ b/sys/boot/usb/storage/umass_loader.c @@ -47,6 +47,7 @@ static int umass_disk_init(void); static int umass_disk_open(struct open_file *,...); static int umass_disk_close(struct open_file *); static void umass_disk_cleanup(void); +static int umass_disk_ioctl(struct open_file *, u_long, void *); static int umass_disk_strategy(void *, int, daddr_t, size_t, char *, size_t *); static void umass_disk_print(int); @@ -57,7 +58,7 @@ struct devsw umass_disk = { .dv_strategy = umass_disk_strategy, .dv_open = umass_disk_open, .dv_close = umass_disk_close, - .dv_ioctl = noioctl, + .dv_ioctl = umass_disk_ioctl, .dv_print = umass_disk_print, .dv_cleanup = umass_disk_cleanup, }; @@ -135,6 +136,30 @@ umass_disk_open(struct open_file *f,...) return (umass_disk_open_sub(dev)); } +static int +umass_disk_ioctl(struct open_file *f __unused, u_long cmd, void *buf) +{ + uint32_t nblock; + uint32_t blocksize; + + switch (cmd) { + case IOCTL_GET_BLOCK_SIZE: + case IOCTL_GET_BLOCKS: + if (usb_msc_read_capacity(umass_uaa.device, 0, + &nblock, &blocksize) != 0) + return (EINVAL); + + if (cmd == IOCTL_GET_BLOCKS) + *(uint32_t*)buf = nblock; + else + *(uint32_t*)buf = blocksize; + + return (0); + default: + return (ENXIO); + } +} + static int umass_disk_close(struct open_file *f) {