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
bootflags(char * args,size_t argsz)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(¶ms);
71 while ((c = getoptstr(¶ms)) != -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