xref: /titanic_52/usr/src/lib/libbe/common/be_activate.c (revision 9a4a12bd7ce60cd60eae508b25eb7a8dae765274)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
28  * Copyright 2016 Toomas Soome <tsoome@me.com>
29  */
30 
31 #include <assert.h>
32 #include <libintl.h>
33 #include <libnvpair.h>
34 #include <libzfs.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <strings.h>
39 #include <errno.h>
40 #include <sys/mnttab.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include <sys/efi_partition.h>
46 
47 #include <libbe.h>
48 #include <libbe_priv.h>
49 
50 char	*mnttab = MNTTAB;
51 
52 /*
53  * Private function prototypes
54  */
55 static int set_bootfs(char *boot_rpool, char *be_root_ds);
56 static int set_canmount(be_node_list_t *, char *);
57 static boolean_t be_do_install_mbr(char *, nvlist_t *);
58 static int be_do_installboot_helper(zpool_handle_t *, nvlist_t *, char *,
59     char *, uint16_t);
60 static int be_do_installboot(be_transaction_data_t *, uint16_t);
61 static int be_get_grub_vers(be_transaction_data_t *, char **, char **);
62 static int get_ver_from_capfile(char *, char **);
63 static int be_promote_zone_ds(char *, char *);
64 static int be_promote_ds_callback(zfs_handle_t *, void *);
65 
66 /* ******************************************************************** */
67 /*			Public Functions				*/
68 /* ******************************************************************** */
69 
70 /*
71  * Function:	be_activate
72  * Description:	Calls _be_activate which activates the BE named in the
73  *		attributes passed in through be_attrs. The process of
74  *		activation sets the bootfs property of the root pool, resets
75  *		the canmount property to noauto, and sets the default in the
76  *		grub menu to the entry corresponding to the entry for the named
77  *		BE.
78  * Parameters:
79  *		be_attrs - pointer to nvlist_t of attributes being passed in.
80  *			The follow attribute values are used by this function:
81  *
82  *			BE_ATTR_ORIG_BE_NAME		*required
83  * Return:
84  *		BE_SUCCESS - Success
85  *		be_errno_t - Failure
86  * Scope:
87  *		Public
88  */
89 int
90 be_activate(nvlist_t *be_attrs)
91 {
92 	int	ret = BE_SUCCESS;
93 	char	*be_name = NULL;
94 
95 	/* Initialize libzfs handle */
96 	if (!be_zfs_init())
97 		return (BE_ERR_INIT);
98 
99 	/* Get the BE name to activate */
100 	if (nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, &be_name)
101 	    != 0) {
102 		be_print_err(gettext("be_activate: failed to "
103 		    "lookup BE_ATTR_ORIG_BE_NAME attribute\n"));
104 		be_zfs_fini();
105 		return (BE_ERR_INVAL);
106 	}
107 
108 	/* Validate BE name */
109 	if (!be_valid_be_name(be_name)) {
110 		be_print_err(gettext("be_activate: invalid BE name %s\n"),
111 		    be_name);
112 		be_zfs_fini();
113 		return (BE_ERR_INVAL);
114 	}
115 
116 	ret = _be_activate(be_name);
117 
118 	be_zfs_fini();
119 
120 	return (ret);
121 }
122 
123 /*
124  * Function:	be_installboot
125  * Description:	Calls be_do_installboot to install/update bootloader on
126  *		pool passed in through be_attrs. The primary consumer is
127  *		bootadm command to avoid duplication of the code.
128  * Parameters:
129  *		be_attrs - pointer to nvlist_t of attributes being passed in.
130  *			The following attribute values are used:
131  *
132  *			BE_ATTR_ORIG_BE_NAME		*required
133  *			BE_ATTR_ORIG_BE_POOL		*required
134  *			BE_ATTR_ORIG_BE_ROOT		*required
135  *			BE_ATTR_INSTALL_FLAGS		optional
136  *
137  * Return:
138  *		BE_SUCCESS - Success
139  *		be_errno_t - Failure
140  * Scope:
141  *		Public
142  */
143 int
144 be_installboot(nvlist_t *be_attrs)
145 {
146 	int		ret = BE_SUCCESS;
147 	uint16_t	flags = 0;
148 	uint16_t	verbose;
149 	be_transaction_data_t bt = { 0 };
150 
151 	/* Get flags */
152 	if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK,
153 	    BE_ATTR_INSTALL_FLAGS, DATA_TYPE_UINT16, &flags, NULL) != 0) {
154 		be_print_err(gettext("be_installboot: failed to lookup "
155 		    "BE_ATTR_INSTALL_FLAGS attribute\n"));
156 		return (BE_ERR_INVAL);
157 	}
158 
159 	/* Set verbose early, so we get all messages */
160 	verbose = flags & BE_INSTALLBOOT_FLAG_VERBOSE;
161 	if (verbose == BE_INSTALLBOOT_FLAG_VERBOSE)
162 		libbe_print_errors(B_TRUE);
163 
164 	ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME,
165 	    &bt.obe_name);
166 	if (ret != 0) {
167 		be_print_err(gettext("be_installboot: failed to "
168 		    "lookup BE_ATTR_ORIG_BE_NAME attribute\n"));
169 		return (BE_ERR_INVAL);
170 	}
171 
172 	ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_POOL,
173 	    &bt.obe_zpool);
174 	if (ret != 0) {
175 		be_print_err(gettext("be_installboot: failed to "
176 		    "lookup BE_ATTR_ORIG_BE_POOL attribute\n"));
177 		return (BE_ERR_INVAL);
178 	}
179 
180 	ret = nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_ROOT,
181 	    &bt.obe_root_ds);
182 	if (ret != 0) {
183 		be_print_err(gettext("be_installboot: failed to "
184 		    "lookup BE_ATTR_ORIG_BE_ROOT attribute\n"));
185 		return (BE_ERR_INVAL);
186 	}
187 
188 	/* Initialize libzfs handle */
189 	if (!be_zfs_init())
190 		return (BE_ERR_INIT);
191 
192 	ret = be_do_installboot(&bt, flags);
193 
194 	be_zfs_fini();
195 
196 	return (ret);
197 }
198 
199 /* ******************************************************************** */
200 /*			Semi Private Functions				*/
201 /* ******************************************************************** */
202 
203 /*
204  * Function:	_be_activate
205  * Description:	This does the actual work described in be_activate.
206  * Parameters:
207  *		be_name - pointer to the name of BE to activate.
208  *
209  * Return:
210  *		BE_SUCCESS - Success
211  *		be_errnot_t - Failure
212  * Scope:
213  *		Public
214  */
215 int
216 _be_activate(char *be_name)
217 {
218 	be_transaction_data_t cb = { 0 };
219 	zfs_handle_t	*zhp = NULL;
220 	char		root_ds[MAXPATHLEN];
221 	char		active_ds[MAXPATHLEN];
222 	be_node_list_t	*be_nodes = NULL;
223 	uuid_t		uu = {0};
224 	int		entry, ret = BE_SUCCESS;
225 	int		zret = 0;
226 
227 	/*
228 	 * TODO: The BE needs to be validated to make sure that it is actually
229 	 * a bootable BE.
230 	 */
231 
232 	if (be_name == NULL)
233 		return (BE_ERR_INVAL);
234 
235 	/* Set obe_name to be_name in the cb structure */
236 	cb.obe_name = be_name;
237 
238 	/* find which zpool the be is in */
239 	if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &cb)) == 0) {
240 		be_print_err(gettext("be_activate: failed to "
241 		    "find zpool for BE (%s)\n"), cb.obe_name);
242 		return (BE_ERR_BE_NOENT);
243 	} else if (zret < 0) {
244 		be_print_err(gettext("be_activate: "
245 		    "zpool_iter failed: %s\n"),
246 		    libzfs_error_description(g_zfs));
247 		ret = zfs_err_to_be_err(g_zfs);
248 		return (ret);
249 	}
250 
251 	be_make_root_ds(cb.obe_zpool, cb.obe_name, root_ds, sizeof (root_ds));
252 	cb.obe_root_ds = strdup(root_ds);
253 
254 	if (getzoneid() == GLOBAL_ZONEID) {
255 		ret = be_do_installboot(&cb, BE_INSTALLBOOT_FLAG_NULL);
256 		if (ret != BE_SUCCESS)
257 			return (ret);
258 
259 		if (!be_has_menu_entry(root_ds, cb.obe_zpool, &entry)) {
260 			if ((ret = be_append_menu(cb.obe_name, cb.obe_zpool,
261 			    NULL, NULL, NULL)) != BE_SUCCESS) {
262 				be_print_err(gettext("be_activate: Failed to "
263 				    "add BE (%s) to the menu\n"),
264 				    cb.obe_name);
265 				goto done;
266 			}
267 		}
268 		if (be_has_grub()) {
269 			if ((ret = be_change_grub_default(cb.obe_name,
270 			    cb.obe_zpool)) != BE_SUCCESS) {
271 				be_print_err(gettext("be_activate: failed to "
272 				    "change the default entry in menu.lst\n"));
273 				goto done;
274 			}
275 		}
276 	}
277 
278 	if ((ret = _be_list(cb.obe_name, &be_nodes)) != BE_SUCCESS) {
279 		return (ret);
280 	}
281 
282 	if ((ret = set_canmount(be_nodes, "noauto")) != BE_SUCCESS) {
283 		be_print_err(gettext("be_activate: failed to set "
284 		    "canmount dataset property\n"));
285 		goto done;
286 	}
287 
288 	if (getzoneid() == GLOBAL_ZONEID) {
289 		if ((ret = set_bootfs(be_nodes->be_rpool,
290 		    root_ds)) != BE_SUCCESS) {
291 			be_print_err(gettext("be_activate: failed to set "
292 			    "bootfs pool property for %s\n"), root_ds);
293 			goto done;
294 		}
295 	}
296 
297 	if ((zhp = zfs_open(g_zfs, root_ds, ZFS_TYPE_FILESYSTEM)) != NULL) {
298 		/*
299 		 * We don't need to close the zfs handle at this
300 		 * point because The callback funtion
301 		 * be_promote_ds_callback() will close it for us.
302 		 */
303 		if (be_promote_ds_callback(zhp, NULL) != 0) {
304 			be_print_err(gettext("be_activate: "
305 			    "failed to activate the "
306 			    "datasets for %s: %s\n"),
307 			    root_ds,
308 			    libzfs_error_description(g_zfs));
309 			ret = BE_ERR_PROMOTE;
310 			goto done;
311 		}
312 	} else {
313 		be_print_err(gettext("be_activate: failed to open "
314 		    "dataset (%s): %s\n"), root_ds,
315 		    libzfs_error_description(g_zfs));
316 		ret = zfs_err_to_be_err(g_zfs);
317 		goto done;
318 	}
319 
320 	if (getzoneid() == GLOBAL_ZONEID &&
321 	    be_get_uuid(cb.obe_root_ds, &uu) == BE_SUCCESS &&
322 	    (ret = be_promote_zone_ds(cb.obe_name, cb.obe_root_ds))
323 	    != BE_SUCCESS) {
324 		be_print_err(gettext("be_activate: failed to promote "
325 		    "the active zonepath datasets for zones in BE %s\n"),
326 		    cb.obe_name);
327 	}
328 
329 	if (getzoneid() != GLOBAL_ZONEID) {
330 		if (!be_zone_compare_uuids(root_ds)) {
331 			be_print_err(gettext("be_activate: activating zone "
332 			    "root dataset from non-active global BE is not "
333 			    "supported\n"));
334 			ret = BE_ERR_NOTSUP;
335 			goto done;
336 		}
337 		if ((zhp = zfs_open(g_zfs, root_ds,
338 		    ZFS_TYPE_FILESYSTEM)) == NULL) {
339 			be_print_err(gettext("be_activate: failed to open "
340 			    "dataset (%s): %s\n"), root_ds,
341 			    libzfs_error_description(g_zfs));
342 			ret = zfs_err_to_be_err(g_zfs);
343 			goto done;
344 		}
345 		/* Find current active zone root dataset */
346 		if ((ret = be_find_active_zone_root(zhp, cb.obe_zpool,
347 		    active_ds, sizeof (active_ds))) != BE_SUCCESS) {
348 			be_print_err(gettext("be_activate: failed to find "
349 			    "active zone root dataset\n"));
350 			ZFS_CLOSE(zhp);
351 			goto done;
352 		}
353 		/* Do nothing if requested BE is already active */
354 		if (strcmp(root_ds, active_ds) == 0) {
355 			ret = BE_SUCCESS;
356 			ZFS_CLOSE(zhp);
357 			goto done;
358 		}
359 
360 		/* Set active property for BE */
361 		if (zfs_prop_set(zhp, BE_ZONE_ACTIVE_PROPERTY, "on") != 0) {
362 			be_print_err(gettext("be_activate: failed to set "
363 			    "active property (%s): %s\n"), root_ds,
364 			    libzfs_error_description(g_zfs));
365 			ret = zfs_err_to_be_err(g_zfs);
366 			ZFS_CLOSE(zhp);
367 			goto done;
368 		}
369 		ZFS_CLOSE(zhp);
370 
371 		/* Unset active property for old active root dataset */
372 		if ((zhp = zfs_open(g_zfs, active_ds,
373 		    ZFS_TYPE_FILESYSTEM)) == NULL) {
374 			be_print_err(gettext("be_activate: failed to open "
375 			    "dataset (%s): %s\n"), active_ds,
376 			    libzfs_error_description(g_zfs));
377 			ret = zfs_err_to_be_err(g_zfs);
378 			goto done;
379 		}
380 		if (zfs_prop_set(zhp, BE_ZONE_ACTIVE_PROPERTY, "off") != 0) {
381 			be_print_err(gettext("be_activate: failed to unset "
382 			    "active property (%s): %s\n"), active_ds,
383 			    libzfs_error_description(g_zfs));
384 			ret = zfs_err_to_be_err(g_zfs);
385 			ZFS_CLOSE(zhp);
386 			goto done;
387 		}
388 		ZFS_CLOSE(zhp);
389 	}
390 done:
391 	be_free_list(be_nodes);
392 	return (ret);
393 }
394 
395 /*
396  * Function:	be_activate_current_be
397  * Description:	Set the currently "active" BE to be "active on boot"
398  * Paramters:
399  *		none
400  * Returns:
401  *		BE_SUCCESS - Success
402  *		be_errnot_t - Failure
403  * Scope:
404  *		Semi-private (library wide use only)
405  */
406 int
407 be_activate_current_be(void)
408 {
409 	int ret = BE_SUCCESS;
410 	be_transaction_data_t bt = { 0 };
411 
412 	if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) {
413 		return (ret);
414 	}
415 
416 	if ((ret = _be_activate(bt.obe_name)) != BE_SUCCESS) {
417 		be_print_err(gettext("be_activate_current_be: failed to "
418 		    "activate %s\n"), bt.obe_name);
419 		return (ret);
420 	}
421 
422 	return (BE_SUCCESS);
423 }
424 
425 /*
426  * Function:	be_is_active_on_boot
427  * Description:	Checks if the BE name passed in has the "active on boot"
428  *		property set to B_TRUE.
429  * Paramters:
430  *		be_name - the name of the BE to check
431  * Returns:
432  *		B_TRUE - if active on boot.
433  *		B_FALSE - if not active on boot.
434  * Scope:
435  *		Semi-private (library wide use only)
436  */
437 boolean_t
438 be_is_active_on_boot(char *be_name)
439 {
440 	be_node_list_t *be_node = NULL;
441 
442 	if (be_name == NULL) {
443 		be_print_err(gettext("be_is_active_on_boot: "
444 		    "be_name must not be NULL\n"));
445 		return (B_FALSE);
446 	}
447 
448 	if (_be_list(be_name, &be_node) != BE_SUCCESS) {
449 		return (B_FALSE);
450 	}
451 
452 	if (be_node == NULL) {
453 		return (B_FALSE);
454 	}
455 
456 	if (be_node->be_active_on_boot) {
457 		be_free_list(be_node);
458 		return (B_TRUE);
459 	} else {
460 		be_free_list(be_node);
461 		return (B_FALSE);
462 	}
463 }
464 
465 /* ******************************************************************** */
466 /*			Private Functions				*/
467 /* ******************************************************************** */
468 
469 /*
470  * Function:	set_bootfs
471  * Description:	Sets the bootfs property on the boot pool to be the
472  *		root dataset of the activated BE.
473  * Parameters:
474  *		boot_pool - The pool we're setting bootfs in.
475  *		be_root_ds - The main dataset for the BE.
476  * Return:
477  *		BE_SUCCESS - Success
478  *		be_errno_t - Failure
479  * Scope:
480  *		Private
481  */
482 static int
483 set_bootfs(char *boot_rpool, char *be_root_ds)
484 {
485 	zpool_handle_t *zhp;
486 	int err = BE_SUCCESS;
487 
488 	if ((zhp = zpool_open(g_zfs, boot_rpool)) == NULL) {
489 		be_print_err(gettext("set_bootfs: failed to open pool "
490 		    "(%s): %s\n"), boot_rpool, libzfs_error_description(g_zfs));
491 		err = zfs_err_to_be_err(g_zfs);
492 		return (err);
493 	}
494 
495 	err = zpool_set_prop(zhp, "bootfs", be_root_ds);
496 	if (err) {
497 		be_print_err(gettext("set_bootfs: failed to set "
498 		    "bootfs property for pool %s: %s\n"), boot_rpool,
499 		    libzfs_error_description(g_zfs));
500 		err = zfs_err_to_be_err(g_zfs);
501 		zpool_close(zhp);
502 		return (err);
503 	}
504 
505 	zpool_close(zhp);
506 	return (BE_SUCCESS);
507 }
508 
509 /*
510  * Function:	set_canmount
511  * Description:	Sets the canmount property on the datasets of the
512  *		activated BE.
513  * Parameters:
514  *		be_nodes - The be_node_t returned from be_list
515  *		value - The value of canmount we setting, on|off|noauto.
516  * Return:
517  *		BE_SUCCESS - Success
518  *		be_errno_t - Failure
519  * Scope:
520  *		Private
521  */
522 static int
523 set_canmount(be_node_list_t *be_nodes, char *value)
524 {
525 	char		ds_path[MAXPATHLEN];
526 	zfs_handle_t	*zhp = NULL;
527 	be_node_list_t	*list = be_nodes;
528 	int		err = BE_SUCCESS;
529 
530 	while (list != NULL) {
531 		be_dataset_list_t *datasets = list->be_node_datasets;
532 
533 		be_make_root_ds(list->be_rpool, list->be_node_name, ds_path,
534 		    sizeof (ds_path));
535 
536 		if ((zhp = zfs_open(g_zfs, ds_path, ZFS_TYPE_DATASET)) ==
537 		    NULL) {
538 			be_print_err(gettext("set_canmount: failed to open "
539 			    "dataset (%s): %s\n"), ds_path,
540 			    libzfs_error_description(g_zfs));
541 			err = zfs_err_to_be_err(g_zfs);
542 			return (err);
543 		}
544 		if (zfs_prop_get_int(zhp, ZFS_PROP_MOUNTED)) {
545 			/*
546 			 * it's already mounted so we can't change the
547 			 * canmount property anyway.
548 			 */
549 			err = BE_SUCCESS;
550 		} else {
551 			err = zfs_prop_set(zhp,
552 			    zfs_prop_to_name(ZFS_PROP_CANMOUNT), value);
553 			if (err) {
554 				ZFS_CLOSE(zhp);
555 				be_print_err(gettext("set_canmount: failed to "
556 				    "set dataset property (%s): %s\n"),
557 				    ds_path, libzfs_error_description(g_zfs));
558 				err = zfs_err_to_be_err(g_zfs);
559 				return (err);
560 			}
561 		}
562 		ZFS_CLOSE(zhp);
563 
564 		while (datasets != NULL) {
565 			be_make_root_ds(list->be_rpool,
566 			    datasets->be_dataset_name, ds_path,
567 			    sizeof (ds_path));
568 
569 			if ((zhp = zfs_open(g_zfs, ds_path, ZFS_TYPE_DATASET))
570 			    == NULL) {
571 				be_print_err(gettext("set_canmount: failed to "
572 				    "open dataset %s: %s\n"), ds_path,
573 				    libzfs_error_description(g_zfs));
574 				err = zfs_err_to_be_err(g_zfs);
575 				return (err);
576 			}
577 			if (zfs_prop_get_int(zhp, ZFS_PROP_MOUNTED)) {
578 				/*
579 				 * it's already mounted so we can't change the
580 				 * canmount property anyway.
581 				 */
582 				err = BE_SUCCESS;
583 				ZFS_CLOSE(zhp);
584 				break;
585 			}
586 			err = zfs_prop_set(zhp,
587 			    zfs_prop_to_name(ZFS_PROP_CANMOUNT), value);
588 			if (err) {
589 				ZFS_CLOSE(zhp);
590 				be_print_err(gettext("set_canmount: "
591 				    "Failed to set property value %s "
592 				    "for dataset %s: %s\n"), value, ds_path,
593 				    libzfs_error_description(g_zfs));
594 				err = zfs_err_to_be_err(g_zfs);
595 				return (err);
596 			}
597 			ZFS_CLOSE(zhp);
598 			datasets = datasets->be_next_dataset;
599 		}
600 		list = list->be_next_node;
601 	}
602 	return (err);
603 }
604 
605 /*
606  * Function:	be_get_grub_vers
607  * Description:	Gets the grub version number from /boot/grub/capability. If
608  *              capability file doesn't exist NULL is returned.
609  * Parameters:
610  *              bt - The transaction data for the BE we're getting the grub
611  *                   version for.
612  *              cur_vers - used to return the current version of grub from
613  *                         the root pool.
614  *              new_vers - used to return the grub version of the BE we're
615  *                         activating.
616  * Return:
617  *              BE_SUCCESS - Success
618  *              be_errno_t - Failed to find version
619  * Scope:
620  *		Private
621  */
622 static int
623 be_get_grub_vers(be_transaction_data_t *bt, char **cur_vers, char **new_vers)
624 {
625 	zfs_handle_t	*zhp = NULL;
626 	zfs_handle_t	*pool_zhp = NULL;
627 	int ret = BE_SUCCESS;
628 	char cap_file[MAXPATHLEN];
629 	char *temp_mntpnt = NULL;
630 	char *zpool_mntpt = NULL;
631 	char *ptmp_mntpnt = NULL;
632 	char *orig_mntpnt = NULL;
633 	boolean_t be_mounted = B_FALSE;
634 	boolean_t pool_mounted = B_FALSE;
635 
636 	if (!be_has_grub()) {
637 		be_print_err(gettext("be_get_grub_vers: Not supported on "
638 		    "this architecture\n"));
639 		return (BE_ERR_NOTSUP);
640 	}
641 
642 	if (bt == NULL || bt->obe_name == NULL || bt->obe_zpool == NULL ||
643 	    bt->obe_root_ds == NULL) {
644 		be_print_err(gettext("be_get_grub_vers: Invalid BE\n"));
645 		return (BE_ERR_INVAL);
646 	}
647 
648 	if ((pool_zhp = zfs_open(g_zfs, bt->obe_zpool, ZFS_TYPE_FILESYSTEM)) ==
649 	    NULL) {
650 		be_print_err(gettext("be_get_grub_vers: zfs_open failed: %s\n"),
651 		    libzfs_error_description(g_zfs));
652 		return (zfs_err_to_be_err(g_zfs));
653 	}
654 
655 	/*
656 	 * Check to see if the pool's dataset is mounted. If it isn't we'll
657 	 * attempt to mount it.
658 	 */
659 	if ((ret = be_mount_pool(pool_zhp, &ptmp_mntpnt,
660 	    &orig_mntpnt, &pool_mounted)) != BE_SUCCESS) {
661 		be_print_err(gettext("be_get_grub_vers: pool dataset "
662 		    "(%s) could not be mounted\n"), bt->obe_zpool);
663 		ZFS_CLOSE(pool_zhp);
664 		return (ret);
665 	}
666 
667 	/*
668 	 * Get the mountpoint for the root pool dataset.
669 	 */
670 	if (!zfs_is_mounted(pool_zhp, &zpool_mntpt)) {
671 		be_print_err(gettext("be_get_grub_vers: pool "
672 		    "dataset (%s) is not mounted. Can't read the "
673 		    "grub capability file.\n"), bt->obe_zpool);
674 		ret = BE_ERR_NO_MENU;
675 		goto cleanup;
676 	}
677 
678 	/*
679 	 * get the version of the most recent grub update.
680 	 */
681 	(void) snprintf(cap_file, sizeof (cap_file), "%s%s",
682 	    zpool_mntpt, BE_CAP_FILE);
683 	free(zpool_mntpt);
684 	zpool_mntpt = NULL;
685 
686 	if ((ret = get_ver_from_capfile(cap_file, cur_vers)) != BE_SUCCESS)
687 		goto cleanup;
688 
689 	if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) ==
690 	    NULL) {
691 		be_print_err(gettext("be_get_grub_vers: failed to "
692 		    "open BE root dataset (%s): %s\n"), bt->obe_root_ds,
693 		    libzfs_error_description(g_zfs));
694 		free(cur_vers);
695 		ret = zfs_err_to_be_err(g_zfs);
696 		goto cleanup;
697 	}
698 	if (!zfs_is_mounted(zhp, &temp_mntpnt)) {
699 		if ((ret = _be_mount(bt->obe_name, &temp_mntpnt,
700 		    BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) {
701 			be_print_err(gettext("be_get_grub_vers: failed to "
702 			    "mount BE (%s)\n"), bt->obe_name);
703 			free(*cur_vers);
704 			*cur_vers = NULL;
705 			ZFS_CLOSE(zhp);
706 			goto cleanup;
707 		}
708 		be_mounted = B_TRUE;
709 	}
710 	ZFS_CLOSE(zhp);
711 
712 	/*
713 	 * Now get the grub version for the BE being activated.
714 	 */
715 	(void) snprintf(cap_file, sizeof (cap_file), "%s%s", temp_mntpnt,
716 	    BE_CAP_FILE);
717 	ret = get_ver_from_capfile(cap_file, new_vers);
718 	if (ret != BE_SUCCESS) {
719 		free(*cur_vers);
720 		*cur_vers = NULL;
721 	}
722 	if (be_mounted)
723 		(void) _be_unmount(bt->obe_name, 0);
724 
725 cleanup:
726 	if (pool_mounted) {
727 		int iret = BE_SUCCESS;
728 		iret = be_unmount_pool(pool_zhp, ptmp_mntpnt, orig_mntpnt);
729 		if (ret == BE_SUCCESS)
730 			ret = iret;
731 		free(orig_mntpnt);
732 		free(ptmp_mntpnt);
733 	}
734 	ZFS_CLOSE(pool_zhp);
735 
736 	free(temp_mntpnt);
737 	return (ret);
738 }
739 
740 /*
741  * Function:	get_ver_from_capfile
742  * Description: Parses the capability file passed in looking for the VERSION
743  *              line. If found the version is returned in vers, if not then
744  *              NULL is returned in vers.
745  *
746  * Parameters:
747  *              file - the path to the capability file we want to parse.
748  *              vers - the version string that will be passed back.
749  * Return:
750  *              BE_SUCCESS - Success
751  *              be_errno_t - Failed to find version
752  * Scope:
753  *		Private
754  */
755 static int
756 get_ver_from_capfile(char *file, char **vers)
757 {
758 	FILE *fp = NULL;
759 	char line[BUFSIZ];
760 	char *last = NULL;
761 	int err = BE_SUCCESS;
762 	errno = 0;
763 
764 	if (!be_has_grub()) {
765 		be_print_err(gettext("get_ver_from_capfile: Not supported "
766 		    "on this architecture\n"));
767 		return (BE_ERR_NOTSUP);
768 	}
769 
770 	/*
771 	 * Set version string to NULL; the only case this shouldn't be set
772 	 * to be NULL is when we've actually found a version in the capability
773 	 * file, which is set below.
774 	 */
775 	*vers = NULL;
776 
777 	/*
778 	 * If the capability file doesn't exist, we're returning success
779 	 * because on older releases, the capability file did not exist
780 	 * so this is a valid scenario.
781 	 */
782 	if (access(file, F_OK) == 0) {
783 		if ((fp = fopen(file, "r")) == NULL) {
784 			err = errno;
785 			be_print_err(gettext("get_ver_from_capfile: failed to "
786 			    "open file %s with error %s\n"), file,
787 			    strerror(err));
788 			err = errno_to_be_err(err);
789 			return (err);
790 		}
791 
792 		while (fgets(line, BUFSIZ, fp)) {
793 			char *tok = strtok_r(line, "=", &last);
794 
795 			if (tok == NULL || tok[0] == '#') {
796 				continue;
797 			} else if (strcmp(tok, "VERSION") == 0) {
798 				*vers = strdup(last);
799 				break;
800 			}
801 		}
802 		(void) fclose(fp);
803 	}
804 
805 	return (BE_SUCCESS);
806 }
807 
808 /*
809  * To be able to boot EFI labeled disks, stage1 needs to be written
810  * into the MBR. We do not do this if we're on disks with a traditional
811  * fdisk partition table only, or if any foreign EFI partitions exist.
812  * In the trivial case of a whole-disk vdev we always write stage1 into
813  * the MBR.
814  */
815 static boolean_t
816 be_do_install_mbr(char *diskname, nvlist_t *child)
817 {
818 	struct uuid allowed_uuids[] = {
819 		EFI_UNUSED,
820 		EFI_RESV1,
821 		EFI_BOOT,
822 		EFI_ROOT,
823 		EFI_SWAP,
824 		EFI_USR,
825 		EFI_BACKUP,
826 		EFI_RESV2,
827 		EFI_VAR,
828 		EFI_HOME,
829 		EFI_ALTSCTR,
830 		EFI_RESERVED,
831 		EFI_SYSTEM,
832 		EFI_BIOS_BOOT,
833 		EFI_SYMC_PUB,
834 		EFI_SYMC_CDS
835 	};
836 
837 	uint64_t whole;
838 	struct dk_gpt *gpt;
839 	struct uuid *u;
840 	int fd, npart, i, j;
841 
842 	(void) nvlist_lookup_uint64(child, ZPOOL_CONFIG_WHOLE_DISK,
843 	    &whole);
844 
845 	if (whole)
846 		return (B_TRUE);
847 
848 	if ((fd = open(diskname, O_RDONLY|O_NDELAY)) < 0)
849 		return (B_FALSE);
850 
851 	if ((npart = efi_alloc_and_read(fd, &gpt)) <= 0)
852 		return (B_FALSE);
853 
854 	for (i = 0; i != npart; i++) {
855 		int match = 0;
856 
857 		u = &gpt->efi_parts[i].p_guid;
858 
859 		for (j = 0;
860 		    j != sizeof (allowed_uuids) / sizeof (struct uuid);
861 		    j++)
862 			if (bcmp(u, &allowed_uuids[j],
863 			    sizeof (struct uuid)) == 0)
864 				match++;
865 
866 		if (match == 0)
867 			return (B_FALSE);
868 	}
869 
870 	return (B_TRUE);
871 }
872 
873 static int
874 be_do_installboot_helper(zpool_handle_t *zphp, nvlist_t *child, char *stage1,
875     char *stage2, uint16_t flags)
876 {
877 	char install_cmd[MAXPATHLEN];
878 	char be_run_cmd_errbuf[BUFSIZ];
879 	char be_run_cmd_outbuf[BUFSIZ];
880 	char diskname[MAXPATHLEN];
881 	char *vname;
882 	char *path, *dsk_ptr;
883 	char *flag = "";
884 	int ret;
885 	vdev_stat_t *vs;
886 	uint_t vsc;
887 
888 	if (nvlist_lookup_string(child, ZPOOL_CONFIG_PATH, &path) != 0) {
889 		be_print_err(gettext("be_do_installboot: "
890 		    "failed to get device path\n"));
891 		return (BE_ERR_NODEV);
892 	}
893 
894 	if ((nvlist_lookup_uint64_array(child, ZPOOL_CONFIG_VDEV_STATS,
895 	    (uint64_t **)&vs, &vsc) != 0) ||
896 	    vs->vs_state < VDEV_STATE_DEGRADED) {
897 		/*
898 		 * Don't try to run installgrub on a vdev that is not ONLINE
899 		 * or DEGRADED. Try to print a warning for each such vdev.
900 		 */
901 		be_print_err(gettext("be_do_installboot: "
902 		    "vdev %s is %s, can't install boot loader\n"),
903 		    path, zpool_state_to_name(vs->vs_state, vs->vs_aux));
904 		free(path);
905 		return (BE_SUCCESS);
906 	}
907 
908 	/*
909 	 * Modify the vdev path to point to the raw disk.
910 	 */
911 	path = strdup(path);
912 	if (path == NULL)
913 		return (BE_ERR_NOMEM);
914 
915 	dsk_ptr = strstr(path, "/dsk/");
916 	if (dsk_ptr != NULL) {
917 		*dsk_ptr = '\0';
918 		dsk_ptr++;
919 	} else {
920 		dsk_ptr = "";
921 	}
922 
923 	(void) snprintf(diskname, sizeof (diskname), "%s/r%s", path, dsk_ptr);
924 	free(path);
925 
926 	vname = zpool_vdev_name(g_zfs, zphp, child, B_FALSE);
927 	if (vname == NULL) {
928 		be_print_err(gettext("be_do_installboot: "
929 		    "failed to get device name: %s\n"),
930 		    libzfs_error_description(g_zfs));
931 		return (zfs_err_to_be_err(g_zfs));
932 	}
933 
934 	if (be_is_isa("i386")) {
935 		uint16_t force = flags & BE_INSTALLBOOT_FLAG_FORCE;
936 		uint16_t mbr = flags & BE_INSTALLBOOT_FLAG_MBR;
937 
938 		if (force == BE_INSTALLBOOT_FLAG_FORCE) {
939 			if (mbr == BE_INSTALLBOOT_FLAG_MBR ||
940 			    be_do_install_mbr(diskname, child))
941 				flag = "-F -m -f";
942 			else
943 				flag = "-F";
944 		} else {
945 			if (mbr == BE_INSTALLBOOT_FLAG_MBR ||
946 			    be_do_install_mbr(diskname, child))
947 				flag = "-m -f";
948 		}
949 
950 		if (be_has_grub()) {
951 			(void) snprintf(install_cmd, sizeof (install_cmd),
952 			    "%s %s %s %s %s", BE_INSTALL_GRUB, flag,
953 			    stage1, stage2, diskname);
954 		} else {
955 			(void) snprintf(install_cmd, sizeof (install_cmd),
956 			    "%s %s %s %s %s", BE_INSTALL_BOOT, flag,
957 			    stage1, stage2, diskname);
958 		}
959 	} else if (be_is_isa("sparc")) {
960 		if ((flags & BE_INSTALLBOOT_FLAG_FORCE) ==
961 		    BE_INSTALLBOOT_FLAG_FORCE)
962 			flag = "-f -F zfs";
963 		else
964 			flag = "-F zfs";
965 
966 		(void) snprintf(install_cmd, sizeof (install_cmd),
967 		    "%s %s %s %s", BE_INSTALL_BOOT, flag, stage2, diskname);
968 	} else {
969 		be_print_err(gettext("be_do_installboot: unsupported "
970 		    "architecture.\n"));
971 		return (BE_ERR_BOOTFILE_INST);
972 	}
973 
974 	*be_run_cmd_outbuf = '\0';
975 	*be_run_cmd_errbuf = '\0';
976 
977 	ret = be_run_cmd(install_cmd, be_run_cmd_errbuf, BUFSIZ,
978 	    be_run_cmd_outbuf, BUFSIZ);
979 
980 	if (ret != BE_SUCCESS) {
981 		be_print_err(gettext("be_do_installboot: install "
982 		    "failed for device %s.\n"), vname);
983 		ret = BE_ERR_BOOTFILE_INST;
984 	}
985 
986 	be_print_err(gettext("  Command: \"%s\"\n"), install_cmd);
987 	if (be_run_cmd_outbuf[0] != 0) {
988 		be_print_err(gettext("  Output:\n"));
989 		be_print_err("%s", be_run_cmd_outbuf);
990 	}
991 
992 	if (be_run_cmd_errbuf[0] != 0) {
993 		be_print_err(gettext("  Errors:\n"));
994 		be_print_err("%s", be_run_cmd_errbuf);
995 	}
996 	free(vname);
997 
998 	return (ret);
999 }
1000 
1001 /*
1002  * Function:	be_do_copy_grub_cap
1003  * Description:	This function will copy grub capability file to BE.
1004  *
1005  * Parameters:
1006  *              bt - The transaction data for the BE we're activating.
1007  * Return:
1008  *		BE_SUCCESS - Success
1009  *		be_errno_t - Failure
1010  *
1011  * Scope:
1012  *		Private
1013  */
1014 static int
1015 be_do_copy_grub_cap(be_transaction_data_t *bt)
1016 {
1017 	zfs_handle_t *zhp = NULL;
1018 	char cap_file[MAXPATHLEN];
1019 	char zpool_cap_file[MAXPATHLEN];
1020 	char line[BUFSIZ];
1021 	char *tmp_mntpnt = NULL;
1022 	char *orig_mntpnt = NULL;
1023 	char *pool_mntpnt = NULL;
1024 	FILE *cap_fp = NULL;
1025 	FILE *zpool_cap_fp = NULL;
1026 	int err = 0;
1027 	int ret = BE_SUCCESS;
1028 	boolean_t pool_mounted = B_FALSE;
1029 	boolean_t be_mounted = B_FALSE;
1030 
1031 	/*
1032 	 * first get BE dataset mountpoint, we can free all the resources
1033 	 * once cap_file is built, leaving only be unmount to be done.
1034 	 */
1035 	if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) ==
1036 	    NULL) {
1037 		be_print_err(gettext("be_do_copy_grub_cap: failed to "
1038 		    "open BE root dataset (%s): %s\n"), bt->obe_root_ds,
1039 		    libzfs_error_description(g_zfs));
1040 		return (zfs_err_to_be_err(g_zfs));
1041 	}
1042 
1043 	if (!zfs_is_mounted(zhp, &tmp_mntpnt)) {
1044 		if ((ret = _be_mount(bt->obe_name, &tmp_mntpnt,
1045 		    BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) {
1046 			be_print_err(gettext("be_do_copy_grub_cap: failed to "
1047 			    "mount BE (%s)\n"), bt->obe_name);
1048 			ZFS_CLOSE(zhp);
1049 			goto done;
1050 		}
1051 		be_mounted = B_TRUE;
1052 	}
1053 	ZFS_CLOSE(zhp);	/* BE dataset handle is not needed any more */
1054 
1055 	(void) snprintf(cap_file, sizeof (cap_file), "%s%s", tmp_mntpnt,
1056 	    BE_CAP_FILE);
1057 	free(tmp_mntpnt);
1058 
1059 	/* get pool root dataset mountpoint */
1060 	zhp = zfs_open(g_zfs, bt->obe_zpool, ZFS_TYPE_FILESYSTEM);
1061 	if (zhp == NULL) {
1062 		be_print_err(gettext("be_do_copy_grub_cap: zfs_open "
1063 		    "failed: %s\n"), libzfs_error_description(g_zfs));
1064 		ret = zfs_err_to_be_err(g_zfs);
1065 		goto done;
1066 	}
1067 
1068 	/*
1069 	 * Check to see if the pool's dataset is mounted. If it isn't we'll
1070 	 * attempt to mount it.
1071 	 */
1072 	if ((ret = be_mount_pool(zhp, &tmp_mntpnt,
1073 	    &orig_mntpnt, &pool_mounted)) != BE_SUCCESS) {
1074 		be_print_err(gettext("be_do_copy_grub_cap: pool dataset "
1075 		    "(%s) could not be mounted\n"), bt->obe_zpool);
1076 		ZFS_CLOSE(zhp);
1077 		goto done;
1078 	}
1079 
1080 	/*
1081 	 * Get the mountpoint for the root pool dataset.
1082 	 * NOTE: zhp must be kept for _be_unmount_pool()
1083 	 */
1084 	if (!zfs_is_mounted(zhp, &pool_mntpnt)) {
1085 		be_print_err(gettext("be_do_copy_grub_cap: pool "
1086 		    "dataset (%s) is not mounted. Can't check the grub "
1087 		    "version from the grub capability file.\n"), bt->obe_zpool);
1088 		ret = BE_ERR_NO_MENU;
1089 		goto done;
1090 	}
1091 
1092 	(void) snprintf(zpool_cap_file, sizeof (zpool_cap_file), "%s%s",
1093 	    pool_mntpnt, BE_CAP_FILE);
1094 	free(pool_mntpnt);
1095 
1096 	if ((cap_fp = fopen(cap_file, "r")) == NULL) {
1097 		err = errno;
1098 		be_print_err(gettext("be_do_copy_grub_cap: failed to open grub "
1099 		    "capability file\n"));
1100 		ret = errno_to_be_err(err);
1101 		goto done;
1102 	}
1103 	if ((zpool_cap_fp = fopen(zpool_cap_file, "w")) == NULL) {
1104 		err = errno;
1105 		be_print_err(gettext("be_do_copy_grub_cap: failed to open new "
1106 		    "grub capability file\n"));
1107 		ret = errno_to_be_err(err);
1108 		(void) fclose(cap_fp);
1109 		goto done;
1110 	}
1111 
1112 	while (fgets(line, BUFSIZ, cap_fp)) {
1113 		(void) fputs(line, zpool_cap_fp);
1114 	}
1115 
1116 	(void) fclose(zpool_cap_fp);
1117 	(void) fclose(cap_fp);
1118 
1119 done:
1120 	if (be_mounted)
1121 		(void) _be_unmount(bt->obe_name, 0);
1122 
1123 	if (pool_mounted) {
1124 		err = be_unmount_pool(zhp, tmp_mntpnt, orig_mntpnt);
1125 		if (ret == BE_SUCCESS)
1126 			ret = err;
1127 		free(orig_mntpnt);
1128 		free(tmp_mntpnt);
1129 		zfs_close(zhp);
1130 	}
1131 	return (ret);
1132 }
1133 
1134 /*
1135  * Function:	be_is_install_needed
1136  * Description:	Check detached version files to detect if bootloader
1137  *		install/update is needed.
1138  *
1139  * Parameters:
1140  *              bt - The transaction data for the BE we're activating.
1141  *		update - set B_TRUE is update is needed.
1142  * Return:
1143  *		BE_SUCCESS - Success
1144  *		be_errno_t - Failure
1145  *
1146  * Scope:
1147  *		Private
1148  */
1149 static int
1150 be_is_install_needed(be_transaction_data_t *bt, boolean_t *update)
1151 {
1152 	int	ret = BE_SUCCESS;
1153 	char	*cur_vers = NULL, *new_vers = NULL;
1154 
1155 	assert(bt != NULL);
1156 	assert(update != NULL);
1157 
1158 	if (!be_has_grub()) {
1159 		/*
1160 		 * no detached versioning, let installboot to manage
1161 		 * versioning.
1162 		 */
1163 		*update = B_TRUE;
1164 		return (ret);
1165 	}
1166 
1167 	*update = B_FALSE;	/* set default */
1168 
1169 	/*
1170 	 * We need to check to see if the version number from
1171 	 * the BE being activated is greater than the current
1172 	 * one.
1173 	 */
1174 	ret = be_get_grub_vers(bt, &cur_vers, &new_vers);
1175 	if (ret != BE_SUCCESS) {
1176 		be_print_err(gettext("be_activate: failed to get grub "
1177 		    "versions from capability files.\n"));
1178 		return (ret);
1179 	}
1180 	/* update if we have both versions and can compare */
1181 	if (cur_vers != NULL) {
1182 		if (new_vers != NULL) {
1183 			if (atof(cur_vers) < atof(new_vers))
1184 				*update = B_TRUE;
1185 			free(new_vers);
1186 		}
1187 		free(cur_vers);
1188 	} else if (new_vers != NULL) {
1189 		/* we only got new version - update */
1190 		*update = B_TRUE;
1191 		free(new_vers);
1192 	}
1193 	return (ret);
1194 }
1195 
1196 /*
1197  * Function:	be_do_installboot
1198  * Description:	This function runs installgrub/installboot using the boot
1199  *		loader files from the BE we're activating and installing
1200  *		them on the pool the BE lives in.
1201  *
1202  * Parameters:
1203  *              bt - The transaction data for the BE we're activating.
1204  *		flags - flags for bootloader install
1205  * Return:
1206  *		BE_SUCCESS - Success
1207  *		be_errno_t - Failure
1208  *
1209  * Scope:
1210  *		Private
1211  */
1212 static int
1213 be_do_installboot(be_transaction_data_t *bt, uint16_t flags)
1214 {
1215 	zpool_handle_t  *zphp = NULL;
1216 	zfs_handle_t	*zhp = NULL;
1217 	nvlist_t **child, *nv, *config;
1218 	uint_t c, children = 0;
1219 	char *tmp_mntpt = NULL;
1220 	char stage1[MAXPATHLEN];
1221 	char stage2[MAXPATHLEN];
1222 	char *vname;
1223 	int ret = BE_SUCCESS;
1224 	boolean_t be_mounted = B_FALSE;
1225 	boolean_t update = B_FALSE;
1226 	boolean_t verbose = B_FALSE;
1227 
1228 	/*
1229 	 * check versions. This call is to support detached
1230 	 * version implementation like grub. Embedded versioning is
1231 	 * checked by actual installer.
1232 	 */
1233 	if ((flags & BE_INSTALLBOOT_FLAG_FORCE) != BE_INSTALLBOOT_FLAG_FORCE) {
1234 		ret = be_is_install_needed(bt, &update);
1235 		if (ret != BE_SUCCESS || update == B_FALSE)
1236 			return (ret);
1237 	}
1238 	verbose = do_print;
1239 
1240 	if ((zhp = zfs_open(g_zfs, bt->obe_root_ds, ZFS_TYPE_FILESYSTEM)) ==
1241 	    NULL) {
1242 		be_print_err(gettext("be_do_installboot: failed to "
1243 		    "open BE root dataset (%s): %s\n"), bt->obe_root_ds,
1244 		    libzfs_error_description(g_zfs));
1245 		ret = zfs_err_to_be_err(g_zfs);
1246 		return (ret);
1247 	}
1248 	if (!zfs_is_mounted(zhp, &tmp_mntpt)) {
1249 		if ((ret = _be_mount(bt->obe_name, &tmp_mntpt,
1250 		    BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) {
1251 			be_print_err(gettext("be_do_installboot: failed to "
1252 			    "mount BE (%s)\n"), bt->obe_name);
1253 			ZFS_CLOSE(zhp);
1254 			return (ret);
1255 		}
1256 		be_mounted = B_TRUE;
1257 	}
1258 	ZFS_CLOSE(zhp);
1259 
1260 	if (be_is_isa("i386")) {
1261 		if (be_has_grub()) {
1262 			(void) snprintf(stage1, sizeof (stage1), "%s%s",
1263 			    tmp_mntpt, BE_GRUB_STAGE_1);
1264 			(void) snprintf(stage2, sizeof (stage2), "%s%s",
1265 			    tmp_mntpt, BE_GRUB_STAGE_2);
1266 		} else {
1267 			(void) snprintf(stage1, sizeof (stage1), "%s%s",
1268 			    tmp_mntpt, BE_LOADER_STAGE_1);
1269 			(void) snprintf(stage2, sizeof (stage2), "%s%s",
1270 			    tmp_mntpt, BE_LOADER_STAGE_2);
1271 		}
1272 	} else if (be_is_isa("sparc")) {
1273 		char *platform = be_get_platform();
1274 
1275 		if (platform == NULL) {
1276 			be_print_err(gettext("be_do_installboot: "
1277 			    "failed to detect system platform name\n"));
1278 			if (be_mounted)
1279 				(void) _be_unmount(bt->obe_name, 0);
1280 			free(tmp_mntpt);
1281 			return (BE_ERR_BOOTFILE_INST);
1282 		}
1283 		stage1[0] = '\0';	/* sparc has no stage1 */
1284 		(void) snprintf(stage2, sizeof (stage2),
1285 		    "%s/usr/platform/%s%s", tmp_mntpt,
1286 		    platform, BE_SPARC_BOOTBLK);
1287 	} else {
1288 		be_print_err(gettext("be_do_installboot: unsupported "
1289 		    "architecture.\n"));
1290 		return (BE_ERR_BOOTFILE_INST);
1291 	}
1292 
1293 	if ((zphp = zpool_open(g_zfs, bt->obe_zpool)) == NULL) {
1294 		be_print_err(gettext("be_do_installboot: failed to open "
1295 		    "pool (%s): %s\n"), bt->obe_zpool,
1296 		    libzfs_error_description(g_zfs));
1297 		ret = zfs_err_to_be_err(g_zfs);
1298 		if (be_mounted)
1299 			(void) _be_unmount(bt->obe_name, 0);
1300 		free(tmp_mntpt);
1301 		return (ret);
1302 	}
1303 
1304 	if ((config = zpool_get_config(zphp, NULL)) == NULL) {
1305 		be_print_err(gettext("be_do_installboot: failed to get zpool "
1306 		    "configuration information. %s\n"),
1307 		    libzfs_error_description(g_zfs));
1308 		ret = zfs_err_to_be_err(g_zfs);
1309 		goto done;
1310 	}
1311 
1312 	/*
1313 	 * Get the vdev tree
1314 	 */
1315 	if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nv) != 0) {
1316 		be_print_err(gettext("be_do_installboot: failed to get vdev "
1317 		    "tree: %s\n"), libzfs_error_description(g_zfs));
1318 		ret = zfs_err_to_be_err(g_zfs);
1319 		goto done;
1320 	}
1321 
1322 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1323 	    &children) != 0) {
1324 		be_print_err(gettext("be_do_installboot: failed to traverse "
1325 		    "the vdev tree: %s\n"), libzfs_error_description(g_zfs));
1326 		ret = zfs_err_to_be_err(g_zfs);
1327 		goto done;
1328 	}
1329 	for (c = 0; c < children; c++) {
1330 		uint_t i, nchildren = 0;
1331 		nvlist_t **nvchild;
1332 
1333 		/* ensure update on child status */
1334 		vname = zpool_vdev_name(g_zfs, zphp, child[c], verbose);
1335 		if (vname == NULL) {
1336 			be_print_err(gettext(
1337 			    "be_do_installboot: "
1338 			    "failed to get device name: %s\n"),
1339 			    libzfs_error_description(g_zfs));
1340 			ret = zfs_err_to_be_err(g_zfs);
1341 			goto done;
1342 		} else if (verbose == B_TRUE) {
1343 			be_print_err(gettext("be_do_installboot: "
1344 			    "device %s\n"), vname);
1345 		}
1346 		free(vname);
1347 
1348 		ret = nvlist_lookup_nvlist_array(child[c],
1349 		    ZPOOL_CONFIG_CHILDREN, &nvchild, &nchildren);
1350 		if (ret != 0) {
1351 			if (ret != ENOENT) {
1352 				be_print_err(gettext("be_do_installboot: "
1353 				    "failed to traverse the vdev tree: %s\n"),
1354 				    libzfs_error_description(g_zfs));
1355 				ret = zfs_err_to_be_err(g_zfs);
1356 				goto done;
1357 			}
1358 			nchildren = 0;	/* This is leaf device. */
1359 		}
1360 
1361 		if (nchildren != 0) {
1362 			for (i = 0; i < nchildren; i++) {
1363 				/* ensure update on child status */
1364 				vname = zpool_vdev_name(g_zfs, zphp,
1365 				    nvchild[i], verbose);
1366 				if (vname == NULL) {
1367 					be_print_err(gettext(
1368 					    "be_do_installboot: "
1369 					    "failed to get device name: %s\n"),
1370 					    libzfs_error_description(g_zfs));
1371 					ret = zfs_err_to_be_err(g_zfs);
1372 					goto done;
1373 				} else if (verbose == B_TRUE) {
1374 					be_print_err(gettext(
1375 					    "be_do_installboot: device %s\n"),
1376 					    vname);
1377 				}
1378 				free(vname);
1379 				ret = be_do_installboot_helper(zphp, nvchild[i],
1380 				    stage1, stage2, flags);
1381 				if (ret != BE_SUCCESS)
1382 					goto done;
1383 			}
1384 		} else {
1385 			ret = be_do_installboot_helper(zphp, child[c], stage1,
1386 			    stage2, flags);
1387 			if (ret != BE_SUCCESS)
1388 				goto done;
1389 		}
1390 	}
1391 
1392 	if (be_has_grub()) {
1393 		ret = be_do_copy_grub_cap(bt);
1394 	}
1395 
1396 done:
1397 	ZFS_CLOSE(zhp);
1398 	if (be_mounted)
1399 		(void) _be_unmount(bt->obe_name, 0);
1400 	zpool_close(zphp);
1401 	free(tmp_mntpt);
1402 	return (ret);
1403 }
1404 
1405 /*
1406  * Function:	be_promote_zone_ds
1407  * Description:	This function finds the zones for the BE being activated
1408  *              and the active zonepath dataset for each zone. Then each
1409  *              active zonepath dataset is promoted.
1410  *
1411  * Parameters:
1412  *              be_name - the name of the global zone BE that we need to
1413  *                       find the zones for.
1414  *              be_root_ds - the root dataset for be_name.
1415  * Return:
1416  *		BE_SUCCESS - Success
1417  *		be_errno_t - Failure
1418  *
1419  * Scope:
1420  *		Private
1421  */
1422 static int
1423 be_promote_zone_ds(char *be_name, char *be_root_ds)
1424 {
1425 	char		*zone_ds = NULL;
1426 	char		*temp_mntpt = NULL;
1427 	char		origin[MAXPATHLEN];
1428 	char		zoneroot_ds[MAXPATHLEN];
1429 	zfs_handle_t	*zhp = NULL;
1430 	zfs_handle_t	*z_zhp = NULL;
1431 	zoneList_t	zone_list = NULL;
1432 	zoneBrandList_t *brands = NULL;
1433 	boolean_t	be_mounted = B_FALSE;
1434 	int		zone_index = 0;
1435 	int		err = BE_SUCCESS;
1436 
1437 	/*
1438 	 * Get the supported zone brands so we can pass that
1439 	 * to z_get_nonglobal_zone_list_by_brand. Currently
1440 	 * only the ipkg and labeled brand zones are supported
1441 	 *
1442 	 */
1443 	if ((brands = be_get_supported_brandlist()) == NULL) {
1444 		be_print_err(gettext("be_promote_zone_ds: no supported "
1445 		    "brands\n"));
1446 		return (BE_SUCCESS);
1447 	}
1448 
1449 	if ((zhp = zfs_open(g_zfs, be_root_ds,
1450 	    ZFS_TYPE_FILESYSTEM)) == NULL) {
1451 		be_print_err(gettext("be_promote_zone_ds: Failed to open "
1452 		    "dataset (%s): %s\n"), be_root_ds,
1453 		    libzfs_error_description(g_zfs));
1454 		err = zfs_err_to_be_err(g_zfs);
1455 		z_free_brand_list(brands);
1456 		return (err);
1457 	}
1458 
1459 	if (!zfs_is_mounted(zhp, &temp_mntpt)) {
1460 		if ((err = _be_mount(be_name, &temp_mntpt,
1461 		    BE_MOUNT_FLAG_NO_ZONES)) != BE_SUCCESS) {
1462 			be_print_err(gettext("be_promote_zone_ds: failed to "
1463 			    "mount the BE for zones procesing.\n"));
1464 			ZFS_CLOSE(zhp);
1465 			z_free_brand_list(brands);
1466 			return (err);
1467 		}
1468 		be_mounted = B_TRUE;
1469 	}
1470 
1471 	/*
1472 	 * Set the zone root to the temp mount point for the BE we just mounted.
1473 	 */
1474 	z_set_zone_root(temp_mntpt);
1475 
1476 	/*
1477 	 * Get all the zones based on the brands we're looking for. If no zones
1478 	 * are found that we're interested in unmount the BE and move on.
1479 	 */
1480 	if ((zone_list = z_get_nonglobal_zone_list_by_brand(brands)) == NULL) {
1481 		if (be_mounted)
1482 			(void) _be_unmount(be_name, 0);
1483 		ZFS_CLOSE(zhp);
1484 		z_free_brand_list(brands);
1485 		free(temp_mntpt);
1486 		return (BE_SUCCESS);
1487 	}
1488 	for (zone_index = 0; z_zlist_get_zonename(zone_list, zone_index)
1489 	    != NULL; zone_index++) {
1490 		char *zone_path = NULL;
1491 
1492 		/* Skip zones that aren't at least installed */
1493 		if (z_zlist_get_current_state(zone_list, zone_index) <
1494 		    ZONE_STATE_INSTALLED)
1495 			continue;
1496 
1497 		if (((zone_path =
1498 		    z_zlist_get_zonepath(zone_list, zone_index)) == NULL) ||
1499 		    ((zone_ds = be_get_ds_from_dir(zone_path)) == NULL) ||
1500 		    !be_zone_supported(zone_ds))
1501 			continue;
1502 
1503 		if (be_find_active_zone_root(zhp, zone_ds,
1504 		    zoneroot_ds, sizeof (zoneroot_ds)) != 0) {
1505 			be_print_err(gettext("be_promote_zone_ds: "
1506 			    "Zone does not have an active root "
1507 			    "dataset, skipping this zone.\n"));
1508 			continue;
1509 		}
1510 
1511 		if ((z_zhp = zfs_open(g_zfs, zoneroot_ds,
1512 		    ZFS_TYPE_FILESYSTEM)) == NULL) {
1513 			be_print_err(gettext("be_promote_zone_ds: "
1514 			    "Failed to open dataset "
1515 			    "(%s): %s\n"), zoneroot_ds,
1516 			    libzfs_error_description(g_zfs));
1517 			err = zfs_err_to_be_err(g_zfs);
1518 			goto done;
1519 		}
1520 
1521 		if (zfs_prop_get(z_zhp, ZFS_PROP_ORIGIN, origin,
1522 		    sizeof (origin), NULL, NULL, 0, B_FALSE) != 0) {
1523 			ZFS_CLOSE(z_zhp);
1524 			continue;
1525 		}
1526 
1527 		/*
1528 		 * We don't need to close the zfs handle at this
1529 		 * point because the callback funtion
1530 		 * be_promote_ds_callback() will close it for us.
1531 		 */
1532 		if (be_promote_ds_callback(z_zhp, NULL) != 0) {
1533 			be_print_err(gettext("be_promote_zone_ds: "
1534 			    "failed to activate the "
1535 			    "datasets for %s: %s\n"),
1536 			    zoneroot_ds,
1537 			    libzfs_error_description(g_zfs));
1538 			err = BE_ERR_PROMOTE;
1539 			goto done;
1540 		}
1541 	}
1542 done:
1543 	if (be_mounted)
1544 		(void) _be_unmount(be_name, 0);
1545 	ZFS_CLOSE(zhp);
1546 	free(temp_mntpt);
1547 	z_free_brand_list(brands);
1548 	z_free_zone_list(zone_list);
1549 	return (err);
1550 }
1551 
1552 /*
1553  * Function:	be_promote_ds_callback
1554  * Description:	This function is used to promote the datasets for the BE
1555  *		being activated as well as the datasets for the zones BE
1556  *		being activated.
1557  *
1558  * Parameters:
1559  *              zhp - the zfs handle for zone BE being activated.
1560  *		data - not used.
1561  * Return:
1562  *		0 - Success
1563  *		be_errno_t - Failure
1564  *
1565  * Scope:
1566  *		Private
1567  */
1568 static int
1569 /* LINTED */
1570 be_promote_ds_callback(zfs_handle_t *zhp, void *data)
1571 {
1572 	char	origin[MAXPATHLEN];
1573 	char	*sub_dataset = NULL;
1574 	int	ret = 0;
1575 
1576 	if (zhp != NULL) {
1577 		sub_dataset = strdup(zfs_get_name(zhp));
1578 		if (sub_dataset == NULL) {
1579 			ret = BE_ERR_NOMEM;
1580 			goto done;
1581 		}
1582 	} else {
1583 		be_print_err(gettext("be_promote_ds_callback: "
1584 		    "Invalid zfs handle passed into function\n"));
1585 		ret = BE_ERR_INVAL;
1586 		goto done;
1587 	}
1588 
1589 	/*
1590 	 * This loop makes sure that we promote the dataset to the
1591 	 * top of the tree so that it is no longer a decendent of any
1592 	 * dataset. The ZFS close and then open is used to make sure that
1593 	 * the promotion is updated before we move on.
1594 	 */
1595 	while (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin,
1596 	    sizeof (origin), NULL, NULL, 0, B_FALSE) == 0) {
1597 		if (zfs_promote(zhp) != 0) {
1598 			if (libzfs_errno(g_zfs) != EZFS_EXISTS) {
1599 				be_print_err(gettext("be_promote_ds_callback: "
1600 				    "promote of %s failed: %s\n"),
1601 				    zfs_get_name(zhp),
1602 				    libzfs_error_description(g_zfs));
1603 				ret = zfs_err_to_be_err(g_zfs);
1604 				goto done;
1605 			} else {
1606 				/*
1607 				 * If the call to zfs_promote returns the
1608 				 * error EZFS_EXISTS we've hit a snapshot name
1609 				 * collision. This means we're probably
1610 				 * attemping to promote a zone dataset above a
1611 				 * parent dataset that belongs to another zone
1612 				 * which this zone was cloned from.
1613 				 *
1614 				 * TODO: If this is a zone dataset at some
1615 				 * point we should skip this if the zone
1616 				 * paths for the dataset and the snapshot
1617 				 * don't match.
1618 				 */
1619 				be_print_err(gettext("be_promote_ds_callback: "
1620 				    "promote of %s failed due to snapshot "
1621 				    "name collision: %s\n"), zfs_get_name(zhp),
1622 				    libzfs_error_description(g_zfs));
1623 				ret = zfs_err_to_be_err(g_zfs);
1624 				goto done;
1625 			}
1626 		}
1627 		ZFS_CLOSE(zhp);
1628 		if ((zhp = zfs_open(g_zfs, sub_dataset,
1629 		    ZFS_TYPE_FILESYSTEM)) == NULL) {
1630 			be_print_err(gettext("be_promote_ds_callback: "
1631 			    "Failed to open dataset (%s): %s\n"), sub_dataset,
1632 			    libzfs_error_description(g_zfs));
1633 			ret = zfs_err_to_be_err(g_zfs);
1634 			goto done;
1635 		}
1636 	}
1637 
1638 	/* Iterate down this dataset's children and promote them */
1639 	ret = zfs_iter_filesystems(zhp, be_promote_ds_callback, NULL);
1640 
1641 done:
1642 	free(sub_dataset);
1643 	ZFS_CLOSE(zhp);
1644 	return (ret);
1645 }
1646