/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include char *kobj_kmdb_argv[11]; /* 10 arguments and trailing NULL */ /* * Parse the boot line to determine boot flags. */ void bootflags(struct bootops *ops) { struct gos_params params; uchar_t num_O_opt = 0; char *cp; int c; char scratch[BOOTARGS_MAX]; if (BOP_GETPROP(ops, "bootargs", kern_bootargs) == -1) { boothowto |= RB_ASKNAME; return; } (void) BOP_GETPROP(ops, "boot-file", kern_bootfile); cp = kern_bootargs; #if defined(_OBP) /* * x86: The boot scripts (i.e., /etc/bootrc) don't prepend the kernel * name to the boot arguments. (And beware making it do so: if the * run-kernel command returns, it will loop, and you will end up with * multiple copies of the kernel name.) */ if (cp[0] != '-') { /* if user booted kadb or kmdb, load kmdb */ if (cp[0] == 'k' && (cp[1] == 'a' || cp[1] == 'm') && cp[2] == 'd' && cp[3] == 'b' && (cp[4] == ' ' || cp[4] == ' ' || cp[4] == 0)) boothowto |= RB_KMDB; SKIP_WORD(cp); /* Skip the kernel's filename. */ } #endif SKIP_SPC(cp); #if defined(_OBP) /* skip bootblk args */ params.gos_opts = "abcdDf:F:gGHhi:km:o:O:rsvVwxZ:"; #else params.gos_opts = "abcdgGhi:km:O:rsvwx"; #endif params.gos_strp = cp; getoptstr_init(¶ms); while ((c = getoptstr(¶ms)) != -1) { switch (c) { case 'a': boothowto |= RB_ASKNAME; break; case 'b': boothowto |= RB_NOBOOTRC; break; case 'c': boothowto |= RB_CONFIG; break; case 'd': boothowto |= RB_DEBUGENTER; break; #if defined(_OBP) case 'D': case 'F': break; case 'f': (void)prom_setprop(prom_optionsnode(), "diag-level", (char *)params.gos_optargp, params.gos_optarglen + 1); break; #endif case 'g': boothowto |= RB_FORTHDEBUG; break; case 'G': boothowto |= RB_FORTHDEBUGDBP; break; case 'h': boothowto |= RB_HALT; break; #if defined(_OBP) case 'H': break; #endif case 'i': if (params.gos_optarglen + 1 > sizeof (initname)) { _kobj_printf(ops, "krtld: initname too long. " "Ignoring.\n"); } else { (void) strncpy(initname, params.gos_optargp, params.gos_optarglen); initname[params.gos_optarglen] = '\0'; } break; case 'k': boothowto |= RB_KMDB; break; case 'm': if (strlen(initargs) + 3 + params.gos_optarglen + 1 > sizeof (initargs)) { _kobj_printf(ops, "unix: init options too long. " "Ignoring -m.\n"); break; } /* gos_optargp is not null terminated */ (void) strncpy(scratch, params.gos_optargp, params.gos_optarglen); scratch[params.gos_optarglen] = '\0'; (void) strlcat(initargs, "-m ", sizeof (initargs)); (void) strlcat(initargs, scratch, sizeof (initargs)); (void) strlcat(initargs, " ", sizeof (initargs)); break; #if defined(_OBP) /* Ignore argument meant for wanboot standalone */ case 'o': break; #endif case 'O': { char **str = &kobj_kmdb_argv[num_O_opt]; if (++num_O_opt > (sizeof (kobj_kmdb_argv) / sizeof (char *)) - 1) { _kobj_printf(ops, "krtld: too many kmdb " "options - ignoring option #%d.\n", num_O_opt); continue; } *str = kobj_alloc(params.gos_optarglen + 1, KM_TMP); (void) strncpy(*str, params.gos_optargp, params.gos_optarglen); (*str)[params.gos_optarglen] = '\0'; break; } case 'r': if (strlen(initargs) + 3 + 1 > sizeof (initargs)) { _kobj_printf(ops, "unix: init options too " "long. Ignoring -r.\n"); break; } boothowto |= RB_RECONFIG; (void) strlcat(initargs, "-r ", sizeof (initargs)); break; case 's': if (strlen(initargs) + 3 + 1 > sizeof (initargs)) { _kobj_printf(ops, "unix: init options too " "long. Ignoring -s.\n"); break; } boothowto |= RB_SINGLE; (void) strlcat(initargs, "-s ", sizeof (initargs)); break; case 'v': if (strlen(initargs) + 3 + 1 > sizeof (initargs)) { _kobj_printf(ops, "unix: init options too " "long. Ignoring -v.\n"); break; } boothowto |= RB_VERBOSE; (void) strlcat(initargs, "-v ", sizeof (initargs)); break; #if defined(_OBP) case 'V': break; case 'Z': break; #endif case 'w': boothowto |= RB_WRITABLE; break; case 'x': boothowto |= RB_NOBOOTCLUSTER; break; case '?': switch (params.gos_last_opt) { case 'i': _kobj_printf(ops, "krtld: Required argument " "for -i flag missing. Ignoring.\n"); break; default: _kobj_printf(ops, "krtld: Ignoring invalid " "kernel option -%c.\n", params.gos_last_opt); } break; default: _kobj_printf(ops, "krtld: Ignoring unimplemented " "option -%c.\n", c); } } if ((boothowto & (RB_DEBUGENTER | RB_KMDB)) == RB_DEBUGENTER) { _kobj_printf(ops, "krtld: -d is not valid without -k.\n"); boothowto &= ~RB_DEBUGENTER; } if (*params.gos_strp) { /* Unused arguments. */ if (params.gos_strp[0] == '-' && ISSPACE(params.gos_strp[1])) { /*EMPTY*/ /* Lousy install arguments. Silently ignore. */ } else { _kobj_printf(ops, "krtld: Unused kernel arguments: " "`%s'.\n", params.gos_strp); } } }