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

Annotation of sys/arch/i386/i386/dkcsum.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: dkcsum.c,v 1.21 2006/05/11 13:21:11 mickey Exp $      */
                      2:
                      3: /*-
                      4:  * Copyright (c) 1997 Niklas Hallqvist.  All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     17:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     18:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     19:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     20:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     21:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     22:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     23:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     24:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     25:  */
                     26:
                     27: /*
                     28:  * A checksumming pseudo device used to get unique labels of each disk
                     29:  * that needs to be matched to BIOS disks.
                     30:  */
                     31:
                     32: #include <sys/param.h>
                     33: #include <sys/buf.h>
                     34: #include <sys/conf.h>
                     35: #include <sys/device.h>
                     36: #include <sys/disklabel.h>
                     37: #include <sys/fcntl.h>
                     38: #include <sys/proc.h>
                     39: #include <sys/reboot.h>
                     40: #include <sys/stat.h>
                     41: #include <sys/systm.h>
                     42:
                     43: #include <machine/biosvar.h>
                     44:
                     45: #include <lib/libz/zlib.h>
                     46:
                     47: dev_t dev_rawpart(struct device *);    /* XXX */
                     48:
                     49: extern u_int32_t bios_cksumlen;
                     50: extern bios_diskinfo_t *bios_diskinfo;
                     51: extern dev_t bootdev;
                     52:
                     53: void
                     54: dkcsumattach(void)
                     55: {
                     56:        struct device *dv;
                     57:        struct buf *bp;
                     58:        struct bdevsw *bdsw;
                     59:        dev_t dev, pribootdev, altbootdev;
                     60:        int error, picked;
                     61:        u_int32_t csum;
                     62:        bios_diskinfo_t *bdi, *hit;
                     63:
                     64:        /* do nothing if no diskinfo passed from /boot, or a bad length */
                     65:        if (bios_diskinfo == NULL || bios_cksumlen * DEV_BSIZE > MAXBSIZE)
                     66:                return;
                     67:
                     68: #ifdef DEBUG
                     69:        printf("dkcsum: bootdev=%#x\n", bootdev);
                     70:        for (bdi = bios_diskinfo; bdi->bios_number != -1; bdi++)
                     71:                if (bdi->bios_number & 0x80)
                     72:                        printf("dkcsum: BIOS drive %#x checksum is %#x\n",
                     73:                            bdi->bios_number, bdi->checksum);
                     74: #endif
                     75:        pribootdev = altbootdev = 0;
                     76:
                     77:        /*
                     78:         * XXX What if DEV_BSIZE is changed to something else than the BIOS
                     79:         * blocksize?  Today, /boot doesn't cover that case so neither need
                     80:         * I care here.
                     81:         */
                     82:        bp = geteblk(bios_cksumlen * DEV_BSIZE);        /* XXX error check?  */
                     83:
                     84:        TAILQ_FOREACH(dv, &alldevs, dv_list) {
                     85:                if (dv->dv_class != DV_DISK)
                     86:                        continue;
                     87:                bp->b_dev = dev = dev_rawpart(dv);
                     88:                if (dev == NODEV)
                     89:                        continue;
                     90:                bdsw = &bdevsw[major(dev)];
                     91:
                     92:                /*
                     93:                 * This open operation guarantees a proper initialization
                     94:                 * of the device, for future strategy calls.
                     95:                 */
                     96:                error = (*bdsw->d_open)(dev, FREAD, S_IFCHR, curproc);
                     97:                if (error) {
                     98:                        /* XXX What to do here? */
                     99: #ifdef DEBUG
                    100:                        printf("dkcsum: %s open failed (%d)\n",
                    101:                            dv->dv_xname, error);
                    102: #endif
                    103:                        continue;
                    104:                }
                    105:
                    106:                /* Read blocks to cksum.  XXX maybe a d_read should be used. */
                    107:                bp->b_blkno = 0;
                    108:                bp->b_bcount = bios_cksumlen * DEV_BSIZE;
                    109:                bp->b_flags = B_BUSY | B_READ;
                    110:                bp->b_cylinder = 0;
                    111:                (*bdsw->d_strategy)(bp);
                    112:                if ((error = biowait(bp))) {
                    113:                        /* XXX What to do here? */
                    114: #ifdef DEBUG
                    115:                        printf("dkcsum: %s read failed (%d)\n",
                    116:                            dv->dv_xname, error);
                    117: #endif
                    118:                        error = (*bdsw->d_close)(dev, 0, S_IFCHR, curproc);
                    119: #ifdef DEBUG
                    120:                        if (error)
                    121:                                printf("dkcsum: %s close failed (%d)\n",
                    122:                                    dv->dv_xname, error);
                    123: #endif
                    124:                        continue;
                    125:                }
                    126:                error = (*bdsw->d_close)(dev, FREAD, S_IFCHR, curproc);
                    127:                if (error) {
                    128:                        /* XXX What to do here? */
                    129: #ifdef DEBUG
                    130:                        printf("dkcsum: %s closed failed (%d)\n",
                    131:                            dv->dv_xname, error);
                    132: #endif
                    133:                        continue;
                    134:                }
                    135:
                    136:                csum = adler32(0, bp->b_data, bios_cksumlen * DEV_BSIZE);
                    137: #ifdef DEBUG
                    138:                printf("dkcsum: %s checksum is %#x\n", dv->dv_xname, csum);
                    139: #endif
                    140:
                    141:                /* Find the BIOS device */
                    142:                hit = 0;
                    143:                for (bdi = bios_diskinfo; bdi->bios_number != -1; bdi++) {
                    144:                        /* Skip non-harddrives */
                    145:                        if (!(bdi->bios_number & 0x80))
                    146:                                continue;
                    147:                        if (bdi->checksum != csum)
                    148:                                continue;
                    149:                        picked = hit || (bdi->flags & BDI_PICKED);
                    150:                        if (!picked)
                    151:                                hit = bdi;
                    152:                        printf("dkcsum: %s matches BIOS drive %#x%s\n",
                    153:                            dv->dv_xname, bdi->bios_number,
                    154:                            (picked ? " IGNORED" : ""));
                    155:                }
                    156:
                    157:                /*
                    158:                 * If we have no hit, that's OK, we can see a lot more devices
                    159:                 * than the BIOS can, so this case is pretty normal.
                    160:                 */
                    161:                if (!hit) {
                    162: #ifdef DEBUG
                    163:                        printf("dkcsum: %s has no matching BIOS drive\n",
                    164:                            dv->dv_xname);
                    165: #endif
                    166:                        continue;
                    167:                }
                    168:
                    169:                /*
                    170:                 * Fixup bootdev if units match.  This means that all of
                    171:                 * hd*, sd*, wd*, will be interpreted the same.  Not 100%
                    172:                 * backwards compatible, but sd* and wd* should be phased-
                    173:                 * out in the bootblocks.
                    174:                 */
                    175:
                    176:                /* B_TYPE dependent hd unit counting bootblocks */
                    177:                if ((B_TYPE(bootdev) == B_TYPE(hit->bsd_dev)) &&
                    178:                    (B_UNIT(bootdev) == B_UNIT(hit->bsd_dev))) {
                    179:                        int type, ctrl, adap, part, unit;
                    180:
                    181:                        type = major(bp->b_dev);
                    182:                        adap = B_ADAPTOR(bootdev);
                    183:                        ctrl = B_CONTROLLER(bootdev);
                    184:                        unit = DISKUNIT(bp->b_dev);
                    185:                        part = B_PARTITION(bootdev);
                    186:
                    187:                        pribootdev = MAKEBOOTDEV(type, ctrl, adap, unit, part);
                    188: #ifdef DEBUG
                    189:                        printf("dkcsum: %s is primary boot disk\n",
                    190:                            dv->dv_xname);
                    191: #endif
                    192:                }
                    193:                /* B_TYPE independent hd unit counting bootblocks */
                    194:                if (B_UNIT(bootdev) == (hit->bios_number & 0x7F)) {
                    195:                        int type, ctrl, adap, part, unit;
                    196:
                    197:                        type = major(bp->b_dev);
                    198:                        adap = B_ADAPTOR(bootdev);
                    199:                        ctrl = B_CONTROLLER(bootdev);
                    200:                        unit = DISKUNIT(bp->b_dev);
                    201:                        part = B_PARTITION(bootdev);
                    202:
                    203:                        altbootdev = MAKEBOOTDEV(type, ctrl, adap, unit, part);
                    204: #ifdef DEBUG
                    205:                        printf("dkcsum: %s is alternate boot disk\n",
                    206:                            dv->dv_xname);
                    207: #endif
                    208:                }
                    209:
                    210:                /* This will overwrite /boot's guess, just so you remember */
                    211:                hit->bsd_dev = MAKEBOOTDEV(major(bp->b_dev), 0, 0,
                    212:                    DISKUNIT(bp->b_dev), RAW_PART);
                    213:                hit->flags |= BDI_PICKED;
                    214:        }
                    215:        bootdev = pribootdev ? pribootdev : altbootdev ? altbootdev : bootdev;
                    216:
                    217:        bp->b_flags |= B_INVAL;
                    218:        brelse(bp);
                    219: }

CVSweb