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(¶ms); 87 while ((c = getoptstr(¶ms)) != -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