19160SSherry.Moore@Sun.COM /* 29160SSherry.Moore@Sun.COM * CDDL HEADER START 39160SSherry.Moore@Sun.COM * 49160SSherry.Moore@Sun.COM * The contents of this file are subject to the terms of the 59160SSherry.Moore@Sun.COM * Common Development and Distribution License (the "License"). 69160SSherry.Moore@Sun.COM * You may not use this file except in compliance with the License. 79160SSherry.Moore@Sun.COM * 89160SSherry.Moore@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99160SSherry.Moore@Sun.COM * or http://www.opensolaris.org/os/licensing. 109160SSherry.Moore@Sun.COM * See the License for the specific language governing permissions 119160SSherry.Moore@Sun.COM * and limitations under the License. 129160SSherry.Moore@Sun.COM * 139160SSherry.Moore@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 149160SSherry.Moore@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159160SSherry.Moore@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 169160SSherry.Moore@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 179160SSherry.Moore@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 189160SSherry.Moore@Sun.COM * 199160SSherry.Moore@Sun.COM * CDDL HEADER END 209160SSherry.Moore@Sun.COM */ 219160SSherry.Moore@Sun.COM /* 229160SSherry.Moore@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 239160SSherry.Moore@Sun.COM * Use is subject to license terms. 249160SSherry.Moore@Sun.COM */ 259160SSherry.Moore@Sun.COM 269160SSherry.Moore@Sun.COM /* 279160SSherry.Moore@Sun.COM * This file contains all the functions that implement the following 289160SSherry.Moore@Sun.COM * GRUB commands: 299160SSherry.Moore@Sun.COM * kernel, kernel$, module, module$, findroot, bootfs 309160SSherry.Moore@Sun.COM * Return 0 on success, errno on failure. 319160SSherry.Moore@Sun.COM */ 329160SSherry.Moore@Sun.COM #include <stdio.h> 339160SSherry.Moore@Sun.COM #include <stdlib.h> 349160SSherry.Moore@Sun.COM #include <assert.h> 359160SSherry.Moore@Sun.COM #include <alloca.h> 369160SSherry.Moore@Sun.COM #include <errno.h> 379160SSherry.Moore@Sun.COM #include <strings.h> 389160SSherry.Moore@Sun.COM #include <unistd.h> 399160SSherry.Moore@Sun.COM #include <fcntl.h> 409160SSherry.Moore@Sun.COM #include <sys/types.h> 419160SSherry.Moore@Sun.COM #include <sys/fs/ufs_mount.h> 429160SSherry.Moore@Sun.COM #include <sys/dktp/fdisk.h> 439160SSherry.Moore@Sun.COM #if defined(__i386) 449160SSherry.Moore@Sun.COM #include <sys/x86_archext.h> 459160SSherry.Moore@Sun.COM #endif /* __i386 */ 469160SSherry.Moore@Sun.COM 479160SSherry.Moore@Sun.COM #include "libgrub_impl.h" 489160SSherry.Moore@Sun.COM 499160SSherry.Moore@Sun.COM #define RESET_MODULE(barg) ((barg)->gb_module[0] = 0) 509160SSherry.Moore@Sun.COM 519160SSherry.Moore@Sun.COM #if defined(__i386) 529160SSherry.Moore@Sun.COM static const char cpuid_dev[] = "/dev/cpu/self/cpuid"; 539160SSherry.Moore@Sun.COM 549160SSherry.Moore@Sun.COM /* 559160SSherry.Moore@Sun.COM * Return 1 if the system supports 64-bit mode, 0 if it doesn't, 569160SSherry.Moore@Sun.COM * or -1 on failure. 579160SSherry.Moore@Sun.COM */ 589160SSherry.Moore@Sun.COM static int 599160SSherry.Moore@Sun.COM cpuid_64bit_capable(void) 609160SSherry.Moore@Sun.COM { 619160SSherry.Moore@Sun.COM int fd, ret = -1; 629160SSherry.Moore@Sun.COM struct { 639160SSherry.Moore@Sun.COM uint32_t cp_eax, cp_ebx, cp_ecx, cp_edx; 649160SSherry.Moore@Sun.COM } cpuid_regs; 659160SSherry.Moore@Sun.COM 669160SSherry.Moore@Sun.COM if ((fd = open(cpuid_dev, O_RDONLY)) == -1) 679160SSherry.Moore@Sun.COM return (ret); 689160SSherry.Moore@Sun.COM 699160SSherry.Moore@Sun.COM if (pread(fd, &cpuid_regs, sizeof (cpuid_regs), 0x80000001) == 709160SSherry.Moore@Sun.COM sizeof (cpuid_regs)) 719160SSherry.Moore@Sun.COM ret = ((CPUID_AMD_EDX_LM & cpuid_regs.cp_edx) != 0); 729160SSherry.Moore@Sun.COM 739160SSherry.Moore@Sun.COM (void) close(fd); 749160SSherry.Moore@Sun.COM return (ret); 759160SSherry.Moore@Sun.COM } 769160SSherry.Moore@Sun.COM #endif /* __i386 */ 779160SSherry.Moore@Sun.COM 789160SSherry.Moore@Sun.COM 799160SSherry.Moore@Sun.COM /* 809160SSherry.Moore@Sun.COM * Expand $ISAIDR 819160SSherry.Moore@Sun.COM */ 829160SSherry.Moore@Sun.COM #if !defined(__i386) 839160SSherry.Moore@Sun.COM /* ARGSUSED */ 849160SSherry.Moore@Sun.COM #endif /* __i386 */ 859160SSherry.Moore@Sun.COM static size_t 869160SSherry.Moore@Sun.COM barg_isadir_var(char *var, int sz) 879160SSherry.Moore@Sun.COM { 889160SSherry.Moore@Sun.COM #if defined(__i386) 899160SSherry.Moore@Sun.COM if (cpuid_64bit_capable() == 1) 909160SSherry.Moore@Sun.COM return (strlcpy(var, "amd64", sz)); 919160SSherry.Moore@Sun.COM #endif /* __i386 */ 929160SSherry.Moore@Sun.COM 939160SSherry.Moore@Sun.COM var[0] = 0; 949160SSherry.Moore@Sun.COM return (0); 959160SSherry.Moore@Sun.COM } 969160SSherry.Moore@Sun.COM 979160SSherry.Moore@Sun.COM /* 989160SSherry.Moore@Sun.COM * Expand $ZFS-BOOTFS 999160SSherry.Moore@Sun.COM */ 1009160SSherry.Moore@Sun.COM static size_t 1019160SSherry.Moore@Sun.COM barg_bootfs_var(const grub_barg_t *barg, char *var, int sz) 1029160SSherry.Moore@Sun.COM { 1039160SSherry.Moore@Sun.COM int n; 1049160SSherry.Moore@Sun.COM 1059160SSherry.Moore@Sun.COM assert(barg); 1069160SSherry.Moore@Sun.COM if (strcmp(barg->gb_root.gr_fstyp, MNTTYPE_ZFS) == 0) { 1079160SSherry.Moore@Sun.COM n = snprintf(var, sz, "zfs-bootfs=%s,bootpath=\"%s\"", 1089160SSherry.Moore@Sun.COM barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev, 1099160SSherry.Moore@Sun.COM barg->gb_root.gr_physpath); 1109160SSherry.Moore@Sun.COM } else { 1119160SSherry.Moore@Sun.COM var[0] = 0; 1129160SSherry.Moore@Sun.COM n = 0; 1139160SSherry.Moore@Sun.COM } 1149160SSherry.Moore@Sun.COM return (n); 1159160SSherry.Moore@Sun.COM } 1169160SSherry.Moore@Sun.COM 1179160SSherry.Moore@Sun.COM /* 1189160SSherry.Moore@Sun.COM * Expand all the variables without appending them more than once. 1199160SSherry.Moore@Sun.COM */ 1209160SSherry.Moore@Sun.COM static int 1219160SSherry.Moore@Sun.COM expand_var(char *arg, size_t argsz, const char *var, size_t varsz, 1229160SSherry.Moore@Sun.COM char *val, size_t valsz) 1239160SSherry.Moore@Sun.COM { 1249160SSherry.Moore@Sun.COM char *sp = arg; 1259160SSherry.Moore@Sun.COM size_t sz = argsz, len; 1269160SSherry.Moore@Sun.COM char *buf, *dst, *src; 1279160SSherry.Moore@Sun.COM int ret = 0; 1289160SSherry.Moore@Sun.COM 1299160SSherry.Moore@Sun.COM buf = alloca(argsz); 1309160SSherry.Moore@Sun.COM dst = buf; 1319160SSherry.Moore@Sun.COM 1329160SSherry.Moore@Sun.COM while ((src = strstr(sp, var)) != NULL) { 1339160SSherry.Moore@Sun.COM 1349160SSherry.Moore@Sun.COM len = src - sp; 1359160SSherry.Moore@Sun.COM 1369160SSherry.Moore@Sun.COM if (len + valsz > sz) { 1379160SSherry.Moore@Sun.COM ret = E2BIG; 1389160SSherry.Moore@Sun.COM break; 1399160SSherry.Moore@Sun.COM } 1409160SSherry.Moore@Sun.COM 1419160SSherry.Moore@Sun.COM (void) bcopy(sp, dst, len); 1429160SSherry.Moore@Sun.COM (void) bcopy(val, dst + len, valsz); 1439160SSherry.Moore@Sun.COM dst += len + valsz; 1449160SSherry.Moore@Sun.COM sz -= len + valsz; 1459160SSherry.Moore@Sun.COM sp = src + varsz; 1469160SSherry.Moore@Sun.COM } 1479160SSherry.Moore@Sun.COM 1489160SSherry.Moore@Sun.COM if (strlcpy(dst, sp, sz) >= sz) 1499160SSherry.Moore@Sun.COM ret = E2BIG; 1509160SSherry.Moore@Sun.COM 1519160SSherry.Moore@Sun.COM if (ret == 0) 1529160SSherry.Moore@Sun.COM bcopy(buf, arg, argsz); 1539160SSherry.Moore@Sun.COM return (ret); 1549160SSherry.Moore@Sun.COM } 1559160SSherry.Moore@Sun.COM 1569160SSherry.Moore@Sun.COM static int 1579160SSherry.Moore@Sun.COM match_bootfs(zfs_handle_t *zfh, void *data) 1589160SSherry.Moore@Sun.COM { 1599160SSherry.Moore@Sun.COM int ret; 1609160SSherry.Moore@Sun.COM const char *zfn; 1619160SSherry.Moore@Sun.COM grub_barg_t *barg = (grub_barg_t *)data; 1629160SSherry.Moore@Sun.COM 1639160SSherry.Moore@Sun.COM ret = (zfs_get_type(zfh) == ZFS_TYPE_FILESYSTEM && 1649160SSherry.Moore@Sun.COM (zfn = zfs_get_name(zfh)) != NULL && 1659160SSherry.Moore@Sun.COM strcmp(barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev, zfn) == 0); 1669160SSherry.Moore@Sun.COM 1679160SSherry.Moore@Sun.COM if (ret != 0) 1689160SSherry.Moore@Sun.COM barg->gb_walkret = 0; 1699160SSherry.Moore@Sun.COM else 1709160SSherry.Moore@Sun.COM (void) zfs_iter_filesystems(zfh, match_bootfs, barg); 1719160SSherry.Moore@Sun.COM 1729160SSherry.Moore@Sun.COM zfs_close(zfh); 1739160SSherry.Moore@Sun.COM return (barg->gb_walkret == 0); 1749160SSherry.Moore@Sun.COM } 1759160SSherry.Moore@Sun.COM 1769160SSherry.Moore@Sun.COM static void 1779160SSherry.Moore@Sun.COM reset_root(grub_barg_t *barg) 1789160SSherry.Moore@Sun.COM { 1799160SSherry.Moore@Sun.COM (void) memset(&barg->gb_root, 0, sizeof (barg->gb_root)); 1809160SSherry.Moore@Sun.COM barg->gb_bootsign[0] = 0; 1819160SSherry.Moore@Sun.COM barg->gb_kernel[0] = 0; 1829160SSherry.Moore@Sun.COM RESET_MODULE(barg); 1839160SSherry.Moore@Sun.COM } 1849160SSherry.Moore@Sun.COM 1859160SSherry.Moore@Sun.COM /* ARGSUSED */ 1869160SSherry.Moore@Sun.COM int 1879160SSherry.Moore@Sun.COM skip_line(const grub_line_t *lp, grub_barg_t *barg) 1889160SSherry.Moore@Sun.COM { 1899160SSherry.Moore@Sun.COM return (0); 1909160SSherry.Moore@Sun.COM } 1919160SSherry.Moore@Sun.COM 1929160SSherry.Moore@Sun.COM /* ARGSUSED */ 1939160SSherry.Moore@Sun.COM int 1949160SSherry.Moore@Sun.COM error_line(const grub_line_t *lp, grub_barg_t *barg) 1959160SSherry.Moore@Sun.COM { 196*9444SKonstantin.Ananyev@Sun.COM if (lp->gl_cmdtp == GRBM_ROOT_CMD) 197*9444SKonstantin.Ananyev@Sun.COM return (EG_ROOTNOTSUPP); 1989160SSherry.Moore@Sun.COM return (EG_INVALIDLINE); 1999160SSherry.Moore@Sun.COM } 2009160SSherry.Moore@Sun.COM 2019160SSherry.Moore@Sun.COM int 2029160SSherry.Moore@Sun.COM kernel(const grub_line_t *lp, grub_barg_t *barg) 2039160SSherry.Moore@Sun.COM { 2049160SSherry.Moore@Sun.COM RESET_MODULE(barg); 2059160SSherry.Moore@Sun.COM if (strlcpy(barg->gb_kernel, lp->gl_arg, sizeof (barg->gb_kernel)) >= 2069160SSherry.Moore@Sun.COM sizeof (barg->gb_kernel)) 2079160SSherry.Moore@Sun.COM return (E2BIG); 2089160SSherry.Moore@Sun.COM 2099160SSherry.Moore@Sun.COM return (0); 2109160SSherry.Moore@Sun.COM } 2119160SSherry.Moore@Sun.COM 2129160SSherry.Moore@Sun.COM int 2139160SSherry.Moore@Sun.COM module(const grub_line_t *lp, grub_barg_t *barg) 2149160SSherry.Moore@Sun.COM { 2159160SSherry.Moore@Sun.COM if (strlcpy(barg->gb_module, lp->gl_arg, sizeof (barg->gb_module)) >= 2169160SSherry.Moore@Sun.COM sizeof (barg->gb_module)) 2179160SSherry.Moore@Sun.COM return (E2BIG); 2189160SSherry.Moore@Sun.COM 2199160SSherry.Moore@Sun.COM return (0); 2209160SSherry.Moore@Sun.COM } 2219160SSherry.Moore@Sun.COM 2229160SSherry.Moore@Sun.COM int 2239160SSherry.Moore@Sun.COM dollar_kernel(const grub_line_t *lp, grub_barg_t *barg) 2249160SSherry.Moore@Sun.COM { 2259160SSherry.Moore@Sun.COM int ret; 2269160SSherry.Moore@Sun.COM size_t bfslen, isalen; 2279160SSherry.Moore@Sun.COM char isadir[32]; 2289160SSherry.Moore@Sun.COM char bootfs[BOOTARGS_MAX]; 2299160SSherry.Moore@Sun.COM 2309160SSherry.Moore@Sun.COM RESET_MODULE(barg); 2319160SSherry.Moore@Sun.COM if (strlcpy(barg->gb_kernel, lp->gl_arg, sizeof (barg->gb_kernel)) >= 2329160SSherry.Moore@Sun.COM sizeof (barg->gb_kernel)) 2339160SSherry.Moore@Sun.COM return (E2BIG); 2349160SSherry.Moore@Sun.COM 2359160SSherry.Moore@Sun.COM bfslen = barg_bootfs_var(barg, bootfs, sizeof (bootfs)); 2369160SSherry.Moore@Sun.COM isalen = barg_isadir_var(isadir, sizeof (isadir)); 2379160SSherry.Moore@Sun.COM 2389160SSherry.Moore@Sun.COM if (bfslen >= sizeof (bootfs) || isalen >= sizeof (isadir)) 2399160SSherry.Moore@Sun.COM return (EINVAL); 2409160SSherry.Moore@Sun.COM 2419160SSherry.Moore@Sun.COM if ((ret = expand_var(barg->gb_kernel, sizeof (barg->gb_kernel), 2429160SSherry.Moore@Sun.COM ZFS_BOOT_VAR, strlen(ZFS_BOOT_VAR), bootfs, bfslen)) != 0) 2439160SSherry.Moore@Sun.COM return (ret); 2449160SSherry.Moore@Sun.COM 2459160SSherry.Moore@Sun.COM ret = expand_var(barg->gb_kernel, sizeof (barg->gb_kernel), 2469160SSherry.Moore@Sun.COM ISADIR_VAR, strlen(ISADIR_VAR), isadir, isalen); 2479160SSherry.Moore@Sun.COM 2489160SSherry.Moore@Sun.COM return (ret); 2499160SSherry.Moore@Sun.COM } 2509160SSherry.Moore@Sun.COM 2519160SSherry.Moore@Sun.COM int 2529160SSherry.Moore@Sun.COM dollar_module(const grub_line_t *lp, grub_barg_t *barg) 2539160SSherry.Moore@Sun.COM { 2549160SSherry.Moore@Sun.COM int ret; 2559160SSherry.Moore@Sun.COM size_t isalen; 2569160SSherry.Moore@Sun.COM char isadir[32]; 2579160SSherry.Moore@Sun.COM 2589160SSherry.Moore@Sun.COM if (strlcpy(barg->gb_module, lp->gl_arg, sizeof (barg->gb_module)) >= 2599160SSherry.Moore@Sun.COM sizeof (barg->gb_module)) 2609160SSherry.Moore@Sun.COM return (E2BIG); 2619160SSherry.Moore@Sun.COM 2629160SSherry.Moore@Sun.COM if ((isalen = barg_isadir_var(isadir, sizeof (isadir))) >= sizeof 2639160SSherry.Moore@Sun.COM (isadir)) 2649160SSherry.Moore@Sun.COM return (EINVAL); 2659160SSherry.Moore@Sun.COM 2669160SSherry.Moore@Sun.COM ret = expand_var(barg->gb_module, sizeof (barg->gb_module), 2679160SSherry.Moore@Sun.COM ISADIR_VAR, strlen(ISADIR_VAR), isadir, isalen); 2689160SSherry.Moore@Sun.COM 2699160SSherry.Moore@Sun.COM return (ret); 2709160SSherry.Moore@Sun.COM } 2719160SSherry.Moore@Sun.COM 2729160SSherry.Moore@Sun.COM 2739160SSherry.Moore@Sun.COM int 2749160SSherry.Moore@Sun.COM findroot(const grub_line_t *lp, grub_barg_t *barg) 2759160SSherry.Moore@Sun.COM { 2769160SSherry.Moore@Sun.COM size_t sz, bsz; 2779160SSherry.Moore@Sun.COM const char *sign; 2789160SSherry.Moore@Sun.COM 2799160SSherry.Moore@Sun.COM reset_root(barg); 2809160SSherry.Moore@Sun.COM 2819160SSherry.Moore@Sun.COM sign = lp->gl_arg; 2829160SSherry.Moore@Sun.COM barg->gb_prtnum = (uint_t)PRTNUM_INVALID; 2839160SSherry.Moore@Sun.COM barg->gb_slcnum = (uint_t)SLCNUM_WHOLE_DISK; 2849160SSherry.Moore@Sun.COM 2859160SSherry.Moore@Sun.COM if (sign[0] == '(') { 2869160SSherry.Moore@Sun.COM const char *pos; 2879160SSherry.Moore@Sun.COM 2889160SSherry.Moore@Sun.COM ++sign; 2899160SSherry.Moore@Sun.COM if ((pos = strchr(sign, ',')) == NULL || (sz = pos - sign) == 0) 2909160SSherry.Moore@Sun.COM return (EG_FINDROOTFMT); 2919160SSherry.Moore@Sun.COM 2929160SSherry.Moore@Sun.COM ++pos; 2939160SSherry.Moore@Sun.COM if (!IS_PRTNUM_VALID(barg->gb_prtnum = pos[0] - '0')) 2949160SSherry.Moore@Sun.COM return (EG_FINDROOTFMT); 2959160SSherry.Moore@Sun.COM 2969160SSherry.Moore@Sun.COM ++pos; 2979160SSherry.Moore@Sun.COM if (pos[0] != ',' || 2989160SSherry.Moore@Sun.COM !IS_SLCNUM_VALID(barg->gb_slcnum = pos[1]) || 2999160SSherry.Moore@Sun.COM pos[2] != ')') 3009160SSherry.Moore@Sun.COM return (EG_FINDROOTFMT); 3019160SSherry.Moore@Sun.COM } else { 3029160SSherry.Moore@Sun.COM sz = strlen(sign); 3039160SSherry.Moore@Sun.COM } 3049160SSherry.Moore@Sun.COM 3059160SSherry.Moore@Sun.COM bsz = strlen(BOOTSIGN_DIR "/"); 3069160SSherry.Moore@Sun.COM if (bsz + sz + 1 > sizeof (barg->gb_bootsign)) 3079160SSherry.Moore@Sun.COM return (E2BIG); 3089160SSherry.Moore@Sun.COM 3099160SSherry.Moore@Sun.COM bcopy(BOOTSIGN_DIR "/", barg->gb_bootsign, bsz); 3109160SSherry.Moore@Sun.COM bcopy(sign, barg->gb_bootsign + bsz, sz); 3119160SSherry.Moore@Sun.COM barg->gb_bootsign [bsz + sz] = 0; 3129160SSherry.Moore@Sun.COM 3139160SSherry.Moore@Sun.COM return (grub_find_bootsign(barg)); 3149160SSherry.Moore@Sun.COM } 3159160SSherry.Moore@Sun.COM 3169160SSherry.Moore@Sun.COM int 3179160SSherry.Moore@Sun.COM bootfs(const grub_line_t *lp, grub_barg_t *barg) 3189160SSherry.Moore@Sun.COM { 3199160SSherry.Moore@Sun.COM zfs_handle_t *zfh; 3209160SSherry.Moore@Sun.COM grub_menu_t *mp = barg->gb_entry->ge_menu; 3219160SSherry.Moore@Sun.COM char *gfs_devp; 3229160SSherry.Moore@Sun.COM size_t gfs_dev_len; 3239160SSherry.Moore@Sun.COM 3249160SSherry.Moore@Sun.COM /* Check if root is zfs */ 3259160SSherry.Moore@Sun.COM if (strcmp(barg->gb_root.gr_fstyp, MNTTYPE_ZFS) != 0) 3269160SSherry.Moore@Sun.COM return (EG_NOTZFS); 3279160SSherry.Moore@Sun.COM 3289160SSherry.Moore@Sun.COM gfs_devp = barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev; 3299160SSherry.Moore@Sun.COM gfs_dev_len = sizeof (barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev); 3309160SSherry.Moore@Sun.COM 3319160SSherry.Moore@Sun.COM /* 3329160SSherry.Moore@Sun.COM * If the bootfs value is the same as the bootfs for the pool, 3339160SSherry.Moore@Sun.COM * do nothing. 3349160SSherry.Moore@Sun.COM */ 3359160SSherry.Moore@Sun.COM if (strcmp(lp->gl_arg, gfs_devp) == 0) 3369160SSherry.Moore@Sun.COM return (0); 3379160SSherry.Moore@Sun.COM 3389160SSherry.Moore@Sun.COM if (strlcpy(gfs_devp, lp->gl_arg, gfs_dev_len) >= gfs_dev_len) 3399160SSherry.Moore@Sun.COM return (E2BIG); 3409160SSherry.Moore@Sun.COM 3419160SSherry.Moore@Sun.COM /* check if specified bootfs belongs to the root pool */ 3429160SSherry.Moore@Sun.COM if ((zfh = zfs_open(mp->gm_fs.gf_lzfh, 3439160SSherry.Moore@Sun.COM barg->gb_root.gr_fs[GRBM_ZFS_TOPFS].gfs_dev, 3449160SSherry.Moore@Sun.COM ZFS_TYPE_FILESYSTEM)) == NULL) 3459160SSherry.Moore@Sun.COM return (EG_OPENZFS); 3469160SSherry.Moore@Sun.COM 3479160SSherry.Moore@Sun.COM barg->gb_walkret = EG_UNKBOOTFS; 3489160SSherry.Moore@Sun.COM (void) zfs_iter_filesystems(zfh, match_bootfs, barg); 3499160SSherry.Moore@Sun.COM zfs_close(zfh); 3509160SSherry.Moore@Sun.COM 3519160SSherry.Moore@Sun.COM if (barg->gb_walkret == 0) 3529160SSherry.Moore@Sun.COM (void) grub_fsd_get_mountp(barg->gb_root.gr_fs + 3539160SSherry.Moore@Sun.COM GRBM_ZFS_BOOTFS, MNTTYPE_ZFS); 3549160SSherry.Moore@Sun.COM 3559160SSherry.Moore@Sun.COM return (barg->gb_walkret); 3569160SSherry.Moore@Sun.COM } 357