[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

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