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