usr/src/psm/stand/bootlst/common/bootlst.c
changeset 6423 437422a29d3a
equal deleted inserted replaced
6422:d51a10d738ba 6423:437422a29d3a
       
     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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
       
    23  * Use is subject to license terms.
       
    24  */
       
    25 #pragma ident	"%Z%%M%	%I%	%E% SMI"
       
    26 
       
    27 #include <sys/promif.h>
       
    28 #include <sys/salib.h>
       
    29 
       
    30 #define	MAX_CMDLINE	1600  /* from GRUB source */
       
    31 
       
    32 char **titles;
       
    33 char **datasets;
       
    34 
       
    35 int	menu_entry_count;
       
    36 int	menu_table_size;
       
    37 
       
    38 int	in_menu_entry;
       
    39 
       
    40 #define	ENTRY_ALLOC_COUNT	10
       
    41 
       
    42 extern void	set_default_fs(char *fsw_name);
       
    43 extern int	mountroot(char *str);
       
    44 
       
    45 void
       
    46 init_table(void)
       
    47 {
       
    48 
       
    49 	menu_entry_count = 0;
       
    50 	titles = (char **)calloc(ENTRY_ALLOC_COUNT, sizeof (char *));
       
    51 	datasets = (char **)calloc(ENTRY_ALLOC_COUNT, sizeof (char *));
       
    52 	if (titles == NULL || datasets == NULL)
       
    53 		prom_panic("out of mem");
       
    54 	menu_table_size = ENTRY_ALLOC_COUNT;
       
    55 	in_menu_entry = 0;
       
    56 }
       
    57 
       
    58 void
       
    59 add_title_entry(char *title_str)
       
    60 {
       
    61 
       
    62 	/* skip leading white space */
       
    63 	while (isspace(*title_str))
       
    64 		title_str++;
       
    65 
       
    66 	if (menu_entry_count == menu_table_size) {
       
    67 		printf("Reallocating at count %d\n", menu_table_size);
       
    68 		titles = (char **)realloc(titles,
       
    69 		    ENTRY_ALLOC_COUNT * sizeof (char *));
       
    70 		datasets = (char **)realloc(datasets,
       
    71 		    ENTRY_ALLOC_COUNT * sizeof (char *));
       
    72 		if (titles == NULL || datasets == NULL)
       
    73 			prom_panic("out of mem");
       
    74 		menu_table_size += ENTRY_ALLOC_COUNT;
       
    75 	}
       
    76 
       
    77 	if (in_menu_entry)
       
    78 		free(titles[menu_entry_count]);
       
    79 	if ((titles[menu_entry_count] = strdup(title_str)) == NULL)
       
    80 		prom_panic("out of mem");
       
    81 	in_menu_entry = 1;
       
    82 }
       
    83 
       
    84 void
       
    85 add_dataset_entry(char *dataset_str)
       
    86 {
       
    87 	char	*cp;
       
    88 
       
    89 	/* skip leading white space */
       
    90 	while (isspace(*dataset_str))
       
    91 		dataset_str++;
       
    92 
       
    93 	/* if there is still any white space in the line, it's invalid */
       
    94 	for (cp = dataset_str; *cp; cp++)
       
    95 		if (isspace(*cp))
       
    96 			break;
       
    97 	if (*cp)
       
    98 		return;  /* dataset name was invalid */
       
    99 
       
   100 	if (!in_menu_entry)
       
   101 		return;	 /* dataset line was not preceded by a title */
       
   102 
       
   103 	if ((datasets[menu_entry_count] = strdup(dataset_str)) == NULL)
       
   104 		prom_panic("out of mem");
       
   105 	menu_entry_count++;
       
   106 	in_menu_entry = 0;
       
   107 }
       
   108 
       
   109 
       
   110 char *
       
   111 trim_white_space(char *cp)
       
   112 {
       
   113 	char	*ep;
       
   114 
       
   115 	/* skip leading white space */
       
   116 	while (isspace(*cp))
       
   117 		cp++;
       
   118 
       
   119 	/*
       
   120 	 *  if the string contained nothing but white space, return a
       
   121 	 *  null string.
       
   122 	 */
       
   123 	if (*cp == '\0')
       
   124 		return (cp);
       
   125 
       
   126 	/* truncate trailing white space */
       
   127 	for (ep = cp + strlen(cp) - 1; isspace(*ep); ep--)
       
   128 		;
       
   129 	ep++;
       
   130 	*ep = '\0';
       
   131 	return (cp);
       
   132 }
       
   133 
       
   134 char *cons_gets(char *, int);
       
   135 
       
   136 void
       
   137 main(void *cif)
       
   138 {
       
   139 	char linebuf[MAX_CMDLINE];
       
   140 	FILE	*file;
       
   141 	char	*cp, *ep;
       
   142 	int	n;
       
   143 	unsigned long	choice;
       
   144 
       
   145 	prom_init("bootlst", cif);
       
   146 	set_default_fs("promfs");
       
   147 	if (mountroot("bootfs") != 0)
       
   148 		prom_panic("can't mount root");
       
   149 
       
   150 	if ((file = fopen("/boot/menu.lst", "r")) == NULL)
       
   151 		prom_panic("can't open menu.lst");
       
   152 	init_table();
       
   153 
       
   154 	while (fgets(linebuf, MAX_CMDLINE, file)) {
       
   155 		cp = trim_white_space(linebuf);
       
   156 
       
   157 		/* skip comments and blank lines */
       
   158 		if (*cp == '#' || *cp == '\0')
       
   159 			continue;
       
   160 
       
   161 		/* find end of first keyword on line */
       
   162 		for (ep = cp; !isspace(*ep) && *ep; ep++)
       
   163 			;
       
   164 
       
   165 		/* if at the end of the line, the line had no arguments */
       
   166 		if (*ep == '\0')
       
   167 			continue;
       
   168 
       
   169 		*ep = '\0';
       
   170 
       
   171 		if (strcmp(cp, "title") == 0) {
       
   172 			add_title_entry(ep + 1);
       
   173 			continue;
       
   174 		}
       
   175 
       
   176 		if (strcmp(cp, "bootfs") == 0) {
       
   177 			add_dataset_entry(ep + 1);
       
   178 			continue;
       
   179 		}
       
   180 	}
       
   181 
       
   182 	if (menu_entry_count == 0)
       
   183 		prom_panic("no menu entries found");
       
   184 
       
   185 	for (n = 0; n < menu_entry_count; n++) {
       
   186 		printf("%d %s\n", n + 1, titles[n]);
       
   187 	}
       
   188 
       
   189 	printf("Select environment to boot: [ 1 - %d ]: ", menu_entry_count);
       
   190 
       
   191 	while (cons_gets(linebuf, MAX_CMDLINE)) {
       
   192 		/* cut off leading and trailing white space */
       
   193 		cp = trim_white_space(linebuf);
       
   194 		choice = strtoul(cp, NULL, 0);
       
   195 
       
   196 		/*
       
   197 		 * If the input is totally invalid, the return value of
       
   198 		 * strtoul() will be 0 or ULONG_MAX.  Either way, it's
       
   199 		 * of the acceptable range.
       
   200 		 */
       
   201 		if (choice == 0 || choice > menu_entry_count) {
       
   202 			printf("Invalid entry.\n");
       
   203 			continue;
       
   204 		}
       
   205 		/* XXX here is the result */
       
   206 		printf("\nTo boot the selected entry, invoke:\n");
       
   207 		printf("boot [<root-device>] -Z %s\n\n", datasets[choice - 1]);
       
   208 		prom_exit_to_mon();
       
   209 	}
       
   210 }