diff options
| author | Andrey V. Elsukov <ae@FreeBSD.org> | 2012-08-05 12:15:15 +0000 |
|---|---|---|
| committer | Andrey V. Elsukov <ae@FreeBSD.org> | 2012-08-05 12:15:15 +0000 |
| commit | 2c6f04dc0a1fc38959acb378f6d48203cd351f60 (patch) | |
| tree | 501c361d26f74b81898691e07cc2c47566e5946b /sys/boot/userboot | |
| parent | 9cef00000859df891c0536e2f4c4c1f527955eb0 (diff) | |
Notes
Diffstat (limited to 'sys/boot/userboot')
| -rw-r--r-- | sys/boot/userboot/test/test.c | 26 | ||||
| -rw-r--r-- | sys/boot/userboot/userboot.h | 5 | ||||
| -rw-r--r-- | sys/boot/userboot/userboot/Makefile | 1 | ||||
| -rw-r--r-- | sys/boot/userboot/userboot/devicename.c | 80 | ||||
| -rw-r--r-- | sys/boot/userboot/userboot/userboot_disk.c | 83 |
5 files changed, 102 insertions, 93 deletions
diff --git a/sys/boot/userboot/test/test.c b/sys/boot/userboot/test/test.c index a752a8032ef80..8745d315cbf51 100644 --- a/sys/boot/userboot/test/test.c +++ b/sys/boot/userboot/test/test.c @@ -26,6 +26,8 @@ * $FreeBSD$ */ +#include <sys/types.h> +#include <sys/disk.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <dirent.h> @@ -251,6 +253,29 @@ test_diskread(void *arg, int unit, uint64_t offset, void *dst, size_t size, return (0); } +int +test_diskioctl(void *arg, int unit, u_long cmd, void *data) +{ + struct stat sb; + + if (unit != 0 || disk_fd == -1) + return (EBADF); + switch (cmd) { + case DIOCGSECTORSIZE: + *(u_int *)data = 512; + break; + case DIOCGMEDIASIZE: + if (fstat(disk_fd, &sb) == 0) + *(off_t *)data = sb.st_size; + else + return (ENOTTY); + break; + default: + return (ENOTTY); + }; + return (0); +} + /* * Guest virtual machine i/o * @@ -353,6 +378,7 @@ struct loader_callbacks_v1 cb = { .stat = test_stat, .diskread = test_diskread, + .diskioctl = test_diskioctl, .copyin = test_copyin, .copyout = test_copyout, diff --git a/sys/boot/userboot/userboot.h b/sys/boot/userboot/userboot.h index 7d8263ee01042..9b0572e5ab007 100644 --- a/sys/boot/userboot/userboot.h +++ b/sys/boot/userboot/userboot.h @@ -175,4 +175,9 @@ struct loader_callbacks_v1 { */ void (*getmem)(void *arg, uint64_t *lowmem, uint64_t *highmem); + /* + * ioctl interface to the disk device + */ + int (*diskioctl)(void *arg, int unit, u_long cmd, + void *data); }; diff --git a/sys/boot/userboot/userboot/Makefile b/sys/boot/userboot/userboot/Makefile index 28ddc129f99cf..bc0a309827375 100644 --- a/sys/boot/userboot/userboot/Makefile +++ b/sys/boot/userboot/userboot/Makefile @@ -32,7 +32,6 @@ CFLAGS+= -I${.CURDIR}/../../common CFLAGS+= -I${.CURDIR}/../../.. CFLAGS+= -I${.CURDIR}/../../../../lib/libstand CFLAGS+= -ffreestanding -I. -CFLAGS+= -DLOADER_GPT_SUPPORT -DLOADER_MBR_SUPPORT LDFLAGS+= -nostdlib -Wl,-Bsymbolic diff --git a/sys/boot/userboot/userboot/devicename.c b/sys/boot/userboot/userboot/devicename.c index 24c5179f8593c..d54d0230d7b94 100644 --- a/sys/boot/userboot/userboot/devicename.c +++ b/sys/boot/userboot/userboot/devicename.c @@ -29,7 +29,6 @@ __FBSDID("$FreeBSD$"); #include <stand.h> #include <string.h> -#include <sys/disklabel.h> #include "bootstrap.h" #include "disk.h" @@ -87,7 +86,7 @@ userboot_parsedev(struct disk_devdesc **dev, const char *devspec, const char **p { struct disk_devdesc *idev; struct devsw *dv; - int i, unit, slice, partition, err; + int i, unit, err; char *cp; const char *np; @@ -113,62 +112,9 @@ userboot_parsedev(struct disk_devdesc **dev, const char *devspec, const char **p break; case DEVT_DISK: - unit = -1; - slice = -1; - partition = -1; - if (*np && (*np != ':')) { - unit = strtol(np, &cp, 10); /* next comes the unit number */ - if (cp == np) { - err = EUNIT; - goto fail; - } -#ifdef LOADER_GPT_SUPPORT - if (*cp == 'p') { /* got a GPT partition */ - np = cp + 1; - slice = strtol(np, &cp, 10); - if (cp == np) { - err = ESLICE; - goto fail; - } - if (*cp && (*cp != ':')) { - err = EINVAL; - goto fail; - } - partition = 0xff; - } else { -#endif - if (*cp == 's') { /* got a slice number */ - np = cp + 1; - slice = strtol(np, &cp, 10); - if (cp == np) { - err = ESLICE; - goto fail; - } - } - if (*cp && (*cp != ':')) { - partition = *cp - 'a'; /* got a partition number */ - if ((partition < 0) || (partition >= MAXPARTITIONS)) { - err = EPART; - goto fail; - } - cp++; - } -#ifdef LOADER_GPT_SUPPORT - } -#endif - } else { - cp = np; - } - if (*cp && (*cp != ':')) { - err = EINVAL; + err = disk_parsedev(idev, np, path); + if (err != 0) goto fail; - } - - idev->d_unit = unit; - idev->d_slice = slice; - idev->d_partition = partition; - if (path != NULL) - *path = (*cp == 0) ? cp : cp + 1; break; case DEVT_CD: @@ -219,8 +165,7 @@ userboot_fmtdev(void *vdev) { struct disk_devdesc *dev = (struct disk_devdesc *)vdev; static char buf[128]; /* XXX device length constant? */ - char *cp; - + switch(dev->d_type) { case DEVT_NONE: strcpy(buf, "(no device)"); @@ -231,22 +176,7 @@ userboot_fmtdev(void *vdev) break; case DEVT_DISK: - cp = buf; - cp += sprintf(cp, "%s%d", dev->d_dev->dv_name, dev->d_unit); -#ifdef LOADER_GPT_SUPPORT - if (dev->d_partition == 0xff) { - cp += sprintf(cp, "p%d", dev->d_slice); - } else { -#endif - if (dev->d_slice > 0) - cp += sprintf(cp, "s%d", dev->d_slice); - if (dev->d_partition >= 0) - cp += sprintf(cp, "%c", dev->d_partition + 'a'); -#ifdef LOADER_GPT_SUPPORT - } -#endif - strcat(cp, ":"); - break; + return (disk_fmtdev(vdev)); case DEVT_NET: case DEVT_ZFS: diff --git a/sys/boot/userboot/userboot/userboot_disk.c b/sys/boot/userboot/userboot/userboot_disk.c index 074d3e1620be1..84c4038ee7509 100644 --- a/sys/boot/userboot/userboot/userboot_disk.c +++ b/sys/boot/userboot/userboot/userboot_disk.c @@ -31,23 +31,31 @@ __FBSDID("$FreeBSD$"); * Userboot disk image handling. */ +#include <sys/disk.h> #include <stand.h> - #include <stdarg.h> -#include <uuid.h> - #include <bootstrap.h> #include "disk.h" #include "libuserboot.h" +struct userdisk_info { + uint64_t mediasize; + uint16_t sectorsize; +}; + int userboot_disk_maxunit = 0; +static int userdisk_maxunit = 0; +static struct userdisk_info *ud_info; + static int userdisk_init(void); +static void userdisk_cleanup(void); static int userdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size, char *buf, size_t *rsize); static int userdisk_open(struct open_file *f, ...); static int userdisk_close(struct open_file *f); +static int userdisk_ioctl(struct open_file *f, u_long cmd, void *data); static void userdisk_print(int verbose); struct devsw userboot_disk = { @@ -57,41 +65,70 @@ struct devsw userboot_disk = { userdisk_strategy, userdisk_open, userdisk_close, - noioctl, + userdisk_ioctl, userdisk_print, - NULL + userdisk_cleanup }; /* - * Nothing to do here. + * Initialize userdisk_info structure for each disk. */ static int userdisk_init(void) { + off_t mediasize; + u_int sectorsize; + int i; + + userdisk_maxunit = userboot_disk_maxunit; + if (userdisk_maxunit > 0) { + ud_info = malloc(sizeof(*ud_info) * userdisk_maxunit); + if (ud_info == NULL) + return (ENOMEM); + for (i = 0; i < userdisk_maxunit; i++) { + if (CALLBACK(diskioctl, i, DIOCGSECTORSIZE, + §orsize) != 0 || CALLBACK(diskioctl, i, + DIOCGMEDIASIZE, &mediasize) != 0) + return (ENXIO); + ud_info[i].mediasize = mediasize; + ud_info[i].sectorsize = sectorsize; + } + } return(0); } +static void +userdisk_cleanup(void) +{ + + if (userdisk_maxunit > 0) + free(ud_info); +} + /* * Print information about disks */ static void userdisk_print(int verbose) { - int i; - char line[80]; - struct disk_devdesc dev; + struct disk_devdesc dev; + char line[80]; + int i; - for (i = 0; i < userboot_disk_maxunit; i++) { + for (i = 0; i < userdisk_maxunit; i++) { sprintf(line, " disk%d: Guest drive image\n", i); pager_output(line); dev.d_dev = &userboot_disk; dev.d_unit = i; dev.d_slice = -1; dev.d_partition = -1; - dev.d_offset = 0; - sprintf(line, " disk%d", i); - disk_print(&dev, line, verbose); + if (disk_open(&dev, ud_info[i].mediasize, + ud_info[i].sectorsize) == 0) { + sprintf(line, " disk%d", i); + disk_print(&dev, line, verbose); + disk_close(&dev); + } } } @@ -108,17 +145,20 @@ userdisk_open(struct open_file *f, ...) dev = va_arg(ap, struct disk_devdesc *); va_end(ap); - if (dev->d_unit < 0 || dev->d_unit >= userboot_disk_maxunit) + if (dev->d_unit < 0 || dev->d_unit >= userdisk_maxunit) return (EIO); - return (disk_open(dev)); + return (disk_open(dev, ud_info[dev->d_unit].mediasize, + ud_info[dev->d_unit].sectorsize)); } static int userdisk_close(struct open_file *f) { + struct disk_devdesc *dev; - return(0); + dev = (struct disk_devdesc *)f->f_devdata; + return (disk_close(dev)); } static int @@ -136,7 +176,7 @@ userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t size, return (EINVAL); if (rsize) *rsize = 0; - off = (dblk + dev->d_offset) * DISK_SECSIZE; + off = (dblk + dev->d_offset) * ud_info[dev->d_unit].sectorsize; rc = CALLBACK(diskread, dev->d_unit, off, buf, size, &resid); if (rc) return (rc); @@ -144,3 +184,12 @@ userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t size, *rsize = size - resid; return (0); } + +static int +userdisk_ioctl(struct open_file *f, u_long cmd, void *data) +{ + struct disk_devdesc *dev; + + dev = (struct disk_devdesc *)f->f_devdata; + return (CALLBACK(diskioctl, dev->d_unit, cmd, data)); +} |
