6699956 bootadm fixes for GRUB findroot
authorvikram
Thu, 22 May 2008 22:08:42 -0700
changeset 6694 d1503f9c5de3
parent 6693 944dc748ba76
child 6695 12d7dd4459fd
6699956 bootadm fixes for GRUB findroot 6699964 Update GRUB capability and findroot help message
usr/src/cmd/boot/bootadm/Makefile
usr/src/cmd/boot/bootadm/bootadm.c
usr/src/cmd/boot/bootadm/bootadm.h
usr/src/cmd/boot/bootadm/bootadm_upgrade.c
usr/src/cmd/boot/bootadm/message.h
usr/src/grub/capability
usr/src/grub/grub-0.95/stage2/builtins.c
--- a/usr/src/cmd/boot/bootadm/Makefile	Thu May 22 20:47:36 2008 -0700
+++ b/usr/src/cmd/boot/bootadm/Makefile	Thu May 22 22:08:42 2008 -0700
@@ -37,7 +37,7 @@
 
 .KEEP_STATE:
 
-LDLIBS +=	-lnvpair -lgen -ladm -lefi
+LDLIBS +=	-lnvpair -lgen -ladm -lefi -lscf
 
 # Writing into string literals is incorrect.  We need to match gcc's
 # behavior, which causes us to take SIGSEGV on such a write.
--- a/usr/src/cmd/boot/bootadm/bootadm.c	Thu May 22 20:47:36 2008 -0700
+++ b/usr/src/cmd/boot/bootadm/bootadm.c	Thu May 22 22:08:42 2008 -0700
@@ -58,6 +58,7 @@
 #include <ctype.h>
 #include <libgen.h>
 #include <sys/sysmacros.h>
+#include <libscf.h>
 
 #if !defined(_OPB)
 #include <sys/ucode.h>
@@ -104,8 +105,10 @@
 #define	ALL_ENTRIES	-2	/* selects all boot entries */
 
 #define	GRUB_DIR		"/boot/grub"
+#define	GRUB_STAGE2		GRUB_DIR "/stage2"
 #define	GRUB_MENU		"/boot/grub/menu.lst"
 #define	MENU_TMP		"/boot/grub/menu.lst.tmp"
+#define	GRUB_BACKUP_MENU	"/etc/lu/GRUB_backup_menu"
 #define	RAMDISK_SPECIAL		"/ramdisk"
 #define	STUBBOOT		"/stubboot"
 #define	MULTIBOOT		"/platform/i86pc/multiboot"
@@ -132,6 +135,12 @@
 #define	GRUB_root		"/etc/lu/GRUB_root"
 #define	GRUB_fdisk		"/etc/lu/GRUB_fdisk"
 #define	GRUB_fdisk_target	"/etc/lu/GRUB_fdisk_target"
+#define	FINDROOT_INSTALLGRUB	"/etc/lu/installgrub.findroot"
+#define	LULIB			"/usr/lib/lu/lulib"
+#define	LULIB_PROPAGATE_FILE	"lulib_propagate_file"
+#define	CKSUM			"/usr/bin/cksum"
+#define	LU_MENU_CKSUM		"/etc/lu/menu.cksum"
+#define	BOOTADM			"/sbin/bootadm"
 
 #define	INSTALLGRUB		"/sbin/installgrub"
 #define	STAGE1			"/boot/grub/stage1"
@@ -274,6 +283,7 @@
 static char *mount_top_dataset(char *pool, zfs_mnted_t *mnted);
 static int umount_top_dataset(char *pool, zfs_mnted_t mnted, char *mntpt);
 static int ufs_add_to_sign_list(char *sign);
+static error_t synchronize_BE_menu(void);
 
 #if !defined(_OPB)
 static void ucode_install();
@@ -1153,7 +1163,9 @@
 		bam_error(OPEN_FAIL, tmpfile, strerror(errno));
 		return (BAM_ERROR);
 	}
-	if (fclose(fp) == EOF) {
+	ret = fclose(fp);
+	INJECT_ERROR1("LIST2FILE_TRUNC_FCLOSE", ret = EOF);
+	if (ret == EOF) {
 		bam_error(CLOSE_FAIL, tmpfile, strerror(errno));
 		return (BAM_ERROR);
 	}
@@ -1166,14 +1178,18 @@
 	}
 
 	for (; start; start = start->next) {
-		if (s_fputs(start->line, fp) == EOF) {
+		ret = s_fputs(start->line, fp);
+		INJECT_ERROR1("LIST2FILE_FPUTS", ret = EOF);
+		if (ret == EOF) {
 			bam_error(WRITE_FAIL, tmpfile, strerror(errno));
 			(void) fclose(fp);
 			return (BAM_ERROR);
 		}
 	}
 
-	if (fclose(fp) == EOF) {
+	ret = fclose(fp);
+	INJECT_ERROR1("LIST2FILE_APPEND_FCLOSE", ret = EOF);
+	if (ret == EOF) {
 		bam_error(CLOSE_FAIL, tmpfile, strerror(errno));
 		return (BAM_ERROR);
 	}
@@ -1202,6 +1218,7 @@
 	 * Do an atomic rename
 	 */
 	ret = rename(tmpfile, path);
+	INJECT_ERROR1("LIST2FILE_RENAME", ret = -1);
 	if (ret != 0) {
 		bam_error(RENAME_FAIL, path, strerror(errno));
 		return (BAM_ERROR);
@@ -1926,6 +1943,12 @@
 
 /*
  * Need to call this for anything that operates on the GRUB menu
+ * In the x86 live upgrade case the directory /boot/grub may be present
+ * even on pre-newboot BEs. The authoritative way to check for a GRUB target
+ * is to check for the presence of the stage2 binary which is present
+ * only on GRUB targets (even on x86 boot partitions). Checking for the
+ * presence of the multiboot binary is not correct as it is not present
+ * on x86 boot partitions.
  */
 int
 is_grub(const char *root)
@@ -1934,7 +1957,7 @@
 	struct stat sb;
 	const char *fcn = "is_grub()";
 
-	(void) snprintf(path, sizeof (path), "%s%s", root, GRUB_DIR);
+	(void) snprintf(path, sizeof (path), "%s%s", root, GRUB_STAGE2);
 	if (stat(path, &sb) == -1) {
 		BAM_DPRINTF((D_NO_GRUB_DIR, fcn, path));
 		return (0);
@@ -2124,32 +2147,186 @@
 	return (ret);
 }
 
-static void
-update_fdisk(void)
-{
-	struct stat sb;
-	char cmd[PATH_MAX];
-	int ret1, ret2;
-
-	assert(stat(GRUB_fdisk, &sb) == 0);
-	assert(stat(GRUB_fdisk_target, &sb) == 0);
-
-	(void) snprintf(cmd, sizeof (cmd), "/sbin/fdisk -F %s `/bin/cat %s`",
-	    GRUB_fdisk, GRUB_fdisk_target);
-
-	bam_print(UPDATING_FDISK);
-	if (exec_cmd(cmd, NULL) != 0) {
-		bam_error(FDISK_UPDATE_FAILED);
-	}
-
-	/*
-	 * We are done, remove the files.
-	 */
-	ret1 = unlink(GRUB_fdisk);
-	ret2 = unlink(GRUB_fdisk_target);
-	if (ret1 != 0 || ret2 != 0) {
-		bam_error(FILE_REMOVE_FAILED, GRUB_fdisk, GRUB_fdisk_target);
-	}
+static error_t
+synchronize_BE_menu(void)
+{
+	struct stat	sb;
+	char		cmdline[PATH_MAX];
+	char		cksum_line[PATH_MAX];
+	filelist_t	flist = {0};
+	char		*old_cksum_str;
+	char		*old_size_str;
+	char		*old_file;
+	char		*curr_cksum_str;
+	char		*curr_size_str;
+	char		*curr_file;
+	FILE		*cfp;
+	int		found;
+	int		ret;
+	const char	*fcn = "synchronize_BE_menu()";
+
+	BAM_DPRINTF((D_FUNC_ENTRY0, fcn));
+
+	/* Check if findroot enabled LU BE */
+	if (stat(FINDROOT_INSTALLGRUB, &sb) != 0) {
+		BAM_DPRINTF((D_NOT_LU_BE, fcn));
+		return (BAM_SUCCESS);
+	}
+
+	if (stat(LU_MENU_CKSUM, &sb) != 0) {
+		BAM_DPRINTF((D_NO_CKSUM_FILE, fcn, LU_MENU_CKSUM));
+		goto menu_sync;
+	}
+
+	cfp = fopen(LU_MENU_CKSUM, "r");
+	INJECT_ERROR1("CKSUM_FILE_MISSING", cfp = NULL);
+	if (cfp == NULL) {
+		bam_error(CANNOT_READ_LU_CKSUM, LU_MENU_CKSUM);
+		goto menu_sync;
+	}
+	BAM_DPRINTF((D_CKSUM_FILE_OPENED, fcn, LU_MENU_CKSUM));
+
+	found = 0;
+	while (s_fgets(cksum_line, sizeof (cksum_line), cfp) != NULL) {
+		INJECT_ERROR1("MULTIPLE_CKSUM", found = 1);
+		if (found) {
+			bam_error(MULTIPLE_LU_CKSUM, LU_MENU_CKSUM);
+			(void) fclose(cfp);
+			goto menu_sync;
+		}
+		found = 1;
+	}
+	BAM_DPRINTF((D_CKSUM_FILE_READ, fcn, LU_MENU_CKSUM));
+
+
+	old_cksum_str = strtok(cksum_line, " \t");
+	old_size_str = strtok(NULL, " \t");
+	old_file = strtok(NULL, " \t");
+
+	INJECT_ERROR1("OLD_CKSUM_NULL", old_cksum_str = NULL);
+	INJECT_ERROR1("OLD_SIZE_NULL", old_size_str = NULL);
+	INJECT_ERROR1("OLD_FILE_NULL", old_file = NULL);
+	if (old_cksum_str == NULL || old_size_str == NULL || old_file == NULL) {
+		bam_error(CANNOT_PARSE_LU_CKSUM, LU_MENU_CKSUM);
+		goto menu_sync;
+	}
+	BAM_DPRINTF((D_CKSUM_FILE_PARSED, fcn, LU_MENU_CKSUM));
+
+	/* Get checksum of current menu */
+	(void) snprintf(cmdline, sizeof (cmdline), "%s %s",
+	    CKSUM, GRUB_MENU);
+	ret = exec_cmd(cmdline, &flist);
+	INJECT_ERROR1("GET_CURR_CKSUM", ret = 1);
+	if (ret != 0) {
+		bam_error(MENU_CKSUM_FAIL);
+		return (BAM_ERROR);
+	}
+	BAM_DPRINTF((D_CKSUM_GEN_SUCCESS, fcn));
+
+	INJECT_ERROR1("GET_CURR_CKSUM_OUTPUT", flist.head = NULL);
+	if ((flist.head == NULL) || (flist.head != flist.tail)) {
+		bam_error(BAD_CKSUM);
+		filelist_free(&flist);
+		return (BAM_ERROR);
+	}
+	BAM_DPRINTF((D_CKSUM_GEN_OUTPUT_VALID, fcn));
+
+	curr_cksum_str = strtok(flist.head->line, " \t");
+	curr_size_str = strtok(NULL, " \t");
+	curr_file = strtok(NULL, " \t");
+
+	INJECT_ERROR1("CURR_CKSUM_NULL", curr_cksum_str = NULL);
+	INJECT_ERROR1("CURR_SIZE_NULL", curr_size_str = NULL);
+	INJECT_ERROR1("CURR_FILE_NULL", curr_file = NULL);
+	if (curr_cksum_str == NULL || curr_size_str == NULL ||
+	    curr_file == NULL) {
+		bam_error(BAD_CKSUM_PARSE);
+		filelist_free(&flist);
+		return (BAM_ERROR);
+	}
+	BAM_DPRINTF((D_CKSUM_GEN_PARSED, fcn));
+
+	if (strcmp(old_cksum_str, curr_cksum_str) == 0 &&
+	    strcmp(old_size_str, curr_size_str) == 0 &&
+	    strcmp(old_file, curr_file) == 0) {
+		filelist_free(&flist);
+		BAM_DPRINTF((D_CKSUM_NO_CHANGE, fcn));
+		return (BAM_SUCCESS);
+	}
+
+	filelist_free(&flist);
+
+	/* cksum doesn't match - the menu has changed */
+	BAM_DPRINTF((D_CKSUM_HAS_CHANGED, fcn));
+
+menu_sync:
+	bam_print(PROP_GRUB_MENU);
+
+	(void) snprintf(cmdline, sizeof (cmdline),
+	    "/bin/sh -c '. %s; %s %s yes'",
+	    LULIB, LULIB_PROPAGATE_FILE, GRUB_MENU);
+	ret = exec_cmd(cmdline, NULL);
+	INJECT_ERROR1("PROPAGATE_MENU", ret = 1);
+	if (ret != 0) {
+		bam_error(MENU_PROP_FAIL);
+		return (BAM_ERROR);
+	}
+	BAM_DPRINTF((D_PROPAGATED_MENU, fcn));
+
+	(void) snprintf(cmdline, sizeof (cmdline), "/bin/cp %s %s",
+	    GRUB_MENU, GRUB_BACKUP_MENU);
+	ret = exec_cmd(cmdline, NULL);
+	INJECT_ERROR1("CREATE_BACKUP", ret = 1);
+	if (ret != 0) {
+		bam_error(MENU_BACKUP_FAIL, GRUB_BACKUP_MENU);
+		return (BAM_ERROR);
+	}
+	BAM_DPRINTF((D_CREATED_BACKUP, fcn, GRUB_BACKUP_MENU));
+
+	(void) snprintf(cmdline, sizeof (cmdline),
+	    "/bin/sh -c '. %s; %s %s no'",
+	    LULIB, LULIB_PROPAGATE_FILE, GRUB_BACKUP_MENU);
+	ret = exec_cmd(cmdline, NULL);
+	INJECT_ERROR1("PROPAGATE_BACKUP", ret = 1);
+	if (ret != 0) {
+		bam_error(BACKUP_PROP_FAIL, GRUB_BACKUP_MENU);
+		return (BAM_ERROR);
+	}
+	BAM_DPRINTF((D_PROPAGATED_BACKUP, fcn, GRUB_BACKUP_MENU));
+
+	(void) snprintf(cmdline, sizeof (cmdline), "%s %s > %s",
+	    CKSUM, GRUB_MENU, LU_MENU_CKSUM);
+	ret = exec_cmd(cmdline, NULL);
+	INJECT_ERROR1("CREATE_CKSUM_FILE", ret = 1);
+	if (ret != 0) {
+		bam_error(MENU_CKSUM_WRITE_FAIL, LU_MENU_CKSUM);
+		return (BAM_ERROR);
+	}
+	BAM_DPRINTF((D_CREATED_CKSUM_FILE, fcn, LU_MENU_CKSUM));
+
+	(void) snprintf(cmdline, sizeof (cmdline),
+	    "/bin/sh -c '. %s; %s %s no'",
+	    LULIB, LULIB_PROPAGATE_FILE, LU_MENU_CKSUM);
+	ret = exec_cmd(cmdline, NULL);
+	INJECT_ERROR1("PROPAGATE_MENU_CKSUM_FILE", ret = 1);
+	if (ret != 0) {
+		bam_error(MENU_CKSUM_PROP_FAIL, LU_MENU_CKSUM);
+		return (BAM_ERROR);
+	}
+	BAM_DPRINTF((D_PROPAGATED_CKSUM_FILE, fcn, LU_MENU_CKSUM));
+
+	(void) snprintf(cmdline, sizeof (cmdline),
+	    "/bin/sh -c '. %s; %s %s no'",
+	    LULIB, LULIB_PROPAGATE_FILE, BOOTADM);
+	ret = exec_cmd(cmdline, NULL);
+	INJECT_ERROR1("PROPAGATE_BOOTADM_FILE", ret = 1);
+	if (ret != 0) {
+		bam_error(BOOTADM_PROP_FAIL, BOOTADM);
+		return (BAM_ERROR);
+	}
+	BAM_DPRINTF((D_PROPAGATED_BOOTADM, fcn, BOOTADM));
+
+	return (BAM_SUCCESS);
 }
 
 static error_t
@@ -2161,7 +2338,6 @@
 	char multibt[PATH_MAX];
 	char creatram[PATH_MAX];
 	error_t ret = BAM_SUCCESS;
-	int ret1, ret2;
 
 	assert(root);
 	assert(opt == NULL);
@@ -2268,25 +2444,20 @@
 
 out:
 	/*
-	 * Update fdisk table as we go down. Updating it when
-	 * the system is running will confuse biosdev.
+	 * We no longer use biosdev for Live Upgrade. Hence
+	 * there is no need to defer (to shutdown time) any fdisk
+	 * updates
 	 */
-	ret1 = stat(GRUB_fdisk, &sb);
-	ret2 = stat(GRUB_fdisk_target, &sb);
-	if ((ret1 == 0) && (ret2 == 0)) {
-		update_fdisk();
-	} else if ((ret1 == 0) ^ (ret2 == 0)) {
-		/*
-		 * It is an error for one file to be
-		 * present and the other absent.
-		 * It is normal for both files to be
-		 * absent - it indicates that no fdisk
-		 * update is required.
-		 */
-		bam_error(MISSING_FDISK_FILE,
-		    ret1 ? GRUB_fdisk : GRUB_fdisk_target);
+	if (stat(GRUB_fdisk, &sb) == 0 || stat(GRUB_fdisk_target, &sb) == 0) {
+		bam_error(FDISK_FILES_FOUND, GRUB_fdisk, GRUB_fdisk_target);
+	}
+
+	/*
+	 * If user has updated menu in current BE, propagate the
+	 * updates to all BEs.
+	 */
+	if (synchronize_BE_menu() != BAM_SUCCESS)
 		ret = BAM_ERROR;
-	}
 
 	return (ret);
 }
@@ -5509,6 +5680,92 @@
 	return (0);
 }
 
+/*
+ * Certain services needed to run metastat successfully may not
+ * be enabled. Enable them now.
+ */
+/*
+ * Checks if the specified service is online
+ * Returns: 	1 if the service is online
+ *		0 if the service is not online
+ *		-1 on error
+ */
+static int
+is_svc_online(char *svc)
+{
+	char			*state;
+	const char		*fcn = "is_svc_online()";
+
+	BAM_DPRINTF((D_FUNC_ENTRY1, fcn, svc));
+
+	state = smf_get_state(svc);
+	INJECT_ERROR2("GET_SVC_STATE", free(state), state = NULL);
+	if (state == NULL) {
+		bam_error(GET_SVC_STATE_ERR, svc);
+		return (-1);
+	}
+	BAM_DPRINTF((D_GOT_SVC_STATUS, fcn, svc));
+
+	if (strcmp(state, SCF_STATE_STRING_ONLINE) == 0) {
+		BAM_DPRINTF((D_SVC_ONLINE, fcn, svc));
+		free(state);
+		return (1);
+	}
+
+	BAM_DPRINTF((D_SVC_NOT_ONLINE, fcn, state, svc));
+
+	free(state);
+
+	return (0);
+}
+
+static int
+enable_svc(char *svc)
+{
+	int			ret;
+	int			sleeptime;
+	const char		*fcn = "enable_svc()";
+
+	ret = is_svc_online(svc);
+	if (ret == -1) {
+		bam_error(SVC_IS_ONLINE_FAILED, svc);
+		return (-1);
+	} else if (ret == 1) {
+		BAM_DPRINTF((D_SVC_ALREADY_ONLINE, fcn, svc));
+		return (0);
+	}
+
+	/* Service is not enabled. Enable it now. */
+	ret = smf_enable_instance(svc, 0);
+	INJECT_ERROR1("ENABLE_SVC_FAILED", ret = -1);
+	if (ret != 0) {
+		bam_error(ENABLE_SVC_FAILED, svc);
+		return (-1);
+	}
+
+	BAM_DPRINTF((D_SVC_ONLINE_INITIATED, fcn, svc));
+
+	sleeptime = 0;
+	do {
+		ret = is_svc_online(svc);
+		INJECT_ERROR1("SVC_ONLINE_SUCCESS", ret = 1);
+		INJECT_ERROR1("SVC_ONLINE_FAILURE", ret = -1);
+		INJECT_ERROR1("SVC_ONLINE_NOTYET", ret = 0);
+		if (ret == -1) {
+			bam_error(ERR_SVC_GET_ONLINE, svc);
+			return (-1);
+		} else if (ret == 1) {
+			BAM_DPRINTF((D_SVC_NOW_ONLINE, fcn, svc));
+			return (1);
+		}
+		(void) sleep(1);
+	} while (sleeptime < 60);
+
+	bam_error(TIMEOUT_ENABLE_SVC, svc);
+
+	return (-1);
+}
+
 static int
 ufs_get_physical(char *special, char ***physarray, int *n)
 {
@@ -5524,6 +5781,7 @@
 	int			i;
 	line_t			*lp;
 	int			ret;
+	char			*svc;
 	const char		*fcn = "ufs_get_physical()";
 
 	assert(special);
@@ -5547,6 +5805,11 @@
 
 	BAM_DPRINTF((D_UFS_SVM_SHORT, fcn, special, shortname));
 
+	svc = "network/rpc/meta:default";
+	if (enable_svc(svc) == -1) {
+		bam_error(UFS_SVM_METASTAT_SVC_ERR, svc);
+	}
+
 	(void) snprintf(cmd, sizeof (cmd), "/sbin/metastat -p %s", shortname);
 
 	ret = exec_cmd(cmd, &flist);
@@ -6214,9 +6477,7 @@
 		(void) snprintf(failsafe, sizeof (failsafe), "%s%s", osroot,
 		    DIRECT_BOOT_FAILSAFE_KERNEL);
 		if (stat(failsafe, &sbuf) == 0) {
-			failsafe_kernel =
-			    (bam_zfs ? DIRECT_BOOT_FAILSAFE_LINE_ZFS :
-			    DIRECT_BOOT_FAILSAFE_LINE);
+			failsafe_kernel = DIRECT_BOOT_FAILSAFE_LINE;
 		} else {
 			(void) snprintf(failsafe, sizeof (failsafe), "%s%s",
 			    osroot, MULTI_BOOT_FAILSAFE);
--- a/usr/src/cmd/boot/bootadm/bootadm.h	Thu May 22 20:47:36 2008 -0700
+++ b/usr/src/cmd/boot/bootadm/bootadm.h	Thu May 22 22:08:42 2008 -0700
@@ -216,7 +216,6 @@
 #define	DIRECT_BOOT_FAILSAFE_KERNEL	"/boot/platform/i86pc/kernel/unix"
 #define	DIRECT_BOOT_FAILSAFE_LINE	DIRECT_BOOT_FAILSAFE_KERNEL " -s"
 #define	DIRECT_BOOT_KERNEL_ZFS	DIRECT_BOOT_KERNEL " " ZFS_BOOT
-#define	DIRECT_BOOT_FAILSAFE_LINE_ZFS	DIRECT_BOOT_FAILSAFE_LINE " " ZFS_BOOT
 
 /* xVM kernels */
 #define	XEN_KERNEL_SUBSTR "xen.gz"
--- a/usr/src/cmd/boot/bootadm/bootadm_upgrade.c	Thu May 22 20:47:36 2008 -0700
+++ b/usr/src/cmd/boot/bootadm/bootadm_upgrade.c	Thu May 22 22:08:42 2008 -0700
@@ -622,11 +622,9 @@
 	BAM_DPRINTF((D_FUNC_ENTRY3, fcn, grubsign, grubroot, opt));
 
 	for (entry = estart; entry; entry = entry->next) {
-#if 0
+
 		if (!(entry->flags & (BAM_ENTRY_BOOTADM|BAM_ENTRY_LU)) &&
 		    !bam_force) {
-#endif
-		if (!(entry->flags & BAM_ENTRY_BOOTADM) && !bam_force) {
 			BAM_DPRINTF((D_SKIP_ENTRY, fcn, entry->entryNum));
 			continue;
 		}
--- a/usr/src/cmd/boot/bootadm/message.h	Thu May 22 20:47:36 2008 -0700
+++ b/usr/src/cmd/boot/bootadm/message.h	Thu May 22 22:08:42 2008 -0700
@@ -237,15 +237,8 @@
 #define	REBOOT_WITH_ARGS_ADD_ENTRY_FAILED \
 	gettext("Cannot update menu. Cannot reboot with requested arguments\n")
 
-#define	UPDATING_FDISK gettext("Updating fdisk table.\n")
-
-#define	FDISK_UPDATE_FAILED gettext("Update of fdisk table failed.\n")
-
-#define	MISSING_FDISK_FILE \
-	gettext("Missing file (%s). Cannot update fdisk table.\n")
-
-#define	FILE_REMOVE_FAILED \
-	gettext("Failed to delete one or more of (%s,%s). Remove manually.\n")
+#define	FDISK_FILES_FOUND \
+	gettext("Deferred FDISK update file(s) found: %s, %s. Not supported.\n")
 
 #define	UNKNOWN_KERNEL	gettext("Unable to expand %s to a full file path.\n")
 
@@ -552,6 +545,9 @@
 #define	UFS_SVM_METASTAT_ERR \
 gettext("metastat command failed on SVM metadevice: %s\n")
 
+#define	UFS_SVM_METASTAT_SVC_ERR \
+gettext("failed to start service %s for metastat command\n")
+
 #define	BAD_UFS_SVM_METASTAT \
 gettext("bad output from metastat command on SVM metadevice: %s\n")
 
@@ -576,6 +572,57 @@
 #define	GET_MENU_ROOT_SPECIAL_ERR \
 gettext("failed to get special file for menu_root: %s\n")
 
+#define	GET_SVC_STATE_ERR gettext("failed to determine state of service: %s\n")
+
+#define	SVC_IS_ONLINE_FAILED \
+	gettext("failed to determine if service is online: %s\n")
+
+#define	ENABLE_SVC_FAILED gettext("failed to online service: %s\n")
+
+#define	ERR_SVC_GET_ONLINE \
+	gettext("failed to get online status for service: %s\n")
+
+#define	TIMEOUT_ENABLE_SVC \
+	gettext("timed out waiting for service to online: %s\n")
+
+#define	CANNOT_READ_LU_CKSUM \
+	gettext("failed to read GRUB menu checksum file: %s\n")
+
+#define	MULTIPLE_LU_CKSUM \
+	gettext("multiple checksums for GRUB menu in checksum file: %s\n")
+
+#define	CANNOT_PARSE_LU_CKSUM \
+	gettext("error parsing GRUB menu checksum file: %s\n")
+
+#define	MENU_CKSUM_FAIL \
+	gettext("error generating checksum of GRUB menu\n")
+
+#define	BAD_CKSUM \
+	gettext("bad checksum generated for GRUB menu\n")
+
+#define	BAD_CKSUM_PARSE \
+	gettext("error parsing checksum generated for GRUB menu\n")
+
+#define	MENU_PROP_FAIL \
+	gettext("error propagating updated GRUB menu\n")
+
+#define	MENU_BACKUP_FAIL \
+	gettext("failed to create backup for GRUB menu: %s\n")
+
+#define	BACKUP_PROP_FAIL \
+	gettext("error propagating backup GRUB menu: %s\n")
+
+#define	MENU_CKSUM_WRITE_FAIL \
+	gettext("failed to write GRUB menu checksum file: %s\n")
+
+#define	MENU_CKSUM_PROP_FAIL \
+	gettext("error propagating GRUB menu checksum file: %s\n")
+
+#define	BOOTADM_PROP_FAIL \
+	gettext("error propagating bootadm: %s\n")
+
+#define	PROP_GRUB_MENU \
+	gettext("propagating updated GRUB menu\n")
 
 /*
  * NOTE: The following are debug messages and not I18Ned
@@ -1158,6 +1205,52 @@
 
 #define	D_MENU_WRITE_ENTER "%s: entered menu_write() for root: <%s>\n"
 
+#define	D_GOT_SVC_STATUS "%s: got status for service: %s\n"
+
+#define	D_SVC_ONLINE "%s: service is online: %s\n"
+
+#define	D_SVC_NOT_ONLINE "%s: service is *NOT* online(%s): %s\n"
+
+#define	D_SVC_ALREADY_ONLINE "%s: service is already online: %s\n"
+
+#define	D_SVC_ONLINE_INITIATED "%s: initiated online of service: %s\n"
+
+#define	D_SVC_NOW_ONLINE "%s: service is NOW online: %s\n"
+
+#define	D_NOT_LU_BE "%s: not a Live Upgrade BE\n"
+
+#define	D_NO_CKSUM_FILE "%s: checksum file absent: %s\n"
+
+#define	D_CKSUM_FILE_OPENED "%s: opened checksum file: %s\n"
+
+#define	D_CKSUM_FILE_READ "%s: read checksum file: %s\n"
+
+#define	D_CKSUM_FILE_PARSED "%s: parsed checksum file: %s\n"
+
+#define	D_CKSUM_GEN_SUCCESS "%s: successfully generated checksum\n"
+
+#define	D_CKSUM_GEN_OUTPUT_VALID "%s: generated checksum output valid\n"
+
+#define	D_CKSUM_GEN_PARSED "%s: successfully parsed generated checksum\n"
+
+#define	D_CKSUM_NO_CHANGE "%s: no change in checksum of GRUB menu\n"
+
+#define	D_CKSUM_HAS_CHANGED "%s: checksum of GRUB menu has changed\n"
+
+#define	D_PROPAGATED_MENU "%s: successfully propagated GRUB menu\n"
+
+#define	D_CREATED_BACKUP "%s: successfully created backup GRUB menu: %s\n"
+
+#define	D_PROPAGATED_BACKUP "%s: successfully propagated backup GRUB menu: %s\n"
+
+#define	D_CREATED_CKSUM_FILE "%s: successfully created checksum file: %s\n"
+
+#define	D_PROPAGATED_CKSUM_FILE \
+	"%s: successfully propagated checksum file: %s\n"
+
+#define	D_PROPAGATED_BOOTADM \
+	"%s: successfully propagated bootadm: %s\n"
+
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/grub/capability	Thu May 22 20:47:36 2008 -0700
+++ b/usr/src/grub/capability	Thu May 22 22:08:42 2008 -0700
@@ -21,7 +21,7 @@
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
 #
 #
 # This file defines the current capabilities of GRUB over and above that
@@ -29,4 +29,5 @@
 #
 dboot
 xVM
+zfs
 findroot
--- a/usr/src/grub/grub-0.95/stage2/builtins.c	Thu May 22 20:47:36 2008 -0700
+++ b/usr/src/grub/grub-0.95/stage2/builtins.c	Thu May 22 22:08:42 2008 -0700
@@ -4023,12 +4023,14 @@
   "findroot",
   findroot_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
-  "findroot  <SIGNATURE-FILE | (SIGNATURE-FILE,partition[,slice])>",
-  "Search for the root partition that contains the specified SIGNATURE-FILE."
-  " The SIGNATURE-FILE is assumed to be unique across all partitions."
+  "findroot  <SIGNATURE | (SIGNATURE,partition[,slice])>",
+  "Searches across all partitions for the file name SIGNATURE."
+  " GRUB looks only in the directory /boot/grub/bootsign for the"
+  " filename and it stops as soon as it finds the first instance of"
+  " the file - so to be useful the name of the signature file must be"
+  " unique across all partitions. Once the signature file is found,"
+  " GRUB invokes the \"root\" command on that partition."
   " An optional partition and slice may be specified to optimize the search."
-  " GRUB stops at the first root partition that has the specified"
-  " SIGNATURE-FILE and then invokes the \"root\" command on that device."
 };