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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/reboot.h>
31 #include <sys/cmn_err.h>
32 #include <sys/bootconf.h>
33 #include <sys/promif.h>
34 #include <sys/obpdefs.h>
35 #include <sys/sunddi.h>
36 #include <sys/systm.h>
37 #include <sys/kobj.h>
38 #include <sys/kobj_impl.h>
39 #include <util/getoptstr.h>
40 
41 char *kobj_kmdb_argv[11];	/* 10 arguments and trailing NULL */
42 
43 /*
44  * Parse the boot line to determine boot flags.
45  */
46 void
47 bootflags(struct bootops *ops)
48 {
49 	struct gos_params params;
50 	uchar_t num_O_opt = 0;
51 	char *cp;
52 	int c;
53 
54 
55 	if (BOP_GETPROP(ops, "boot-args", kern_bootargs) != 0) {
56 		boothowto |= RB_ASKNAME;
57 		return;
58 	}
59 
60 	cp = kern_bootargs;
61 
62 #if !defined(__i386) && !defined(__amd64)
63 	/*
64 	 * x86: The boot scripts (i.e., /etc/bootrc) don't prepend the kernel
65 	 * name to the boot arguments.  (And beware making it do so: if the
66 	 * run-kernel command returns, it will loop, and you will end up with
67 	 * multiple copies of the kernel name.)
68 	 */
69 	SKIP_WORD(cp);		/* Skip the kernel's filename. */
70 #endif
71 	SKIP_SPC(cp);
72 
73 	params.gos_opts = "abcdgGhi:km:O:rsvwx";
74 	params.gos_strp = cp;
75 	getoptstr_init(&params);
76 	while ((c = getoptstr(&params)) != -1) {
77 		switch (c) {
78 		case 'a':
79 			boothowto |= RB_ASKNAME;
80 			break;
81 		case 'b':
82 			boothowto |= RB_NOBOOTRC;
83 			break;
84 		case 'c':
85 			boothowto |= RB_CONFIG;
86 			break;
87 		case 'd':
88 			boothowto |= RB_DEBUGENTER;
89 			break;
90 		case 'g':
91 			boothowto |= RB_FORTHDEBUG;
92 			break;
93 		case 'G':
94 			boothowto |= RB_FORTHDEBUGDBP;
95 			break;
96 		case 'h':
97 			boothowto |= RB_HALT;
98 			break;
99 		case 'i':
100 			if (params.gos_optarglen + 1 > sizeof (initname)) {
101 				_kobj_printf(ops, "krtld: initname too long.  "
102 				    "Ignoring.\n");
103 			} else {
104 				(void) strncpy(initname, params.gos_optargp,
105 				    params.gos_optarglen);
106 				initname[params.gos_optarglen] = '\0';
107 			}
108 			break;
109 		case 'k':
110 			boothowto |= RB_KMDB;
111 			break;
112 		case 'm':
113 			if (2 + params.gos_optarglen + 1 > sizeof (initargs))
114 				printf(
115 				    "unix: -m argument too long.  Ignoring.\n");
116 			else {
117 				(void) strcpy(initargs, "-m");
118 				(void) strncat(initargs, params.gos_optargp,
119 				    params.gos_optarglen);
120 				initargs[sizeof ("-m") - 1 +
121 				    params.gos_optarglen] = '\0';
122 			}
123 			break;
124 		case 'O': {
125 			char **str = &kobj_kmdb_argv[num_O_opt];
126 
127 			if (++num_O_opt > (sizeof (kobj_kmdb_argv) /
128 			    sizeof (char *)) - 1) {
129 				_kobj_printf(ops, "krtld: too many kmdb "
130 				    "options - ignoring option #%d.\n",
131 				    num_O_opt);
132 				continue;
133 			}
134 
135 			*str = kobj_alloc(params.gos_optarglen + 1, KM_TMP);
136 			(void) strncpy(*str, params.gos_optargp,
137 			    params.gos_optarglen);
138 			(*str)[params.gos_optarglen] = '\0';
139 			break;
140 		}
141 		case 'r':
142 			boothowto |= RB_RECONFIG;
143 			break;
144 		case 's':
145 			boothowto |= RB_SINGLE;
146 			break;
147 		case 'v':
148 			boothowto |= RB_VERBOSE;
149 			break;
150 		case 'w':
151 			boothowto |= RB_WRITABLE;
152 			break;
153 		case 'x':
154 			boothowto |= RB_NOBOOTCLUSTER;
155 			break;
156 		case '?':
157 			switch (params.gos_last_opt) {
158 			case 'i':
159 				_kobj_printf(ops, "krtld: Required argument "
160 				    "for -i flag missing.  Ignoring.\n");
161 				break;
162 			default:
163 				_kobj_printf(ops, "krtld: Ignoring invalid "
164 				    "kernel option -%c.\n",
165 				    params.gos_last_opt);
166 			}
167 			break;
168 		default:
169 			_kobj_printf(ops, "krtld: Ignoring unimplemented "
170 			    "option -%c.\n", c);
171 		}
172 	}
173 
174 	if ((boothowto & (RB_DEBUGENTER | RB_KMDB)) == RB_DEBUGENTER) {
175 		_kobj_printf(ops, "krtld: -d is not valid without -k.\n");
176 		boothowto &= ~RB_DEBUGENTER;
177 	}
178 
179 	if (*params.gos_strp) {
180 		/* Unused arguments. */
181 		if (params.gos_strp[0] == '-' && ISSPACE(params.gos_strp[1])) {
182 			/*EMPTY*/
183 			/* Lousy install arguments.  Silently ignore. */
184 		} else {
185 			_kobj_printf(ops, "krtld: Unused kernel arguments: "
186 			    "`%s'.\n", params.gos_strp);
187 		}
188 	}
189 }
190