Index: sys/boot/ofw/libofw/ofw_disk.c =================================================================== --- sys/boot/ofw/libofw/ofw_disk.c +++ sys/boot/ofw/libofw/ofw_disk.c @@ -37,6 +37,7 @@ #include #include +#include #include "bootstrap.h" #include "libofw.h" @@ -154,11 +155,26 @@ } static int -ofwd_ioctl(struct open_file *f __unused, u_long cmd __unused, - void *data __unused) +ofwd_ioctl(struct open_file *f, u_long cmd, void *data) { + struct ofw_devdesc *dev = f->f_devdata; + int block_size; + unsigned int n; - return (EINVAL); + switch (cmd) { + case DIOCGSECTORSIZE: + block_size = OF_block_size(dev->d_handle); + *(u_int *)data = block_size; + break; + case DIOCGMEDIASIZE: + block_size = OF_block_size(dev->d_handle); + n = OF_blocks(dev->d_handle); + *(uint64_t *)data = (uint64_t)(n * block_size); + break; + default: + return (ENOTTY); + } + return (0); } static int Index: sys/boot/ofw/libofw/openfirm.h =================================================================== --- sys/boot/ofw/libofw/openfirm.h +++ sys/boot/ofw/libofw/openfirm.h @@ -105,6 +105,8 @@ int OF_read(ihandle_t, void *, int); int OF_write(ihandle_t, void *, int); int OF_seek(ihandle_t, u_quad_t); +unsigned int OF_blocks(ihandle_t); +int OF_block_size(ihandle_t); /* Memory functions */ void *OF_claim(void *, u_int, u_int); Index: sys/boot/ofw/libofw/openfirm.c =================================================================== --- sys/boot/ofw/libofw/openfirm.c +++ sys/boot/ofw/libofw/openfirm.c @@ -622,6 +622,53 @@ return (args.status); } +/* Blocks. */ +unsigned int +OF_blocks(ihandle_t instance) +{ + static struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t instance; + cell_t result; + cell_t blocks; + } args = { + (cell_t)"#blocks", + 2, + 1, + }; + + args.instance = instance; + if (openfirmware(&args) == -1) + return ((unsigned int)-1); + return (args.blocks); +} + +/* Block size. */ +int +OF_block_size(ihandle_t instance) +{ + static struct { + cell_t name; + cell_t nargs; + cell_t nreturns; + cell_t instance; + cell_t result; + cell_t size; + } args = { + (cell_t)"block-size", + 2, + 1, + }; + + args.instance = instance; + if (openfirmware(&args) == -1) + return (512); + return (args.size); +} + +/* /* * Memory functions */ Index: sys/boot/sparc64/loader/main.c =================================================================== --- sys/boot/sparc64/loader/main.c +++ sys/boot/sparc64/loader/main.c @@ -735,6 +735,16 @@ } #ifdef LOADER_ZFS_SUPPORT + +/* Set by sparc64_zfs_probe to provide partition size. */ +static size_t part_size; + +uint64_t +ldi_get_size(void *priv __unused) +{ + return ((uint64_t)part_size); +} + static void sparc64_zfs_probe(void) { @@ -742,13 +752,11 @@ char alias[64], devname[sizeof(alias) + sizeof(":x") - 1]; char type[sizeof("device_type")]; char *bdev, *dev, *odev; - uint64_t guid; + uint64_t guid, *guidp; int fd, len, part; phandle_t aliases, options; - /* Get the GUID of the ZFS pool on the boot device. */ guid = 0; - zfs_probe_dev(bootpath, &guid); /* * Get the GUIDs of the ZFS pools on any additional disks listed in @@ -771,12 +779,6 @@ continue; strcpy(alias, dev); (void)OF_getprop(aliases, dev, alias, sizeof(alias)); - /* - * Don't probe the boot disk twice. Note that bootpath - * includes the partition specifier. - */ - if (strncmp(alias, bootpath, strlen(alias)) == 0) - continue; if (OF_getprop(OF_finddevice(alias), "device_type", type, sizeof(type)) == -1) continue; @@ -798,8 +800,14 @@ if (part == 2 || vtoc.part[part].tag != VTOC_TAG_FREEBSD_ZFS) continue; + part_size = vtoc.map[part].nblks; (void)sprintf(devname, "%s:%c", alias, part + 'a'); - if (zfs_probe_dev(devname, NULL) == ENXIO) + /* Get the GUID of the ZFS pool on the boot device. */ + if (strcmp(devname, bootpath) == 0) + guidp = &guid; + else + guidp = NULL; + if (zfs_probe_dev(devname, guidp) == ENXIO) break; } } Index: sys/boot/userboot/userboot/main.c =================================================================== --- sys/boot/userboot/userboot/main.c +++ sys/boot/userboot/userboot/main.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "bootstrap.h" #include "disk.h" @@ -270,6 +271,16 @@ return (CMD_OK); } + +uint64_t +ldi_get_size(void *priv) +{ + int fd = (uintptr_t) priv; + uint64_t size; + + ioctl(fd, DIOCGMEDIASIZE, &size); + return (size); +} #endif /* USERBOOT_ZFS_SUPPORT */ COMMAND_SET(quit, "quit", "exit the loader", command_quit); Index: sys/boot/userboot/userboot/userboot_disk.c =================================================================== --- sys/boot/userboot/userboot/userboot_disk.c +++ sys/boot/userboot/userboot/userboot_disk.c @@ -91,8 +91,8 @@ return (ENOMEM); for (i = 0; i < userdisk_maxunit; i++) { if (CALLBACK(diskioctl, i, DIOCGSECTORSIZE, - §orsize) != NULL || CALLBACK(diskioctl, i, - DIOCGMEDIASIZE, &mediasize) != NULL) + §orsize) != 0 || CALLBACK(diskioctl, i, + DIOCGMEDIASIZE, &mediasize) != 0) return (ENXIO); ud_info[i].mediasize = mediasize; ud_info[i].sectorsize = sectorsize; @@ -230,7 +230,12 @@ userdisk_ioctl(struct open_file *f, u_long cmd, void *data) { struct disk_devdesc *dev; + int rc; dev = (struct disk_devdesc *)f->f_devdata; + rc = disk_ioctl(dev, cmd, data); + if (rc != ENOTTY) + return (rc); + return (CALLBACK(diskioctl, dev->d_unit, cmd, data)); }