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