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 2006 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, "boot-args", kern_bootargs) != 0) { 55 boothowto |= RB_ASKNAME; 56 return; 57 } 58 59 cp = kern_bootargs; 60 61 #if !defined(__i386) && !defined(__amd64) 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 SKIP_WORD(cp); /* Skip the kernel's filename. */ 69 #endif 70 SKIP_SPC(cp); 71 72 params.gos_opts = "abcdgGhi:km:O:rsvwx"; 73 params.gos_strp = cp; 74 getoptstr_init(¶ms); 75 while ((c = getoptstr(¶ms)) != -1) { 76 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 (strlen(initargs) + 3 + params.gos_optarglen + 1 > 114 sizeof (initargs)) { 115 _kobj_printf(ops, 116 "unix: init options too long. " 117 "Ignoring -m.\n"); 118 break; 119 } 120 /* gos_optargp is not null terminated */ 121 (void) strncpy(scratch, params.gos_optargp, 122 params.gos_optarglen); 123 scratch[params.gos_optarglen] = '\0'; 124 (void) strlcat(initargs, "-m ", sizeof (initargs)); 125 (void) strlcat(initargs, scratch, sizeof (initargs)); 126 (void) strlcat(initargs, " ", sizeof (initargs)); 127 break; 128 case 'O': { 129 char **str = &kobj_kmdb_argv[num_O_opt]; 130 131 if (++num_O_opt > (sizeof (kobj_kmdb_argv) / 132 sizeof (char *)) - 1) { 133 _kobj_printf(ops, "krtld: too many kmdb " 134 "options - ignoring option #%d.\n", 135 num_O_opt); 136 continue; 137 } 138 139 *str = kobj_alloc(params.gos_optarglen + 1, KM_TMP); 140 (void) strncpy(*str, params.gos_optargp, 141 params.gos_optarglen); 142 (*str)[params.gos_optarglen] = '\0'; 143 break; 144 } 145 case 'r': 146 if (strlen(initargs) + 3 + 1 > sizeof (initargs)) { 147 _kobj_printf(ops, "unix: init options too " 148 "long. Ignoring -r.\n"); 149 break; 150 } 151 boothowto |= RB_RECONFIG; 152 (void) strlcat(initargs, "-r ", sizeof (initargs)); 153 break; 154 case 's': 155 if (strlen(initargs) + 3 + 1 > sizeof (initargs)) { 156 _kobj_printf(ops, "unix: init options too " 157 "long. Ignoring -s.\n"); 158 break; 159 } 160 boothowto |= RB_SINGLE; 161 (void) strlcat(initargs, "-s ", sizeof (initargs)); 162 break; 163 case 'v': 164 if (strlen(initargs) + 3 + 1 > sizeof (initargs)) { 165 _kobj_printf(ops, "unix: init options too " 166 "long. Ignoring -v.\n"); 167 break; 168 } 169 boothowto |= RB_VERBOSE; 170 (void) strlcat(initargs, "-v ", sizeof (initargs)); 171 break; 172 case 'w': 173 boothowto |= RB_WRITABLE; 174 break; 175 case 'x': 176 boothowto |= RB_NOBOOTCLUSTER; 177 break; 178 case '?': 179 switch (params.gos_last_opt) { 180 case 'i': 181 _kobj_printf(ops, "krtld: Required argument " 182 "for -i flag missing. Ignoring.\n"); 183 break; 184 default: 185 _kobj_printf(ops, "krtld: Ignoring invalid " 186 "kernel option -%c.\n", 187 params.gos_last_opt); 188 } 189 break; 190 default: 191 _kobj_printf(ops, "krtld: Ignoring unimplemented " 192 "option -%c.\n", c); 193 } 194 } 195 196 if ((boothowto & (RB_DEBUGENTER | RB_KMDB)) == RB_DEBUGENTER) { 197 _kobj_printf(ops, "krtld: -d is not valid without -k.\n"); 198 boothowto &= ~RB_DEBUGENTER; 199 } 200 201 if (*params.gos_strp) { 202 /* Unused arguments. */ 203 if (params.gos_strp[0] == '-' && ISSPACE(params.gos_strp[1])) { 204 /*EMPTY*/ 205 /* Lousy install arguments. Silently ignore. */ 206 } else { 207 _kobj_printf(ops, "krtld: Unused kernel arguments: " 208 "`%s'.\n", params.gos_strp); 209 } 210 } 211 } 212