xref: /illumos-gate/usr/src/psm/stand/boot/sparc/common/bootflags.c (revision f012ee0c3db17469b492c2cf757226f3d7b1ebbc)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/types.h>
29 #include <sys/bootconf.h>
30 #include <sys/reboot.h>
31 #include <sys/param.h>
32 #include <sys/salib.h>
33 #include <sys/debug.h>
34 #include <sys/promif.h>
35 #include <sys/boot.h>
36 #include <sys/sysmacros.h>
37 #include <util/getoptstr.h>
38 #include "boot_plat.h"
39 
40 static char default_path_buf[MAXPATHLEN];
41 
42 char	wanboot_arguments[OBP_MAXPATHLEN];	/* args following "-o" */
43 
44 char	cmd_line_boot_archive[MAXPATHLEN];
45 
46 boolean_t	halt;
47 
48 /*
49  * Parse the boot arguments, adding the options found to the existing boothowto
50  * value (if any) or other state.  Then rewrite the buffer with arguments for
51  * the standalone.
52  *
53  * NOTE: boothowto may already have bits set when this function is called
54  */
55 void
56 bootflags(char *args, size_t argsz)
57 {
58 	static char newargs[OBP_MAXPATHLEN];
59 	struct gos_params params;
60 	const char *cp;
61 	char *np;
62 	size_t npres;
63 	int c;
64 	char *cmd_line_default_path;
65 
66 	cmd_line_default_path = NULL;
67 
68 	params.gos_opts = "HXF:VnI:D:advhko:";
69 	params.gos_strp = args;
70 	getoptstr_init(&params);
71 	while ((c = getoptstr(&params)) != -1) {
72 		switch (c) {
73 		/*
74 		 * Bootblock flags.
75 		 */
76 		case 'H':
77 			halt = B_TRUE;
78 			/*FALLTHRU*/
79 		case 'X':
80 			break;
81 
82 		case 'F':
83 			if (params.gos_optarglen >=
84 			    sizeof (cmd_line_boot_archive)) {
85 				printf("boot: -F argument too long.  "
86 				    "Ignoring.\n");
87 				break;
88 			}
89 			(void) strncpy(cmd_line_boot_archive,
90 			    params.gos_optargp, params.gos_optarglen);
91 			cmd_line_boot_archive[params.gos_optarglen] = '\0';
92 			break;
93 
94 		/*
95 		 * Boot flags.
96 		 */
97 		case 'V':
98 			verbosemode = 1;
99 			break;
100 		case 'n':
101 			cache_state = 0;
102 			printf("Warning: boot will not enable cache\n");
103 			break;
104 
105 		case 'D':
106 			if (params.gos_optarglen >= sizeof (default_path_buf)) {
107 				printf("boot: -D argument too long.  "
108 				    "Ignoring.\n");
109 				break;
110 			}
111 			(void) strncpy(default_path_buf, params.gos_optargp,
112 			    params.gos_optarglen);
113 			default_path_buf[params.gos_optarglen] = '\0';
114 			cmd_line_default_path = default_path_buf;
115 			break;
116 
117 		case 'o':
118 			if (params.gos_optarglen >=
119 			    sizeof (wanboot_arguments)) {
120 				printf("boot: -o argument too long.  "
121 				    "Ignoring.\n");
122 				break;
123 			}
124 			(void) strncpy(wanboot_arguments, params.gos_optargp,
125 			    params.gos_optarglen);
126 			wanboot_arguments[params.gos_optarglen] = '\0';
127 			break;
128 
129 		case 'a':
130 			boothowto |= RB_ASKNAME;
131 			break;
132 
133 		case 'd':
134 			boothowto |= RB_DEBUGENTER;
135 			break;
136 		case 'v':
137 			boothowto |= RB_VERBOSE;
138 			break;
139 		case 'h':
140 			boothowto |= RB_HALT;
141 			break;
142 
143 		/* Consumed by the kernel */
144 		case 'k':
145 			boothowto |= RB_KMDB;
146 			break;
147 
148 		/*
149 		 * Unrecognized flags: stop.
150 		 */
151 		case '?':
152 			/*
153 			 * Error.  Either an unrecognized option, or an option
154 			 * without an argument.  Check for the latter.
155 			 */
156 			switch (params.gos_last_opt) {
157 			case 'F':
158 			case 'I':
159 			case 'D':
160 			case 'o':
161 				printf("boot: -%c flag missing required "
162 				    "argument.  Ignoring.\n",
163 				    params.gos_last_opt);
164 				break;
165 			default:
166 				/* Unrecognized option.  Stop. */
167 				goto done;
168 			}
169 			break;
170 
171 		default:
172 			printf("boot: Ignoring unimplemented option -%c.\n", c);
173 		}
174 	}
175 done:
176 
177 	/*
178 	 * Construct the arguments for the standalone.
179 	 */
180 
181 	*newargs = '\0';
182 	np = newargs;
183 
184 	/*
185 	 * We need a dash if we encountered an unrecognized option or if we
186 	 * need to pass flags on.
187 	 */
188 	if (c == '?' || (boothowto &
189 	    /* These flags are to be passed to the standalone. */
190 	    (RB_ASKNAME | RB_DEBUGENTER | RB_VERBOSE | RB_HALT | RB_KMDB))) {
191 		*np++ = '-';
192 
193 		/*
194 		 * boot(1M) says to pass these on.
195 		 */
196 		if (boothowto & RB_ASKNAME)
197 			*np++ = 'a';
198 
199 		/*
200 		 * boot isn't documented as consuming these flags, so pass
201 		 * them on.
202 		 */
203 		if (boothowto & RB_DEBUGENTER)
204 			*np++ = 'd';
205 		if (boothowto & RB_KMDB)
206 			*np++ = 'k';
207 		if (boothowto & RB_VERBOSE)
208 			*np++ = 'v';
209 		if (boothowto & RB_HALT)
210 			*np++ = 'h';
211 
212 		/*
213 		 * If we didn't encounter an unrecognized flag and there's
214 		 * more to copy, add a space to separate these flags.
215 		 * (Otherwise, unrecognized flags can be appended since we
216 		 * started this word with a dash.)
217 		 */
218 		if (c == -1 && params.gos_strp[0] != '\0')
219 			*np++ = ' ';
220 	}
221 
222 	npres = sizeof (newargs) - (size_t)(np - newargs);
223 
224 	if (c == '?') {
225 		/*
226 		 * Unrecognized flag: Copy gos_errp to end of line or a "--"
227 		 * word.
228 		 */
229 		cp = params.gos_errp;
230 		while (*cp && npres > 0) {
231 			if (cp[0] == '-' && cp[1] == '-' &&
232 			    (cp[2] == '\0' || ISSPACE(cp[2]))) {
233 				cp += 2;
234 				SKIP_SPC(cp);
235 				break;
236 			} else {
237 				const char *sp = cp;
238 				size_t sz;
239 
240 				/* Copy until the next word. */
241 				while (*cp && !ISSPACE(*cp))
242 					cp++;
243 				while (ISSPACE(*cp))
244 					cp++;
245 
246 				sz = MIN(npres, (size_t)(cp - sp));
247 				npres -= sz;
248 				bcopy(sp, np, sz);
249 				np += sz;
250 			}
251 		}
252 	} else {
253 		cp = params.gos_strp;
254 	}
255 
256 	while (npres > 0 && (*np++ = *cp++) != '\0')
257 		npres--;
258 
259 	newargs[sizeof (newargs) - 1] = '\0';
260 	(void) strlcpy(args, newargs, argsz);
261 
262 	/*
263 	 * If a default filename was specified in the args, set it.
264 	 */
265 	if (cmd_line_default_path)
266 		set_default_filename(cmd_line_default_path);
267 
268 	/*
269 	 * See if user wants to examine things
270 	 */
271 	if (halt == B_TRUE)
272 		prom_enter_mon();
273 }
274