[BACK]Return to diskprobe.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / stand / libsa

Annotation of sys/arch/i386/stand/libsa/diskprobe.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: diskprobe.c,v 1.29 2007/06/18 22:11:20 krw Exp $      */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1997 Tobias Weingartner
        !             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 AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            18:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            19:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            20:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            26:  * SUCH DAMAGE.
        !            27:  *
        !            28:  */
        !            29:
        !            30: /* We want the disk type names from disklabel.h */
        !            31: #undef DKTYPENAMES
        !            32:
        !            33: #include <sys/param.h>
        !            34: #include <sys/queue.h>
        !            35: #include <sys/reboot.h>
        !            36: #include <sys/disklabel.h>
        !            37: #include <stand/boot/bootarg.h>
        !            38: #include <machine/biosvar.h>
        !            39: #include <lib/libz/zlib.h>
        !            40: #include "disk.h"
        !            41: #include "biosdev.h"
        !            42: #include "libsa.h"
        !            43:
        !            44: #define MAX_CKSUMLEN MAXBSIZE / DEV_BSIZE      /* Max # of blks to cksum */
        !            45:
        !            46: /* Local Prototypes */
        !            47: static int disksum(int);
        !            48:
        !            49: /* List of disk devices we found/probed */
        !            50: struct disklist_lh disklist;
        !            51:
        !            52: /* Pointer to boot device */
        !            53: struct diskinfo *bootdev_dip;
        !            54:
        !            55: extern int debug;
        !            56: extern int bios_bootdev;
        !            57: extern int bios_cddev;
        !            58:
        !            59: /* Probe for all BIOS floppies */
        !            60: static void
        !            61: floppyprobe(void)
        !            62: {
        !            63:        struct diskinfo *dip;
        !            64:        int i;
        !            65:
        !            66:        /* Floppies */
        !            67:        for (i = 0; i < 4; i++) {
        !            68:                dip = alloc(sizeof(struct diskinfo));
        !            69:                bzero(dip, sizeof(*dip));
        !            70:
        !            71:                if (bios_getdiskinfo(i, &dip->bios_info)) {
        !            72: #ifdef BIOS_DEBUG
        !            73:                        if (debug)
        !            74:                                printf(" <!fd%u>", i);
        !            75: #endif
        !            76:                        free(dip, 0);
        !            77:                        break;
        !            78:                }
        !            79:
        !            80:                printf(" fd%u", i);
        !            81:
        !            82:                /* Fill out best we can - (fd?) */
        !            83:                dip->bios_info.bsd_dev = MAKEBOOTDEV(2, 0, 0, i, RAW_PART);
        !            84:
        !            85:                /*
        !            86:                 * Delay reading the disklabel until we're sure we want
        !            87:                 * to boot from the floppy. Doing this avoids a delay
        !            88:                 * (sometimes very long) when trying to read the label
        !            89:                 * and the drive is unplugged.
        !            90:                 */
        !            91:                dip->bios_info.flags |= BDI_BADLABEL;
        !            92:
        !            93:                /* Add to queue of disks */
        !            94:                TAILQ_INSERT_TAIL(&disklist, dip, list);
        !            95:        }
        !            96: }
        !            97:
        !            98:
        !            99: /* Probe for all BIOS hard disks */
        !           100: static void
        !           101: hardprobe(void)
        !           102: {
        !           103:        struct diskinfo *dip;
        !           104:        int i;
        !           105:        u_int bsdunit, type;
        !           106:        u_int scsi = 0, ide = 0;
        !           107:        const char *dc = (const char *)((0x40 << 4) + 0x75);
        !           108:
        !           109:        /* Hard disks */
        !           110:        for (i = 0x80; i < (0x80 + *dc); i++) {
        !           111:                dip = alloc(sizeof(struct diskinfo));
        !           112:                bzero(dip, sizeof(*dip));
        !           113:
        !           114:                if (bios_getdiskinfo(i, &dip->bios_info)) {
        !           115: #ifdef BIOS_DEBUG
        !           116:                        if (debug)
        !           117:                                printf(" <!hd%u>", i&0x7f);
        !           118: #endif
        !           119:                        free(dip, 0);
        !           120:                        break;
        !           121:                }
        !           122:
        !           123:                printf(" hd%u%s", i&0x7f, (dip->bios_info.bios_edd > 0?"+":""));
        !           124:
        !           125:                /* Try to find the label, to figure out device type */
        !           126:                if ((bios_getdisklabel(&dip->bios_info, &dip->disklabel)) ) {
        !           127:                        printf("*");
        !           128:                        bsdunit = ide++;
        !           129:                        type = 0;       /* XXX let it be IDE */
        !           130:                } else {
        !           131:                        /* Best guess */
        !           132:                        switch (dip->disklabel.d_type) {
        !           133:                        case DTYPE_SCSI:
        !           134:                                type = 4;
        !           135:                                bsdunit = scsi++;
        !           136:                                dip->bios_info.flags |= BDI_GOODLABEL;
        !           137:                                break;
        !           138:
        !           139:                        case DTYPE_ESDI:
        !           140:                        case DTYPE_ST506:
        !           141:                                type = 0;
        !           142:                                bsdunit = ide++;
        !           143:                                dip->bios_info.flags |= BDI_GOODLABEL;
        !           144:                                break;
        !           145:
        !           146:                        default:
        !           147:                                dip->bios_info.flags |= BDI_BADLABEL;
        !           148:                                type = 0;       /* XXX Suggest IDE */
        !           149:                                bsdunit = ide++;
        !           150:                        }
        !           151:                }
        !           152:
        !           153:                dip->bios_info.checksum = 0; /* just in case */
        !           154:                /* Fill out best we can */
        !           155:                dip->bios_info.bsd_dev =
        !           156:                    MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART);
        !           157:
        !           158:                /* Add to queue of disks */
        !           159:                TAILQ_INSERT_TAIL(&disklist, dip, list);
        !           160:        }
        !           161: }
        !           162:
        !           163:
        !           164: /* Probe for all BIOS supported disks */
        !           165: u_int32_t bios_cksumlen;
        !           166: void
        !           167: diskprobe(void)
        !           168: {
        !           169:        struct diskinfo *dip;
        !           170:        int i;
        !           171:
        !           172:        /* These get passed to kernel */
        !           173:        bios_diskinfo_t *bios_diskinfo;
        !           174:
        !           175:        /* Init stuff */
        !           176:        TAILQ_INIT(&disklist);
        !           177:
        !           178:        /* Do probes */
        !           179:        floppyprobe();
        !           180: #ifdef BIOS_DEBUG
        !           181:        if (debug)
        !           182:                printf(";");
        !           183: #endif
        !           184:        hardprobe();
        !           185:
        !           186:        /* Checksumming of hard disks */
        !           187:        for (i = 0; disksum(i++) && i < MAX_CKSUMLEN; )
        !           188:                ;
        !           189:        bios_cksumlen = i;
        !           190:
        !           191:        /* Get space for passing bios_diskinfo stuff to kernel */
        !           192:        for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
        !           193:            dip = TAILQ_NEXT(dip, list))
        !           194:                i++;
        !           195:        bios_diskinfo = alloc(++i * sizeof(bios_diskinfo_t));
        !           196:
        !           197:        /* Copy out the bios_diskinfo stuff */
        !           198:        for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
        !           199:            dip = TAILQ_NEXT(dip, list))
        !           200:                bios_diskinfo[i++] = dip->bios_info;
        !           201:
        !           202:        bios_diskinfo[i++].bios_number = -1;
        !           203:        /* Register for kernel use */
        !           204:        addbootarg(BOOTARG_CKSUMLEN, sizeof(u_int32_t), &bios_cksumlen);
        !           205:        addbootarg(BOOTARG_DISKINFO, i * sizeof(bios_diskinfo_t),
        !           206:            bios_diskinfo);
        !           207: }
        !           208:
        !           209:
        !           210: void
        !           211: cdprobe(void)
        !           212: {
        !           213:        struct diskinfo *dip;
        !           214:        int cddev = bios_cddev & 0xff;
        !           215:
        !           216:        /* Another BIOS boot device... */
        !           217:
        !           218:        if (bios_cddev == -1)                   /* Not been set, so don't use */
        !           219:                return;
        !           220:
        !           221:        dip = alloc(sizeof(struct diskinfo));
        !           222:        bzero(dip, sizeof(*dip));
        !           223:
        !           224: #if 0
        !           225:        if (bios_getdiskinfo(cddev, &dip->bios_info)) {
        !           226:                printf(" <!cd0>");      /* XXX */
        !           227:                free(dip, 0);
        !           228:                return;
        !           229:        }
        !           230: #endif
        !           231:
        !           232:        printf(" cd0");
        !           233:
        !           234:        dip->bios_info.bios_number = cddev;
        !           235:        dip->bios_info.bios_edd = 1;            /* Use the LBA calls */
        !           236:        dip->bios_info.flags |= BDI_GOODLABEL | BDI_EL_TORITO;
        !           237:        dip->bios_info.checksum = 0;             /* just in case */
        !           238:        dip->bios_info.bsd_dev =
        !           239:            MAKEBOOTDEV(0, 0, 0, 0xff, RAW_PART);
        !           240:
        !           241:        /* Create an imaginary disk label */
        !           242:        dip->disklabel.d_secsize = 2048;
        !           243:        dip->disklabel.d_ntracks = 1;
        !           244:        dip->disklabel.d_nsectors = 100;
        !           245:        dip->disklabel.d_ncylinders = 1;
        !           246:        dip->disklabel.d_secpercyl = dip->disklabel.d_ntracks *
        !           247:            dip->disklabel.d_nsectors;
        !           248:        if (dip->disklabel.d_secpercyl == 0) {
        !           249:                dip->disklabel.d_secpercyl = 100;
        !           250:                /* as long as it's not 0, since readdisklabel divides by it */
        !           251:        }
        !           252:
        !           253:        strncpy(dip->disklabel.d_typename, "ATAPI CD-ROM",
        !           254:            sizeof(dip->disklabel.d_typename));
        !           255:        dip->disklabel.d_type = DTYPE_ATAPI;
        !           256:
        !           257:        strncpy(dip->disklabel.d_packname, "fictitious",
        !           258:            sizeof(dip->disklabel.d_packname));
        !           259:        dip->disklabel.d_secperunit = 100;
        !           260:        dip->disklabel.d_rpm = 300;
        !           261:        dip->disklabel.d_interleave = 1;
        !           262:
        !           263:        dip->disklabel.d_bbsize = 2048;
        !           264:        dip->disklabel.d_sbsize = 2048;
        !           265:
        !           266:        /* 'a' partition covering the "whole" disk */
        !           267:        dip->disklabel.d_partitions[0].p_offset = 0;
        !           268:        dip->disklabel.d_partitions[0].p_size = 100;
        !           269:        dip->disklabel.d_partitions[0].p_fstype = FS_UNUSED;
        !           270:
        !           271:        /* The raw partition is special */
        !           272:        dip->disklabel.d_partitions[RAW_PART].p_offset = 0;
        !           273:        dip->disklabel.d_partitions[RAW_PART].p_size = 100;
        !           274:        dip->disklabel.d_partitions[RAW_PART].p_fstype = FS_UNUSED;
        !           275:
        !           276:        dip->disklabel.d_npartitions = RAW_PART + 1;
        !           277:
        !           278:        dip->disklabel.d_magic = DISKMAGIC;
        !           279:        dip->disklabel.d_magic2 = DISKMAGIC;
        !           280:        dip->disklabel.d_checksum = dkcksum(&dip->disklabel);
        !           281:
        !           282:        /* Add to queue of disks */
        !           283:        TAILQ_INSERT_TAIL(&disklist, dip, list);
        !           284: }
        !           285:
        !           286:
        !           287: /* Find info on given BIOS disk */
        !           288: struct diskinfo *
        !           289: dklookup(int dev)
        !           290: {
        !           291:        struct diskinfo *dip;
        !           292:
        !           293:        for (dip = TAILQ_FIRST(&disklist); dip; dip = TAILQ_NEXT(dip, list))
        !           294:                if (dip->bios_info.bios_number == dev)
        !           295:                        return dip;
        !           296:
        !           297:        return NULL;
        !           298: }
        !           299:
        !           300: void
        !           301: dump_diskinfo(void)
        !           302: {
        !           303:        struct diskinfo *dip;
        !           304:
        !           305:        printf("Disk\tBIOS#\tType\tCyls\tHeads\tSecs\tFlags\tChecksum\n");
        !           306:        for (dip = TAILQ_FIRST(&disklist); dip; dip = TAILQ_NEXT(dip, list)) {
        !           307:                bios_diskinfo_t *bdi = &dip->bios_info;
        !           308:                int d = bdi->bios_number;
        !           309:                int u = d & 0x7f;
        !           310:                char c;
        !           311:
        !           312:                if (bdi->flags & BDI_EL_TORITO) {
        !           313:                        c = 'c';
        !           314:                        u = 0;
        !           315:                } else {
        !           316:                        c = (d & 0x80) ? 'h' : 'f';
        !           317:                }
        !           318:
        !           319:                printf("%cd%d\t0x%x\t%s\t%d\t%d\t%d\t0x%x\t0x%x\n",
        !           320:                    c, u, d,
        !           321:                    (bdi->flags & BDI_BADLABEL)?"*none*":"label",
        !           322:                    bdi->bios_cylinders, bdi->bios_heads, bdi->bios_sectors,
        !           323:                    bdi->flags, bdi->checksum);
        !           324:        }
        !           325: }
        !           326:
        !           327: /* Find BIOS portion on given BIOS disk
        !           328:  * XXX - Use dklookup() instead.
        !           329:  */
        !           330: bios_diskinfo_t *
        !           331: bios_dklookup(int dev)
        !           332: {
        !           333:        struct diskinfo *dip;
        !           334:
        !           335:        dip = dklookup(dev);
        !           336:        if (dip)
        !           337:                return &dip->bios_info;
        !           338:
        !           339:        return NULL;
        !           340: }
        !           341:
        !           342: /*
        !           343:  * Checksum one more block on all harddrives
        !           344:  *
        !           345:  * Use the adler32() function from libz,
        !           346:  * as it is quick, small, and available.
        !           347:  */
        !           348: int
        !           349: disksum(int blk)
        !           350: {
        !           351:        struct diskinfo *dip, *dip2;
        !           352:        int st, reprobe = 0;
        !           353:        char *buf;
        !           354:
        !           355:        buf = alloca(DEV_BSIZE);
        !           356:        for (dip = TAILQ_FIRST(&disklist); dip; dip = TAILQ_NEXT(dip, list)) {
        !           357:                bios_diskinfo_t *bdi = &dip->bios_info;
        !           358:
        !           359:                /* Skip this disk if it is not a HD or has had an I/O error */
        !           360:                if (!(bdi->bios_number & 0x80) || bdi->flags & BDI_INVALID)
        !           361:                        continue;
        !           362:
        !           363:                /* Adler32 checksum */
        !           364:                st = biosd_io(F_READ, bdi, blk, 1, buf);
        !           365:                if (st) {
        !           366:                        bdi->flags |= BDI_INVALID;
        !           367:                        continue;
        !           368:                }
        !           369:                bdi->checksum = adler32(bdi->checksum, buf, DEV_BSIZE);
        !           370:
        !           371:                for (dip2 = TAILQ_FIRST(&disklist); dip2 != dip;
        !           372:                                dip2 = TAILQ_NEXT(dip2, list)) {
        !           373:                        bios_diskinfo_t *bd = &dip2->bios_info;
        !           374:                        if ((bd->bios_number & 0x80) &&
        !           375:                            !(bd->flags & BDI_INVALID) &&
        !           376:                            bdi->checksum == bd->checksum)
        !           377:                                reprobe = 1;
        !           378:                }
        !           379:        }
        !           380:
        !           381:        return reprobe;
        !           382: }

CVSweb