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

Annotation of src/sys/arch/landisk/stand/boot/boot2.c, Revision 1.3.6.1

1.3.6.1 ! tls         1: /*     $NetBSD$        */
1.1       uwe         2:
                      3: /*
                      4:  * Copyright (c) 2003
                      5:  *     David Laight.  All rights reserved
                      6:  * Copyright (c) 1996, 1997, 1999
                      7:  *     Matthias Drochner.  All rights reserved.
                      8:  * Copyright (c) 1996, 1997
                      9:  *     Perry E. Metzger.  All rights reserved.
                     10:  * Copyright (c) 1997
                     11:  *     Jason R. Thorpe.  All rights reserved
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. All advertising materials mentioning features or use of this software
                     22:  *    must display the following acknowledgements:
                     23:  *     This product includes software developed for the NetBSD Project
                     24:  *     by Matthias Drochner.
                     25:  *     This product includes software developed for the NetBSD Project
                     26:  *     by Perry E. Metzger.
                     27:  * 4. The names of the authors may not be used to endorse or promote products
                     28:  *    derived from this software without specific prior written permission.
                     29:  *
                     30:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     31:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     32:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     33:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     34:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     35:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     36:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     37:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     38:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     39:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     40:  */
                     41:
                     42: /* Based on stand/biosboot/main.c */
                     43:
                     44: #include <sys/types.h>
                     45: #include <sys/reboot.h>
                     46: #include <sys/bootblock.h>
                     47: #include <sys/boot_flag.h>
                     48:
                     49: #include <lib/libsa/stand.h>
                     50: #include <lib/libsa/loadfile.h>
                     51: #include <lib/libsa/ufs.h>
                     52: #include <lib/libkern/libkern.h>
                     53:
                     54: #include "biosdisk.h"
                     55:
                     56: #include "boot.h"
                     57: #include "bootinfo.h"
                     58: #include "cons.h"
                     59:
                     60: int errno;
                     61:
                     62: extern struct landisk_boot_params boot_params;
                     63:
                     64: static const char * const names[][2] = {
                     65:        { "netbsd", "netbsd.gz" },
                     66:        { "netbsd.old", "netbsd.old.gz", },
                     67:        { "onetbsd", "onetbsd.gz" },
                     68: };
                     69:
                     70: #define        NUMNAMES        (sizeof(names) / sizeof(names[0]))
                     71: #define DEFFILENAME    names[0][0]
                     72:
                     73: #define        MAXDEVNAME      16
                     74:
                     75: static char *default_devname;
                     76: static uint default_unit, default_partition;
                     77: static const char *default_filename;
                     78:
                     79: char *sprint_bootsel(const char *filename);
                     80: void bootit(const char *filename, int howto, int tell);
                     81: void print_banner(void);
                     82: void boot2(uint32_t boot_biossector);
                     83:
                     84: int exec_netbsd(const char *file, int howto);
                     85:
                     86: static char *gettrailer(char *arg);
                     87: static int parseopts(const char *opts, int *howto);
                     88: static int parseboot(char *arg, char **filename, int *howto);
                     89:
                     90: void bootmenu(void);
                     91: static void bootcmd_help(char *);
                     92: static void bootcmd_ls(char *);
                     93: static void bootcmd_quit(char *);
                     94: static void bootcmd_halt(char *);
                     95: static void bootcmd_boot(char *);
                     96: static void bootcmd_monitor(char *);
                     97:
                     98: static const struct bootblk_command {
                     99:        const char *c_name;
                    100:        void (*c_fn)(char *arg);
                    101: } bootcmds[] = {
                    102:        { "help",       bootcmd_help },
                    103:        { "?",          bootcmd_help },
                    104:        { "ls",         bootcmd_ls },
                    105:        { "quit",       bootcmd_quit },
                    106:        { "halt",       bootcmd_halt },
                    107:        { "boot",       bootcmd_boot },
                    108:        { "!",          bootcmd_monitor },
                    109:        { NULL,         NULL },
                    110: };
                    111:
                    112: int
                    113: parsebootfile(const char *fname, char **devname,
                    114:        uint *unit, uint *partition, const char **file)
                    115: {
                    116:        const char *col;
                    117:
                    118:        *devname = default_devname;
                    119:        *unit = default_unit;
                    120:        *partition = default_partition;
                    121:        *file = default_filename;
                    122:
                    123:        if (fname == NULL)
                    124:                return (0);
                    125:
                    126:        if((col = strchr(fname, ':'))) {        /* device given */
                    127:                static char savedevname[MAXDEVNAME+1];
                    128:                int devlen;
                    129:                unsigned int u = 0, p = 0;
                    130:                int i = 0;
                    131:
                    132:                devlen = col - fname;
                    133:                if (devlen > MAXDEVNAME)
                    134:                        return (EINVAL);
                    135:
                    136: #define isvalidname(c) ((c) >= 'a' && (c) <= 'z')
                    137:                if (!isvalidname(fname[i]))
                    138:                        return (EINVAL);
                    139:                do {
                    140:                        savedevname[i] = fname[i];
                    141:                        i++;
                    142:                } while (isvalidname(fname[i]));
                    143:                savedevname[i] = '\0';
                    144:
                    145: #define isnum(c) ((c) >= '0' && (c) <= '9')
                    146:                if (i < devlen) {
                    147:                        if (!isnum(fname[i]))
                    148:                                return (EUNIT);
                    149:                        do {
                    150:                                u *= 10;
                    151:                                u += fname[i++] - '0';
                    152:                        } while (isnum(fname[i]));
                    153:                }
                    154:
                    155: #define isvalidpart(c) ((c) >= 'a' && (c) <= 'p')
                    156:                if (i < devlen) {
                    157:                        if (!isvalidpart(fname[i]))
                    158:                                return (EPART);
                    159:                        p = fname[i++] - 'a';
                    160:                }
                    161:
                    162:                if (i != devlen)
                    163:                        return (ENXIO);
                    164:
                    165:                *devname = savedevname;
                    166:                *unit = u;
                    167:                *partition = p;
                    168:                fname = col + 1;
                    169:        }
                    170:
                    171:        if (*fname)
                    172:                *file = fname;
                    173:
                    174:        return (0);
                    175: }
                    176:
                    177: char *
                    178: sprint_bootsel(const char *filename)
                    179: {
                    180:        static char buf[80];
                    181:        char *devname;
                    182:        uint unit, partition;
                    183:        const char *file;
                    184:
                    185:        if (parsebootfile(filename, &devname, &unit, &partition, &file) == 0) {
1.3.6.1 ! tls       186:                snprintf(buf, sizeof(buf), "%s%d%c:%s", devname, unit,
        !           187:                    'a' + partition, file);
1.1       uwe       188:                return (buf);
                    189:        }
                    190:        return ("(invalid)");
                    191: }
                    192:
                    193: void
                    194: bootit(const char *filename, int howto, int tell)
                    195: {
                    196:
                    197:        if (tell) {
                    198:                printf("booting %s", sprint_bootsel(filename));
                    199:                if (howto)
                    200:                        printf(" (howto 0x%x)", howto);
                    201:                printf("\n");
                    202:        }
                    203:
                    204:        if (exec_netbsd(filename, howto) < 0) {
                    205:                printf("boot: %s: %s\n", sprint_bootsel(filename),
                    206:                       strerror(errno));
                    207:        } else {
                    208:                printf("boot returned\n");
                    209:        }
                    210: }
                    211:
                    212: void
                    213: print_banner(void)
                    214: {
                    215:        extern const char bootprog_name[];
                    216:        extern const char bootprog_rev[];
                    217:
                    218:        printf("\n");
                    219:        printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
                    220: }
                    221:
                    222: void
                    223: boot2(uint32_t boot_biossector)
                    224: {
                    225:        int currname;
                    226:        int c;
                    227:
                    228:        /* Initialize hardware */
                    229:        tick_init();
                    230:
                    231:        /* Initialize console */
                    232:        cninit(boot_params.bp_consdev);
                    233:
                    234:        print_banner();
                    235:
                    236:        /* try to set default device to what BIOS tells us */
                    237:        bios2dev(0x40, &default_devname, &default_unit,
                    238:                boot_biossector, &default_partition);
                    239:
                    240:        /* if the user types "boot" without filename */
                    241:        default_filename = DEFFILENAME;
                    242:
                    243:        printf("Press return to boot now, any other key for boot menu\n");
                    244:        currname = 0;
                    245:        for (;;) {
                    246:                printf("booting %s - starting in ",
                    247:                    sprint_bootsel(names[currname][0]));
                    248:
                    249:                c = awaitkey(boot_params.bp_timeout, 1);
                    250:                if ((c != '\r') && (c != '\n') && (c != '\0')) {
                    251:                        printf("type \"?\" or \"help\" for help.\n");
                    252:                        bootmenu(); /* does not return */
                    253:                }
                    254:
                    255:                /*
                    256:                 * try pairs of names[] entries, foo and foo.gz
                    257:                 */
                    258:                /* don't print "booting..." again */
                    259:                bootit(names[currname][0], 0, 0);
                    260:                /* since it failed, try compressed bootfile. */
                    261:                bootit(names[currname][1], 0, 1);
                    262:                /* since it failed, try switching bootfile. */
                    263:                currname = (currname + 1) % NUMNAMES;
                    264:        }
                    265: }
                    266:
                    267: int
                    268: exec_netbsd(const char *file, int howto)
                    269: {
                    270:        static char bibuf[BOOTINFO_MAXSIZE];
                    271:        u_long marks[MARK_MAX];
                    272:        int fd;
                    273:
                    274:        BI_ALLOC(6);    /* XXX */
                    275:
                    276:        marks[MARK_START] = 0;  /* loadaddr */
                    277:        if ((fd = loadfile(file, marks, LOAD_KERNEL)) == -1)
                    278:                goto out;
                    279:
                    280:        printf("Start @ 0x%lx [%ld=0x%lx-0x%lx]...\n", marks[MARK_ENTRY],
                    281:            marks[MARK_NSYM], marks[MARK_SYM], marks[MARK_END]);
                    282:
                    283:        {
                    284:                struct btinfo_common *help;
                    285:                char *p;
                    286:                int i;
                    287:
                    288:                p = bibuf;
                    289:                memcpy(p, &bootinfo->nentries, sizeof(bootinfo->nentries));
                    290:                p += sizeof(bootinfo->nentries);
                    291:                for (i = 0; i < bootinfo->nentries; i++) {
                    292:                        help = (struct btinfo_common *)(bootinfo->entry[i]);
                    293:                        memcpy(p, help, help->len);
                    294:                        p += help->len;
                    295:                }
                    296:        }
                    297:
                    298:        cache_flush();
                    299:        cache_disable();
                    300:
                    301:        (*(void (*)(int, void *))marks[MARK_ENTRY])(howto, bibuf);
                    302:        panic("exec returned");
                    303:
                    304: out:
                    305:        BI_FREE();
                    306:        bootinfo = 0;
                    307:        return (-1);
                    308: }
                    309:
                    310: /*
                    311:  * boot menu
                    312:  */
                    313: /* ARGSUSED */
                    314: static void
                    315: bootcmd_help(char *arg)
                    316: {
                    317:
                    318:        printf("commands are:\n"
                    319:            "boot [xdNx:][filename] [-acdqsv]\n"
                    320:            "     (ex. \"hd0a:netbsd.old -s\"\n"
                    321:            "ls [path]\n"
                    322:            "help|?\n"
                    323:            "halt\n"
                    324:            "quit\n");
                    325: }
                    326:
                    327: static void
                    328: bootcmd_ls(char *arg)
                    329: {
                    330:        const char *save = default_filename;
                    331:
                    332:        default_filename = "/";
1.3       tsutsui   333:        ls(arg);
1.1       uwe       334:        default_filename = save;
                    335: }
                    336:
                    337: /* ARGSUSED */
                    338: static void
                    339: bootcmd_quit(char *arg)
                    340: {
                    341:
                    342:        printf("Exiting...\n");
                    343:        delay(1000);
                    344:        reboot();
                    345:        /* Note: we shouldn't get to this point! */
                    346:        panic("Could not reboot!");
                    347:        exit(0);
                    348: }
                    349:
                    350: /* ARGSUSED */
                    351: static void
                    352: bootcmd_halt(char *arg)
                    353: {
                    354:
                    355:        printf("Exiting...\n");
                    356:        delay(1000);
                    357:        halt();
                    358:        /* Note: we shouldn't get to this point! */
                    359:        panic("Could not halt!");
                    360:        exit(0);
                    361: }
                    362:
                    363: static void
                    364: bootcmd_boot(char *arg)
                    365: {
                    366:        char *filename;
                    367:        int howto;
                    368:
                    369:        if (parseboot(arg, &filename, &howto)) {
                    370:                bootit(filename, howto, 1);
                    371:        }
                    372: }
                    373:
                    374: /* ARGSUSED */
                    375: static void
                    376: bootcmd_monitor(char *arg)
                    377: {
                    378:
                    379:        db_monitor();
                    380:        printf("\n");
                    381: }
                    382:
                    383: static void
                    384: docommand(const struct bootblk_command * const cmds, char *arg)
                    385: {
                    386:        char *options;
                    387:        int i;
                    388:
                    389:        options = gettrailer(arg);
                    390:
                    391:        for (i = 0; cmds[i].c_name != NULL; i++) {
                    392:                if (strcmp(arg, cmds[i].c_name) == 0) {
                    393:                        (*cmds[i].c_fn)(options);
                    394:                        return;
                    395:                }
                    396:        }
                    397:
                    398:        printf("unknown command\n");
                    399:        bootcmd_help(NULL);
                    400: }
                    401:
                    402: void
                    403: bootmenu(void)
                    404: {
                    405:        char input[256];
                    406:        char *c;
                    407:
                    408:        for (;;) {
                    409:                c = input;
                    410:
                    411:                input[0] = '\0';
                    412:                printf("> ");
                    413:                gets(input);
                    414:
                    415:                /*
                    416:                 * Skip leading whitespace.
                    417:                 */
                    418:                while (*c == ' ') {
                    419:                        c++;
                    420:                }
                    421:                if (*c != '\0') {
                    422:                        docommand(bootcmds, c);
                    423:                }
                    424:        }
                    425: }
                    426:
                    427: /*
                    428:  * from arch/i386/stand/lib/parseutil.c
                    429:  */
                    430: /*
                    431:  * chops the head from the arguments and returns the arguments if any,
                    432:  * or possibly an empty string.
                    433:  */
                    434: static char *
                    435: gettrailer(char *arg)
                    436: {
                    437:        char *options;
                    438:
                    439:        if ((options = strchr(arg, ' ')) == NULL)
                    440:                return ("");
                    441:        else
                    442:                *options++ = '\0';
                    443:
                    444:        /* trim leading blanks */
                    445:        while (*options && *options == ' ')
                    446:                options++;
                    447:
                    448:        return (options);
                    449: }
                    450:
                    451: static int
                    452: parseopts(const char *opts, int *howto)
                    453: {
                    454:        int r, tmpopt = 0;
                    455:
                    456:        opts++;         /* skip - */
                    457:        while (*opts && *opts != ' ') {
                    458:                r = 0;
                    459:                BOOT_FLAG(*opts, r);
                    460:                if (r == 0) {
                    461:                        printf("-%c: unknown flag\n", *opts);
                    462:                        bootcmd_help(NULL);
                    463:                        return (0);
                    464:                }
                    465:                tmpopt |= r;
                    466:                opts++;
                    467:        }
                    468:
                    469:        *howto = tmpopt;
                    470:        return (1);
                    471: }
                    472:
                    473: static int
                    474: parseboot(char *arg, char **filename, int *howto)
                    475: {
                    476:        char *opts = NULL;
                    477:
                    478:        *filename = 0;
                    479:        *howto = 0;
                    480:
                    481:        /* if there were no arguments */
                    482:        if (*arg == NULL)
                    483:                return (1);
                    484:
                    485:        /* format is... */
                    486:        /* [[xxNx:]filename] [-adqsv] */
                    487:
                    488:        /* check for just args */
                    489:        if (arg[0] == '-') {
                    490:                opts = arg;
                    491:        } else {
                    492:                /* there's a file name */
                    493:                *filename = arg;
                    494:
                    495:                opts = gettrailer(arg);
                    496:                if (*opts == NULL) {
                    497:                        opts = NULL;
                    498:                } else if (*opts != '-') {
                    499:                        printf("invalid arguments\n");
                    500:                        bootcmd_help(NULL);
                    501:                        return (0);
                    502:                }
                    503:        }
                    504:
                    505:        /* at this point, we have dealt with filenames. */
                    506:
                    507:        /* now, deal with options */
                    508:        if (opts) {
                    509:                if (parseopts(opts, howto) == 0) {
                    510:                        return (0);
                    511:                }
                    512:        }
                    513:        return (1);
                    514: }
                    515:
                    516: /*
                    517:  * for common/lib/libc/arch/sh3/gen/udivsi3.S
                    518:  */
                    519: int raise(int sig);
                    520:
                    521: /*ARGSUSED*/
                    522: int
                    523: raise(int sig)
                    524: {
                    525:
                    526:        return 0;
                    527: }

CVSweb <webmaster@jp.NetBSD.org>