Index: head/sys/boot/common/disk.h =================================================================== --- head/sys/boot/common/disk.h +++ head/sys/boot/common/disk.h @@ -89,6 +89,11 @@ 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 @@ #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. Index: head/sys/boot/common/disk.c =================================================================== --- head/sys/boot/common/disk.c +++ head/sys/boot/common/disk.c @@ -233,6 +233,42 @@ } 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) { Index: head/sys/boot/usb/storage/umass_loader.c =================================================================== --- head/sys/boot/usb/storage/umass_loader.c +++ head/sys/boot/usb/storage/umass_loader.c @@ -47,6 +47,7 @@ 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 @@ .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, }; @@ -136,6 +137,30 @@ } 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) { struct disk_devdesc *dev;