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