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
5*5648Ssetje * Common Development and Distribution License (the "License").
6*5648Ssetje * 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*5648Ssetje * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include <sys/types.h>
290Sstevel@tonic-gate #include <sys/bootconf.h>
300Sstevel@tonic-gate #include <sys/reboot.h>
310Sstevel@tonic-gate #include <sys/param.h>
320Sstevel@tonic-gate #include <sys/salib.h>
330Sstevel@tonic-gate #include <sys/debug.h>
340Sstevel@tonic-gate #include <sys/promif.h>
350Sstevel@tonic-gate #include <sys/boot.h>
360Sstevel@tonic-gate #include <sys/sysmacros.h>
370Sstevel@tonic-gate #include <util/getoptstr.h>
380Sstevel@tonic-gate #include "boot_plat.h"
390Sstevel@tonic-gate
400Sstevel@tonic-gate static char default_path_buf[MAXPATHLEN];
410Sstevel@tonic-gate
420Sstevel@tonic-gate char wanboot_arguments[OBP_MAXPATHLEN]; /* args following "-o" */
430Sstevel@tonic-gate
44*5648Ssetje char cmd_line_boot_archive[MAXPATHLEN];
45*5648Ssetje
46*5648Ssetje boolean_t halt;
47*5648Ssetje
480Sstevel@tonic-gate /*
490Sstevel@tonic-gate * Parse the boot arguments, adding the options found to the existing boothowto
500Sstevel@tonic-gate * value (if any) or other state. Then rewrite the buffer with arguments for
510Sstevel@tonic-gate * the standalone.
520Sstevel@tonic-gate *
530Sstevel@tonic-gate * NOTE: boothowto may already have bits set when this function is called
540Sstevel@tonic-gate */
550Sstevel@tonic-gate void
bootflags(char * args,size_t argsz)560Sstevel@tonic-gate bootflags(char *args, size_t argsz)
570Sstevel@tonic-gate {
580Sstevel@tonic-gate static char newargs[OBP_MAXPATHLEN];
590Sstevel@tonic-gate struct gos_params params;
600Sstevel@tonic-gate const char *cp;
610Sstevel@tonic-gate char *np;
620Sstevel@tonic-gate size_t npres;
630Sstevel@tonic-gate int c;
64*5648Ssetje char *cmd_line_default_path;
650Sstevel@tonic-gate
660Sstevel@tonic-gate cmd_line_default_path = NULL;
670Sstevel@tonic-gate
680Sstevel@tonic-gate params.gos_opts = "HXF:VnI:D:advhko:";
690Sstevel@tonic-gate params.gos_strp = args;
700Sstevel@tonic-gate getoptstr_init(¶ms);
710Sstevel@tonic-gate while ((c = getoptstr(¶ms)) != -1) {
720Sstevel@tonic-gate switch (c) {
730Sstevel@tonic-gate /*
74*5648Ssetje * Bootblock flags.
750Sstevel@tonic-gate */
760Sstevel@tonic-gate case 'H':
77*5648Ssetje halt = B_TRUE;
78*5648Ssetje /*FALLTHRU*/
790Sstevel@tonic-gate case 'X':
80*5648Ssetje break;
81*5648Ssetje
820Sstevel@tonic-gate case 'F':
83*5648Ssetje if (params.gos_optarglen >=
84*5648Ssetje sizeof (cmd_line_boot_archive)) {
85*5648Ssetje printf("boot: -F argument too long. "
86*5648Ssetje "Ignoring.\n");
87*5648Ssetje break;
88*5648Ssetje }
89*5648Ssetje (void) strncpy(cmd_line_boot_archive,
90*5648Ssetje params.gos_optargp, params.gos_optarglen);
91*5648Ssetje cmd_line_boot_archive[params.gos_optarglen] = '\0';
920Sstevel@tonic-gate break;
930Sstevel@tonic-gate
940Sstevel@tonic-gate /*
950Sstevel@tonic-gate * Boot flags.
960Sstevel@tonic-gate */
970Sstevel@tonic-gate case 'V':
980Sstevel@tonic-gate verbosemode = 1;
990Sstevel@tonic-gate break;
1000Sstevel@tonic-gate case 'n':
1010Sstevel@tonic-gate cache_state = 0;
1020Sstevel@tonic-gate printf("Warning: boot will not enable cache\n");
1030Sstevel@tonic-gate break;
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate case 'D':
1060Sstevel@tonic-gate if (params.gos_optarglen >= sizeof (default_path_buf)) {
1070Sstevel@tonic-gate printf("boot: -D argument too long. "
1080Sstevel@tonic-gate "Ignoring.\n");
1090Sstevel@tonic-gate break;
1100Sstevel@tonic-gate }
1110Sstevel@tonic-gate (void) strncpy(default_path_buf, params.gos_optargp,
1120Sstevel@tonic-gate params.gos_optarglen);
1130Sstevel@tonic-gate default_path_buf[params.gos_optarglen] = '\0';
1140Sstevel@tonic-gate cmd_line_default_path = default_path_buf;
1150Sstevel@tonic-gate break;
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate case 'o':
1180Sstevel@tonic-gate if (params.gos_optarglen >=
1190Sstevel@tonic-gate sizeof (wanboot_arguments)) {
1200Sstevel@tonic-gate printf("boot: -o argument too long. "
1210Sstevel@tonic-gate "Ignoring.\n");
1220Sstevel@tonic-gate break;
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate (void) strncpy(wanboot_arguments, params.gos_optargp,
1250Sstevel@tonic-gate params.gos_optarglen);
1260Sstevel@tonic-gate wanboot_arguments[params.gos_optarglen] = '\0';
1270Sstevel@tonic-gate break;
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate case 'a':
1300Sstevel@tonic-gate boothowto |= RB_ASKNAME;
1310Sstevel@tonic-gate break;
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate case 'd':
1340Sstevel@tonic-gate boothowto |= RB_DEBUGENTER;
1350Sstevel@tonic-gate break;
1360Sstevel@tonic-gate case 'v':
1370Sstevel@tonic-gate boothowto |= RB_VERBOSE;
1380Sstevel@tonic-gate break;
1390Sstevel@tonic-gate case 'h':
1400Sstevel@tonic-gate boothowto |= RB_HALT;
1410Sstevel@tonic-gate break;
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate /* Consumed by the kernel */
1440Sstevel@tonic-gate case 'k':
1450Sstevel@tonic-gate boothowto |= RB_KMDB;
1460Sstevel@tonic-gate break;
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate /*
1490Sstevel@tonic-gate * Unrecognized flags: stop.
1500Sstevel@tonic-gate */
1510Sstevel@tonic-gate case '?':
1520Sstevel@tonic-gate /*
1530Sstevel@tonic-gate * Error. Either an unrecognized option, or an option
1540Sstevel@tonic-gate * without an argument. Check for the latter.
1550Sstevel@tonic-gate */
1560Sstevel@tonic-gate switch (params.gos_last_opt) {
1570Sstevel@tonic-gate case 'F':
1580Sstevel@tonic-gate case 'I':
1590Sstevel@tonic-gate case 'D':
1600Sstevel@tonic-gate case 'o':
1610Sstevel@tonic-gate printf("boot: -%c flag missing required "
1620Sstevel@tonic-gate "argument. Ignoring.\n",
1630Sstevel@tonic-gate params.gos_last_opt);
1640Sstevel@tonic-gate break;
1650Sstevel@tonic-gate default:
1660Sstevel@tonic-gate /* Unrecognized option. Stop. */
1670Sstevel@tonic-gate goto done;
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate break;
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate default:
1720Sstevel@tonic-gate printf("boot: Ignoring unimplemented option -%c.\n", c);
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate done:
1760Sstevel@tonic-gate
1770Sstevel@tonic-gate /*
1780Sstevel@tonic-gate * Construct the arguments for the standalone.
1790Sstevel@tonic-gate */
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate *newargs = '\0';
1820Sstevel@tonic-gate np = newargs;
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate /*
1850Sstevel@tonic-gate * We need a dash if we encountered an unrecognized option or if we
1860Sstevel@tonic-gate * need to pass flags on.
1870Sstevel@tonic-gate */
1880Sstevel@tonic-gate if (c == '?' || (boothowto &
1890Sstevel@tonic-gate /* These flags are to be passed to the standalone. */
1900Sstevel@tonic-gate (RB_ASKNAME | RB_DEBUGENTER | RB_VERBOSE | RB_HALT | RB_KMDB))) {
1910Sstevel@tonic-gate *np++ = '-';
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate /*
1940Sstevel@tonic-gate * boot(1M) says to pass these on.
1950Sstevel@tonic-gate */
1960Sstevel@tonic-gate if (boothowto & RB_ASKNAME)
1970Sstevel@tonic-gate *np++ = 'a';
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate /*
2000Sstevel@tonic-gate * boot isn't documented as consuming these flags, so pass
2010Sstevel@tonic-gate * them on.
2020Sstevel@tonic-gate */
2030Sstevel@tonic-gate if (boothowto & RB_DEBUGENTER)
2040Sstevel@tonic-gate *np++ = 'd';
2050Sstevel@tonic-gate if (boothowto & RB_KMDB)
2060Sstevel@tonic-gate *np++ = 'k';
2070Sstevel@tonic-gate if (boothowto & RB_VERBOSE)
2080Sstevel@tonic-gate *np++ = 'v';
2090Sstevel@tonic-gate if (boothowto & RB_HALT)
2100Sstevel@tonic-gate *np++ = 'h';
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate /*
2130Sstevel@tonic-gate * If we didn't encounter an unrecognized flag and there's
2140Sstevel@tonic-gate * more to copy, add a space to separate these flags.
2150Sstevel@tonic-gate * (Otherwise, unrecognized flags can be appended since we
2160Sstevel@tonic-gate * started this word with a dash.)
2170Sstevel@tonic-gate */
2180Sstevel@tonic-gate if (c == -1 && params.gos_strp[0] != '\0')
2190Sstevel@tonic-gate *np++ = ' ';
2200Sstevel@tonic-gate }
2210Sstevel@tonic-gate
2220Sstevel@tonic-gate npres = sizeof (newargs) - (size_t)(np - newargs);
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate if (c == '?') {
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate * Unrecognized flag: Copy gos_errp to end of line or a "--"
2270Sstevel@tonic-gate * word.
2280Sstevel@tonic-gate */
2290Sstevel@tonic-gate cp = params.gos_errp;
2300Sstevel@tonic-gate while (*cp && npres > 0) {
2310Sstevel@tonic-gate if (cp[0] == '-' && cp[1] == '-' &&
2320Sstevel@tonic-gate (cp[2] == '\0' || ISSPACE(cp[2]))) {
2330Sstevel@tonic-gate cp += 2;
2340Sstevel@tonic-gate SKIP_SPC(cp);
2350Sstevel@tonic-gate break;
2360Sstevel@tonic-gate } else {
2370Sstevel@tonic-gate const char *sp = cp;
2380Sstevel@tonic-gate size_t sz;
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate /* Copy until the next word. */
2410Sstevel@tonic-gate while (*cp && !ISSPACE(*cp))
2420Sstevel@tonic-gate cp++;
2430Sstevel@tonic-gate while (ISSPACE(*cp))
2440Sstevel@tonic-gate cp++;
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate sz = MIN(npres, (size_t)(cp - sp));
2470Sstevel@tonic-gate npres -= sz;
2480Sstevel@tonic-gate bcopy(sp, np, sz);
2490Sstevel@tonic-gate np += sz;
2500Sstevel@tonic-gate }
2510Sstevel@tonic-gate }
2520Sstevel@tonic-gate } else {
2530Sstevel@tonic-gate cp = params.gos_strp;
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate while (npres > 0 && (*np++ = *cp++) != '\0')
2570Sstevel@tonic-gate npres--;
2580Sstevel@tonic-gate
2590Sstevel@tonic-gate newargs[sizeof (newargs) - 1] = '\0';
2600Sstevel@tonic-gate (void) strlcpy(args, newargs, argsz);
2610Sstevel@tonic-gate
2620Sstevel@tonic-gate /*
2630Sstevel@tonic-gate * If a default filename was specified in the args, set it.
2640Sstevel@tonic-gate */
2650Sstevel@tonic-gate if (cmd_line_default_path)
2660Sstevel@tonic-gate set_default_filename(cmd_line_default_path);
267*5648Ssetje
268*5648Ssetje /*
269*5648Ssetje * See if user wants to examine things
270*5648Ssetje */
271*5648Ssetje if (halt == B_TRUE)
272*5648Ssetje prom_enter_mon();
2730Sstevel@tonic-gate }
274