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

Annotation of sys/arch/zaurus/stand/zboot/diskprobe.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: diskprobe.c,v 1.3 2006/10/13 00:00:55 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: #if 0
                     39: #include <machine/biosvar.h>
                     40: #endif
                     41: #include <lib/libz/zlib.h>
                     42: #include "disk.h"
                     43: #if 0
                     44: #include "biosdev.h"
                     45: #endif
                     46: #include "libsa.h"
                     47:
                     48: #define MAX_CKSUMLEN MAXBSIZE / DEV_BSIZE      /* Max # of blks to cksum */
                     49:
                     50: /* Disk spin-up wait timeout. */
                     51: static u_int timeout = 10;
                     52:
                     53: /* Local Prototypes */
                     54: static void hardprobe(void);
                     55:
                     56: /* List of disk devices we found/probed */
                     57: struct disklist_lh disklist;
                     58:
                     59: /*
                     60:  * Probe for all hard disks.
                     61:  */
                     62: static void
                     63: hardprobe(void)
                     64: {
                     65:        struct diskinfo *dip;
                     66:        int i, order[] = { 0x80, 0x82 }; /* XXX probe disks in this order */
                     67:        u_int bsdunit, type;
                     68:        u_int scsi = 0, ide = 0;
                     69:        u_int disk = 0;
                     70:
                     71:        /* Hard disks */
                     72:        for (i = 0; i < sizeof(order) / sizeof(order[0]); i++) {
                     73:                dip = alloc(sizeof(struct diskinfo));
                     74:                bzero(dip, sizeof(*dip));
                     75:
                     76:                if (bios_getdiskinfo(order[i], &dip->bios_info) != NULL) {
                     77:                        free(dip, 0);
                     78:                        continue;
                     79:                }
                     80:
                     81:                printf("hd%u", disk++);
                     82:
                     83:                /* Try to find the label, to figure out device type. */
                     84:                if (bios_getdisklabel(&dip->bios_info, &dip->disklabel)
                     85:                    == NULL) {
                     86:                        printf("*");
                     87:                        bsdunit = ide++;
                     88:                        type = 0;       /* XXX let it be IDE */
                     89:                } else {
                     90:                        /* Best guess */
                     91:                        switch (dip->disklabel.d_type) {
                     92:                        case DTYPE_SCSI:
                     93:                                type = 4;
                     94:                                bsdunit = scsi++;
                     95:                                dip->bios_info.flags |= BDI_GOODLABEL;
                     96:                                break;
                     97:
                     98:                        case DTYPE_ESDI:
                     99:                        case DTYPE_ST506:
                    100:                                type = 0;
                    101:                                bsdunit = ide++;
                    102:                                dip->bios_info.flags |= BDI_GOODLABEL;
                    103:                                break;
                    104:
                    105:                        default:
                    106:                                dip->bios_info.flags |= BDI_BADLABEL;
                    107:                                type = 0;       /* XXX Suggest IDE */
                    108:                                bsdunit = ide++;
                    109:                        }
                    110:                }
                    111:
                    112:                dip->bios_info.checksum = 0; /* just in case */
                    113:                /* Fill out best we can. */
                    114:                dip->bios_info.bsd_dev =
                    115:                    MAKEBOOTDEV(type, 0, 0, bsdunit, RAW_PART);
                    116:
                    117:                /* Add to queue of disks. */
                    118:                TAILQ_INSERT_TAIL(&disklist, dip, list);
                    119:
                    120:                printf(" ");
                    121:        }
                    122: }
                    123:
                    124: /* Probe for all BIOS supported disks */
                    125: u_int32_t bios_cksumlen;
                    126: void
                    127: diskprobe(void)
                    128: {
                    129:        struct diskinfo *dip;
                    130:        int i;
                    131:
                    132:        /* These get passed to kernel */
                    133:        bios_diskinfo_t *bios_diskinfo;
                    134:
                    135:        /* Init stuff */
                    136:        TAILQ_INIT(&disklist);
                    137:
                    138:        /* Do probes */
                    139:        hardprobe();
                    140:
                    141: #if 0
                    142:        /* Checksumming of hard disks */
                    143:        for (i = 0; disksum(i++) && i < MAX_CKSUMLEN; )
                    144:                ;
                    145:        bios_cksumlen = i;
                    146:
                    147:        /* Get space for passing bios_diskinfo stuff to kernel */
                    148:        for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
                    149:            dip = TAILQ_NEXT(dip, list))
                    150:                i++;
                    151:        bios_diskinfo = alloc(++i * sizeof(bios_diskinfo_t));
                    152:
                    153:        /* Copy out the bios_diskinfo stuff */
                    154:        for (i = 0, dip = TAILQ_FIRST(&disklist); dip;
                    155:            dip = TAILQ_NEXT(dip, list))
                    156:                bios_diskinfo[i++] = dip->bios_info;
                    157:
                    158:        bios_diskinfo[i++].bios_number = -1;
                    159:        /* Register for kernel use */
                    160:        addbootarg(BOOTARG_CKSUMLEN, sizeof(u_int32_t), &bios_cksumlen);
                    161:        addbootarg(BOOTARG_DISKINFO, i * sizeof(bios_diskinfo_t),
                    162:            bios_diskinfo);
                    163: #endif
                    164: }
                    165:
                    166: /*
                    167:  * Find info on the disk given by major + unit number.
                    168:  */
                    169: struct diskinfo *
                    170: dkdevice(dev_t maj, dev_t unit)
                    171: {
                    172:        struct diskinfo *dip;
                    173:
                    174:        for (dip = TAILQ_FIRST(&disklist); dip;
                    175:             dip = TAILQ_NEXT(dip, list)) {
                    176:                /* XXX skip non-matching entries according to maj. */
                    177:
                    178:                if (unit-- == 0)
                    179:                        return dip;
                    180:        }
                    181:
                    182:        return NULL;
                    183: }
                    184:
                    185: /*
                    186:  * Find the Linux device path that corresponds to the given "BIOS" disk,
                    187:  * where 0x80 corresponds to /dev/hda, 0x81 to /dev/hdb, and so on.
                    188:  */
                    189: void
                    190: bios_devpath(int dev, int part, char *p)
                    191: {
                    192:        *p++ = '/';
                    193:        *p++ = 'd';
                    194:        *p++ = 'e';
                    195:        *p++ = 'v';
                    196:        *p++ = '/';
                    197:        if ((dev & 0x80) != 0)
                    198:                *p++ = 'h';
                    199:        else
                    200:                *p++ = 'f';
                    201:        *p++ = 'd';
                    202:        *p++ = 'a' + (dev & 0x7f);
                    203:        if (part != -1)
                    204:                *p++ = '1' + part;
                    205:        *p = '\0';
                    206: }
                    207:
                    208: /*
                    209:  * Fill out a bios_diskinfo_t for this device.
                    210:  */
                    211: char *
                    212: bios_getdiskinfo(int dev, bios_diskinfo_t *bdi)
                    213: {
                    214:        static char path[PATH_MAX];
                    215:        struct linux_stat sb;
                    216:        char *p;
                    217:
                    218:        bzero(bdi, sizeof *bdi);
                    219:        bdi->bios_number = -1;
                    220:
                    221:        bios_devpath(dev, -1, path);
                    222:
                    223:        if (ustat(path, &sb) != 0)
                    224:                return "no device node";
                    225:
                    226:        bdi->bios_number = dev;
                    227:
                    228:        if (bios_getdospart(bdi) < 0)
                    229:                return "no OpenBSD partition";
                    230:
                    231:        return 0;
                    232: }
                    233:
                    234: int
                    235: bios_getdospart(bios_diskinfo_t *bdi)
                    236: {
                    237:        char path[PATH_MAX];
                    238:        char buf[DEV_BSIZE];
                    239:        struct dos_partition *dp;
                    240:        int fd;
                    241:        u_int part;
                    242:        size_t rsize;
                    243:
                    244:        bios_devpath(bdi->bios_number, -1, path);
                    245:
                    246:        /*
                    247:         * Give disk devices some time to become ready when the first open
                    248:         * fails.  Even when open succeeds the disk is sometimes not ready.
                    249:         */
                    250:        if ((fd = uopen(path, O_RDONLY)) == -1 && errno == ENXIO) {
                    251:                int t;
                    252:
                    253:                while (fd == -1 && timeout > 0) {
                    254:                        timeout--;
                    255:                        sleep(1);
                    256:                        fd = uopen(path, O_RDONLY);
                    257:                }
                    258:                if (fd != -1)
                    259:                        sleep(2);
                    260:        }
                    261:        if (fd == -1)
                    262:                return -1;
                    263:
                    264:        /* Read the disk's MBR. */
                    265:        if (unixstrategy((void *)fd, F_READ, DOSBBSECTOR,
                    266:            DEV_BSIZE, buf, &rsize) != 0 || rsize != DEV_BSIZE) {
                    267:                uclose(fd);
                    268:                errno = EIO;
                    269:                return -1;
                    270:        }
                    271:
                    272:        /* Find OpenBSD primary partition in the disk's MBR. */
                    273:        dp = (struct dos_partition *)&buf[DOSPARTOFF];
                    274:        for (part = 0; part < NDOSPART; part++)
                    275:                if (dp[part].dp_typ == DOSPTYP_OPENBSD)
                    276:                        break;
                    277:        if (part == NDOSPART) {
                    278:                uclose(fd);
                    279:                errno = ERDLAB;
                    280:                return -1;
                    281:        }
                    282:        uclose(fd);
                    283:
                    284:        return part;
                    285: }
                    286:
                    287: char *
                    288: bios_getdisklabel(bios_diskinfo_t *bdi, struct disklabel *label)
                    289: {
                    290:        char path[PATH_MAX];
                    291:        char buf[DEV_BSIZE];
                    292:        int part;
                    293:        int fd;
                    294:        size_t rsize;
                    295:
                    296:        part = bios_getdospart(bdi);
                    297:        if (part < 0)
                    298:                return "no OpenBSD partition";
                    299:
                    300:        bios_devpath(bdi->bios_number, part, path);
                    301:
                    302:        /* Test if the OpenBSD partition has a valid disklabel. */
                    303:        if ((fd = uopen(path, O_RDONLY)) != -1) {
                    304:                char *msg = "failed to read disklabel";
                    305:
                    306:                if (unixstrategy((void *)fd, F_READ, LABELSECTOR,
                    307:                    DEV_BSIZE, buf, &rsize) == 0 && rsize == DEV_BSIZE)
                    308:                        msg = getdisklabel(buf, label);
                    309:                uclose(fd);
                    310:                /* Don't wait for other disks if this label is ok. */
                    311:                if (msg == NULL)
                    312:                        timeout = 0;
                    313:                return (msg);
                    314:        }
                    315:
                    316:        return "failed to open partition";
                    317: }

CVSweb