[BACK]Return to boot2.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / i386 / stand / boot

Annotation of src/sys/arch/i386/stand/boot/boot2.c, Revision 1.30

1.30    ! lukem       1: /*     $NetBSD: boot2.c,v 1.29 2008/05/06 09:48:00 apb Exp $   */
1.25      ad          2:
                      3: /*-
                      4:  * Copyright (c) 2008 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     17:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     18:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     19:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     20:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     21:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     22:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     23:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     24:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     25:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     26:  * POSSIBILITY OF SUCH DAMAGE.
                     27:  */
1.1       dsl        28:
                     29: /*
                     30:  * Copyright (c) 2003
                     31:  *     David Laight.  All rights reserved
                     32:  * Copyright (c) 1996, 1997, 1999
                     33:  *     Matthias Drochner.  All rights reserved.
                     34:  * Copyright (c) 1996, 1997
                     35:  *     Perry E. Metzger.  All rights reserved.
                     36:  * Copyright (c) 1997
                     37:  *     Jason R. Thorpe.  All rights reserved
                     38:  *
                     39:  * Redistribution and use in source and binary forms, with or without
                     40:  * modification, are permitted provided that the following conditions
                     41:  * are met:
                     42:  * 1. Redistributions of source code must retain the above copyright
                     43:  *    notice, this list of conditions and the following disclaimer.
                     44:  * 2. Redistributions in binary form must reproduce the above copyright
                     45:  *    notice, this list of conditions and the following disclaimer in the
                     46:  *    documentation and/or other materials provided with the distribution.
                     47:  * 3. All advertising materials mentioning features or use of this software
                     48:  *    must display the following acknowledgements:
                     49:  *     This product includes software developed for the NetBSD Project
                     50:  *     by Matthias Drochner.
                     51:  *     This product includes software developed for the NetBSD Project
                     52:  *     by Perry E. Metzger.
                     53:  * 4. The names of the authors may not be used to endorse or promote products
                     54:  *    derived from this software without specific prior written permission.
                     55:  *
                     56:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     57:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     58:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     59:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     60:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     61:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     62:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     63:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     64:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     65:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     66:  */
                     67:
                     68: /* Based on stand/biosboot/main.c */
                     69:
1.5       christos   70: #include <sys/types.h>
1.1       dsl        71: #include <sys/reboot.h>
                     72: #include <sys/bootblock.h>
                     73:
                     74: #include <lib/libsa/stand.h>
                     75: #include <lib/libsa/ufs.h>
                     76: #include <lib/libkern/libkern.h>
                     77:
                     78: #include <libi386.h>
                     79: #include "devopen.h"
1.25      ad         80: #include "bootmod.h"
1.1       dsl        81:
1.17      sborrill   82: #ifdef SUPPORT_USTARFS
                     83: #include "ustarfs.h"
                     84: #endif
1.1       dsl        85: #ifdef SUPPORT_PS2
                     86: #include <biosmca.h>
                     87: #endif
                     88:
1.4       lukem      89: extern struct x86_boot_params boot_params;
1.1       dsl        90:
                     91: extern const char bootprog_name[], bootprog_rev[], bootprog_date[],
                     92:        bootprog_maker[];
                     93:
1.11      junyoung   94: int errno;
                     95:
                     96: int boot_biosdev;
                     97: u_int boot_biossector;
                     98:
1.1       dsl        99: static const char * const names[][2] = {
1.8       junyoung  100:        { "netbsd", "netbsd.gz" },
                    101:        { "onetbsd", "onetbsd.gz" },
                    102:        { "netbsd.old", "netbsd.old.gz" },
1.1       dsl       103: };
                    104:
                    105: #define NUMNAMES (sizeof(names)/sizeof(names[0]))
                    106: #define DEFFILENAME names[0][0]
                    107:
                    108: #define MAXDEVNAME 16
                    109:
1.15      sborrill  110: #ifndef SMALL
                    111: #define BOOTCONF "boot.cfg"
                    112: #define MAXMENU 10
1.28      chris     113: #define MAXBANNER 12
1.26      sborrill  114: #define COMMAND_SEPARATOR ';'
1.15      sborrill  115: #endif /* !SMALL */
                    116:
1.1       dsl       117: static char *default_devname;
                    118: static int default_unit, default_partition;
                    119: static const char *default_filename;
                    120:
                    121: char *sprint_bootsel(const char *);
                    122: void bootit(const char *, int, int);
                    123: void print_banner(void);
1.11      junyoung  124: void boot2(int, u_int);
1.1       dsl       125:
1.15      sborrill  126: #ifndef SMALL
                    127: void parsebootconf(const char *);
                    128: void doboottypemenu(void);
                    129: int atoi(const char *);
                    130: #endif /* !SMALL */
                    131:
1.1       dsl       132: void   command_help(char *);
                    133: void   command_ls(char *);
                    134: void   command_quit(char *);
                    135: void   command_boot(char *);
                    136: void   command_dev(char *);
                    137: void   command_consdev(char *);
1.25      ad        138: void   command_modules(char *);
                    139: void   command_load(char *);
1.1       dsl       140:
                    141: const struct bootblk_command commands[] = {
                    142:        { "help",       command_help },
                    143:        { "?",          command_help },
                    144:        { "ls",         command_ls },
                    145:        { "quit",       command_quit },
                    146:        { "boot",       command_boot },
                    147:        { "dev",        command_dev },
                    148:        { "consdev",    command_consdev },
1.25      ad        149:        { "modules",    command_modules },
                    150:        { "load",       command_load },
1.1       dsl       151:        { NULL,         NULL },
                    152: };
                    153:
1.15      sborrill  154: #ifndef SMALL
                    155: struct bootconf_def {
                    156:        char *banner[MAXBANNER];        /* Banner text */
                    157:        char *command[MAXMENU];         /* Menu commands per entry*/
                    158:        char *consdev;                  /* Console device */
                    159:        int def;                        /* Default menu option */
                    160:        char *desc[MAXMENU];            /* Menu text per entry */
                    161:        int nummenu;                    /* Number of menu items */
                    162:        int timeout;                    /* Timeout in seconds */
                    163: } bootconf;
                    164: #endif /* !SMALL */
                    165:
1.1       dsl       166: int
                    167: parsebootfile(const char *fname, char **fsname, char **devname,
1.11      junyoung  168:              int *unit, int *partition, const char **file)
1.1       dsl       169: {
                    170:        const char *col;
                    171:
                    172:        *fsname = "ufs";
                    173:        *devname = default_devname;
                    174:        *unit = default_unit;
                    175:        *partition = default_partition;
                    176:        *file = default_filename;
                    177:
                    178:        if (fname == NULL)
1.7       junyoung  179:                return 0;
1.1       dsl       180:
1.8       junyoung  181:        if ((col = strchr(fname, ':')) != NULL) {       /* device given */
1.1       dsl       182:                static char savedevname[MAXDEVNAME+1];
                    183:                int devlen;
1.11      junyoung  184:                int u = 0, p = 0;
1.1       dsl       185:                int i = 0;
                    186:
                    187:                devlen = col - fname;
                    188:                if (devlen > MAXDEVNAME)
1.6       junyoung  189:                        return EINVAL;
1.1       dsl       190:
                    191: #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
                    192:                if (!isvalidname(fname[i]))
1.6       junyoung  193:                        return EINVAL;
1.1       dsl       194:                do {
                    195:                        savedevname[i] = fname[i];
                    196:                        i++;
                    197:                } while (isvalidname(fname[i]));
                    198:                savedevname[i] = '\0';
                    199:
                    200: #define isnum(c) ((c) >= '0' && (c) <= '9')
                    201:                if (i < devlen) {
                    202:                        if (!isnum(fname[i]))
1.6       junyoung  203:                                return EUNIT;
1.1       dsl       204:                        do {
                    205:                                u *= 10;
                    206:                                u += fname[i++] - '0';
                    207:                        } while (isnum(fname[i]));
                    208:                }
                    209:
                    210: #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z')
                    211:                if (i < devlen) {
                    212:                        if (!isvalidpart(fname[i]))
1.6       junyoung  213:                                return EPART;
1.1       dsl       214:                        p = fname[i++] - 'a';
                    215:                }
                    216:
                    217:                if (i != devlen)
1.6       junyoung  218:                        return ENXIO;
1.1       dsl       219:
                    220:                *devname = savedevname;
                    221:                *unit = u;
                    222:                *partition = p;
                    223:                fname = col + 1;
                    224:        }
                    225:
                    226:        if (*fname)
                    227:                *file = fname;
                    228:
1.6       junyoung  229:        return 0;
1.1       dsl       230: }
                    231:
                    232: char *
                    233: sprint_bootsel(const char *filename)
                    234: {
                    235:        char *fsname, *devname;
                    236:        int unit, partition;
                    237:        const char *file;
                    238:        static char buf[80];
                    239:
                    240:        if (parsebootfile(filename, &fsname, &devname, &unit,
                    241:                          &partition, &file) == 0) {
                    242:                sprintf(buf, "%s%d%c:%s", devname, unit, 'a' + partition, file);
1.6       junyoung  243:                return buf;
1.1       dsl       244:        }
1.6       junyoung  245:        return "(invalid)";
1.1       dsl       246: }
                    247:
                    248: void
                    249: bootit(const char *filename, int howto, int tell)
                    250: {
                    251:
                    252:        if (tell) {
                    253:                printf("booting %s", sprint_bootsel(filename));
                    254:                if (howto)
                    255:                        printf(" (howto 0x%x)", howto);
                    256:                printf("\n");
                    257:        }
                    258:
                    259:        if (exec_netbsd(filename, 0, howto) < 0)
                    260:                printf("boot: %s: %s\n", sprint_bootsel(filename),
                    261:                       strerror(errno));
                    262:        else
                    263:                printf("boot returned\n");
                    264: }
                    265:
                    266: void
                    267: print_banner(void)
                    268: {
1.15      sborrill  269: #ifndef SMALL
                    270:        int n;
                    271:        if (bootconf.banner[0]) {
1.22      sborrill  272:                for (n = 0; bootconf.banner[n] && n < MAXBANNER; n++)
1.15      sborrill  273:                        printf("%s\n", bootconf.banner[n]);
                    274:        } else {
                    275: #endif /* !SMALL */
                    276:                printf("\n");
                    277:                printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
                    278:                printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
                    279:                printf(">> Memory: %d/%d k\n", getbasemem(), getextmem());
                    280:
                    281: #ifndef SMALL
                    282:        }
                    283: #endif /* !SMALL */
                    284: }
                    285:
                    286: #ifndef SMALL
                    287: int
                    288: atoi(const char *in)
                    289: {
                    290:        char *c;
                    291:        int ret;
                    292:
                    293:        ret = 0;
                    294:        c = (char *)in;
                    295:        if (*c == '-')
                    296:                c++;
                    297:        for (; isnum(*c); c++)
                    298:                ret = (ret * 10) + (*c - '0');
                    299:
                    300:        return (*in == '-') ? -ret : ret;
                    301: }
                    302:
                    303: /*
1.20      sborrill  304:  * This function parses a boot.cfg file in the root of the filesystem
1.15      sborrill  305:  * (if present) and populates the global boot configuration.
                    306:  *
                    307:  * The file consists of a number of lines each terminated by \n
                    308:  * The lines are in the format keyword=value. There should be spaces
                    309:  * around the = sign.
                    310:  *
                    311:  * The recognised keywords are:
                    312:  * banner: text displayed instead of the normal welcome text
                    313:  * menu: Descriptive text:command to use
                    314:  * timeout: Timeout in seconds (overrides that set by installboot)
                    315:  * default: the default menu option to use if Return is pressed
                    316:  * consdev: the console device to use
                    317:  *
1.20      sborrill  318:  * Example boot.cfg file:
1.15      sborrill  319:  * banner=Welcome to NetBSD
                    320:  * banner=Please choose the boot type from the following menu
                    321:  * menu=Boot NetBSD:boot netbsd
                    322:  * menu=Boot into single user mode:boot netbsd -s
1.21      apb       323:  * menu=:boot hd1a:netbsd -cs
1.15      sborrill  324:  * menu=Goto boot comand line:prompt
                    325:  * timeout=10
                    326:  * consdev=com0
                    327:  * default=1
                    328: */
                    329: void
                    330: parsebootconf(const char *conf)
                    331: {
                    332:        char *bc, *c;
                    333:        int cmenu, cbanner, len;
                    334:        int fd, err, off;
                    335:        struct stat st;
1.21      apb       336:        char *key, *value, *v2;
1.24      ad        337:        extern char twiddle_toggle;
1.17      sborrill  338: #ifdef SUPPORT_USTARFS
                    339:        void *op_open;
                    340: #endif
1.15      sborrill  341:
                    342:        /* Clear bootconf structure */
                    343:        bzero((void *)&bootconf, sizeof(bootconf));
                    344:
                    345:        /* Set timeout to configured */
                    346:        bootconf.timeout = boot_params.bp_timeout;
                    347:
1.17      sborrill  348:        /* don't try to open BOOTCONF if the target fs is ustarfs */
                    349: #ifdef SUPPORT_USTARFS
                    350: #if !defined(LIBSA_SINGLE_FILESYSTEM)
                    351:        fd = open("boot", 0);   /* assume we are loaded as "boot" from here */
                    352:        if (fd < 0)
                    353:                op_open = NULL; /* XXX */
                    354:        else {
                    355:                op_open = files[fd].f_ops->open;
                    356:                close(fd);
                    357:        }
                    358: #else
                    359:        op_open = file_system[0].open;
                    360: #endif /* !LIBSA_SINGLE_FILESYSTEM */
                    361:        if (op_open == ustarfs_open)
1.15      sborrill  362:                return;
1.17      sborrill  363: #endif /* SUPPORT_USTARFS */
1.1       dsl       364:
1.15      sborrill  365:        fd = open(BOOTCONF, 0);
                    366:        if (fd < 0)
                    367:                return;
                    368:
1.17      sborrill  369:        err = fstat(fd, &st);
                    370:        if (err == -1) {
                    371:                close(fd);
                    372:                return;
                    373:        }
                    374:
1.15      sborrill  375:        bc = alloc(st.st_size + 1);
                    376:        if (bc == NULL) {
                    377:                printf("Could not allocate memory for boot configuration\n");
                    378:                return;
                    379:        }
                    380:
1.24      ad        381:        twiddle_toggle = 1;
1.15      sborrill  382:        off = 0;
                    383:        do {
                    384:                len = read(fd, bc + off, 1024);
                    385:                if (len <= 0)
                    386:                        break;
                    387:                off += len;
                    388:        } while (len > 0);
                    389:        bc[off] = '\0';
1.24      ad        390:        twiddle_toggle = 0;
1.15      sborrill  391:
                    392:        close(fd);
1.20      sborrill  393:        /* bc now contains the whole boot.cfg file */
1.15      sborrill  394:
                    395:        cmenu = 0;
                    396:        cbanner = 0;
                    397:        for(c = bc; *c; c++) {
                    398:                key = c;
                    399:                /* Look for = separator between key and value */
                    400:                for (; *c && *c != '='; c++)
                    401:                        continue;
                    402:                if (*c == '\0')
                    403:                        break; /* break if at end of data */
                    404:
                    405:                /* zero terminate key which points to keyword */
                    406:                *c++ = 0;
                    407:                value = c;
                    408:                /* Look for end of line (or file) and zero terminate value */
                    409:                for (; *c && *c != '\n'; c++)
                    410:                        continue;
                    411:                *c = 0;
                    412:
                    413:                if (!strncmp(key, "menu", 4)) {
1.21      apb       414:                        /*
                    415:                         * Parse "menu=<description>:<command>".  If the
                    416:                         * description is empty ("menu=:<command>)",
                    417:                         * then re-use the command as the description.
                    418:                         * Note that the command may contain embedded
                    419:                         * colons.
                    420:                         */
1.15      sborrill  421:                        if (cmenu >= MAXMENU)
                    422:                                continue;
                    423:                        bootconf.desc[cmenu] = value;
1.21      apb       424:                        for (v2=value; *v2 && *v2 != ':'; v2++)
1.15      sborrill  425:                                continue;
1.21      apb       426:                        if (*v2) {
                    427:                                *v2++ = 0;
                    428:                                bootconf.command[cmenu] = v2;
                    429:                                if (! *value)
                    430:                                        bootconf.desc[cmenu] = v2;
1.15      sborrill  431:                                cmenu++;
                    432:                        } else {
                    433:                                /* No delimiter means invalid line */
                    434:                                bootconf.desc[cmenu] = NULL;
                    435:                        }
                    436:                } else if (!strncmp(key, "banner", 6)) {
                    437:                        if (cbanner < MAXBANNER)
                    438:                                bootconf.banner[cbanner++] = value;
                    439:                } else if (!strncmp(key, "timeout", 7)) {
                    440:                        if (!isnum(*value))
                    441:                                bootconf.timeout = -1;
                    442:                        else
                    443:                                bootconf.timeout = atoi(value);
                    444:                } else if (!strncmp(key, "default", 7)) {
                    445:                        bootconf.def = atoi(value) - 1;
                    446:                } else if (!strncmp(key, "consdev", 7)) {
                    447:                        bootconf.consdev = value;
1.25      ad        448:                } else if (!strncmp(key, "load", 6)) {
                    449:                        command_load(value);
1.15      sborrill  450:                }
                    451:        }
                    452:        bootconf.nummenu = cmenu;
                    453:        if (bootconf.def < 0)
                    454:                bootconf.def = 0;
                    455:        if (bootconf.def >= cmenu)
                    456:                bootconf.def = cmenu - 1;
                    457: }
                    458:
                    459: /*
                    460:  * doboottypemenu will render the menu and parse any user input
                    461:  */
                    462:
                    463: void
                    464: doboottypemenu(void)
                    465: {
                    466:        int choice;
1.26      sborrill  467:        char input[80], c, *ic, *oc;
1.15      sborrill  468:
1.16      sborrill  469:        printf("\n");
1.15      sborrill  470:        /* Display menu */
                    471:        for (choice = 0; bootconf.desc[choice]; choice++)
                    472:                printf("    %d. %s\n", choice+1, bootconf.desc[choice]);
                    473:
                    474:        choice = -1;
                    475:        for(;;) {
                    476:                input[0] = '\0';
                    477:
                    478:                if (bootconf.timeout < 0) {
                    479:                        printf("\nOption: [%d]:", bootconf.def + 1);
                    480:                        gets(input);
                    481:                        if (input[0] == '\0') choice = bootconf.def;
                    482:                        if (input[0] >= '1' &&
                    483:                                input[0] <= bootconf.nummenu + '0')
                    484:                                    choice = input[0] - '1';
                    485:                } else if (bootconf.timeout == 0)
                    486:                        choice = bootconf.def;
                    487:                else  {
1.29      apb       488:                        printf("\nChoose an option; RETURN for default; "
1.30    ! lukem     489:                               "SPACE to stop countdown.\n");
1.15      sborrill  490:                        printf("Option %d will be chosen in ",
                    491:                              bootconf.def + 1);
                    492:                        c = awaitkey(bootconf.timeout, 1);
                    493:                        if (c >= '1' && c <= bootconf.nummenu + '0')
                    494:                                choice = c - '1';
                    495:                        else if (c ==  '\r' || c == '\n' || c == '\0')
                    496:                                /* default if timed out or Return pressed */
                    497:                                choice = bootconf.def;
                    498:                        else {
                    499:                                /* If any other key pressed, drop to menu */
                    500:                                bootconf.timeout = -1;
                    501:                                choice = -1;
                    502:                        }
                    503:                }
                    504:                if (choice < 0)
                    505:                        continue;
                    506:                if (!strcmp(bootconf.command[choice], "prompt") &&
                    507:                    ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0 ||
                    508:                    check_password(boot_params.bp_password))) {
                    509:                        printf("type \"?\" or \"help\" for help.\n");
                    510:                        bootmenu(); /* does not return */
1.26      sborrill  511:                } else {
                    512:                        ic = bootconf.command[choice];
                    513:                        /* Split command string at ; into separate commands */
                    514:                        do {
                    515:                                oc = input;
                    516:                                /* Look for ; separator */
                    517:                                for (; *ic && *ic != COMMAND_SEPARATOR; ic++)
                    518:                                        *oc++ = *ic;
                    519:                                if (*input == '\0')
                    520:                                        continue;
                    521:                                /* Strip out any trailing spaces */
                    522:                                oc--;
                    523:                                for (; *oc ==' ' && oc > input; oc--);
                    524:                                *++oc = '\0';
                    525:                                if (*ic == COMMAND_SEPARATOR)
                    526:                                        ic++;
                    527:                                /* Stop silly command strings like ;;; */
                    528:                                if (*input != '\0')
                    529:                                        docommand(input);
                    530:                                /* Skip leading spaces */
                    531:                                for (; *ic == ' '; ic++);
                    532:                        } while (*ic);
                    533:                }
1.15      sborrill  534:
                    535:        }
1.1       dsl       536: }
1.15      sborrill  537: #endif /* !SMALL */
1.1       dsl       538:
1.11      junyoung  539: /*
                    540:  * Called from the initial entry point boot_start in biosboot.S
                    541:  *
                    542:  * biosdev: BIOS drive number the system booted from
                    543:  * biossector: Sector number of the NetBSD partition
                    544:  */
1.1       dsl       545: void
1.11      junyoung  546: boot2(int biosdev, u_int biossector)
1.1       dsl       547: {
                    548:        int currname;
                    549:        char c;
                    550:
                    551:        initio(boot_params.bp_consdev);
                    552:
                    553: #ifdef SUPPORT_PS2
                    554:        biosmca();
                    555: #endif
                    556:        gateA20();
                    557:
1.4       lukem     558:        if (boot_params.bp_flags & X86_BP_FLAGS_RESET_VIDEO)
1.1       dsl       559:                biosvideomode();
                    560:
1.11      junyoung  561:        /* need to remember these */
                    562:        boot_biosdev = biosdev;
                    563:        boot_biossector = biossector;
                    564:
1.1       dsl       565:        /* try to set default device to what BIOS tells us */
1.11      junyoung  566:        bios2dev(biosdev, biossector, &default_devname, &default_unit,
                    567:                 &default_partition);
1.1       dsl       568:
                    569:        /* if the user types "boot" without filename */
                    570:        default_filename = DEFFILENAME;
                    571:
1.15      sborrill  572: #ifndef SMALL
                    573:        parsebootconf(BOOTCONF);
                    574:
                    575:        /*
1.20      sborrill  576:         * If console set in boot.cfg, switch to it.
1.15      sborrill  577:         * This will print the banner, so we don't need to explicitly do it
                    578:         */
                    579:        if (bootconf.consdev)
                    580:                command_consdev(bootconf.consdev);
                    581:        else
                    582:                print_banner();
                    583:
                    584:        /* Display the menu, if applicable */
                    585:        if (bootconf.nummenu > 0) {
                    586:                /* Does not return */
                    587:                doboottypemenu();
                    588:        }
                    589: #else
                    590:                print_banner();
                    591: #endif
                    592:
1.1       dsl       593:        printf("Press return to boot now, any other key for boot menu\n");
1.10      junyoung  594:        for (currname = 0; currname < NUMNAMES; currname++) {
1.1       dsl       595:                printf("booting %s - starting in ",
                    596:                       sprint_bootsel(names[currname][0]));
                    597:
1.15      sborrill  598: #ifdef SMALL
1.1       dsl       599:                c = awaitkey(boot_params.bp_timeout, 1);
1.15      sborrill  600: #else
                    601:                c = awaitkey((bootconf.timeout < 0) ? 0 : bootconf.timeout, 1);
                    602: #endif
1.1       dsl       603:                if ((c != '\r') && (c != '\n') && (c != '\0') &&
1.4       lukem     604:                    ((boot_params.bp_flags & X86_BP_FLAGS_PASSWORD) == 0
1.9       junyoung  605:                     || check_password(boot_params.bp_password))) {
1.1       dsl       606:                        printf("type \"?\" or \"help\" for help.\n");
                    607:                        bootmenu(); /* does not return */
                    608:                }
                    609:
                    610:                /*
                    611:                 * try pairs of names[] entries, foo and foo.gz
                    612:                 */
                    613:                /* don't print "booting..." again */
                    614:                bootit(names[currname][0], 0, 0);
                    615:                /* since it failed, try compressed bootfile. */
                    616:                bootit(names[currname][1], 0, 1);
                    617:        }
1.10      junyoung  618:
                    619:        bootmenu();     /* does not return */
1.1       dsl       620: }
                    621:
                    622: /* ARGSUSED */
                    623: void
                    624: command_help(char *arg)
                    625: {
                    626:
                    627:        printf("commands are:\n"
1.23      ad        628:               "boot [xdNx:][filename] [-12acdqsvxz]\n"
1.8       junyoung  629:               "     (ex. \"hd0a:netbsd.old -s\"\n"
                    630:               "ls [path]\n"
                    631:               "dev xd[N[x]]:\n"
                    632:               "consdev {pc|com[0123]|com[0123]kbd|auto}\n"
1.25      ad        633:               "modules {enabled|disabled}\n"
                    634:               "load {path_to_module}\n"
1.8       junyoung  635:               "help|?\n"
                    636:               "quit\n");
1.1       dsl       637: }
                    638:
                    639: void
                    640: command_ls(char *arg)
                    641: {
                    642:        const char *save = default_filename;
                    643:
                    644:        default_filename = "/";
                    645:        ufs_ls(arg);
                    646:        default_filename = save;
                    647: }
                    648:
                    649: /* ARGSUSED */
                    650: void
                    651: command_quit(char *arg)
                    652: {
                    653:
                    654:        printf("Exiting...\n");
                    655:        delay(1000000);
                    656:        reboot();
                    657:        /* Note: we shouldn't get to this point! */
                    658:        panic("Could not reboot!");
                    659:        exit(0);
                    660: }
                    661:
                    662: void
                    663: command_boot(char *arg)
                    664: {
                    665:        char *filename;
                    666:        int howto;
                    667:
                    668:        if (parseboot(arg, &filename, &howto))
                    669:                bootit(filename, howto, 1);
                    670: }
                    671:
                    672: void
                    673: command_dev(char *arg)
                    674: {
                    675:        static char savedevname[MAXDEVNAME + 1];
                    676:        char *fsname, *devname;
                    677:        const char *file; /* dummy */
                    678:
                    679:        if (*arg == '\0') {
                    680:                printf("%s%d%c:\n", default_devname, default_unit,
                    681:                       'a' + default_partition);
                    682:                return;
                    683:        }
                    684:
1.13      ws        685:        if (strchr(arg, ':') == NULL ||
1.1       dsl       686:            parsebootfile(arg, &fsname, &devname, &default_unit,
                    687:                          &default_partition, &file)) {
                    688:                command_help(NULL);
                    689:                return;
                    690:        }
                    691:
                    692:        /* put to own static storage */
                    693:        strncpy(savedevname, devname, MAXDEVNAME + 1);
                    694:        default_devname = savedevname;
                    695: }
                    696:
                    697: static const struct cons_devs {
1.8       junyoung  698:        const char      *name;
1.9       junyoung  699:        u_int           tag;
1.1       dsl       700: } cons_devs[] = {
                    701:        { "pc",         CONSDEV_PC },
                    702:        { "com0",       CONSDEV_COM0 },
                    703:        { "com1",       CONSDEV_COM1 },
                    704:        { "com2",       CONSDEV_COM2 },
                    705:        { "com3",       CONSDEV_COM3 },
                    706:        { "com0kbd",    CONSDEV_COM0KBD },
                    707:        { "com1kbd",    CONSDEV_COM1KBD },
                    708:        { "com2kbd",    CONSDEV_COM2KBD },
                    709:        { "com3kbd",    CONSDEV_COM3KBD },
                    710:        { "auto",       CONSDEV_AUTO },
1.8       junyoung  711:        { NULL,         0 }
                    712: };
1.1       dsl       713:
                    714: void
                    715: command_consdev(char *arg)
                    716: {
                    717:        const struct cons_devs *cdp;
                    718:
                    719:        for (cdp = cons_devs; cdp->name; cdp++) {
1.6       junyoung  720:                if (strcmp(arg, cdp->name) == 0) {
1.1       dsl       721:                        initio(cdp->tag);
                    722:                        print_banner();
                    723:                        return;
                    724:                }
                    725:        }
                    726:        printf("invalid console device.\n");
                    727: }
1.25      ad        728:
                    729: void
                    730: command_modules(char *arg)
                    731: {
                    732:
                    733:        if (strcmp(arg, "enabled") == 0 ||
                    734:            strcmp(arg, "on") == 0)
                    735:                boot_modules_enabled = true;
                    736:        else if (strcmp(arg, "disabled") == 0 ||
                    737:            strcmp(arg, "off") == 0)
                    738:                boot_modules_enabled = false;
                    739:        else
                    740:                printf("invalid flag, must be 'enabled' or 'disabled'.\n");
                    741: }
                    742:
                    743: void
                    744: command_load(char *arg)
                    745: {
                    746:        boot_module_t *bm, *bmp;
                    747:        size_t len;
                    748:        char *str;
                    749:
                    750:        bm = alloc(sizeof(boot_module_t));
                    751:        len = strlen(arg) + 1;
                    752:        str = alloc(len);
                    753:        if (bm == NULL || str == NULL) {
                    754:                printf("couldn't allocate module\n");
                    755:                return;
                    756:        }
                    757:        memcpy(str, arg, len);
                    758:        bm->bm_path = str;
                    759:        bm->bm_next = NULL;
                    760:        if (boot_modules == NULL)
                    761:                boot_modules = bm;
                    762:        else {
                    763:                for (bmp = boot_modules; bmp->bm_next;
                    764:                    bmp = bmp->bm_next)
                    765:                        ;
                    766:                bmp->bm_next = bm;
                    767:        }
                    768: }

CVSweb <webmaster@jp.NetBSD.org>