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