xref: /illumos-gate/usr/src/uts/common/krtld/kobj_bootflags.c (revision 74a8d72a557428e11e39b309193987d43fc7d66e)
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 2008 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/reboot.h>
30 #include <sys/cmn_err.h>
31 #include <sys/bootconf.h>
32 #include <sys/promif.h>
33 #include <sys/obpdefs.h>
34 #include <sys/sunddi.h>
35 #include <sys/systm.h>
36 #include <sys/kobj.h>
37 #include <sys/kobj_impl.h>
38 #include <util/getoptstr.h>
39 
40 char *kobj_kmdb_argv[11];	/* 10 arguments and trailing NULL */
41 
42 /*
43  * Parse the boot line to determine boot flags.
44  */
45 void
46 bootflags(struct bootops *ops)
47 {
48 	struct gos_params params;
49 	uchar_t num_O_opt = 0;
50 	char *cp;
51 	int c;
52 	char scratch[BOOTARGS_MAX];
53 
54 	if (BOP_GETPROP(ops, "bootargs", kern_bootargs) == -1) {
55 		boothowto |= RB_ASKNAME;
56 		return;
57 	}
58 
59 	cp = kern_bootargs;
60 
61 #if defined(_OBP)
62 	/*
63 	 * x86: The boot scripts (i.e., /etc/bootrc) don't prepend the kernel
64 	 * name to the boot arguments.  (And beware making it do so: if the
65 	 * run-kernel command returns, it will loop, and you will end up with
66 	 * multiple copies of the kernel name.)
67 	 */
68 	if (cp[0] != '-') {
69 		/* if user booted kadb or kmdb, load kmdb */
70 		if (cp[0] == 'k' && (cp[1] == 'a' || cp[1] == 'm') &&
71 		    cp[2] == 'd' && cp[3] == 'b' &&
72 		    (cp[4] == ' ' || cp[4] == '	' || cp[4] == 0))
73 			boothowto |= RB_KMDB;
74 		SKIP_WORD(cp);		/* Skip the kernel's filename. */
75 	}
76 #endif
77 	SKIP_SPC(cp);
78 
79 #if defined(_OBP)
80 	/* skip bootblk args */
81 	params.gos_opts = "abcdDF:gGHhi:km:o:O:rsvVwxZ:";
82 #else
83 	params.gos_opts = "abcdgGhi:km:O:rsvwx";
84 #endif
85 	params.gos_strp = cp;
86 	getoptstr_init(&params);
87 	while ((c = getoptstr(&params)) != -1) {
88 
89 		switch (c) {
90 		case 'a':
91 			boothowto |= RB_ASKNAME;
92 			break;
93 		case 'b':
94 			boothowto |= RB_NOBOOTRC;
95 			break;
96 		case 'c':
97 			boothowto |= RB_CONFIG;
98 			break;
99 		case 'd':
100 			boothowto |= RB_DEBUGENTER;
101 			break;
102 #if defined(_OBP)
103 		case 'D':
104 		case 'F':
105 			break;
106 #endif
107 		case 'g':
108 			boothowto |= RB_FORTHDEBUG;
109 			break;
110 		case 'G':
111 			boothowto |= RB_FORTHDEBUGDBP;
112 			break;
113 		case 'h':
114 			boothowto |= RB_HALT;
115 			break;
116 #if defined(_OBP)
117 		case 'H':
118 			break;
119 #endif
120 		case 'i':
121 			if (params.gos_optarglen + 1 > sizeof (initname)) {
122 				_kobj_printf(ops, "krtld: initname too long.  "
123 				    "Ignoring.\n");
124 			} else {
125 				(void) strncpy(initname, params.gos_optargp,
126 				    params.gos_optarglen);
127 				initname[params.gos_optarglen] = '\0';
128 			}
129 			break;
130 		case 'k':
131 			boothowto |= RB_KMDB;
132 			break;
133 		case 'm':
134 			if (strlen(initargs) + 3 + params.gos_optarglen + 1 >
135 			    sizeof (initargs)) {
136 				_kobj_printf(ops,
137 				    "unix: init options too long.  "
138 				    "Ignoring -m.\n");
139 				break;
140 			}
141 			/* gos_optargp is not null terminated */
142 			(void) strncpy(scratch, params.gos_optargp,
143 			    params.gos_optarglen);
144 			scratch[params.gos_optarglen] = '\0';
145 			(void) strlcat(initargs, "-m ", sizeof (initargs));
146 			(void) strlcat(initargs, scratch,
147 			    sizeof (initargs));
148 			(void) strlcat(initargs, " ", sizeof (initargs));
149 			break;
150 #if defined(_OBP)
151 		/* Ignore argument meant for wanboot standalone */
152 		case 'o':
153 			break;
154 #endif
155 		case 'O': {
156 			char **str = &kobj_kmdb_argv[num_O_opt];
157 
158 			if (++num_O_opt > (sizeof (kobj_kmdb_argv) /
159 			    sizeof (char *)) - 1) {
160 				_kobj_printf(ops, "krtld: too many kmdb "
161 				    "options - ignoring option #%d.\n",
162 				    num_O_opt);
163 				continue;
164 			}
165 
166 			*str = kobj_alloc(params.gos_optarglen + 1, KM_TMP);
167 			(void) strncpy(*str, params.gos_optargp,
168 			    params.gos_optarglen);
169 			(*str)[params.gos_optarglen] = '\0';
170 			break;
171 		}
172 		case 'r':
173 			if (strlen(initargs) + 3 + 1 > sizeof (initargs)) {
174 				_kobj_printf(ops, "unix: init options too "
175 				    "long.  Ignoring -r.\n");
176 				break;
177 			}
178 			boothowto |= RB_RECONFIG;
179 			(void) strlcat(initargs, "-r ", sizeof (initargs));
180 			break;
181 		case 's':
182 			if (strlen(initargs) + 3 + 1 > sizeof (initargs)) {
183 				_kobj_printf(ops, "unix: init options too "
184 				    "long.  Ignoring -s.\n");
185 				break;
186 			}
187 			boothowto |= RB_SINGLE;
188 			(void) strlcat(initargs, "-s ", sizeof (initargs));
189 			break;
190 		case 'v':
191 			if (strlen(initargs) + 3 + 1 > sizeof (initargs)) {
192 				_kobj_printf(ops, "unix: init options too "
193 				    "long.  Ignoring -v.\n");
194 				break;
195 			}
196 			boothowto |= RB_VERBOSE;
197 			(void) strlcat(initargs, "-v ", sizeof (initargs));
198 			break;
199 #if defined(_OBP)
200 		case 'V':
201 			break;
202 		case 'Z':
203 			break;
204 #endif
205 		case 'w':
206 			boothowto |= RB_WRITABLE;
207 			break;
208 		case 'x':
209 			boothowto |= RB_NOBOOTCLUSTER;
210 			break;
211 		case '?':
212 			switch (params.gos_last_opt) {
213 			case 'i':
214 				_kobj_printf(ops, "krtld: Required argument "
215 				    "for -i flag missing.  Ignoring.\n");
216 				break;
217 			default:
218 				_kobj_printf(ops, "krtld: Ignoring invalid "
219 				    "kernel option -%c.\n",
220 				    params.gos_last_opt);
221 			}
222 			break;
223 		default:
224 			_kobj_printf(ops, "krtld: Ignoring unimplemented "
225 			    "option -%c.\n", c);
226 		}
227 	}
228 
229 	if ((boothowto & (RB_DEBUGENTER | RB_KMDB)) == RB_DEBUGENTER) {
230 		_kobj_printf(ops, "krtld: -d is not valid without -k.\n");
231 		boothowto &= ~RB_DEBUGENTER;
232 	}
233 
234 	if (*params.gos_strp) {
235 		/* Unused arguments. */
236 		if (params.gos_strp[0] == '-' && ISSPACE(params.gos_strp[1])) {
237 			/*EMPTY*/
238 			/* Lousy install arguments.  Silently ignore. */
239 		} else {
240 			_kobj_printf(ops, "krtld: Unused kernel arguments: "
241 			    "`%s'.\n", params.gos_strp);
242 		}
243 	}
244 }
245