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