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

Annotation of src/sys/arch/hp300/stand/inst/inst.c, Revision 1.4.2.2

1.4.2.2 ! perry       1: /*     $NetBSD: inst.c,v 1.6 1997/12/29 07:15:10 scottr Exp $  */
1.1       thorpej     2:
1.4       thorpej     3: /*-
                      4:  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
1.1       thorpej     5:  * All rights reserved.
                      6:  *
1.4       thorpej     7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Jason R. Thorpe.
                      9:  *
1.1       thorpej    10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
1.4       thorpej    20:  *     This product includes software developed by the NetBSD
                     21:  *     Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
1.1       thorpej    25:  *
1.4       thorpej    26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
                     38:
                     39: /*
1.1       thorpej    40:  * Portions of this program are inspired by (and have borrowed code from)
                     41:  * the `editlabel' program that accompanies NetBSD/vax, which carries
                     42:  * the following notice:
                     43:  *
                     44:  * Copyright (c) 1995 Ludd, University of Lule}, Sweden.
                     45:  * All rights reserved.
                     46:  *
                     47:  * Redistribution and use in source and binary forms, with or without
                     48:  * modification, are permitted provided that the following conditions
                     49:  * are met:
                     50:  * 1. Redistributions of source code must retain the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer.
                     52:  * 2. Redistributions in binary form must reproduce the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer in the
                     54:  *    documentation and/or other materials provided with the distribution.
                     55:  * 3. All advertising materials mentioning features or use of this software
                     56:  *    must display the following acknowledgement:
                     57:  *     This product includes software developed at Ludd, University of
                     58:  *     Lule}, Sweden and its contributors.
                     59:  * 4. The name of the author may not be used to endorse or promote products
                     60:  *    derived from this software without specific prior written permission
                     61:  *
                     62:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     63:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     64:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     65:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     66:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     67:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     68:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     69:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     70:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     71:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     72:  * SUCH DAMAGE.
                     73:  */
                     74:
                     75: #define DKTYPENAMES
                     76:
                     77: #include <sys/param.h>
                     78: #include <sys/reboot.h>
                     79: #include <sys/disklabel.h>
                     80: #include <a.out.h>
                     81:
                     82: #include <lib/libsa/stand.h>
                     83:
                     84: #include <hp300/stand/common/samachdep.h>
                     85:
                     86: char line[100];
                     87:
                     88: extern u_int opendev;
                     89: extern char *lowram;
                     90: extern int noconsole;
                     91: extern int netio_ask;
                     92:
                     93: char   *kernel_name = "/netbsd";
                     94:
                     95: void   dsklabel __P((void));
                     96: void   miniroot __P((void));
                     97: void   bootmini __P((void));
                     98: void   resetsys __P((void));
                     99: void   gethelp __P((void));
                    100: int    opendisk __P((char *, char *, int, char, int *));
                    101: void   disklabel_edit __P((struct disklabel *));
                    102: void   disklabel_show __P((struct disklabel *));
                    103: int    disklabel_write __P((char *, int, struct open_file *));
1.4.2.1   thorpej   104: void   get_fstype __P((struct disklabel *lp, int));
1.1       thorpej   105: int    a2int __P((char *));
                    106:
                    107: struct inst_command {
                    108:        char    *ic_cmd;                /* command name */
                    109:        char    *ic_desc;               /* command description */
                    110:        void    (*ic_func) __P((void)); /* handling function */
                    111: } inst_commands[] = {
                    112:        { "disklabel",  "place partition map on disk",  dsklabel },
                    113:        { "miniroot",   "place miniroot on disk",       miniroot },
                    114:        { "boot",       "boot from miniroot",           bootmini },
                    115:        { "reset",      "reset the system",             resetsys },
                    116:        { "help",       "display command list",         gethelp },
                    117: };
                    118: #define NCMDS  (sizeof(inst_commands) / sizeof(inst_commands[0]))
                    119:
                    120: main()
                    121: {
                    122:        int i, currname = 0;
                    123:
                    124:        /*
                    125:         * We want netopen() to ask for IP address, etc, rather
                    126:         * that using bootparams.
                    127:         */
                    128:        netio_ask = 1;
                    129:
                    130:        printf("\n");
                    131:        printf(">> %s, Revision %s\n", bootprog_name, bootprog_rev);
                    132:        printf(">> (%s, %s)\n", bootprog_maker, bootprog_date);
1.3       thorpej   133:        printf(">> HP 9000/%s SPU\n", getmachineid());
1.1       thorpej   134:        gethelp();
                    135:
                    136:        for (;;) {
                    137:                printf("sys_inst> ");
                    138:                bzero(line, sizeof(line));
                    139:                gets(line);
                    140:                if (line[0] == '\n' || line[0] == '\0')
                    141:                        continue;
                    142:
                    143:                for (i = 0; i < NCMDS; ++i)
                    144:                        if (strcmp(line, inst_commands[i].ic_cmd) == 0) {
                    145:                                (*inst_commands[i].ic_func)();
                    146:                                break;
                    147:                        }
                    148:
                    149:
                    150:                if (i == NCMDS)
                    151:                        printf("unknown command: %s\n", line);
                    152:        }
                    153: }
                    154:
                    155: void
                    156: gethelp()
                    157: {
                    158:        int i;
                    159:
                    160:        printf(">> Available commands:\n");
                    161:        for (i = 0; i < NCMDS; ++i)
                    162:                printf(">>     %s - %s\n", inst_commands[i].ic_cmd,
                    163:                    inst_commands[i].ic_desc);
                    164: }
                    165:
                    166: /*
                    167:  * Do all the steps necessary to place a disklabel on a disk.
                    168:  * Note, this assumes 512 byte sectors.
                    169:  */
                    170: void
                    171: dsklabel()
                    172: {
                    173:        struct disklabel *lp;
                    174:        struct open_file *disk_ofp;
                    175:        int dfd, error;
                    176:        size_t xfersize;
                    177:        char block[DEV_BSIZE], diskname[64];
                    178:        extern struct open_file files[];
                    179:
                    180:        printf("
                    181: You will be asked several questions about your disk, most of which
                    182: require prior knowledge of the disk's geometry.  There is no easy way
                    183: for the system to provide this information for you.  If you do not have
                    184: this information, please consult your disk's manual or another
                    185: informative source.\n\n");
                    186:
                    187:        /* Error message printed by opendisk() */
                    188:        if (opendisk("Disk to label?", diskname, sizeof(diskname),
                    189:            ('a' + RAW_PART), &dfd))
                    190:                return;
                    191:
                    192:        disk_ofp = &files[dfd];
                    193:
                    194:        bzero(block, sizeof(block));
                    195:        if (error = (*disk_ofp->f_dev->dv_strategy)(disk_ofp->f_devdata,
                    196:            F_READ, LABELSECTOR, sizeof(block), block, &xfersize)) {
                    197:                printf("cannot read disk %s, errno = %d\n", diskname, error);
                    198:                return;
                    199:        }
                    200:
                    201:        printf("Sucessfully read %d bytes from %s\n", xfersize, diskname);
                    202:
                    203:        lp = (struct disklabel *)((void *)(&block[LABELOFFSET]));
                    204:
                    205:  disklabel_loop:
                    206:        bzero(line, sizeof(line));
                    207:        printf("(z)ap, (e)dit, (s)how, (w)rite, (d)one > ");
                    208:        gets(line);
                    209:        if (line[0] == '\n' || line[0] == '\0')
                    210:                goto disklabel_loop;
                    211:
                    212:        switch (line[0]) {
                    213:        case 'z':
                    214:        case 'Z': {
                    215:                char zap[DEV_BSIZE];
                    216:                bzero(zap, sizeof(zap));
                    217:                (void)(*disk_ofp->f_dev->dv_strategy)(disk_ofp->f_devdata,
                    218:                    F_WRITE, LABELSECTOR, sizeof(zap), zap, &xfersize);
                    219:                }
                    220:                goto out;
                    221:                /* NOTREACHED */
                    222:
                    223:        case 'e':
                    224:        case 'E':
                    225:                disklabel_edit(lp);
                    226:                break;
                    227:
                    228:        case 's':
                    229:        case 'S':
                    230:                disklabel_show(lp);
                    231:                break;
                    232:
                    233:        case 'w':
                    234:        case 'W':
                    235:                /*
                    236:                 * Error message will be displayed by disklabel_write()
                    237:                 */
                    238:                if (disklabel_write(block, sizeof(block), disk_ofp))
                    239:                        goto out;
                    240:                else
                    241:                        printf("Sucessfully wrote label to %s\n", diskname);
                    242:                break;
                    243:
                    244:        case 'd':
                    245:        case 'D':
                    246:                goto out;
                    247:                /* NOTREACHED */
                    248:
                    249:        default:
                    250:                printf("unkown command: %s\n", line);
                    251:        }
                    252:
                    253:        goto disklabel_loop;
                    254:        /* NOTREACHED */
                    255:
                    256:  out:
                    257:        /*
                    258:         * Close disk.  Marks disk `not alive' so that partition
                    259:         * information will be reloaded upon next open.
                    260:         */
                    261:        (void)close(dfd);
                    262: }
                    263:
                    264: #define GETNUM(out, num)                                               \
                    265:        printf((out), (num));                                           \
                    266:        bzero(line, sizeof(line));                                      \
                    267:        gets(line);                                                     \
                    268:        if (line[0])                                                    \
                    269:                (num) = atoi(line);
                    270:
                    271: #define GETNUM2(out, num1, num2)                                       \
                    272:        printf((out), (num1), (num2));                                  \
                    273:        bzero(line, sizeof(line));                                      \
                    274:        gets(line);                                                     \
                    275:        if (line[0])                                                    \
                    276:                (num2) = atoi(line);
                    277:
                    278: #define GETSTR(out, str)                                               \
                    279:        printf((out), (str));                                           \
                    280:        bzero(line, sizeof(line));                                      \
                    281:        gets(line);                                                     \
                    282:        if (line[0])                                                    \
                    283:                strcpy((str), line);
                    284:
                    285: #define FLAGS(out, flag)                                               \
                    286:        printf((out), lp->d_flags & (flag) ? 'y' : 'n');                \
                    287:        bzero(line, sizeof(line));                                      \
                    288:        gets(line);                                                     \
                    289:        if (line[0] == 'y' || line[0] == 'Y')                           \
                    290:                lp->d_flags |= (flag);                                  \
                    291:        else                                                            \
                    292:                lp->d_flags &= ~(flag);
                    293:
1.4.2.1   thorpej   294: struct fsname_to_type {
                    295:        const char *name;
                    296:        u_int8_t type;
                    297: } n_to_t[] = {
                    298:        { "unused",     FS_UNUSED },
                    299:        { "ffs",        FS_BSDFFS },
                    300:        { "swap",       FS_SWAP },
                    301:        { "boot",       FS_BOOT },
                    302:        { NULL,         0 },
                    303: };
                    304:
                    305: void
                    306: get_fstype(lp, partno)
                    307:        struct disklabel *lp;
                    308:        int partno;
                    309: {
                    310:        static int blocksize = 8192;    /* XXX */
                    311:        struct partition *pp = &lp->d_partitions[partno];
                    312:        struct fsname_to_type *np;
                    313:        int fragsize;
                    314:        char line[80], str[80];
                    315:
                    316:        if (pp->p_size == 0) {
                    317:                /*
                    318:                 * No need to bother asking for a zero-sized partition.
                    319:                 */
                    320:                pp->p_fstype = FS_UNUSED;
                    321:                return;
                    322:        }
                    323:
                    324:        /*
                    325:         * Select a default.
                    326:         * XXX Should we check what might be in the label already?
                    327:         */
                    328:        if (partno == 1)
                    329:                strcpy(str, "swap");
                    330:        else if (partno == RAW_PART)
                    331:                strcpy(str, "boot");
                    332:        else
                    333:                strcpy(str, "ffs");
                    334:
                    335:  again:
                    336:        GETSTR("             fstype? [%s] ", str);
                    337:
                    338:        for (np = n_to_t; np->name != NULL; np++)
                    339:                if (strcmp(str, np->name) == 0)
                    340:                        break;
                    341:
                    342:        if (np->name == NULL) {
                    343:                printf("Please use one of: ");
                    344:                for (np = n_to_t; np->name != NULL; np++)
                    345:                        printf(" %s", np->name);
                    346:                printf(".\n");
                    347:                goto again;
                    348:        }
                    349:
                    350:        pp->p_fstype = np->type;
                    351:
                    352:        if (pp->p_fstype != FS_BSDFFS)
                    353:                return;
                    354:
                    355:        /*
                    356:         * Get additional information needed for FFS.
                    357:         */
                    358:  ffs_again:
                    359:        GETNUM("             FFS block size? [%d] ", blocksize);
                    360:        if (blocksize < NBPG || (blocksize % NBPG) != 0) {
                    361:                printf("FFS block size must be a multiple of %d.\n", NBPG);
                    362:                goto ffs_again;
                    363:        }
                    364:
                    365:        fragsize = blocksize / 8;       /* XXX */
                    366:        fragsize = max(fragsize, lp->d_secsize);
                    367:        GETNUM("             FFS fragment size? [%d] ", fragsize);
                    368:        if (fragsize < lp->d_secsize || (fragsize % lp->d_secsize) != 0) {
                    369:                printf("FFS fragment size must be a multiple of sector size"
                    370:                    " (%d).\n", lp->d_secsize);
                    371:                goto ffs_again;
                    372:        }
                    373:        if ((blocksize % fragsize) != 0) {
                    374:                printf("FFS fragment size must be an even divisor of FFS"
                    375:                    " block size (%d).\n", blocksize);
                    376:                goto ffs_again;
                    377:        }
                    378:
                    379:        /*
                    380:         * XXX Better sanity checking?
                    381:         */
                    382:
                    383:        pp->p_frag = blocksize / fragsize;
                    384:        pp->p_fsize = fragsize;
                    385: }
                    386:
1.1       thorpej   387: void
                    388: disklabel_edit(lp)
                    389:        struct disklabel *lp;
                    390: {
                    391:        int i;
                    392:
                    393:        printf("Select disk type.  Valid types:\n");
                    394:        for (i = 0; i < DKMAXTYPES; i++)
                    395:                printf("%d     %s\n", i, dktypenames[i]);
                    396:        printf("\n");
                    397:
                    398:        GETNUM("Disk type (number)? [%d] ", lp->d_type);
                    399:        GETSTR("Disk model name? [%s] ", lp->d_typename);
                    400:        GETSTR("Disk pack name? [%s] ", lp->d_packname);
                    401:        FLAGS("Bad sectoring? [%c] ", D_BADSECT);
                    402:        FLAGS("Ecc? [%c] ", D_ECC);
                    403:        FLAGS("Removable? [%c] ", D_REMOVABLE);
                    404:
                    405:        printf("\n");
                    406:
                    407:        GETNUM("Interleave? [%d] ", lp->d_interleave);
                    408:        GETNUM("Rpm? [%d] ", lp->d_rpm);
                    409:        GETNUM("Trackskew? [%d] ", lp->d_trackskew);
                    410:        GETNUM("Cylinderskew? [%d] ", lp->d_cylskew);
                    411:        GETNUM("Headswitch? [%d] ", lp->d_headswitch);
                    412:        GETNUM("Track-to-track? [%d] ", lp->d_trkseek);
                    413:        GETNUM("Drivedata 0? [%d] ", lp->d_drivedata[0]);
                    414:        GETNUM("Drivedata 1? [%d] ", lp->d_drivedata[1]);
                    415:        GETNUM("Drivedata 2? [%d] ", lp->d_drivedata[2]);
                    416:        GETNUM("Drivedata 3? [%d] ", lp->d_drivedata[3]);
                    417:        GETNUM("Drivedata 4? [%d] ", lp->d_drivedata[4]);
                    418:
                    419:        printf("\n");
                    420:
                    421:        GETNUM("Bytes/sector? [%d] ", lp->d_secsize);
                    422:        GETNUM("Sectors/track? [%d] ", lp->d_nsectors);
                    423:        GETNUM("Tracks/cylinder? [%d] ", lp->d_ntracks);
1.4.2.2 ! perry     424:        if (lp->d_secpercyl == 0)
        !           425:                lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1.1       thorpej   426:        GETNUM("Sectors/cylinder? [%d] ", lp->d_secpercyl);
                    427:        GETNUM("Cylinders? [%d] ", lp->d_ncylinders);
1.4.2.2 ! perry     428:        if (lp->d_secperunit == 0)
        !           429:                lp->d_secperunit = lp->d_ncylinders * lp->d_secpercyl;
        !           430:        GETNUM("Total sectors? [%d] ", lp->d_secperunit);
1.1       thorpej   431:
                    432:        printf("
                    433: Enter partition table.  Note, sizes and offsets are in sectors.\n\n");
                    434:
                    435:        lp->d_npartitions = MAXPARTITIONS;
                    436:        for (i = 0; i < lp->d_npartitions; ++i) {
                    437:                GETNUM2("%c partition: offset? [%d] ", ('a' + i),
                    438:                    lp->d_partitions[i].p_offset);
                    439:                GETNUM("             size? [%d] ", lp->d_partitions[i].p_size);
1.4.2.1   thorpej   440:                get_fstype(lp, i);
1.1       thorpej   441:        }
                    442:
                    443:        /* Perform magic. */
                    444:        lp->d_magic = lp->d_magic2 = DISKMAGIC;
                    445:
                    446:        /* Calculate disklabel checksum. */
                    447:        lp->d_checksum = 0;
                    448:        lp->d_checksum = dkcksum(lp);
                    449: }
                    450:
                    451: void
                    452: disklabel_show(lp)
                    453:        struct disklabel *lp;
                    454: {
                    455:        int i, npart;
                    456:        struct partition *pp;
                    457:
                    458:        /*
                    459:         * Check for valid disklabel.
                    460:         */
                    461:        if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC) {
                    462:                printf("No disklabel to show.\n");
                    463:                return;
                    464:        }
                    465:
                    466:        if (lp->d_npartitions > MAXPARTITIONS || dkcksum(lp) != 0) {
                    467:                printf("Corrupted disklabel.\n");
                    468:                return;
                    469:        }
                    470:
                    471:        printf("\ndisk type %d (%s), %s: %s%s%s\n", lp->d_type,
                    472:            lp->d_type < DKMAXTYPES ? dktypenames[lp->d_type] :
                    473:            dktypenames[0], lp->d_typename,
                    474:            (lp->d_flags & D_REMOVABLE) ? " removable" : "",
                    475:            (lp->d_flags & D_ECC) ? " ecc" : "",
                    476:            (lp->d_flags & D_BADSECT) ? " badsect" : "");
                    477:
                    478:        printf("interleave %d, rpm %d, trackskew %d, cylinderskew %d\n",
                    479:            lp->d_interleave, lp->d_rpm, lp->d_trackskew, lp->d_cylskew);
                    480:
                    481:        printf("headswitch %d, track-to-track %d, drivedata: %d %d %d %d %d\n",
                    482:            lp->d_headswitch, lp->d_trkseek, lp->d_drivedata[0],
                    483:            lp->d_drivedata[1], lp->d_drivedata[2], lp->d_drivedata[3],
                    484:            lp->d_drivedata[4]);
                    485:
                    486:        printf("\nbytes/sector: %d\n", lp->d_secsize);
                    487:        printf("sectors/track: %d\n", lp->d_nsectors);
                    488:        printf("tracks/cylinder: %d\n", lp->d_ntracks);
                    489:        printf("sectors/cylinder: %d\n", lp->d_secpercyl);
                    490:        printf("cylinders: %d\n", lp->d_ncylinders);
1.4.2.2 ! perry     491:        printf("total sectors: %d\n", lp->d_secperunit);
1.1       thorpej   492:
                    493:        printf("\n%d partitions:\n", lp->d_npartitions);
                    494:        printf("     size   offset\n");
                    495:        pp = lp->d_partitions;
                    496:        for (i = 0; i < lp->d_npartitions; i++) {
                    497:                printf("%c:   %d,    %d\n", 97 + i, lp->d_partitions[i].p_size,
                    498:                    lp->d_partitions[i].p_offset);
                    499:        }
                    500:        printf("\n");
                    501: }
                    502:
                    503: int
                    504: disklabel_write(block, len, ofp)
                    505:        char *block;
                    506:        int len;
                    507:        struct open_file *ofp;
                    508: {
                    509:        int error = 0;
                    510:        size_t xfersize;
                    511:
                    512:        if (error = (*ofp->f_dev->dv_strategy)(ofp->f_devdata, F_WRITE,
                    513:            LABELSECTOR, len, block, &xfersize))
                    514:                printf("cannot write disklabel, errno = %d\n", error);
                    515:
                    516:        return (error);
                    517: }
                    518:
                    519: int
                    520: opendisk(question, diskname, len, partition, fdp)
                    521:        char *question, *diskname;
                    522:        int len;
                    523:        char partition;
                    524:        int *fdp;
                    525: {
                    526:        char fulldiskname[64], *filename;
                    527:        int i, error = 0;
                    528:
                    529:  getdiskname:
                    530:        printf("%s ", question);
                    531:        bzero(diskname, len);
                    532:        bzero(fulldiskname, sizeof(fulldiskname));
                    533:        gets(diskname);
                    534:        if (diskname[0] == '\n' || diskname[0] == '\0')
                    535:                goto getdiskname;
                    536:
                    537:        /*
                    538:         * devopen() is picky.  Make sure it gets the sort of string it
                    539:         * wants.
                    540:         */
                    541:        bcopy(diskname, fulldiskname,
                    542:            len < sizeof(fulldiskname) ? len : sizeof(fulldiskname));
                    543:        for (i = 0; fulldiskname[i + 1] != '\0'; ++i)
                    544:                /* Nothing. */ ;
                    545:        if (fulldiskname[i] < '0' || fulldiskname[i] > '9') {
                    546:                printf("invalid disk name %s\n", diskname);
                    547:                goto getdiskname;
                    548:        }
                    549:        fulldiskname[++i] = partition; fulldiskname[++i] = ':';
                    550:
                    551:        /*
                    552:         * We always open for writing.
                    553:         */
                    554:        if ((*fdp = open(fulldiskname, 1)) < 0) {
                    555:                printf("cannot open %s\n", diskname);
                    556:                return (1);
                    557:        }
                    558:
                    559:        return (0);
                    560: }
                    561:
                    562: /*
                    563:  * Copy a miniroot image from an NFS server or tape to the `b' partition
                    564:  * of the specified disk.  Note, this assumes 512 byte sectors.
                    565:  */
                    566: void
                    567: miniroot()
                    568: {
                    569:        int sfd, dfd, i, nblks;
                    570:        char diskname[64], minirootname[128];
                    571:        char block[DEV_BSIZE];
                    572:        char tapename[64];
1.2       thorpej   573:        int fileno, ignoreshread, eof, len;
1.1       thorpej   574:        struct stat st;
                    575:        size_t xfersize;
                    576:        struct open_file *disk_ofp;
                    577:        extern struct open_file files[];
                    578:
                    579:        /* Error message printed by opendisk() */
                    580:        if (opendisk("Disk for miniroot?", diskname, sizeof(diskname),
                    581:            'b', &dfd))
                    582:                return;
                    583:
                    584:        disk_ofp = &files[dfd];
                    585:
                    586:  getsource:
                    587:        printf("Source? (N)FS, (t)ape, (d)one > ");
                    588:        bzero(line, sizeof(line));
                    589:        gets(line);
                    590:        if (line[0] == '\0')
                    591:                goto getsource;
                    592:
                    593:        switch (line[0]) {
                    594:        case 'n':
                    595:        case 'N':
                    596:  name_of_nfs_miniroot:
                    597:                printf("Name of miniroot file? ");
                    598:                bzero(line, sizeof(line));
                    599:                bzero(minirootname, sizeof(minirootname));
                    600:                gets(line);
                    601:                if (line[0] == '\0')
                    602:                        goto name_of_nfs_miniroot;
                    603:                (void)strcat(minirootname, "le0a:");
                    604:                (void)strcat(minirootname, line);
                    605:                if ((sfd = open(minirootname, 0)) < 0) {
                    606:                        printf("can't open %s\n", line);
                    607:                        return;
                    608:                }
                    609:
                    610:                /*
1.2       thorpej   611:                 * Find out how big the miniroot is... we can't
                    612:                 * check for size because it may be compressed.
1.1       thorpej   613:                 */
1.2       thorpej   614:                ignoreshread = 1;
1.1       thorpej   615:                if (fstat(sfd, &st) < 0) {
                    616:                        printf("can't stat %s\n", line);
                    617:                        goto done;
                    618:                }
                    619:                nblks = (int)(st.st_size / sizeof(block));
                    620:
1.2       thorpej   621:                printf("Copying miniroot from %s to %s...", line,
1.1       thorpej   622:                    diskname);
                    623:                break;
                    624:
                    625:        case 't':
                    626:        case 'T':
                    627:  name_of_tape_miniroot:
                    628:                printf("Which tape device? ");
                    629:                bzero(line, sizeof(line));
                    630:                bzero(minirootname, sizeof(minirootname));
                    631:                bzero(tapename, sizeof(tapename));
                    632:                gets(line);
                    633:                if (line[0] == '\0')
                    634:                        goto name_of_tape_miniroot;
                    635:                strcat(minirootname, line);
                    636:                strcat(tapename, line);
                    637:
                    638:                printf("File number (first == 1)? ");
                    639:                bzero(line, sizeof(line));
                    640:                gets(line);
                    641:                fileno = a2int(line);
                    642:                if (fileno < 1 || fileno > 8) {
                    643:                        printf("Invalid file number: %s\n", line);
                    644:                        goto getsource;
                    645:                }
                    646:                for (i = 0; i < sizeof(minirootname); ++i) {
                    647:                        if (minirootname[i] == '\0')
                    648:                                break;
                    649:                }
                    650:                if (i == sizeof(minirootname) ||
                    651:                    (sizeof(minirootname) - i) < 8) {
                    652:                        printf("Invalid device name: %s\n", tapename);
                    653:                        goto getsource;
                    654:                }
                    655:                minirootname[i++] = 'a' + (fileno - 1);
                    656:                minirootname[i++] = ':';
                    657:                strcat(minirootname, "XXX");    /* lameness in open() */
                    658:
1.2       thorpej   659:                ignoreshread = 0;
1.1       thorpej   660:                printf("Copy how many %d byte blocks? ", DEV_BSIZE);
                    661:                bzero(line, sizeof(line));
                    662:                gets(line);
                    663:                nblks = a2int(line);
                    664:                if (nblks < 0) {
                    665:                        printf("Invalid block count: %s\n", line);
                    666:                        goto getsource;
                    667:                } else if (nblks == 0) {
                    668:                        printf("Zero blocks?  Ok, aborting.\n");
                    669:                        return;
                    670:                }
                    671:
                    672:                if ((sfd = open(minirootname, 0)) < 0) {
                    673:                        printf("can't open %s file %c\n", tapename, fileno);
                    674:                        return;
                    675:                }
                    676:
1.2       thorpej   677:                printf("Copying %s file %d to %s...", tapename, fileno,
1.1       thorpej   678:                    diskname);
                    679:                break;
                    680:
                    681:        case 'd':
                    682:        case 'D':
                    683:                return;
                    684:
                    685:        default:
                    686:                printf("Unknown source: %s\n", line);
                    687:                goto getsource;
                    688:        }
                    689:
                    690:        /*
                    691:         * Copy loop...
                    692:         * This is fairly slow... if someone wants to speed it
                    693:         * up, they'll get no complaints from me.
                    694:         */
1.2       thorpej   695:        for (i = 0, eof = 0; i < nblks || ignoreshread == 0; i++) {
                    696:                if ((len = read(sfd, block, sizeof(block))) < 0) {
                    697:                        printf("Read error, errno = %d\n", errno);
                    698:                        goto out;
                    699:                }
                    700:
                    701:                /*
                    702:                 * Check for end-of-file.
                    703:                 */
                    704:                if (len == 0)
1.1       thorpej   705:                        goto done;
1.2       thorpej   706:                else if (len < sizeof(block))
                    707:                        eof = 1;
                    708:
1.1       thorpej   709:                if ((*disk_ofp->f_dev->dv_strategy)(disk_ofp->f_devdata,
1.2       thorpej   710:                    F_WRITE, i, len, block, &xfersize) || xfersize != len) {
1.1       thorpej   711:                        printf("Bad write at block %d, errno = %d\n",
                    712:                            i, errno);
1.2       thorpej   713:                        goto out;
                    714:                }
                    715:
                    716:                if (eof)
1.1       thorpej   717:                        goto done;
                    718:        }
1.2       thorpej   719:  done:
1.1       thorpej   720:        printf("done\n");
                    721:
                    722:        printf("Successfully copied miniroot image.\n");
                    723:
1.2       thorpej   724:  out:
1.1       thorpej   725:        close(sfd);
                    726:        close(dfd);
                    727: }
                    728:
                    729: /*
                    730:  * Boot the kernel from the miniroot image into single-user.
                    731:  */
                    732: void
                    733: bootmini()
                    734: {
                    735:        char diskname[64], bootname[64];
                    736:        int i;
                    737:
                    738:  getdiskname:
                    739:        printf("Disk to boot from? ");
                    740:        bzero(diskname, sizeof(diskname));
                    741:        bzero(bootname, sizeof(bootname));
                    742:        gets(diskname);
                    743:        if (diskname[0] == '\n' || diskname[0] == '\0')
                    744:                goto getdiskname;
                    745:
                    746:        /*
                    747:         * devopen() is picky.  Make sure it gets the sort of string it
                    748:         * wants.
                    749:         */
                    750:        (void)strcat(bootname, diskname);
                    751:        for (i = 0; bootname[i + 1] != '\0'; ++i)
                    752:                /* Nothing. */ ;
                    753:        if (bootname[i] < '0' || bootname[i] > '9') {
                    754:                printf("invalid disk name %s\n", diskname);
                    755:                goto getdiskname;
                    756:        }
                    757:        bootname[++i] = 'b'; bootname[++i] = ':';
                    758:        (void)strcat(bootname, kernel_name);
                    759:
                    760:        howto = RB_SINGLE;      /* _Always_ */
                    761:
                    762:        printf("booting: %s -s\n", bootname);
                    763:        exec(bootname, lowram, howto);
                    764:        printf("boot: %s\n", strerror(errno));
                    765: }
                    766:
                    767: /*
                    768:  * Reset the system.
                    769:  */
                    770: void
                    771: resetsys()
                    772: {
                    773:
                    774:        call_req_reboot();
                    775:        printf("panic: can't reboot, halting\n");
                    776:        asm("stop #0x2700");
                    777: }
                    778:
                    779: /*
                    780:  * XXX Should have a generic atoi for libkern/libsa.
                    781:  */
                    782: int
                    783: a2int(cp)
                    784:        char *cp;
                    785: {
                    786:        int i = 0;
                    787:
                    788:        if (*cp == '\0')
                    789:                return (-1);
                    790:
                    791:        while (*cp != '\0')
                    792:                i = i * 10 + *cp++ - '0';
                    793:        return (i);
                    794: }

CVSweb <webmaster@jp.NetBSD.org>