10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
52267Sdp * Common Development and Distribution License (the "License").
62267Sdp * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*11897SChris.Kiick@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <sys/reboot.h>
290Sstevel@tonic-gate #include <sys/cmn_err.h>
300Sstevel@tonic-gate #include <sys/bootconf.h>
310Sstevel@tonic-gate #include <sys/promif.h>
320Sstevel@tonic-gate #include <sys/obpdefs.h>
330Sstevel@tonic-gate #include <sys/sunddi.h>
340Sstevel@tonic-gate #include <sys/systm.h>
350Sstevel@tonic-gate #include <sys/kobj.h>
360Sstevel@tonic-gate #include <sys/kobj_impl.h>
370Sstevel@tonic-gate #include <util/getoptstr.h>
380Sstevel@tonic-gate
390Sstevel@tonic-gate char *kobj_kmdb_argv[11]; /* 10 arguments and trailing NULL */
400Sstevel@tonic-gate
410Sstevel@tonic-gate /*
420Sstevel@tonic-gate * Parse the boot line to determine boot flags.
430Sstevel@tonic-gate */
440Sstevel@tonic-gate void
bootflags(struct bootops * ops)450Sstevel@tonic-gate bootflags(struct bootops *ops)
460Sstevel@tonic-gate {
470Sstevel@tonic-gate struct gos_params params;
480Sstevel@tonic-gate uchar_t num_O_opt = 0;
490Sstevel@tonic-gate char *cp;
500Sstevel@tonic-gate int c;
512267Sdp char scratch[BOOTARGS_MAX];
520Sstevel@tonic-gate
535648Ssetje if (BOP_GETPROP(ops, "bootargs", kern_bootargs) == -1) {
540Sstevel@tonic-gate boothowto |= RB_ASKNAME;
550Sstevel@tonic-gate return;
560Sstevel@tonic-gate }
570Sstevel@tonic-gate
587656SSherry.Moore@Sun.COM (void) BOP_GETPROP(ops, "boot-file", kern_bootfile);
597656SSherry.Moore@Sun.COM
600Sstevel@tonic-gate cp = kern_bootargs;
610Sstevel@tonic-gate
625648Ssetje #if defined(_OBP)
630Sstevel@tonic-gate /*
640Sstevel@tonic-gate * x86: The boot scripts (i.e., /etc/bootrc) don't prepend the kernel
650Sstevel@tonic-gate * name to the boot arguments. (And beware making it do so: if the
660Sstevel@tonic-gate * run-kernel command returns, it will loop, and you will end up with
670Sstevel@tonic-gate * multiple copies of the kernel name.)
680Sstevel@tonic-gate */
695648Ssetje if (cp[0] != '-') {
705648Ssetje /* if user booted kadb or kmdb, load kmdb */
715648Ssetje if (cp[0] == 'k' && (cp[1] == 'a' || cp[1] == 'm') &&
725648Ssetje cp[2] == 'd' && cp[3] == 'b' &&
735648Ssetje (cp[4] == ' ' || cp[4] == ' ' || cp[4] == 0))
745648Ssetje boothowto |= RB_KMDB;
755648Ssetje SKIP_WORD(cp); /* Skip the kernel's filename. */
765648Ssetje }
770Sstevel@tonic-gate #endif
780Sstevel@tonic-gate SKIP_SPC(cp);
790Sstevel@tonic-gate
805648Ssetje #if defined(_OBP)
815648Ssetje /* skip bootblk args */
82*11897SChris.Kiick@Sun.COM params.gos_opts = "abcdDf:F:gGHhi:km:o:O:rsvVwxZ:";
835648Ssetje #else
840Sstevel@tonic-gate params.gos_opts = "abcdgGhi:km:O:rsvwx";
855648Ssetje #endif
860Sstevel@tonic-gate params.gos_strp = cp;
870Sstevel@tonic-gate getoptstr_init(¶ms);
880Sstevel@tonic-gate while ((c = getoptstr(¶ms)) != -1) {
892267Sdp
900Sstevel@tonic-gate switch (c) {
910Sstevel@tonic-gate case 'a':
920Sstevel@tonic-gate boothowto |= RB_ASKNAME;
930Sstevel@tonic-gate break;
940Sstevel@tonic-gate case 'b':
950Sstevel@tonic-gate boothowto |= RB_NOBOOTRC;
960Sstevel@tonic-gate break;
970Sstevel@tonic-gate case 'c':
980Sstevel@tonic-gate boothowto |= RB_CONFIG;
990Sstevel@tonic-gate break;
1000Sstevel@tonic-gate case 'd':
1010Sstevel@tonic-gate boothowto |= RB_DEBUGENTER;
1020Sstevel@tonic-gate break;
1035648Ssetje #if defined(_OBP)
1045648Ssetje case 'D':
1055648Ssetje case 'F':
1065648Ssetje break;
107*11897SChris.Kiick@Sun.COM case 'f':
108*11897SChris.Kiick@Sun.COM (void)prom_setprop(prom_optionsnode(), "diag-level",
109*11897SChris.Kiick@Sun.COM (char *)params.gos_optargp,
110*11897SChris.Kiick@Sun.COM params.gos_optarglen + 1);
111*11897SChris.Kiick@Sun.COM break;
1125648Ssetje #endif
1130Sstevel@tonic-gate case 'g':
1140Sstevel@tonic-gate boothowto |= RB_FORTHDEBUG;
1150Sstevel@tonic-gate break;
1160Sstevel@tonic-gate case 'G':
1170Sstevel@tonic-gate boothowto |= RB_FORTHDEBUGDBP;
1180Sstevel@tonic-gate break;
1190Sstevel@tonic-gate case 'h':
1200Sstevel@tonic-gate boothowto |= RB_HALT;
1210Sstevel@tonic-gate break;
1225648Ssetje #if defined(_OBP)
1235648Ssetje case 'H':
1245648Ssetje break;
1255648Ssetje #endif
1260Sstevel@tonic-gate case 'i':
1270Sstevel@tonic-gate if (params.gos_optarglen + 1 > sizeof (initname)) {
1280Sstevel@tonic-gate _kobj_printf(ops, "krtld: initname too long. "
1290Sstevel@tonic-gate "Ignoring.\n");
1300Sstevel@tonic-gate } else {
1310Sstevel@tonic-gate (void) strncpy(initname, params.gos_optargp,
1320Sstevel@tonic-gate params.gos_optarglen);
1330Sstevel@tonic-gate initname[params.gos_optarglen] = '\0';
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate break;
1360Sstevel@tonic-gate case 'k':
1370Sstevel@tonic-gate boothowto |= RB_KMDB;
1380Sstevel@tonic-gate break;
1390Sstevel@tonic-gate case 'm':
1402267Sdp if (strlen(initargs) + 3 + params.gos_optarglen + 1 >
1412267Sdp sizeof (initargs)) {
1422267Sdp _kobj_printf(ops,
1432267Sdp "unix: init options too long. "
1442267Sdp "Ignoring -m.\n");
1452267Sdp break;
1460Sstevel@tonic-gate }
1472267Sdp /* gos_optargp is not null terminated */
1482267Sdp (void) strncpy(scratch, params.gos_optargp,
1492267Sdp params.gos_optarglen);
1502267Sdp scratch[params.gos_optarglen] = '\0';
1512267Sdp (void) strlcat(initargs, "-m ", sizeof (initargs));
1525648Ssetje (void) strlcat(initargs, scratch,
1535648Ssetje sizeof (initargs));
1542267Sdp (void) strlcat(initargs, " ", sizeof (initargs));
1550Sstevel@tonic-gate break;
1565648Ssetje #if defined(_OBP)
1575648Ssetje /* Ignore argument meant for wanboot standalone */
1585648Ssetje case 'o':
1595648Ssetje break;
1605648Ssetje #endif
1610Sstevel@tonic-gate case 'O': {
1620Sstevel@tonic-gate char **str = &kobj_kmdb_argv[num_O_opt];
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate if (++num_O_opt > (sizeof (kobj_kmdb_argv) /
1650Sstevel@tonic-gate sizeof (char *)) - 1) {
1660Sstevel@tonic-gate _kobj_printf(ops, "krtld: too many kmdb "
1670Sstevel@tonic-gate "options - ignoring option #%d.\n",
1680Sstevel@tonic-gate num_O_opt);
1690Sstevel@tonic-gate continue;
1700Sstevel@tonic-gate }
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate *str = kobj_alloc(params.gos_optarglen + 1, KM_TMP);
1730Sstevel@tonic-gate (void) strncpy(*str, params.gos_optargp,
1740Sstevel@tonic-gate params.gos_optarglen);
1750Sstevel@tonic-gate (*str)[params.gos_optarglen] = '\0';
1760Sstevel@tonic-gate break;
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate case 'r':
1792267Sdp if (strlen(initargs) + 3 + 1 > sizeof (initargs)) {
1802267Sdp _kobj_printf(ops, "unix: init options too "
1812267Sdp "long. Ignoring -r.\n");
1822267Sdp break;
1832267Sdp }
1840Sstevel@tonic-gate boothowto |= RB_RECONFIG;
1852267Sdp (void) strlcat(initargs, "-r ", sizeof (initargs));
1860Sstevel@tonic-gate break;
1870Sstevel@tonic-gate case 's':
1882267Sdp if (strlen(initargs) + 3 + 1 > sizeof (initargs)) {
1892267Sdp _kobj_printf(ops, "unix: init options too "
1902267Sdp "long. Ignoring -s.\n");
1912267Sdp break;
1922267Sdp }
1930Sstevel@tonic-gate boothowto |= RB_SINGLE;
1942267Sdp (void) strlcat(initargs, "-s ", sizeof (initargs));
1950Sstevel@tonic-gate break;
1960Sstevel@tonic-gate case 'v':
1972267Sdp if (strlen(initargs) + 3 + 1 > sizeof (initargs)) {
1982267Sdp _kobj_printf(ops, "unix: init options too "
1992267Sdp "long. Ignoring -v.\n");
2002267Sdp break;
2012267Sdp }
2020Sstevel@tonic-gate boothowto |= RB_VERBOSE;
2032267Sdp (void) strlcat(initargs, "-v ", sizeof (initargs));
2040Sstevel@tonic-gate break;
2055648Ssetje #if defined(_OBP)
2065648Ssetje case 'V':
2075648Ssetje break;
2086659Staylor case 'Z':
2096659Staylor break;
2105648Ssetje #endif
2110Sstevel@tonic-gate case 'w':
2120Sstevel@tonic-gate boothowto |= RB_WRITABLE;
2130Sstevel@tonic-gate break;
2140Sstevel@tonic-gate case 'x':
2150Sstevel@tonic-gate boothowto |= RB_NOBOOTCLUSTER;
2160Sstevel@tonic-gate break;
2170Sstevel@tonic-gate case '?':
2180Sstevel@tonic-gate switch (params.gos_last_opt) {
2190Sstevel@tonic-gate case 'i':
2200Sstevel@tonic-gate _kobj_printf(ops, "krtld: Required argument "
2210Sstevel@tonic-gate "for -i flag missing. Ignoring.\n");
2220Sstevel@tonic-gate break;
2230Sstevel@tonic-gate default:
2240Sstevel@tonic-gate _kobj_printf(ops, "krtld: Ignoring invalid "
2250Sstevel@tonic-gate "kernel option -%c.\n",
2260Sstevel@tonic-gate params.gos_last_opt);
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate break;
2290Sstevel@tonic-gate default:
2300Sstevel@tonic-gate _kobj_printf(ops, "krtld: Ignoring unimplemented "
2310Sstevel@tonic-gate "option -%c.\n", c);
2320Sstevel@tonic-gate }
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate if ((boothowto & (RB_DEBUGENTER | RB_KMDB)) == RB_DEBUGENTER) {
2360Sstevel@tonic-gate _kobj_printf(ops, "krtld: -d is not valid without -k.\n");
2370Sstevel@tonic-gate boothowto &= ~RB_DEBUGENTER;
2380Sstevel@tonic-gate }
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate if (*params.gos_strp) {
2410Sstevel@tonic-gate /* Unused arguments. */
2420Sstevel@tonic-gate if (params.gos_strp[0] == '-' && ISSPACE(params.gos_strp[1])) {
2430Sstevel@tonic-gate /*EMPTY*/
2440Sstevel@tonic-gate /* Lousy install arguments. Silently ignore. */
2450Sstevel@tonic-gate } else {
2460Sstevel@tonic-gate _kobj_printf(ops, "krtld: Unused kernel arguments: "
2470Sstevel@tonic-gate "`%s'.\n", params.gos_strp);
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate }
251