xref: /onnv-gate/usr/src/psm/stand/boot/sparc/common/bootflags.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/bootconf.h>
31*0Sstevel@tonic-gate #include <sys/reboot.h>
32*0Sstevel@tonic-gate #include <sys/param.h>
33*0Sstevel@tonic-gate #include <sys/salib.h>
34*0Sstevel@tonic-gate #include <sys/debug.h>
35*0Sstevel@tonic-gate #include <sys/promif.h>
36*0Sstevel@tonic-gate #include <sys/boot.h>
37*0Sstevel@tonic-gate #include <sys/sysmacros.h>
38*0Sstevel@tonic-gate #include <util/getoptstr.h>
39*0Sstevel@tonic-gate #include "boot_plat.h"
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate static char impl_arch_buf[MAXNAMELEN];
42*0Sstevel@tonic-gate static char default_path_buf[MAXPATHLEN];
43*0Sstevel@tonic-gate 
44*0Sstevel@tonic-gate char	wanboot_arguments[OBP_MAXPATHLEN];	/* args following "-o" */
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*
47*0Sstevel@tonic-gate  * Parse the boot arguments, adding the options found to the existing boothowto
48*0Sstevel@tonic-gate  * value (if any) or other state.  Then rewrite the buffer with arguments for
49*0Sstevel@tonic-gate  * the standalone.
50*0Sstevel@tonic-gate  *
51*0Sstevel@tonic-gate  * We assume that the buffer contains only the arguments (no preceeding
52*0Sstevel@tonic-gate  * filename or whitespace).  We start interpreting flags, ignoring those used
53*0Sstevel@tonic-gate  * by the boot block (-H, -X, and -F filename) and acting on those intended
54*0Sstevel@tonic-gate  * for us (those documented in boot(1M) as well as some undocumented), and
55*0Sstevel@tonic-gate  * stop at unknown flags.  Finally we reconstitute flags to be passed on to
56*0Sstevel@tonic-gate  * the standalone and the remaining arguments, excluding the first "--", to
57*0Sstevel@tonic-gate  * the beginning of the buffer, and return an integer representing our flags.
58*0Sstevel@tonic-gate  *
59*0Sstevel@tonic-gate  * NOTE: boothowto may already have bits set when this function is called
60*0Sstevel@tonic-gate  */
61*0Sstevel@tonic-gate void
62*0Sstevel@tonic-gate bootflags(char *args, size_t argsz)
63*0Sstevel@tonic-gate {
64*0Sstevel@tonic-gate 	static char newargs[OBP_MAXPATHLEN];
65*0Sstevel@tonic-gate 	struct gos_params params;
66*0Sstevel@tonic-gate 	const char *cp;
67*0Sstevel@tonic-gate 	char *np;
68*0Sstevel@tonic-gate 	size_t npres;
69*0Sstevel@tonic-gate 	int c;
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate 	impl_arch_name = NULL;
72*0Sstevel@tonic-gate 	cmd_line_default_path = NULL;
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 	params.gos_opts = "HXF:VnI:D:advhko:";
75*0Sstevel@tonic-gate 	params.gos_strp = args;
76*0Sstevel@tonic-gate 	getoptstr_init(&params);
77*0Sstevel@tonic-gate 	while ((c = getoptstr(&params)) != -1) {
78*0Sstevel@tonic-gate 		switch (c) {
79*0Sstevel@tonic-gate 		/*
80*0Sstevel@tonic-gate 		 * Bootblock flags: ignore.
81*0Sstevel@tonic-gate 		 */
82*0Sstevel@tonic-gate 		case 'H':
83*0Sstevel@tonic-gate 		case 'X':
84*0Sstevel@tonic-gate 		case 'F':
85*0Sstevel@tonic-gate 			break;
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate 		/*
88*0Sstevel@tonic-gate 		 * Boot flags.
89*0Sstevel@tonic-gate 		 */
90*0Sstevel@tonic-gate 		case 'V':
91*0Sstevel@tonic-gate 			verbosemode = 1;
92*0Sstevel@tonic-gate 			break;
93*0Sstevel@tonic-gate 		case 'n':
94*0Sstevel@tonic-gate 			cache_state = 0;
95*0Sstevel@tonic-gate 			printf("Warning: boot will not enable cache\n");
96*0Sstevel@tonic-gate 			break;
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 		case 'I':
99*0Sstevel@tonic-gate 			if (params.gos_optarglen >= sizeof (impl_arch_buf)) {
100*0Sstevel@tonic-gate 				printf("boot: -I argument too long.  "
101*0Sstevel@tonic-gate 				    "Ignoring.\n");
102*0Sstevel@tonic-gate 				break;
103*0Sstevel@tonic-gate 			}
104*0Sstevel@tonic-gate 			(void) strncpy(impl_arch_buf, params.gos_optargp,
105*0Sstevel@tonic-gate 			    params.gos_optarglen);
106*0Sstevel@tonic-gate 			impl_arch_buf[params.gos_optarglen] = '\0';
107*0Sstevel@tonic-gate 			impl_arch_name = impl_arch_buf;
108*0Sstevel@tonic-gate 			break;
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 		case 'D':
111*0Sstevel@tonic-gate 			if (params.gos_optarglen >= sizeof (default_path_buf)) {
112*0Sstevel@tonic-gate 				printf("boot: -D argument too long.  "
113*0Sstevel@tonic-gate 				    "Ignoring.\n");
114*0Sstevel@tonic-gate 				break;
115*0Sstevel@tonic-gate 			}
116*0Sstevel@tonic-gate 			(void) strncpy(default_path_buf, params.gos_optargp,
117*0Sstevel@tonic-gate 			    params.gos_optarglen);
118*0Sstevel@tonic-gate 			default_path_buf[params.gos_optarglen] = '\0';
119*0Sstevel@tonic-gate 			cmd_line_default_path = default_path_buf;
120*0Sstevel@tonic-gate 			break;
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 		case 'o':
123*0Sstevel@tonic-gate 			if (params.gos_optarglen >=
124*0Sstevel@tonic-gate 			    sizeof (wanboot_arguments)) {
125*0Sstevel@tonic-gate 				printf("boot: -o argument too long.  "
126*0Sstevel@tonic-gate 				    "Ignoring.\n");
127*0Sstevel@tonic-gate 				break;
128*0Sstevel@tonic-gate 			}
129*0Sstevel@tonic-gate 			(void) strncpy(wanboot_arguments, params.gos_optargp,
130*0Sstevel@tonic-gate 			    params.gos_optarglen);
131*0Sstevel@tonic-gate 			wanboot_arguments[params.gos_optarglen] = '\0';
132*0Sstevel@tonic-gate 			break;
133*0Sstevel@tonic-gate 
134*0Sstevel@tonic-gate 		case 'a':
135*0Sstevel@tonic-gate 			boothowto |= RB_ASKNAME;
136*0Sstevel@tonic-gate 			break;
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 		case 'd':
139*0Sstevel@tonic-gate 			boothowto |= RB_DEBUGENTER;
140*0Sstevel@tonic-gate 			break;
141*0Sstevel@tonic-gate 		case 'v':
142*0Sstevel@tonic-gate 			boothowto |= RB_VERBOSE;
143*0Sstevel@tonic-gate 			break;
144*0Sstevel@tonic-gate 		case 'h':
145*0Sstevel@tonic-gate 			boothowto |= RB_HALT;
146*0Sstevel@tonic-gate 			break;
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 		/* Consumed by the kernel */
149*0Sstevel@tonic-gate 		case 'k':
150*0Sstevel@tonic-gate 			boothowto |= RB_KMDB;
151*0Sstevel@tonic-gate 			break;
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 		/*
154*0Sstevel@tonic-gate 		 * Unrecognized flags: stop.
155*0Sstevel@tonic-gate 		 */
156*0Sstevel@tonic-gate 		case '?':
157*0Sstevel@tonic-gate 			/*
158*0Sstevel@tonic-gate 			 * Error.  Either an unrecognized option, or an option
159*0Sstevel@tonic-gate 			 * without an argument.  Check for the latter.
160*0Sstevel@tonic-gate 			 */
161*0Sstevel@tonic-gate 			switch (params.gos_last_opt) {
162*0Sstevel@tonic-gate 			case 'F':
163*0Sstevel@tonic-gate 				/* -F is a bootblock flag, so ignore. */
164*0Sstevel@tonic-gate 				break;
165*0Sstevel@tonic-gate 			case 'I':
166*0Sstevel@tonic-gate 			case 'D':
167*0Sstevel@tonic-gate 			case 'o':
168*0Sstevel@tonic-gate 				printf("boot: -%c flag missing required "
169*0Sstevel@tonic-gate 				    "argument.  Ignoring.\n",
170*0Sstevel@tonic-gate 				    params.gos_last_opt);
171*0Sstevel@tonic-gate 				break;
172*0Sstevel@tonic-gate 			default:
173*0Sstevel@tonic-gate 				/* Unrecognized option.  Stop. */
174*0Sstevel@tonic-gate 				goto done;
175*0Sstevel@tonic-gate 			}
176*0Sstevel@tonic-gate 			break;
177*0Sstevel@tonic-gate 
178*0Sstevel@tonic-gate 		default:
179*0Sstevel@tonic-gate 			printf("boot: Ignoring unimplemented option -%c.\n", c);
180*0Sstevel@tonic-gate 		}
181*0Sstevel@tonic-gate 	}
182*0Sstevel@tonic-gate done:
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate 	/*
185*0Sstevel@tonic-gate 	 * Construct the arguments for the standalone.
186*0Sstevel@tonic-gate 	 */
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	*newargs = '\0';
189*0Sstevel@tonic-gate 	np = newargs;
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 	/*
192*0Sstevel@tonic-gate 	 * We need a dash if we encountered an unrecognized option or if we
193*0Sstevel@tonic-gate 	 * need to pass flags on.
194*0Sstevel@tonic-gate 	 */
195*0Sstevel@tonic-gate 	if (c == '?' || (boothowto &
196*0Sstevel@tonic-gate 	    /* These flags are to be passed to the standalone. */
197*0Sstevel@tonic-gate 	    (RB_ASKNAME | RB_DEBUGENTER | RB_VERBOSE | RB_HALT | RB_KMDB))) {
198*0Sstevel@tonic-gate 		*np++ = '-';
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 		/*
201*0Sstevel@tonic-gate 		 * boot(1M) says to pass these on.
202*0Sstevel@tonic-gate 		 */
203*0Sstevel@tonic-gate 		if (boothowto & RB_ASKNAME)
204*0Sstevel@tonic-gate 			*np++ = 'a';
205*0Sstevel@tonic-gate 
206*0Sstevel@tonic-gate 		/*
207*0Sstevel@tonic-gate 		 * boot isn't documented as consuming these flags, so pass
208*0Sstevel@tonic-gate 		 * them on.
209*0Sstevel@tonic-gate 		 */
210*0Sstevel@tonic-gate 		if (boothowto & RB_DEBUGENTER)
211*0Sstevel@tonic-gate 			*np++ = 'd';
212*0Sstevel@tonic-gate 		if (boothowto & RB_KMDB)
213*0Sstevel@tonic-gate 			*np++ = 'k';
214*0Sstevel@tonic-gate 		if (boothowto & RB_VERBOSE)
215*0Sstevel@tonic-gate 			*np++ = 'v';
216*0Sstevel@tonic-gate 		if (boothowto & RB_HALT)
217*0Sstevel@tonic-gate 			*np++ = 'h';
218*0Sstevel@tonic-gate 
219*0Sstevel@tonic-gate 		/*
220*0Sstevel@tonic-gate 		 * If we didn't encounter an unrecognized flag and there's
221*0Sstevel@tonic-gate 		 * more to copy, add a space to separate these flags.
222*0Sstevel@tonic-gate 		 * (Otherwise, unrecognized flags can be appended since we
223*0Sstevel@tonic-gate 		 * started this word with a dash.)
224*0Sstevel@tonic-gate 		 */
225*0Sstevel@tonic-gate 		if (c == -1 && params.gos_strp[0] != '\0')
226*0Sstevel@tonic-gate 			*np++ = ' ';
227*0Sstevel@tonic-gate 	}
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	npres = sizeof (newargs) - (size_t)(np - newargs);
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 	if (c == '?') {
232*0Sstevel@tonic-gate 		/*
233*0Sstevel@tonic-gate 		 * Unrecognized flag: Copy gos_errp to end of line or a "--"
234*0Sstevel@tonic-gate 		 * word.
235*0Sstevel@tonic-gate 		 */
236*0Sstevel@tonic-gate 		cp = params.gos_errp;
237*0Sstevel@tonic-gate 		while (*cp && npres > 0) {
238*0Sstevel@tonic-gate 			if (cp[0] == '-' && cp[1] == '-' &&
239*0Sstevel@tonic-gate 			    (cp[2] == '\0' || ISSPACE(cp[2]))) {
240*0Sstevel@tonic-gate 				cp += 2;
241*0Sstevel@tonic-gate 				SKIP_SPC(cp);
242*0Sstevel@tonic-gate 				break;
243*0Sstevel@tonic-gate 			} else {
244*0Sstevel@tonic-gate 				const char *sp = cp;
245*0Sstevel@tonic-gate 				size_t sz;
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 				/* Copy until the next word. */
248*0Sstevel@tonic-gate 				while (*cp && !ISSPACE(*cp))
249*0Sstevel@tonic-gate 					cp++;
250*0Sstevel@tonic-gate 				while (ISSPACE(*cp))
251*0Sstevel@tonic-gate 					cp++;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 				sz = MIN(npres, (size_t)(cp - sp));
254*0Sstevel@tonic-gate 				npres -= sz;
255*0Sstevel@tonic-gate 				bcopy(sp, np, sz);
256*0Sstevel@tonic-gate 				np += sz;
257*0Sstevel@tonic-gate 			}
258*0Sstevel@tonic-gate 		}
259*0Sstevel@tonic-gate 	} else {
260*0Sstevel@tonic-gate 		cp = params.gos_strp;
261*0Sstevel@tonic-gate 	}
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 	while (npres > 0 && (*np++ = *cp++) != '\0')
264*0Sstevel@tonic-gate 		npres--;
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 	newargs[sizeof (newargs) - 1] = '\0';
267*0Sstevel@tonic-gate 	(void) strlcpy(args, newargs, argsz);
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 	/*
270*0Sstevel@tonic-gate 	 * If a default filename was specified in the args, set it.
271*0Sstevel@tonic-gate 	 */
272*0Sstevel@tonic-gate 	if (cmd_line_default_path)
273*0Sstevel@tonic-gate 		set_default_filename(cmd_line_default_path);
274*0Sstevel@tonic-gate }
275