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