The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sun/disksubr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: disksubr.c,v 1.2 2003/12/10 16:35:20 jdolecek Exp $ */
    2 
    3 /* 
    4  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
    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  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 /*
   32  * Copyright (c) 1994, 1995 Gordon W. Ross
   33  * Copyright (c) 1994 Theo de Raadt
   34  * All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  *
   45  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   46  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   47  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   48  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   49  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   50  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   51  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   52  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   53  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   54  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   55  */
   56 
   57 #include <sys/cdefs.h>
   58 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.2 2003/12/10 16:35:20 jdolecek Exp $");
   59 
   60 #include <sys/param.h>
   61 #include <sys/systm.h>
   62 #include <sys/buf.h>
   63 #include <sys/ioccom.h>
   64 #include <sys/device.h>
   65 #include <sys/disklabel.h>
   66 #include <sys/disk.h>
   67 #include <sys/dkbad.h>
   68 
   69 #include <dev/sun/disklabel.h>
   70 
   71 #if LABELSECTOR != 0
   72 #error  "Default value of LABELSECTOR no longer zero?"
   73 #endif
   74 
   75 static  char *disklabel_sun_to_bsd __P((char *, struct disklabel *));
   76 static  int disklabel_bsd_to_sun __P((struct disklabel *, char *));
   77 
   78 /*
   79  * Attempt to read a disk label from a device
   80  * using the indicated strategy routine.
   81  * The label must be partly set up before this:
   82  * secpercyl, secsize and anything required for a block i/o read
   83  * operation in the driver's strategy/start routines
   84  * must be filled in before calling us.
   85  *
   86  * Return buffer for use in signalling errors if requested.
   87  *
   88  * Returns null on success and an error string on failure.
   89  */
   90 const char *
   91 readdisklabel(dev, strat, lp, clp)
   92         dev_t dev;
   93         void (*strat) __P((struct buf *));
   94         struct disklabel *lp;
   95         struct cpu_disklabel *clp;
   96 {
   97         struct buf *bp;
   98         struct disklabel *dlp;
   99         struct sun_disklabel *slp;
  100         int error;
  101 
  102         /* minimal requirements for archtypal disk label */
  103         if (lp->d_secperunit == 0)
  104                 lp->d_secperunit = 0x1fffffff;
  105         if (lp->d_npartitions == 0) {
  106                 lp->d_npartitions = RAW_PART + 1;
  107                 if (lp->d_partitions[RAW_PART].p_size == 0)
  108                         lp->d_partitions[RAW_PART].p_size = 0x1fffffff;
  109                 lp->d_partitions[RAW_PART].p_offset = 0;
  110         }
  111 
  112         /* obtain buffer to probe drive with */
  113         bp = geteblk((int)lp->d_secsize);
  114 
  115         /* next, dig out disk label */
  116         bp->b_dev = dev;
  117         bp->b_blkno = LABELSECTOR;
  118         bp->b_cylinder = 0;
  119         bp->b_bcount = lp->d_secsize;
  120         bp->b_flags |= B_READ;
  121         (*strat)(bp);
  122 
  123         /* if successful, locate disk label within block and validate */
  124         error = biowait(bp);
  125         if (error == 0) {
  126                 /* Save the whole block in case it has info we need. */
  127                 memcpy(clp->cd_block, bp->b_data, sizeof(clp->cd_block));
  128         }
  129         brelse(bp);
  130         if (error)
  131                 return ("disk label read error");
  132 
  133         /* Check for a NetBSD disk label at LABELOFFSET */
  134         dlp = (struct disklabel *) (clp->cd_block + LABELOFFSET);
  135         if (dlp->d_magic == DISKMAGIC) {
  136                 if (dkcksum(dlp))
  137                         return ("NetBSD disk label corrupted");
  138                 *lp = *dlp;
  139                 return (NULL);
  140         }
  141 
  142         /* Check for a Sun disk label (for PROM compatibility). */
  143         slp = (struct sun_disklabel *) clp->cd_block;
  144         if (slp->sl_magic == SUN_DKMAGIC)
  145                 return (disklabel_sun_to_bsd(clp->cd_block, lp));
  146 
  147         /*
  148          * Check for a NetBSD disk label somewhere in LABELSECTOR
  149          * (compat with others big-endian boxes)
  150          */
  151         for (dlp = (struct disklabel *)clp->cd_block;
  152             dlp <= (struct disklabel *)((char *)clp->cd_block +
  153             DEV_BSIZE - sizeof(*dlp));
  154             dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
  155                 if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
  156                         continue;
  157                 }
  158                 if (dlp->d_npartitions > MAXPARTITIONS || dkcksum(dlp) != 0)
  159                         return("NetBSD disk label corrupted");
  160                 else {
  161                         *lp = *dlp;
  162                         return(NULL);
  163                 }
  164         }
  165 
  166         memset(clp->cd_block, 0, sizeof(clp->cd_block));
  167         return ("no disk label");
  168 }
  169 
  170 /*
  171  * Check new disk label for sensibility
  172  * before setting it.
  173  */
  174 int
  175 setdisklabel(olp, nlp, openmask, clp)
  176         struct disklabel *olp, *nlp;
  177         u_long openmask;
  178         struct cpu_disklabel *clp;
  179 {
  180         int i;
  181         struct partition *opp, *npp;
  182 
  183         /* sanity clause */
  184         if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
  185             (nlp->d_secsize % DEV_BSIZE) != 0)
  186                 return(EINVAL);
  187 
  188         /* special case to allow disklabel to be invalidated */
  189         if (nlp->d_magic == 0xffffffff) {
  190                 *olp = *nlp;
  191                 return (0);
  192         }
  193 
  194         if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
  195             dkcksum(nlp) != 0)
  196                 return (EINVAL);
  197 
  198         while ((i = ffs(openmask)) != 0) {
  199                 i--;
  200                 openmask &= ~(1 << i);
  201                 if (nlp->d_npartitions <= i)
  202                         return (EBUSY);
  203                 opp = &olp->d_partitions[i];
  204                 npp = &nlp->d_partitions[i];
  205                 if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
  206                         return (EBUSY);
  207         }
  208 
  209         *olp = *nlp;
  210         return (0);
  211 }
  212 
  213 /*
  214  * Write disk label back to device after modification.
  215  * Current label is already in clp->cd_block[]
  216  */
  217 int
  218 writedisklabel(dev, strat, lp, clp)
  219         dev_t dev;
  220         void (*strat) __P((struct buf *));
  221         struct disklabel *lp;
  222         struct cpu_disklabel *clp;
  223 {
  224         struct buf *bp;
  225         int error;
  226         struct disklabel *dlp;
  227         struct sun_disklabel *slp;
  228 
  229         /*
  230          * Embed native label in a piece of wasteland.
  231          */
  232         if (sizeof(struct disklabel) > sizeof slp->sl_bsdlabel)
  233                 return EFBIG;
  234 
  235         slp = (struct sun_disklabel *)clp->cd_block;
  236         memset(slp->sl_bsdlabel, 0, sizeof(slp->sl_bsdlabel));
  237         dlp = (struct disklabel *)slp->sl_bsdlabel;
  238         *dlp = *lp;
  239 
  240         /* Build a SunOS compatible label around the native label */
  241         error = disklabel_bsd_to_sun(lp, clp->cd_block);
  242         if (error)
  243                 return (error);
  244 
  245         /* Get a buffer and copy the new label into it. */
  246         bp = geteblk((int)lp->d_secsize);
  247         memcpy(bp->b_data, clp->cd_block, sizeof(clp->cd_block));
  248 
  249         /* Write out the updated label. */
  250         bp->b_dev = dev;
  251         bp->b_blkno = LABELSECTOR;
  252         bp->b_cylinder = 0;
  253         bp->b_bcount = lp->d_secsize;
  254         bp->b_flags |= B_WRITE;
  255         (*strat)(bp);
  256         error = biowait(bp);
  257         brelse(bp);
  258 
  259         return (error);
  260 }
  261 
  262 /*
  263  * Determine the size of the transfer, and make sure it is
  264  * within the boundaries of the partition. Adjust transfer
  265  * if needed, and signal errors or early completion.
  266  */
  267 int
  268 bounds_check_with_label(dk, bp, wlabel)
  269         struct disk *dk;
  270         struct buf *bp;
  271         int wlabel;
  272 {
  273         struct disklabel *lp = dk->dk_label;
  274         struct partition *p = lp->d_partitions + DISKPART(bp->b_dev);
  275         int maxsz = p->p_size;
  276         int sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
  277 
  278         /*
  279          * overwriting disk label ?
  280          * The label is always in sector LABELSECTOR.
  281          * XXX should also protect bootstrap in first 8K
  282          */
  283         if (bp->b_blkno + p->p_offset <= LABELSECTOR &&
  284             (bp->b_flags & B_READ) == 0 && wlabel == 0) {
  285                 bp->b_error = EROFS;
  286                 goto bad;
  287         }
  288 
  289         /* beyond partition? */
  290         if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
  291                 /* if exactly at end of disk, return an EOF */
  292                 if (bp->b_blkno == maxsz) {
  293                         bp->b_resid = bp->b_bcount;
  294                         return(0);
  295                 }
  296                 /* or truncate if part of it fits */
  297                 sz = maxsz - bp->b_blkno;
  298                 if (sz <= 0) {
  299                         bp->b_error = EINVAL;
  300                         goto bad;
  301                 }
  302                 bp->b_bcount = sz << DEV_BSHIFT;
  303         }
  304 
  305         /* calculate cylinder for disksort to order transfers with */
  306         bp->b_resid = (bp->b_blkno + p->p_offset) / lp->d_secpercyl;
  307         return(1);
  308 bad:
  309         bp->b_flags |= B_ERROR;
  310         return(-1);
  311 }
  312 
  313 /************************************************************************
  314  *
  315  * The rest of this was taken from arch/sparc/scsi/sun_disklabel.c
  316  * and then substantially rewritten by Gordon W. Ross
  317  *
  318  ************************************************************************/
  319 
  320 /* What partition types to assume for Sun disklabels: */
  321 static u_char
  322 sun_fstypes[8] = {
  323         FS_BSDFFS,      /* a */
  324         FS_SWAP,        /* b */
  325         FS_OTHER,       /* c - whole disk */
  326         FS_BSDFFS,      /* d */
  327         FS_BSDFFS,      /* e */
  328         FS_BSDFFS,      /* f */
  329         FS_BSDFFS,      /* g */
  330         FS_BSDFFS,      /* h */
  331 };
  332 
  333 /*
  334  * Given a SunOS disk label, set lp to a BSD disk label.
  335  * Returns NULL on success, else an error string.
  336  *
  337  * The BSD label is cleared out before this is called.
  338  */
  339 static char *
  340 disklabel_sun_to_bsd(cp, lp)
  341         char *cp;
  342         struct disklabel *lp;
  343 {
  344         struct sun_disklabel *sl;
  345         struct partition *npp;
  346         struct sun_dkpart *spp;
  347         int i, secpercyl;
  348         u_short cksum, *sp1, *sp2;
  349 
  350         sl = (struct sun_disklabel *)cp;
  351 
  352         /* Verify the XOR check. */
  353         sp1 = (u_short *)sl;
  354         sp2 = (u_short *)(sl + 1);
  355         cksum = 0;
  356         while (sp1 < sp2)
  357                 cksum ^= *sp1++;
  358         if (cksum != 0)
  359                 return("SunOS disk label, bad checksum");
  360 
  361         /* Format conversion. */
  362         lp->d_magic = DISKMAGIC;
  363         lp->d_magic2 = DISKMAGIC;
  364         memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));
  365 
  366         lp->d_secsize = 512;
  367         lp->d_nsectors   = sl->sl_nsectors;
  368         lp->d_ntracks    = sl->sl_ntracks;
  369         lp->d_ncylinders = sl->sl_ncylinders;
  370 
  371         secpercyl = sl->sl_nsectors * sl->sl_ntracks;
  372         lp->d_secpercyl  = secpercyl;
  373         lp->d_secperunit = secpercyl * sl->sl_ncylinders;
  374 
  375         lp->d_sparespercyl = sl->sl_sparespercyl;
  376         lp->d_acylinders   = sl->sl_acylinders;
  377         lp->d_rpm          = sl->sl_rpm;
  378         lp->d_interleave   = sl->sl_interleave;
  379 
  380         lp->d_npartitions = 8;
  381         /* These are as defined in <ufs/ffs/fs.h> */
  382         lp->d_bbsize = 8192;    /* XXX */
  383         lp->d_sbsize = 8192;    /* XXX */
  384 
  385         for (i = 0; i < 8; i++) {
  386                 spp = &sl->sl_part[i];
  387                 npp = &lp->d_partitions[i];
  388                 npp->p_offset = spp->sdkp_cyloffset * secpercyl;
  389                 npp->p_size = spp->sdkp_nsectors;
  390                 if (npp->p_size == 0) {
  391                         npp->p_fstype = FS_UNUSED;
  392                 } else {
  393                         npp->p_fstype = sun_fstypes[i];
  394                         if (npp->p_fstype == FS_BSDFFS) {
  395                                 /*
  396                                  * The sun label does not store the FFS fields,
  397                                  * so just set them with default values here.
  398                                  */
  399                                 npp->p_fsize = 1024;
  400                                 npp->p_frag = 8;
  401                                 npp->p_cpg = 16;
  402                         }
  403                 }
  404         }
  405 
  406         lp->d_checksum = 0;
  407         lp->d_checksum = dkcksum(lp);
  408         return (NULL);
  409 }
  410 
  411 /*
  412  * Given a BSD disk label, update the Sun disklabel
  413  * pointed to by cp with the new info.  Note that the
  414  * Sun disklabel may have other info we need to keep.
  415  * Returns zero or error code.
  416  */
  417 static int
  418 disklabel_bsd_to_sun(lp, cp)
  419         struct disklabel *lp;
  420         char *cp;
  421 {
  422         struct sun_disklabel *sl;
  423         struct partition *npp;
  424         struct sun_dkpart *spp;
  425         int i, secpercyl;
  426         u_short cksum, *sp1, *sp2;
  427 
  428         if (lp->d_secsize != 512)
  429                 return (EINVAL);
  430 
  431         sl = (struct sun_disklabel *)cp;
  432 
  433         /*
  434          * Format conversion.
  435          */
  436         memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname));
  437         sl->sl_rpm = lp->d_rpm;
  438         sl->sl_pcylinders   = lp->d_ncylinders + lp->d_acylinders; /* XXX */
  439         sl->sl_sparespercyl = lp->d_sparespercyl;
  440         sl->sl_interleave   = lp->d_interleave;
  441         sl->sl_ncylinders   = lp->d_ncylinders;
  442         sl->sl_acylinders   = lp->d_acylinders;
  443         sl->sl_ntracks      = lp->d_ntracks;
  444         sl->sl_nsectors     = lp->d_nsectors;
  445 
  446         secpercyl = sl->sl_nsectors * sl->sl_ntracks;
  447         for (i = 0; i < 8; i++) {
  448                 spp = &sl->sl_part[i];
  449                 npp = &lp->d_partitions[i];
  450 
  451                 /*
  452                  * SunOS partitions must start on a cylinder boundary.
  453                  * Note this restriction is forced upon NetBSD/sparc
  454                  * labels too, since we want to keep both labels
  455                  * synchronised.
  456                  */
  457                 if (npp->p_offset % secpercyl)
  458                         return (EINVAL);
  459                 spp->sdkp_cyloffset = npp->p_offset / secpercyl;
  460                 spp->sdkp_nsectors = npp->p_size;
  461         }
  462         sl->sl_magic = SUN_DKMAGIC;
  463 
  464         /* Compute the XOR check. */
  465         sp1 = (u_short *)sl;
  466         sp2 = (u_short *)(sl + 1);
  467         sl->sl_cksum = cksum = 0;
  468         while (sp1 < sp2)
  469                 cksum ^= *sp1++;
  470         sl->sl_cksum = cksum;
  471 
  472         return (0);
  473 }
  474 
  475 /*
  476  * Search the bad sector table looking for the specified sector.
  477  * Return index if found.
  478  * Return -1 if not found.
  479  */
  480 int
  481 isbad(bt, cyl, trk, sec)
  482         struct dkbad *bt;
  483         int cyl, trk, sec;
  484 {
  485         int i;
  486         long blk, bblk;
  487 
  488         blk = ((long)cyl << 16) + (trk << 8) + sec;
  489         for (i = 0; i < 126; i++) {
  490                 bblk = ((long)bt->bt_bad[i].bt_cyl << 16) +
  491                         bt->bt_bad[i].bt_trksec;
  492                 if (blk == bblk)
  493                         return (i);
  494                 if (blk < bblk || bblk < 0)
  495                         break;
  496         }
  497         return (-1);
  498 }

Cache object: ffde95a09e51ce0f69507f78ea6782ce


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.