xref: /onnv-gate/usr/src/lib/libgrubmgmt/common/libgrub_cmd.c (revision 9160:1517e6edbc6f)
1*9160SSherry.Moore@Sun.COM /*
2*9160SSherry.Moore@Sun.COM  * CDDL HEADER START
3*9160SSherry.Moore@Sun.COM  *
4*9160SSherry.Moore@Sun.COM  * The contents of this file are subject to the terms of the
5*9160SSherry.Moore@Sun.COM  * Common Development and Distribution License (the "License").
6*9160SSherry.Moore@Sun.COM  * You may not use this file except in compliance with the License.
7*9160SSherry.Moore@Sun.COM  *
8*9160SSherry.Moore@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9160SSherry.Moore@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*9160SSherry.Moore@Sun.COM  * See the License for the specific language governing permissions
11*9160SSherry.Moore@Sun.COM  * and limitations under the License.
12*9160SSherry.Moore@Sun.COM  *
13*9160SSherry.Moore@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*9160SSherry.Moore@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9160SSherry.Moore@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*9160SSherry.Moore@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*9160SSherry.Moore@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9160SSherry.Moore@Sun.COM  *
19*9160SSherry.Moore@Sun.COM  * CDDL HEADER END
20*9160SSherry.Moore@Sun.COM  */
21*9160SSherry.Moore@Sun.COM /*
22*9160SSherry.Moore@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*9160SSherry.Moore@Sun.COM  * Use is subject to license terms.
24*9160SSherry.Moore@Sun.COM  */
25*9160SSherry.Moore@Sun.COM 
26*9160SSherry.Moore@Sun.COM /*
27*9160SSherry.Moore@Sun.COM  * This file contains all the functions that implement the following
28*9160SSherry.Moore@Sun.COM  * GRUB commands:
29*9160SSherry.Moore@Sun.COM  *	kernel, kernel$, module, module$, findroot, bootfs
30*9160SSherry.Moore@Sun.COM  * Return 0 on success, errno on failure.
31*9160SSherry.Moore@Sun.COM  */
32*9160SSherry.Moore@Sun.COM #include <stdio.h>
33*9160SSherry.Moore@Sun.COM #include <stdlib.h>
34*9160SSherry.Moore@Sun.COM #include <assert.h>
35*9160SSherry.Moore@Sun.COM #include <alloca.h>
36*9160SSherry.Moore@Sun.COM #include <errno.h>
37*9160SSherry.Moore@Sun.COM #include <strings.h>
38*9160SSherry.Moore@Sun.COM #include <unistd.h>
39*9160SSherry.Moore@Sun.COM #include <fcntl.h>
40*9160SSherry.Moore@Sun.COM #include <sys/types.h>
41*9160SSherry.Moore@Sun.COM #include <sys/fs/ufs_mount.h>
42*9160SSherry.Moore@Sun.COM #include <sys/dktp/fdisk.h>
43*9160SSherry.Moore@Sun.COM #if defined(__i386)
44*9160SSherry.Moore@Sun.COM #include <sys/x86_archext.h>
45*9160SSherry.Moore@Sun.COM #endif /* __i386 */
46*9160SSherry.Moore@Sun.COM 
47*9160SSherry.Moore@Sun.COM #include "libgrub_impl.h"
48*9160SSherry.Moore@Sun.COM 
49*9160SSherry.Moore@Sun.COM #define	RESET_MODULE(barg)	((barg)->gb_module[0] = 0)
50*9160SSherry.Moore@Sun.COM 
51*9160SSherry.Moore@Sun.COM #if defined(__i386)
52*9160SSherry.Moore@Sun.COM static const char cpuid_dev[] = "/dev/cpu/self/cpuid";
53*9160SSherry.Moore@Sun.COM 
54*9160SSherry.Moore@Sun.COM /*
55*9160SSherry.Moore@Sun.COM  * Return 1 if the system supports 64-bit mode, 0 if it doesn't,
56*9160SSherry.Moore@Sun.COM  * or -1 on failure.
57*9160SSherry.Moore@Sun.COM  */
58*9160SSherry.Moore@Sun.COM static int
59*9160SSherry.Moore@Sun.COM cpuid_64bit_capable(void)
60*9160SSherry.Moore@Sun.COM {
61*9160SSherry.Moore@Sun.COM 	int fd, ret = -1;
62*9160SSherry.Moore@Sun.COM 	struct {
63*9160SSherry.Moore@Sun.COM 		uint32_t cp_eax, cp_ebx, cp_ecx, cp_edx;
64*9160SSherry.Moore@Sun.COM 	} cpuid_regs;
65*9160SSherry.Moore@Sun.COM 
66*9160SSherry.Moore@Sun.COM 	if ((fd = open(cpuid_dev, O_RDONLY)) == -1)
67*9160SSherry.Moore@Sun.COM 		return (ret);
68*9160SSherry.Moore@Sun.COM 
69*9160SSherry.Moore@Sun.COM 	if (pread(fd, &cpuid_regs, sizeof (cpuid_regs), 0x80000001) ==
70*9160SSherry.Moore@Sun.COM 	    sizeof (cpuid_regs))
71*9160SSherry.Moore@Sun.COM 		ret = ((CPUID_AMD_EDX_LM & cpuid_regs.cp_edx) != 0);
72*9160SSherry.Moore@Sun.COM 
73*9160SSherry.Moore@Sun.COM 	(void) close(fd);
74*9160SSherry.Moore@Sun.COM 	return (ret);
75*9160SSherry.Moore@Sun.COM }
76*9160SSherry.Moore@Sun.COM #endif /* __i386 */
77*9160SSherry.Moore@Sun.COM 
78*9160SSherry.Moore@Sun.COM 
79*9160SSherry.Moore@Sun.COM /*
80*9160SSherry.Moore@Sun.COM  * Expand $ISAIDR
81*9160SSherry.Moore@Sun.COM  */
82*9160SSherry.Moore@Sun.COM #if !defined(__i386)
83*9160SSherry.Moore@Sun.COM /* ARGSUSED */
84*9160SSherry.Moore@Sun.COM #endif /* __i386 */
85*9160SSherry.Moore@Sun.COM static size_t
86*9160SSherry.Moore@Sun.COM barg_isadir_var(char *var, int sz)
87*9160SSherry.Moore@Sun.COM {
88*9160SSherry.Moore@Sun.COM #if defined(__i386)
89*9160SSherry.Moore@Sun.COM 	if (cpuid_64bit_capable() == 1)
90*9160SSherry.Moore@Sun.COM 		return (strlcpy(var, "amd64", sz));
91*9160SSherry.Moore@Sun.COM #endif /* __i386 */
92*9160SSherry.Moore@Sun.COM 
93*9160SSherry.Moore@Sun.COM 	var[0] = 0;
94*9160SSherry.Moore@Sun.COM 	return (0);
95*9160SSherry.Moore@Sun.COM }
96*9160SSherry.Moore@Sun.COM 
97*9160SSherry.Moore@Sun.COM /*
98*9160SSherry.Moore@Sun.COM  * Expand $ZFS-BOOTFS
99*9160SSherry.Moore@Sun.COM  */
100*9160SSherry.Moore@Sun.COM static size_t
101*9160SSherry.Moore@Sun.COM barg_bootfs_var(const grub_barg_t *barg, char *var, int sz)
102*9160SSherry.Moore@Sun.COM {
103*9160SSherry.Moore@Sun.COM 	int n;
104*9160SSherry.Moore@Sun.COM 
105*9160SSherry.Moore@Sun.COM 	assert(barg);
106*9160SSherry.Moore@Sun.COM 	if (strcmp(barg->gb_root.gr_fstyp, MNTTYPE_ZFS) == 0) {
107*9160SSherry.Moore@Sun.COM 		n = snprintf(var, sz, "zfs-bootfs=%s,bootpath=\"%s\"",
108*9160SSherry.Moore@Sun.COM 		    barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev,
109*9160SSherry.Moore@Sun.COM 		    barg->gb_root.gr_physpath);
110*9160SSherry.Moore@Sun.COM 	} else	{
111*9160SSherry.Moore@Sun.COM 		var[0] = 0;
112*9160SSherry.Moore@Sun.COM 		n = 0;
113*9160SSherry.Moore@Sun.COM 	}
114*9160SSherry.Moore@Sun.COM 	return (n);
115*9160SSherry.Moore@Sun.COM }
116*9160SSherry.Moore@Sun.COM 
117*9160SSherry.Moore@Sun.COM /*
118*9160SSherry.Moore@Sun.COM  * Expand all the variables without appending them more than once.
119*9160SSherry.Moore@Sun.COM  */
120*9160SSherry.Moore@Sun.COM static int
121*9160SSherry.Moore@Sun.COM expand_var(char *arg, size_t argsz, const char *var, size_t varsz,
122*9160SSherry.Moore@Sun.COM     char *val, size_t valsz)
123*9160SSherry.Moore@Sun.COM {
124*9160SSherry.Moore@Sun.COM 	char	*sp = arg;
125*9160SSherry.Moore@Sun.COM 	size_t	sz = argsz, len;
126*9160SSherry.Moore@Sun.COM 	char	*buf, *dst, *src;
127*9160SSherry.Moore@Sun.COM 	int	ret = 0;
128*9160SSherry.Moore@Sun.COM 
129*9160SSherry.Moore@Sun.COM 	buf = alloca(argsz);
130*9160SSherry.Moore@Sun.COM 	dst = buf;
131*9160SSherry.Moore@Sun.COM 
132*9160SSherry.Moore@Sun.COM 	while ((src = strstr(sp, var)) != NULL) {
133*9160SSherry.Moore@Sun.COM 
134*9160SSherry.Moore@Sun.COM 		len = src - sp;
135*9160SSherry.Moore@Sun.COM 
136*9160SSherry.Moore@Sun.COM 		if (len + valsz > sz) {
137*9160SSherry.Moore@Sun.COM 			ret = E2BIG;
138*9160SSherry.Moore@Sun.COM 			break;
139*9160SSherry.Moore@Sun.COM 		}
140*9160SSherry.Moore@Sun.COM 
141*9160SSherry.Moore@Sun.COM 		(void) bcopy(sp, dst, len);
142*9160SSherry.Moore@Sun.COM 		(void) bcopy(val, dst + len, valsz);
143*9160SSherry.Moore@Sun.COM 		dst += len + valsz;
144*9160SSherry.Moore@Sun.COM 		sz -= len + valsz;
145*9160SSherry.Moore@Sun.COM 		sp = src + varsz;
146*9160SSherry.Moore@Sun.COM 	}
147*9160SSherry.Moore@Sun.COM 
148*9160SSherry.Moore@Sun.COM 	if (strlcpy(dst, sp, sz) >= sz)
149*9160SSherry.Moore@Sun.COM 		ret = E2BIG;
150*9160SSherry.Moore@Sun.COM 
151*9160SSherry.Moore@Sun.COM 	if (ret == 0)
152*9160SSherry.Moore@Sun.COM 		bcopy(buf, arg, argsz);
153*9160SSherry.Moore@Sun.COM 	return (ret);
154*9160SSherry.Moore@Sun.COM }
155*9160SSherry.Moore@Sun.COM 
156*9160SSherry.Moore@Sun.COM static int
157*9160SSherry.Moore@Sun.COM match_bootfs(zfs_handle_t *zfh, void *data)
158*9160SSherry.Moore@Sun.COM {
159*9160SSherry.Moore@Sun.COM 	int		ret;
160*9160SSherry.Moore@Sun.COM 	const char	*zfn;
161*9160SSherry.Moore@Sun.COM 	grub_barg_t	*barg = (grub_barg_t *)data;
162*9160SSherry.Moore@Sun.COM 
163*9160SSherry.Moore@Sun.COM 	ret = (zfs_get_type(zfh) == ZFS_TYPE_FILESYSTEM &&
164*9160SSherry.Moore@Sun.COM 	    (zfn = zfs_get_name(zfh)) != NULL &&
165*9160SSherry.Moore@Sun.COM 	    strcmp(barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev, zfn) == 0);
166*9160SSherry.Moore@Sun.COM 
167*9160SSherry.Moore@Sun.COM 	if (ret != 0)
168*9160SSherry.Moore@Sun.COM 		barg->gb_walkret = 0;
169*9160SSherry.Moore@Sun.COM 	else
170*9160SSherry.Moore@Sun.COM 		(void) zfs_iter_filesystems(zfh, match_bootfs, barg);
171*9160SSherry.Moore@Sun.COM 
172*9160SSherry.Moore@Sun.COM 	zfs_close(zfh);
173*9160SSherry.Moore@Sun.COM 	return (barg->gb_walkret == 0);
174*9160SSherry.Moore@Sun.COM }
175*9160SSherry.Moore@Sun.COM 
176*9160SSherry.Moore@Sun.COM static void
177*9160SSherry.Moore@Sun.COM reset_root(grub_barg_t *barg)
178*9160SSherry.Moore@Sun.COM {
179*9160SSherry.Moore@Sun.COM 	(void) memset(&barg->gb_root, 0, sizeof (barg->gb_root));
180*9160SSherry.Moore@Sun.COM 	barg->gb_bootsign[0] = 0;
181*9160SSherry.Moore@Sun.COM 	barg->gb_kernel[0] = 0;
182*9160SSherry.Moore@Sun.COM 	RESET_MODULE(barg);
183*9160SSherry.Moore@Sun.COM }
184*9160SSherry.Moore@Sun.COM 
185*9160SSherry.Moore@Sun.COM /* ARGSUSED */
186*9160SSherry.Moore@Sun.COM int
187*9160SSherry.Moore@Sun.COM skip_line(const grub_line_t *lp, grub_barg_t *barg)
188*9160SSherry.Moore@Sun.COM {
189*9160SSherry.Moore@Sun.COM 	return (0);
190*9160SSherry.Moore@Sun.COM }
191*9160SSherry.Moore@Sun.COM 
192*9160SSherry.Moore@Sun.COM /* ARGSUSED */
193*9160SSherry.Moore@Sun.COM int
194*9160SSherry.Moore@Sun.COM error_line(const grub_line_t *lp, grub_barg_t *barg)
195*9160SSherry.Moore@Sun.COM {
196*9160SSherry.Moore@Sun.COM 	return (EG_INVALIDLINE);
197*9160SSherry.Moore@Sun.COM }
198*9160SSherry.Moore@Sun.COM 
199*9160SSherry.Moore@Sun.COM int
200*9160SSherry.Moore@Sun.COM kernel(const grub_line_t *lp, grub_barg_t *barg)
201*9160SSherry.Moore@Sun.COM {
202*9160SSherry.Moore@Sun.COM 	RESET_MODULE(barg);
203*9160SSherry.Moore@Sun.COM 	if (strlcpy(barg->gb_kernel, lp->gl_arg, sizeof (barg->gb_kernel)) >=
204*9160SSherry.Moore@Sun.COM 	    sizeof (barg->gb_kernel))
205*9160SSherry.Moore@Sun.COM 		return (E2BIG);
206*9160SSherry.Moore@Sun.COM 
207*9160SSherry.Moore@Sun.COM 	return (0);
208*9160SSherry.Moore@Sun.COM }
209*9160SSherry.Moore@Sun.COM 
210*9160SSherry.Moore@Sun.COM int
211*9160SSherry.Moore@Sun.COM module(const grub_line_t *lp, grub_barg_t *barg)
212*9160SSherry.Moore@Sun.COM {
213*9160SSherry.Moore@Sun.COM 	if (strlcpy(barg->gb_module, lp->gl_arg, sizeof (barg->gb_module)) >=
214*9160SSherry.Moore@Sun.COM 	    sizeof (barg->gb_module))
215*9160SSherry.Moore@Sun.COM 		return (E2BIG);
216*9160SSherry.Moore@Sun.COM 
217*9160SSherry.Moore@Sun.COM 	return (0);
218*9160SSherry.Moore@Sun.COM }
219*9160SSherry.Moore@Sun.COM 
220*9160SSherry.Moore@Sun.COM int
221*9160SSherry.Moore@Sun.COM dollar_kernel(const grub_line_t *lp, grub_barg_t *barg)
222*9160SSherry.Moore@Sun.COM {
223*9160SSherry.Moore@Sun.COM 	int	ret;
224*9160SSherry.Moore@Sun.COM 	size_t	bfslen, isalen;
225*9160SSherry.Moore@Sun.COM 	char	isadir[32];
226*9160SSherry.Moore@Sun.COM 	char	bootfs[BOOTARGS_MAX];
227*9160SSherry.Moore@Sun.COM 
228*9160SSherry.Moore@Sun.COM 	RESET_MODULE(barg);
229*9160SSherry.Moore@Sun.COM 	if (strlcpy(barg->gb_kernel, lp->gl_arg, sizeof (barg->gb_kernel)) >=
230*9160SSherry.Moore@Sun.COM 	    sizeof (barg->gb_kernel))
231*9160SSherry.Moore@Sun.COM 		return (E2BIG);
232*9160SSherry.Moore@Sun.COM 
233*9160SSherry.Moore@Sun.COM 	bfslen = barg_bootfs_var(barg, bootfs, sizeof (bootfs));
234*9160SSherry.Moore@Sun.COM 	isalen = barg_isadir_var(isadir, sizeof (isadir));
235*9160SSherry.Moore@Sun.COM 
236*9160SSherry.Moore@Sun.COM 	if (bfslen >= sizeof (bootfs) || isalen >= sizeof (isadir))
237*9160SSherry.Moore@Sun.COM 		return (EINVAL);
238*9160SSherry.Moore@Sun.COM 
239*9160SSherry.Moore@Sun.COM 	if ((ret = expand_var(barg->gb_kernel, sizeof (barg->gb_kernel),
240*9160SSherry.Moore@Sun.COM 	    ZFS_BOOT_VAR, strlen(ZFS_BOOT_VAR), bootfs, bfslen)) != 0)
241*9160SSherry.Moore@Sun.COM 		return (ret);
242*9160SSherry.Moore@Sun.COM 
243*9160SSherry.Moore@Sun.COM 	ret = expand_var(barg->gb_kernel, sizeof (barg->gb_kernel),
244*9160SSherry.Moore@Sun.COM 	    ISADIR_VAR, strlen(ISADIR_VAR), isadir, isalen);
245*9160SSherry.Moore@Sun.COM 
246*9160SSherry.Moore@Sun.COM 	return (ret);
247*9160SSherry.Moore@Sun.COM }
248*9160SSherry.Moore@Sun.COM 
249*9160SSherry.Moore@Sun.COM int
250*9160SSherry.Moore@Sun.COM dollar_module(const grub_line_t *lp, grub_barg_t *barg)
251*9160SSherry.Moore@Sun.COM {
252*9160SSherry.Moore@Sun.COM 	int	ret;
253*9160SSherry.Moore@Sun.COM 	size_t	isalen;
254*9160SSherry.Moore@Sun.COM 	char	isadir[32];
255*9160SSherry.Moore@Sun.COM 
256*9160SSherry.Moore@Sun.COM 	if (strlcpy(barg->gb_module, lp->gl_arg, sizeof (barg->gb_module)) >=
257*9160SSherry.Moore@Sun.COM 	    sizeof (barg->gb_module))
258*9160SSherry.Moore@Sun.COM 		return (E2BIG);
259*9160SSherry.Moore@Sun.COM 
260*9160SSherry.Moore@Sun.COM 	if ((isalen = barg_isadir_var(isadir, sizeof (isadir))) >= sizeof
261*9160SSherry.Moore@Sun.COM 	    (isadir))
262*9160SSherry.Moore@Sun.COM 		return (EINVAL);
263*9160SSherry.Moore@Sun.COM 
264*9160SSherry.Moore@Sun.COM 	ret = expand_var(barg->gb_module, sizeof (barg->gb_module),
265*9160SSherry.Moore@Sun.COM 	    ISADIR_VAR, strlen(ISADIR_VAR), isadir, isalen);
266*9160SSherry.Moore@Sun.COM 
267*9160SSherry.Moore@Sun.COM 	return (ret);
268*9160SSherry.Moore@Sun.COM }
269*9160SSherry.Moore@Sun.COM 
270*9160SSherry.Moore@Sun.COM 
271*9160SSherry.Moore@Sun.COM int
272*9160SSherry.Moore@Sun.COM findroot(const grub_line_t *lp, grub_barg_t *barg)
273*9160SSherry.Moore@Sun.COM {
274*9160SSherry.Moore@Sun.COM 	size_t sz, bsz;
275*9160SSherry.Moore@Sun.COM 	const char *sign;
276*9160SSherry.Moore@Sun.COM 
277*9160SSherry.Moore@Sun.COM 	reset_root(barg);
278*9160SSherry.Moore@Sun.COM 
279*9160SSherry.Moore@Sun.COM 	sign = lp->gl_arg;
280*9160SSherry.Moore@Sun.COM 	barg->gb_prtnum = (uint_t)PRTNUM_INVALID;
281*9160SSherry.Moore@Sun.COM 	barg->gb_slcnum = (uint_t)SLCNUM_WHOLE_DISK;
282*9160SSherry.Moore@Sun.COM 
283*9160SSherry.Moore@Sun.COM 	if (sign[0] == '(') {
284*9160SSherry.Moore@Sun.COM 		const char *pos;
285*9160SSherry.Moore@Sun.COM 
286*9160SSherry.Moore@Sun.COM 		++sign;
287*9160SSherry.Moore@Sun.COM 		if ((pos = strchr(sign, ',')) == NULL || (sz = pos - sign) == 0)
288*9160SSherry.Moore@Sun.COM 			return (EG_FINDROOTFMT);
289*9160SSherry.Moore@Sun.COM 
290*9160SSherry.Moore@Sun.COM 		++pos;
291*9160SSherry.Moore@Sun.COM 		if (!IS_PRTNUM_VALID(barg->gb_prtnum = pos[0] - '0'))
292*9160SSherry.Moore@Sun.COM 			return (EG_FINDROOTFMT);
293*9160SSherry.Moore@Sun.COM 
294*9160SSherry.Moore@Sun.COM 		++pos;
295*9160SSherry.Moore@Sun.COM 		if (pos[0] != ',' ||
296*9160SSherry.Moore@Sun.COM 		    !IS_SLCNUM_VALID(barg->gb_slcnum = pos[1]) ||
297*9160SSherry.Moore@Sun.COM 		    pos[2] != ')')
298*9160SSherry.Moore@Sun.COM 			return (EG_FINDROOTFMT);
299*9160SSherry.Moore@Sun.COM 	} else {
300*9160SSherry.Moore@Sun.COM 		sz = strlen(sign);
301*9160SSherry.Moore@Sun.COM 	}
302*9160SSherry.Moore@Sun.COM 
303*9160SSherry.Moore@Sun.COM 	bsz = strlen(BOOTSIGN_DIR "/");
304*9160SSherry.Moore@Sun.COM 	if (bsz + sz + 1 > sizeof (barg->gb_bootsign))
305*9160SSherry.Moore@Sun.COM 		return (E2BIG);
306*9160SSherry.Moore@Sun.COM 
307*9160SSherry.Moore@Sun.COM 	bcopy(BOOTSIGN_DIR "/", barg->gb_bootsign, bsz);
308*9160SSherry.Moore@Sun.COM 	bcopy(sign, barg->gb_bootsign + bsz, sz);
309*9160SSherry.Moore@Sun.COM 	barg->gb_bootsign [bsz + sz] = 0;
310*9160SSherry.Moore@Sun.COM 
311*9160SSherry.Moore@Sun.COM 	return (grub_find_bootsign(barg));
312*9160SSherry.Moore@Sun.COM }
313*9160SSherry.Moore@Sun.COM 
314*9160SSherry.Moore@Sun.COM int
315*9160SSherry.Moore@Sun.COM bootfs(const grub_line_t *lp, grub_barg_t *barg)
316*9160SSherry.Moore@Sun.COM {
317*9160SSherry.Moore@Sun.COM 	zfs_handle_t	*zfh;
318*9160SSherry.Moore@Sun.COM 	grub_menu_t	*mp = barg->gb_entry->ge_menu;
319*9160SSherry.Moore@Sun.COM 	char		*gfs_devp;
320*9160SSherry.Moore@Sun.COM 	size_t		gfs_dev_len;
321*9160SSherry.Moore@Sun.COM 
322*9160SSherry.Moore@Sun.COM 	/* Check if root is zfs */
323*9160SSherry.Moore@Sun.COM 	if (strcmp(barg->gb_root.gr_fstyp, MNTTYPE_ZFS) != 0)
324*9160SSherry.Moore@Sun.COM 		return (EG_NOTZFS);
325*9160SSherry.Moore@Sun.COM 
326*9160SSherry.Moore@Sun.COM 	gfs_devp = barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev;
327*9160SSherry.Moore@Sun.COM 	gfs_dev_len = sizeof (barg->gb_root.gr_fs[GRBM_ZFS_BOOTFS].gfs_dev);
328*9160SSherry.Moore@Sun.COM 
329*9160SSherry.Moore@Sun.COM 	/*
330*9160SSherry.Moore@Sun.COM 	 * If the bootfs value is the same as the bootfs for the pool,
331*9160SSherry.Moore@Sun.COM 	 * do nothing.
332*9160SSherry.Moore@Sun.COM 	 */
333*9160SSherry.Moore@Sun.COM 	if (strcmp(lp->gl_arg, gfs_devp) == 0)
334*9160SSherry.Moore@Sun.COM 		return (0);
335*9160SSherry.Moore@Sun.COM 
336*9160SSherry.Moore@Sun.COM 	if (strlcpy(gfs_devp, lp->gl_arg, gfs_dev_len) >= gfs_dev_len)
337*9160SSherry.Moore@Sun.COM 		return (E2BIG);
338*9160SSherry.Moore@Sun.COM 
339*9160SSherry.Moore@Sun.COM 	/* check if specified bootfs belongs to the root pool */
340*9160SSherry.Moore@Sun.COM 	if ((zfh = zfs_open(mp->gm_fs.gf_lzfh,
341*9160SSherry.Moore@Sun.COM 	    barg->gb_root.gr_fs[GRBM_ZFS_TOPFS].gfs_dev,
342*9160SSherry.Moore@Sun.COM 	    ZFS_TYPE_FILESYSTEM)) == NULL)
343*9160SSherry.Moore@Sun.COM 		return (EG_OPENZFS);
344*9160SSherry.Moore@Sun.COM 
345*9160SSherry.Moore@Sun.COM 	barg->gb_walkret = EG_UNKBOOTFS;
346*9160SSherry.Moore@Sun.COM 	(void) zfs_iter_filesystems(zfh, match_bootfs, barg);
347*9160SSherry.Moore@Sun.COM 	zfs_close(zfh);
348*9160SSherry.Moore@Sun.COM 
349*9160SSherry.Moore@Sun.COM 	if (barg->gb_walkret == 0)
350*9160SSherry.Moore@Sun.COM 		(void) grub_fsd_get_mountp(barg->gb_root.gr_fs +
351*9160SSherry.Moore@Sun.COM 		    GRBM_ZFS_BOOTFS, MNTTYPE_ZFS);
352*9160SSherry.Moore@Sun.COM 
353*9160SSherry.Moore@Sun.COM 	return (barg->gb_walkret);
354*9160SSherry.Moore@Sun.COM }
355