changeset 4346:9468114ab29a

6551710 transient reboots don't properly update grub menu, take 2 6559511 eeprom forces update of boot archives, even when it shouldn't
author rscott
date Tue, 29 May 2007 16:00:54 -0700
parents 20eb5d8abe27
children 65fb0c27d51e
files usr/src/cmd/boot/bootadm/bootadm.c usr/src/cmd/boot/bootadm/message.h usr/src/cmd/eeprom/i386/benv.c
diffstat 3 files changed, 75 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/boot/bootadm/bootadm.c	Tue May 29 15:54:57 2007 -0700
+++ b/usr/src/cmd/boot/bootadm/bootadm.c	Tue May 29 16:00:54 2007 -0700
@@ -3460,7 +3460,7 @@
 update_temp(menu_t *mp, char *menupath, char *opt)
 {
 	int entry;
-	char *grubdisk, *rootdev, *path;
+	char *grubdisk, *rootdev, *path, *opt_ptr;
 	char kernbuf[BUFSIZ];
 	char args_buf[BUFSIZ];
 	struct stat sb;
@@ -3526,14 +3526,62 @@
 			(void) strlcat(kernbuf, " ", BUFSIZ);
 			(void) strlcat(kernbuf, opt, BUFSIZ);
 		} else if (opt[0] == '/') {
-			/* It's a full path - write it out and go home */
+			/* It's a full path, so write it out. */
 			(void) strlcpy(kernbuf, opt, BUFSIZ);
+
+			/*
+			 * If someone runs:
+			 *
+			 *	# eeprom boot-args='-kd'
+			 *	# reboot /platform/i86pc/kernel/unix
+			 *
+			 * we want to use the boot-args as part of the boot
+			 * line.  On the other hand, if someone runs:
+			 *
+			 *	# reboot "/platform/i86pc/kernel/unix -kd"
+			 *
+			 * we don't need to mess with boot-args.  If there's
+			 * no space in the options string, assume we're in the
+			 * first case.
+			 */
+			if (strchr(opt, ' ') == NULL) {
+				if (set_kernel(mp, ARGS_CMD, NULL, args_buf,
+				    BUFSIZ) != BAM_SUCCESS)
+					return (BAM_ERROR);
+
+				if (args_buf[0] != '\0') {
+					(void) strlcat(kernbuf, " ", BUFSIZ);
+					(void) strlcat(kernbuf, args_buf,
+					    BUFSIZ);
+				}
+			}
 		} else {
+			/*
+			 * It may be a partial path, or it may be a partial
+			 * path followed by options.  Assume that only options
+			 * follow a space.  If someone sends us a kernel path
+			 * that includes a space, they deserve to be broken.
+			 */
+			opt_ptr = strchr(opt, ' ');
+			if (opt_ptr != NULL) {
+				*opt_ptr = '\0';
+			}
+
 			path = expand_path(opt);
 			if (path != NULL) {
 				(void) strlcpy(kernbuf, path, BUFSIZ);
 				free(path);
-				if (strcmp(opt, "kmdb") == 0) {
+
+				/*
+				 * If there were options given, use those.
+				 * Otherwise, copy over the default options.
+				 */
+				if (opt_ptr != NULL) {
+					/* Restore the space in opt string */
+					*opt_ptr = ' ';
+					(void) strlcat(kernbuf, opt_ptr,
+					    BUFSIZ);
+				} else {
 					if (set_kernel(mp, ARGS_CMD, NULL,
 					    args_buf, BUFSIZ) != BAM_SUCCESS)
 						return (BAM_ERROR);
@@ -3545,6 +3593,10 @@
 						    args_buf, BUFSIZ);
 					}
 				}
+			} else {
+				bam_error(UNKNOWN_KERNEL, opt);
+				bam_print_stderr(UNKNOWN_KERNEL_REBOOT);
+				return (BAM_ERROR);
 			}
 		}
 		entry = add_boot_entry(mp, REBOOT_TITLE, grubdisk, kernbuf,
@@ -3643,14 +3695,15 @@
 	free(found->line);
 	found->line = s_calloc(1, len);
 	(void) snprintf(found->line, len,
-		"%s%s%s%d", prefix, globalcmd, menu_cmds[SEP_CMD], val);
+	    "%s%s%s%d", prefix, globalcmd, menu_cmds[SEP_CMD], val);
 
 	return (BAM_WRITE); /* need a write to menu */
 }
 
 /*
  * partial_path may be anything like "kernel/unix" or "kmdb".  Try to
- * expand it to a full unix path.
+ * expand it to a full unix path.  The calling function is expected to
+ * output a message if an error occurs and NULL is returned.
  */
 static char *
 expand_path(const char *partial_path)
@@ -3696,7 +3749,6 @@
 		return (new_path);
 	}
 
-	bam_error(UNKNOWN_KERNEL, partial_path);
 	free(new_path);
 	return (NULL);
 }
@@ -3919,6 +3971,7 @@
 	if ((optnum == KERNEL_CMD) && (path[0] != '/')) {
 		new_path = expand_path(path);
 		if (new_path == NULL) {
+			bam_error(UNKNOWN_KERNEL, path);
 			return (BAM_ERROR);
 		}
 		free_new_path = 1;
--- a/usr/src/cmd/boot/bootadm/message.h	Tue May 29 15:54:57 2007 -0700
+++ b/usr/src/cmd/boot/bootadm/message.h	Tue May 29 16:00:54 2007 -0700
@@ -329,6 +329,9 @@
 
 #define	UNKNOWN_KERNEL	gettext("Unable to expand %s to a full file path.\n")
 
+#define	UNKNOWN_KERNEL_REBOOT	\
+	gettext("Rebooting with default kernel and options.\n")
+
 #define	NOT_DBOOT \
 	gettext("bootadm set-menu %s may only be run on directboot kernels.\n")
 
--- a/usr/src/cmd/eeprom/i386/benv.c	Tue May 29 15:54:57 2007 -0700
+++ b/usr/src/cmd/eeprom/i386/benv.c	Tue May 29 16:00:54 2007 -0700
@@ -589,7 +589,10 @@
 	}
 }
 
-static void
+/*
+ * Returns 1 if bootenv.rc was modified, 0 otherwise.
+ */
+static int
 set_var(char *name, char *val, eplist_t *list)
 {
 	benv_ent_t *p;
@@ -598,7 +601,7 @@
 	if ((strcmp(name, "boot-file") == 0) ||
 	    (strcmp(name, "boot-args") == 0)) {
 		set_bootadm_var(name, val);
-		return;
+		return (0);
 	}
 
 	/*
@@ -627,13 +630,14 @@
 		(void) printf("new:");
 		print_var(name, list);
 	}
+	return (1);
 }
 
 /*
- *  Modified to return 1 if value modified or 0 if no modification
- *  was necessary.  This allows us to implement non super-user
- *  look up of variables by name without the user being yelled at for
- *  trying to modify the bootenv.rc file.
+ * Returns 1 if bootenv.rc is modified or 0 if no modification was
+ * necessary.  This allows us to implement non super-user look-up of
+ * variables by name without the user being yelled at for trying to
+ * modify the bootenv.rc file.
  */
 static int
 proc_var(char *name, eplist_t *list)
@@ -645,8 +649,7 @@
 		return (0);
 	} else {
 		*val++ = '\0';
-		set_var(name, val, list);
-		return (1);
+		return (set_var(name, val, list));
 	}
 }
 
@@ -994,12 +997,12 @@
 		if (name) {
 			if (bent->val) {
 				(void) fprintf(fp, "%s %s ",
-					bent->cmd, bent->name);
+				    bent->cmd, bent->name);
 				put_quoted(fp, bent->val);
 				(void) fprintf(fp, "\n");
 			} else {
 				(void) fprintf(fp, "%s %s\n",
-					bent->cmd, bent->name);
+				    bent->cmd, bent->name);
 			}
 		} else {
 			(void) fprintf(fp, "%s\n", bent->cmd);