Index: cddl/contrib/opensolaris/cmd/zpool/zpool_main.c =================================================================== --- cddl/contrib/opensolaris/cmd/zpool/zpool_main.c (revision 271608) +++ cddl/contrib/opensolaris/cmd/zpool/zpool_main.c (working copy) @@ -50,6 +50,7 @@ #include #include #include +#include #include @@ -93,6 +94,7 @@ static int zpool_do_history(int, char **); static int zpool_do_get(int, char **); static int zpool_do_set(int, char **); +static int zpool_do_bootcode(int, char **); /* * These libumem hooks provide a reasonable set of defaults for the allocator's @@ -116,6 +118,7 @@ _umem_logging_init(void) typedef enum { HELP_ADD, HELP_ATTACH, + HELP_BOOTCODE, HELP_CLEAR, HELP_CREATE, HELP_DESTROY, @@ -189,6 +192,7 @@ static zpool_command_t command_table[] = { { "history", zpool_do_history, HELP_HISTORY }, { "get", zpool_do_get, HELP_GET }, { "set", zpool_do_set, HELP_SET }, + { "bootcode", zpool_do_bootcode, HELP_BOOTCODE }, }; #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) @@ -206,6 +210,9 @@ get_usage(zpool_help_t idx) { case HELP_ATTACH: return (gettext("\tattach [-f] " "\n")); + case HELP_BOOTCODE: + return (gettext("\tbootcode -b bootcode-file " + "\n")); case HELP_CLEAR: return (gettext("\tclear [-nF] [device]\n")); case HELP_CREATE: @@ -5423,6 +5430,91 @@ zpool_do_set(int argc, char **argv) } static int +zpool_do_bootcode(int argc, char **argv) +{ + struct stat sb; + zfs_cmd_t zc = { 0 }; + zpool_handle_t *zhp; + nvlist_t *nvl; + char *poolname, *bootfile, *bootcode; + boolean_t spare, cache, log; + int ret, c, fd; + + /* check options */ + bootfile = NULL; + while ((c = getopt(argc, argv, "b:")) != -1) { + switch (c) { + case 'b': + bootfile = optarg; + break; + default: + fprintf(stderr, gettext("invalid option '%c'\n"), + optopt); + case '?': + usage(B_FALSE); + } + } + + if (bootfile == NULL) { + fprintf(stderr, gettext("missing bootcode file name" + " argument\n")); + usage(B_FALSE); + } + if (stat(bootfile, &sb) == -1) { + fprintf(stderr, gettext("bootcode file '%s': %s\n"), + bootfile, strerror(errno)); + usage(B_FALSE); + } + if (!S_ISREG(sb.st_mode)) { + fprintf(stderr, gettext("bootcode file '%s' " + "is not a regular file\n"), bootfile); + usage(B_FALSE); + } + if (sb.st_size == 0) { + fprintf(stderr, gettext("bootcode file '%s' " + "is empty\n"), bootfile); + usage(B_FALSE); + } + if (sb.st_size > VDEV_BOOT_SIZE) { + fprintf(stderr, gettext("bootcode file '%s' " + "is too big\n"), bootfile); + usage(B_FALSE); + } + argc -= optind; + argv += optind; + if (argc < 1) { + fprintf(stderr, gettext("missing pool name argument\n")); + usage(B_FALSE); + } + if (argc < 2) { + fprintf(stderr, gettext("missing vdev specification\n")); + usage(B_FALSE); + } + poolname = argv[0]; + argc--; + argv++; + if ((zhp = zpool_open(g_zfs, poolname)) == NULL) + return (1); + nvl = zpool_find_vdev(zhp, argv[0], &spare, &cache, &log); + if (nvl == NULL || spare || cache || log) + return (1); + if ((fd = open(bootfile, O_RDONLY)) == -1) + return (1); + bootcode = safe_malloc(sb.st_size); + verify(nvlist_add_byte_array(nvl, "bootcode", bootcode, + sb.st_size) == 0); + free(bootcode); + if (zcmd_write_src_nvlist(g_zfs, &zc, nvl) != 0) + return (1); + nvlist_free(nvl); + strlcpy(zc.zc_name, poolname, sizeof(zc.zc_name)); + ret = zfs_ioctl(g_zfs, ZFS_IOC_VDEV_SET_BOOTCODE, &zc); + zpool_close(zhp); + + return (ret); +} + +static int find_command_idx(char *command, int *idx) { int i; Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c (revision 271608) +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c (working copy) @@ -5337,6 +5337,21 @@ zfs_ioc_unjail(zfs_cmd_t *zc) (int)zc->zc_jailid)); } +static int +zfs_ioc_bootcode(const char *name, nvlist_t *innvl, nvlist_t *outnvl) +{ + nvpair_t *pair; + uint64_t pool_guid, vdev_guid; + uint_t size; + u_char *bootcode; + + if (nvlist_lookup_byte_array(innvl, "bootcode", &bootcode, &size) != 0) + return (SET_ERROR(EINVAL)); + printf("zpool bootcode %u size\n", size); + + return (EOPNOTSUPP); +} + /* * innvl: { * "fd" -> file descriptor to write stream to (int32) @@ -5747,6 +5762,9 @@ zfs_ioctl_init(void) zfs_secpolicy_config, POOL_CHECK_NONE); zfs_ioctl_register_dataset_nolog(ZFS_IOC_UNJAIL, zfs_ioc_unjail, zfs_secpolicy_config, POOL_CHECK_NONE); + zfs_ioctl_register("bootcode", ZFS_IOC_VDEV_SET_BOOTCODE, + zfs_ioc_bootcode, zfs_secpolicy_config, POOL_NAME, + POOL_CHECK_NONE, B_FALSE, B_TRUE); #endif } Index: sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h (revision 271608) +++ sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h (working copy) @@ -871,6 +871,7 @@ typedef enum zfs_ioc { ZFS_IOC_BOOKMARK, ZFS_IOC_GET_BOOKMARKS, ZFS_IOC_DESTROY_BOOKMARKS, + ZFS_IOC_VDEV_SET_BOOTCODE, ZFS_IOC_LAST } zfs_ioc_t;