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/kern/subr_disk.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: subr_disk.c,v 1.83 2008/11/21 23:51:30 krw Exp $      */
    2 /*      $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $  */
    3 
    4 /*
    5  * Copyright (c) 1995 Jason R. Thorpe.  All rights reserved.
    6  * Copyright (c) 1982, 1986, 1988, 1993
    7  *      The Regents of the University of California.  All rights reserved.
    8  * (c) UNIX System Laboratories, Inc.
    9  * All or some portions of this file are derived from material licensed
   10  * to the University of California by American Telephone and Telegraph
   11  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   12  * the permission of UNIX System Laboratories, Inc.
   13  *
   14  * Redistribution and use in source and binary forms, with or without
   15  * modification, are permitted provided that the following conditions
   16  * are met:
   17  * 1. Redistributions of source code must retain the above copyright
   18  *    notice, this list of conditions and the following disclaimer.
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  * 3. Neither the name of the University nor the names of its contributors
   23  *    may be used to endorse or promote products derived from this software
   24  *    without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   36  * SUCH DAMAGE.
   37  *
   38  *      @(#)ufs_disksubr.c      8.5 (Berkeley) 1/21/94
   39  */
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/malloc.h>
   45 #include <sys/fcntl.h>
   46 #include <sys/buf.h>
   47 #include <sys/stat.h>
   48 #include <sys/syslog.h>
   49 #include <sys/device.h>
   50 #include <sys/time.h>
   51 #include <sys/disklabel.h>
   52 #include <sys/conf.h>
   53 #include <sys/lock.h>
   54 #include <sys/disk.h>
   55 #include <sys/reboot.h>
   56 #include <sys/dkio.h>
   57 #include <sys/dkstat.h>         /* XXX */
   58 #include <sys/proc.h>
   59 #include <uvm/uvm_extern.h>
   60 
   61 #include <sys/socket.h>
   62 #include <sys/socketvar.h>
   63 
   64 #include <net/if.h>
   65 
   66 #include <dev/rndvar.h>
   67 #include <dev/cons.h>
   68 
   69 /*
   70  * A global list of all disks attached to the system.  May grow or
   71  * shrink over time.
   72  */
   73 struct  disklist_head disklist; /* TAILQ_HEAD */
   74 int     disk_count;             /* number of drives in global disklist */
   75 int     disk_change;            /* set if a disk has been attached/detached
   76                                  * since last we looked at this variable. This
   77                                  * is reset by hw_sysctl()
   78                                  */
   79 
   80 /*
   81  * Seek sort for disks.  We depend on the driver which calls us using b_resid
   82  * as the current cylinder number.
   83  *
   84  * The argument ap structure holds a b_actf activity chain pointer on which we
   85  * keep two queues, sorted in ascending cylinder order.  The first queue holds
   86  * those requests which are positioned after the current cylinder (in the first
   87  * request); the second holds requests which came in after their cylinder number
   88  * was passed.  Thus we implement a one way scan, retracting after reaching the
   89  * end of the drive to the first request on the second queue, at which time it
   90  * becomes the first queue.
   91  *
   92  * A one-way scan is natural because of the way UNIX read-ahead blocks are
   93  * allocated.
   94  */
   95 
   96 void
   97 disksort(struct buf *ap, struct buf *bp)
   98 {
   99         struct buf *bq;
  100 
  101         /* If the queue is empty, then it's easy. */
  102         if (ap->b_actf == NULL) {
  103                 bp->b_actf = NULL;
  104                 ap->b_actf = bp;
  105                 return;
  106         }
  107 
  108         /*
  109          * If we lie after the first (currently active) request, then we
  110          * must locate the second request list and add ourselves to it.
  111          */
  112         bq = ap->b_actf;
  113         if (bp->b_cylinder < bq->b_cylinder) {
  114                 while (bq->b_actf) {
  115                         /*
  116                          * Check for an ``inversion'' in the normally ascending
  117                          * cylinder numbers, indicating the start of the second
  118                          * request list.
  119                          */
  120                         if (bq->b_actf->b_cylinder < bq->b_cylinder) {
  121                                 /*
  122                                  * Search the second request list for the first
  123                                  * request at a larger cylinder number.  We go
  124                                  * before that; if there is no such request, we
  125                                  * go at end.
  126                                  */
  127                                 do {
  128                                         if (bp->b_cylinder <
  129                                             bq->b_actf->b_cylinder)
  130                                                 goto insert;
  131                                         if (bp->b_cylinder ==
  132                                             bq->b_actf->b_cylinder &&
  133                                             bp->b_blkno < bq->b_actf->b_blkno)
  134                                                 goto insert;
  135                                         bq = bq->b_actf;
  136                                 } while (bq->b_actf);
  137                                 goto insert;            /* after last */
  138                         }
  139                         bq = bq->b_actf;
  140                 }
  141                 /*
  142                  * No inversions... we will go after the last, and
  143                  * be the first request in the second request list.
  144                  */
  145                 goto insert;
  146         }
  147         /*
  148          * Request is at/after the current request...
  149          * sort in the first request list.
  150          */
  151         while (bq->b_actf) {
  152                 /*
  153                  * We want to go after the current request if there is an
  154                  * inversion after it (i.e. it is the end of the first
  155                  * request list), or if the next request is a larger cylinder
  156                  * than our request.
  157                  */
  158                 if (bq->b_actf->b_cylinder < bq->b_cylinder ||
  159                     bp->b_cylinder < bq->b_actf->b_cylinder ||
  160                     (bp->b_cylinder == bq->b_actf->b_cylinder &&
  161                     bp->b_blkno < bq->b_actf->b_blkno))
  162                         goto insert;
  163                 bq = bq->b_actf;
  164         }
  165         /*
  166          * Neither a second list nor a larger request... we go at the end of
  167          * the first list, which is the same as the end of the whole schebang.
  168          */
  169 insert: bp->b_actf = bq->b_actf;
  170         bq->b_actf = bp;
  171 }
  172 
  173 /*
  174  * Compute checksum for disk label.
  175  */
  176 u_int
  177 dkcksum(struct disklabel *lp)
  178 {
  179         u_int16_t *start, *end;
  180         u_int16_t sum = 0;
  181 
  182         start = (u_int16_t *)lp;
  183         end = (u_int16_t *)&lp->d_partitions[lp->d_npartitions];
  184         while (start < end)
  185                 sum ^= *start++;
  186         return (sum);
  187 }
  188 
  189 char *
  190 initdisklabel(struct disklabel *lp)
  191 {
  192         int i;
  193 
  194         /* minimal requirements for archetypal disk label */
  195         if (lp->d_secsize < DEV_BSIZE)
  196                 lp->d_secsize = DEV_BSIZE;
  197         if (DL_GETDSIZE(lp) == 0)
  198                 DL_SETDSIZE(lp, MAXDISKSIZE);
  199         if (lp->d_secpercyl == 0)
  200                 return ("invalid geometry");
  201         lp->d_npartitions = RAW_PART + 1;
  202         for (i = 0; i < RAW_PART; i++) {
  203                 DL_SETPSIZE(&lp->d_partitions[i], 0);
  204                 DL_SETPOFFSET(&lp->d_partitions[i], 0);
  205         }
  206         if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) == 0)
  207                 DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
  208         DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
  209         lp->d_version = 1;
  210         lp->d_bbsize = 8192;
  211         lp->d_sbsize = 64*1024;                 /* XXX ? */
  212         return (NULL);
  213 }
  214 
  215 /*
  216  * Check an incoming block to make sure it is a disklabel, convert it to
  217  * a newer version if needed, etc etc.
  218  */
  219 char *
  220 checkdisklabel(void *rlp, struct disklabel *lp)
  221 {
  222         struct disklabel *dlp = rlp;
  223         struct __partitionv0 *v0pp;
  224         struct partition *pp;
  225         daddr64_t disksize;
  226         char *msg = NULL;
  227         int i;
  228 
  229         if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC)
  230                 msg = "no disk label";
  231         else if (dlp->d_npartitions > MAXPARTITIONS)
  232                 msg = "unreasonable partition count";
  233         else if (dkcksum(dlp) != 0)
  234                 msg = "disk label corrupted";
  235 
  236         if (msg) {
  237                 u_int16_t *start, *end, sum = 0;
  238 
  239                 /* If it is byte-swapped, attempt to convert it */
  240                 if (swap32(dlp->d_magic) != DISKMAGIC ||
  241                     swap32(dlp->d_magic2) != DISKMAGIC ||
  242                     swap16(dlp->d_npartitions) > MAXPARTITIONS)
  243                         return (msg);
  244 
  245                 /*
  246                  * Need a byte-swap aware dkcksum varient
  247                  * inlined, because dkcksum uses a sub-field
  248                  */
  249                 start = (u_int16_t *)dlp;
  250                 end = (u_int16_t *)&dlp->d_partitions[
  251                     swap16(dlp->d_npartitions)];
  252                 while (start < end)
  253                         sum ^= *start++;
  254                 if (sum != 0)
  255                         return (msg);
  256 
  257                 dlp->d_magic = swap32(dlp->d_magic);
  258                 dlp->d_type = swap16(dlp->d_type);
  259                 dlp->d_subtype = swap16(dlp->d_subtype);
  260 
  261                 /* d_typename and d_packname are strings */
  262 
  263                 dlp->d_secsize = swap32(dlp->d_secsize);
  264                 dlp->d_nsectors = swap32(dlp->d_nsectors);
  265                 dlp->d_ntracks = swap32(dlp->d_ntracks);
  266                 dlp->d_ncylinders = swap32(dlp->d_ncylinders);
  267                 dlp->d_secpercyl = swap32(dlp->d_secpercyl);
  268                 dlp->d_secperunit = swap32(dlp->d_secperunit);
  269 
  270                 dlp->d_sparespertrack = swap16(dlp->d_sparespertrack);
  271                 dlp->d_sparespercyl = swap16(dlp->d_sparespercyl);
  272 
  273                 dlp->d_acylinders = swap32(dlp->d_acylinders);
  274 
  275                 dlp->d_rpm = swap16(dlp->d_rpm);
  276                 dlp->d_interleave = swap16(dlp->d_interleave);
  277                 dlp->d_trackskew = swap16(dlp->d_trackskew);
  278                 dlp->d_cylskew = swap16(dlp->d_cylskew);
  279                 dlp->d_headswitch = swap32(dlp->d_headswitch);
  280                 dlp->d_trkseek = swap32(dlp->d_trkseek);
  281                 dlp->d_flags = swap32(dlp->d_flags);
  282 
  283                 for (i = 0; i < NDDATA; i++)
  284                         dlp->d_drivedata[i] = swap32(dlp->d_drivedata[i]);
  285 
  286                 dlp->d_secperunith = swap16(dlp->d_secperunith);
  287                 dlp->d_version = swap16(dlp->d_version);
  288 
  289                 for (i = 0; i < NSPARE; i++)
  290                         dlp->d_spare[i] = swap32(dlp->d_spare[i]);
  291 
  292                 dlp->d_magic2 = swap32(dlp->d_magic2);
  293                 dlp->d_checksum = swap16(dlp->d_checksum);
  294 
  295                 dlp->d_npartitions = swap16(dlp->d_npartitions);
  296                 dlp->d_bbsize = swap32(dlp->d_bbsize);
  297                 dlp->d_sbsize = swap32(dlp->d_sbsize);
  298 
  299                 for (i = 0; i < MAXPARTITIONS; i++) {
  300                         pp = &dlp->d_partitions[i];
  301                         pp->p_size = swap32(pp->p_size);
  302                         pp->p_offset = swap32(pp->p_offset);
  303                         if (dlp->d_version == 0) {
  304                                 v0pp = (struct __partitionv0 *)pp;
  305                                 v0pp->p_fsize = swap32(v0pp->p_fsize);
  306                         } else {
  307                                 pp->p_offseth = swap16(pp->p_offseth);
  308                                 pp->p_sizeh = swap16(pp->p_sizeh);
  309                         }
  310                         pp->p_cpg = swap16(pp->p_cpg);
  311                 }
  312 
  313                 dlp->d_checksum = 0;
  314                 dlp->d_checksum = dkcksum(dlp);
  315                 msg = NULL;
  316         }
  317 
  318         /* XXX should verify lots of other fields and whine a lot */
  319 
  320         if (msg)
  321                 return (msg);
  322 
  323         /* Initial passed in lp contains the real disk size. */
  324         disksize = DL_GETDSIZE(lp);
  325 
  326         if (lp != dlp)
  327                 *lp = *dlp;
  328 
  329         if (lp->d_version == 0) {
  330                 lp->d_version = 1;
  331                 lp->d_secperunith = 0;
  332 
  333                 v0pp = (struct __partitionv0 *)lp->d_partitions;
  334                 pp = lp->d_partitions;
  335                 for (i = 0; i < lp->d_npartitions; i++, pp++, v0pp++) {
  336                         pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(v0pp->
  337                             p_fsize, v0pp->p_frag);
  338                         pp->p_offseth = 0;
  339                         pp->p_sizeh = 0;
  340                 }
  341         }
  342 
  343 #ifdef DEBUG
  344         if (DL_GETDSIZE(lp) != disksize)
  345                 printf("on-disk disklabel has incorrect disksize (%lld)\n",
  346                     DL_GETDSIZE(lp));
  347         if (DL_GETPSIZE(&lp->d_partitions[RAW_PART]) != disksize)
  348                 printf("on-disk disklabel RAW_PART has incorrect size (%lld)\n",
  349                     DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
  350         if (DL_GETPOFFSET(&lp->d_partitions[RAW_PART]) != 0)
  351                 printf("on-disk disklabel RAW_PART offset != 0 (%lld)\n",
  352                     DL_GETPOFFSET(&lp->d_partitions[RAW_PART]));
  353 #endif
  354         DL_SETDSIZE(lp, disksize);
  355         DL_SETPSIZE(&lp->d_partitions[RAW_PART], disksize);
  356         DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
  357 
  358         lp->d_checksum = 0;
  359         lp->d_checksum = dkcksum(lp);
  360         return (msg);
  361 }
  362 
  363 /*
  364  * If dos partition table requested, attempt to load it and
  365  * find disklabel inside a DOS partition. Return buffer
  366  * for use in signalling errors if requested.
  367  *
  368  * We would like to check if each MBR has a valid BOOT_MAGIC, but
  369  * we cannot because it doesn't always exist. So.. we assume the
  370  * MBR is valid.
  371  */
  372 char *
  373 readdoslabel(struct buf *bp, void (*strat)(struct buf *),
  374     struct disklabel *lp, int *partoffp, int spoofonly)
  375 {
  376         struct dos_partition dp[NDOSPART], *dp2;
  377         u_int32_t extoff = 0;
  378         daddr64_t part_blkno = DOSBBSECTOR;
  379         int dospartoff = 0, i, ourpart = -1;
  380         int wander = 1, n = 0, loop = 0;
  381         int offset;
  382 
  383         if (lp->d_secpercyl == 0)
  384                 return ("invalid label, d_secpercyl == 0");
  385         if (lp->d_secsize == 0)
  386                 return ("invalid label, d_secsize == 0");
  387 
  388         /* do DOS partitions in the process of getting disklabel? */
  389 
  390         /*
  391          * Read dos partition table, follow extended partitions.
  392          * Map the partitions to disklabel entries i-p
  393          */
  394         while (wander && n < 8 && loop < 8) {
  395                 loop++;
  396                 wander = 0;
  397                 if (part_blkno < extoff)
  398                         part_blkno = extoff;
  399 
  400                 /* read boot record */
  401                 bp->b_blkno = DL_BLKTOSEC(lp, part_blkno) * DL_BLKSPERSEC(lp);
  402                 offset = DL_BLKOFFSET(lp, part_blkno) + DOSPARTOFF;
  403                 bp->b_bcount = lp->d_secsize;
  404                 bp->b_flags = B_BUSY | B_READ | B_RAW;
  405                 (*strat)(bp);
  406                 if (biowait(bp)) {
  407 /*wrong*/               if (partoffp)
  408 /*wrong*/                       *partoffp = -1;
  409                         return ("dos partition I/O error");
  410                 }
  411 
  412                 bcopy(bp->b_data + offset, dp, sizeof(dp));
  413 
  414                 if (ourpart == -1) {
  415                         /* Search for our MBR partition */
  416                         for (dp2=dp, i=0; i < NDOSPART && ourpart == -1;
  417                             i++, dp2++)
  418                                 if (letoh32(dp2->dp_size) &&
  419                                     dp2->dp_typ == DOSPTYP_OPENBSD)
  420                                         ourpart = i;
  421                         if (ourpart == -1)
  422                                 goto donot;
  423                         /*
  424                          * This is our MBR partition. need sector
  425                          * address for SCSI/IDE, cylinder for
  426                          * ESDI/ST506/RLL
  427                          */
  428                         dp2 = &dp[ourpart];
  429                         dospartoff = letoh32(dp2->dp_start) + part_blkno;
  430 
  431                         /* found our OpenBSD partition, finish up */
  432                         if (partoffp)
  433                                 goto notfat;
  434 
  435                         if (lp->d_ntracks == 0)
  436                                 lp->d_ntracks = dp2->dp_ehd + 1;
  437                         if (lp->d_nsectors == 0)
  438                                 lp->d_nsectors = DPSECT(dp2->dp_esect);
  439                         if (lp->d_secpercyl == 0)
  440                                 lp->d_secpercyl = lp->d_ntracks *
  441                                     lp->d_nsectors;
  442                 }
  443 donot:
  444                 /*
  445                  * In case the disklabel read below fails, we want to
  446                  * provide a fake label in i-p.
  447                  */
  448                 for (dp2=dp, i=0; i < NDOSPART && n < 8; i++, dp2++) {
  449                         struct partition *pp = &lp->d_partitions[8+n];
  450                         u_int8_t fstype;
  451 
  452                         if (dp2->dp_typ == DOSPTYP_OPENBSD)
  453                                 continue;
  454                         if (letoh32(dp2->dp_size) > DL_GETDSIZE(lp))
  455                                 continue;
  456                         if (letoh32(dp2->dp_start) > DL_GETDSIZE(lp))
  457                                 continue;
  458                         if (letoh32(dp2->dp_size) == 0)
  459                                 continue;
  460 
  461                         switch (dp2->dp_typ) {
  462                         case DOSPTYP_UNUSED:
  463                                 fstype = FS_UNUSED;
  464                                 n++;
  465                                 break;
  466 
  467                         case DOSPTYP_LINUX:
  468                                 fstype = FS_EXT2FS;
  469                                 n++;
  470                                 break;
  471 
  472                         case DOSPTYP_NTFS:
  473                                 fstype = FS_NTFS;
  474                                 n++;
  475                                 break;
  476 
  477                         case DOSPTYP_FAT12:
  478                         case DOSPTYP_FAT16S:
  479                         case DOSPTYP_FAT16B:
  480                         case DOSPTYP_FAT16L:
  481                         case DOSPTYP_FAT32:
  482                         case DOSPTYP_FAT32L:
  483                                 fstype = FS_MSDOS;
  484                                 n++;
  485                                 break;
  486                         case DOSPTYP_EXTEND:
  487                         case DOSPTYP_EXTENDL:
  488                                 part_blkno = letoh32(dp2->dp_start) + extoff;
  489                                 if (!extoff) {
  490                                         extoff = letoh32(dp2->dp_start);
  491                                         part_blkno = 0;
  492                                 }
  493                                 wander = 1;
  494                                 break;
  495                         default:
  496                                 fstype = FS_OTHER;
  497                                 n++;
  498                                 break;
  499                         }
  500 
  501                         /*
  502                          * Don't set fstype/offset/size when wandering or just
  503                          * looking for the offset of the OpenBSD partition. It
  504                          * would invalidate the disklabel checksum!
  505                          */
  506                         if (wander || partoffp)
  507                                 continue;
  508 
  509                         pp->p_fstype = fstype;
  510                         if (letoh32(dp2->dp_start))
  511                                 DL_SETPOFFSET(pp,
  512                                     letoh32(dp2->dp_start) + part_blkno);
  513                         DL_SETPSIZE(pp, letoh32(dp2->dp_size));
  514                 }
  515         }
  516         if (partoffp)
  517                 /* dospartoff has been set and we must not modify *lp. */
  518                 goto notfat;
  519 
  520         lp->d_npartitions = MAXPARTITIONS;
  521 
  522         if (n == 0 && part_blkno == DOSBBSECTOR) {
  523                 u_int16_t fattest;
  524 
  525                 /* Check for a valid initial jmp instruction. */
  526                 switch ((u_int8_t)bp->b_data[0]) {
  527                 case 0xeb:
  528                         /*
  529                          * Two-byte jmp instruction. The 2nd byte is the number
  530                          * of bytes to jmp and the 3rd byte must be a NOP.
  531                          */
  532                         if ((u_int8_t)bp->b_data[2] != 0x90)
  533                                 goto notfat;
  534                         break;
  535                 case 0xe9:
  536                         /*
  537                          * Three-byte jmp instruction. The next two bytes are a
  538                          * little-endian 16 bit value.
  539                          */
  540                         break;
  541                 default:
  542                         goto notfat;
  543                         break;
  544                 }
  545 
  546                 /* Check for a valid bytes per sector value. */
  547                 fattest = ((bp->b_data[12] << 8) & 0xff00) |
  548                     (bp->b_data[11] & 0xff);
  549                 if (fattest < 512 || fattest > 4096 || (fattest % 512 != 0))
  550                         goto notfat;
  551 
  552                 /* Check the end of sector marker. */
  553                 fattest = ((bp->b_data[510] << 8) & 0xff00) |
  554                     (bp->b_data[511] & 0xff);
  555                 if (fattest != 0x55aa)
  556                         goto notfat;
  557 
  558                 /* Looks like a FAT filesystem. Spoof 'i'. */
  559                 DL_SETPSIZE(&lp->d_partitions['i' - 'a'],
  560                     DL_GETPSIZE(&lp->d_partitions[RAW_PART]));
  561                 DL_SETPOFFSET(&lp->d_partitions['i' - 'a'], 0);
  562                 lp->d_partitions['i' - 'a'].p_fstype = FS_MSDOS;
  563         }
  564 notfat:
  565 
  566         /* record the OpenBSD partition's placement for the caller */
  567         if (partoffp)
  568                 *partoffp = dospartoff;
  569 
  570         /* don't read the on-disk label if we are in spoofed-only mode */
  571         if (spoofonly)
  572                 return (NULL);
  573 
  574         bp->b_blkno = DL_BLKTOSEC(lp, dospartoff + DOS_LABELSECTOR) *
  575             DL_BLKSPERSEC(lp);
  576         offset = DL_BLKOFFSET(lp, dospartoff + DOS_LABELSECTOR);
  577         bp->b_bcount = lp->d_secsize;
  578         bp->b_flags = B_BUSY | B_READ | B_RAW;
  579         (*strat)(bp);
  580         if (biowait(bp))
  581                 return ("disk label I/O error");
  582 
  583         /* sub-MBR disklabels are always at a LABELOFFSET of 0 */
  584         return checkdisklabel(bp->b_data + offset, lp);
  585 }
  586 
  587 /*
  588  * Check new disk label for sensibility
  589  * before setting it.
  590  */
  591 int
  592 setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_int openmask)
  593 {
  594         int i;
  595         struct partition *opp, *npp;
  596 
  597         /* sanity clause */
  598         if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0 ||
  599             (nlp->d_secsize % DEV_BSIZE) != 0)
  600                 return (EINVAL);
  601 
  602         /* special case to allow disklabel to be invalidated */
  603         if (nlp->d_magic == 0xffffffff) {
  604                 *olp = *nlp;
  605                 return (0);
  606         }
  607 
  608         if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
  609             dkcksum(nlp) != 0)
  610                 return (EINVAL);
  611 
  612         /* XXX missing check if other dos partitions will be overwritten */
  613 
  614         while (openmask != 0) {
  615                 i = ffs(openmask) - 1;
  616                 openmask &= ~(1 << i);
  617                 if (nlp->d_npartitions <= i)
  618                         return (EBUSY);
  619                 opp = &olp->d_partitions[i];
  620                 npp = &nlp->d_partitions[i];
  621                 if (DL_GETPOFFSET(npp) != DL_GETPOFFSET(opp) ||
  622                     DL_GETPSIZE(npp) < DL_GETPSIZE(opp))
  623                         return (EBUSY);
  624                 /*
  625                  * Copy internally-set partition information
  626                  * if new label doesn't include it.             XXX
  627                  */
  628                 if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
  629                         npp->p_fstype = opp->p_fstype;
  630                         npp->p_fragblock = opp->p_fragblock;
  631                         npp->p_cpg = opp->p_cpg;
  632                 }
  633         }
  634         nlp->d_checksum = 0;
  635         nlp->d_checksum = dkcksum(nlp);
  636         *olp = *nlp;
  637         return (0);
  638 }
  639 
  640 /*
  641  * Determine the size of the transfer, and make sure it is within the
  642  * boundaries of the partition. Adjust transfer if needed, and signal errors or
  643  * early completion.
  644  */
  645 int
  646 bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
  647 {
  648         struct partition *p = &lp->d_partitions[DISKPART(bp->b_dev)];
  649         daddr64_t sz = howmany(bp->b_bcount, DEV_BSIZE);
  650 
  651         /* avoid division by zero */
  652         if (lp->d_secpercyl == 0)
  653                 goto bad;
  654 
  655         if (bp->b_blkno < 0 || sz < 0)
  656                 panic("bounds_check_with_label %lld %lld\n", bp->b_blkno, sz);
  657 
  658         /* beyond partition? */
  659         if (bp->b_blkno + sz > DL_SECTOBLK(lp, DL_GETPSIZE(p))) {
  660                 sz = DL_SECTOBLK(lp, DL_GETPSIZE(p)) - bp->b_blkno;
  661                 if (sz == 0) {
  662                         /* If exactly at end of disk, return EOF. */
  663                         bp->b_resid = bp->b_bcount;
  664                         return (-1);
  665                 }
  666                 if (sz < 0)
  667                         /* If past end of disk, return EINVAL. */
  668                         goto bad;
  669 
  670                 /* Otherwise, truncate request. */
  671                 bp->b_bcount = sz << DEV_BSHIFT;
  672         }
  673 
  674         /* calculate cylinder for disksort to order transfers with */
  675         bp->b_cylinder = (bp->b_blkno + DL_SECTOBLK(lp, DL_GETPOFFSET(p))) /
  676             DL_SECTOBLK(lp, lp->d_secpercyl);
  677         return (1);
  678 
  679 bad:
  680         bp->b_error = EINVAL;
  681         bp->b_flags |= B_ERROR;
  682         return (-1);
  683 }
  684 
  685 /*
  686  * Disk error is the preface to plaintive error messages
  687  * about failing disk transfers.  It prints messages of the form
  688 
  689 hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d)
  690 
  691  * if the offset of the error in the transfer and a disk label
  692  * are both available.  blkdone should be -1 if the position of the error
  693  * is unknown; the disklabel pointer may be null from drivers that have not
  694  * been converted to use them.  The message is printed with printf
  695  * if pri is LOG_PRINTF, otherwise it uses log at the specified priority.
  696  * The message should be completed (with at least a newline) with printf
  697  * or addlog, respectively.  There is no trailing space.
  698  */
  699 void
  700 diskerr(struct buf *bp, char *dname, char *what, int pri, int blkdone,
  701     struct disklabel *lp)
  702 {
  703         int unit = DISKUNIT(bp->b_dev), part = DISKPART(bp->b_dev);
  704         int (*pr)(const char *, ...);
  705         char partname = 'a' + part;
  706         daddr64_t sn;
  707 
  708         if (pri != LOG_PRINTF) {
  709                 static const char fmt[] = "";
  710                 log(pri, fmt);
  711                 pr = addlog;
  712         } else
  713                 pr = printf;
  714         (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what,
  715             bp->b_flags & B_READ ? "read" : "writ");
  716         sn = bp->b_blkno;
  717         if (bp->b_bcount <= DEV_BSIZE)
  718                 (*pr)("%lld", sn);
  719         else {
  720                 if (blkdone >= 0) {
  721                         sn += blkdone;
  722                         (*pr)("%lld of ", sn);
  723                 }
  724                 (*pr)("%lld-%lld", bp->b_blkno,
  725                     bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE);
  726         }
  727         if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
  728                 sn += DL_GETPOFFSET(&lp->d_partitions[part]);
  729                 (*pr)(" (%s%d bn %lld; cn %lld", dname, unit, sn,
  730                     sn / lp->d_secpercyl);
  731                 sn %= lp->d_secpercyl;
  732                 (*pr)(" tn %lld sn %lld)", sn / lp->d_nsectors,
  733                     sn % lp->d_nsectors);
  734         }
  735 }
  736 
  737 /*
  738  * Initialize the disklist.  Called by main() before autoconfiguration.
  739  */
  740 void
  741 disk_init(void)
  742 {
  743 
  744         TAILQ_INIT(&disklist);
  745         disk_count = disk_change = 0;
  746 }
  747 
  748 int
  749 disk_construct(struct disk *diskp, char *lockname)
  750 {
  751         rw_init(&diskp->dk_lock, lockname);
  752         mtx_init(&diskp->dk_mtx, IPL_BIO);
  753         
  754         diskp->dk_flags |= DKF_CONSTRUCTED;
  755             
  756         return (0);
  757 }
  758 
  759 /*
  760  * Attach a disk.
  761  */
  762 void
  763 disk_attach(struct disk *diskp)
  764 {
  765 
  766         if (!ISSET(diskp->dk_flags, DKF_CONSTRUCTED))
  767                 disk_construct(diskp, diskp->dk_name);
  768 
  769         /*
  770          * Allocate and initialize the disklabel structures.  Note that
  771          * it's not safe to sleep here, since we're probably going to be
  772          * called during autoconfiguration.
  773          */
  774         diskp->dk_label = malloc(sizeof(struct disklabel), M_DEVBUF,
  775             M_NOWAIT|M_ZERO);
  776         if (diskp->dk_label == NULL)
  777                 panic("disk_attach: can't allocate storage for disklabel");
  778 
  779         /*
  780          * Set the attached timestamp.
  781          */
  782         microuptime(&diskp->dk_attachtime);
  783 
  784         /*
  785          * Link into the disklist.
  786          */
  787         TAILQ_INSERT_TAIL(&disklist, diskp, dk_link);
  788         ++disk_count;
  789         disk_change = 1;
  790 }
  791 
  792 /*
  793  * Detach a disk.
  794  */
  795 void
  796 disk_detach(struct disk *diskp)
  797 {
  798 
  799         /*
  800          * Free the space used by the disklabel structures.
  801          */
  802         free(diskp->dk_label, M_DEVBUF);
  803 
  804         /*
  805          * Remove from the disklist.
  806          */
  807         TAILQ_REMOVE(&disklist, diskp, dk_link);
  808         disk_change = 1;
  809         if (--disk_count < 0)
  810                 panic("disk_detach: disk_count < 0");
  811 }
  812 
  813 /*
  814  * Increment a disk's busy counter.  If the counter is going from
  815  * 0 to 1, set the timestamp.
  816  */
  817 void
  818 disk_busy(struct disk *diskp)
  819 {
  820 
  821         /*
  822          * XXX We'd like to use something as accurate as microtime(),
  823          * but that doesn't depend on the system TOD clock.
  824          */
  825         mtx_enter(&diskp->dk_mtx);
  826         if (diskp->dk_busy++ == 0)
  827                 microuptime(&diskp->dk_timestamp);
  828         mtx_leave(&diskp->dk_mtx);
  829 }
  830 
  831 /*
  832  * Decrement a disk's busy counter, increment the byte count, total busy
  833  * time, and reset the timestamp.
  834  */
  835 void
  836 disk_unbusy(struct disk *diskp, long bcount, int read)
  837 {
  838         struct timeval dv_time, diff_time;
  839 
  840         mtx_enter(&diskp->dk_mtx);
  841 
  842         if (diskp->dk_busy-- == 0)
  843                 printf("disk_unbusy: %s: dk_busy < 0\n", diskp->dk_name);
  844 
  845         microuptime(&dv_time);
  846 
  847         timersub(&dv_time, &diskp->dk_timestamp, &diff_time);
  848         timeradd(&diskp->dk_time, &diff_time, &diskp->dk_time);
  849 
  850         diskp->dk_timestamp = dv_time;
  851         if (bcount > 0) {
  852                 if (read) {
  853                         diskp->dk_rbytes += bcount;
  854                         diskp->dk_rxfer++;
  855                 } else {
  856                         diskp->dk_wbytes += bcount;
  857                         diskp->dk_wxfer++;
  858                 }
  859         } else
  860                 diskp->dk_seek++;
  861 
  862         mtx_leave(&diskp->dk_mtx);
  863 
  864         add_disk_randomness(bcount ^ diff_time.tv_usec);
  865 }
  866 
  867 int
  868 disk_lock(struct disk *dk)
  869 {
  870         int error;
  871 
  872         error = rw_enter(&dk->dk_lock, RW_WRITE|RW_INTR);
  873 
  874         return (error);
  875 }
  876 
  877 void
  878 disk_unlock(struct disk *dk)
  879 {
  880         rw_exit(&dk->dk_lock);
  881 }
  882 
  883 int
  884 dk_mountroot(void)
  885 {
  886         dev_t rawdev, rrootdev;
  887         int part = DISKPART(rootdev);
  888         int (*mountrootfn)(void);
  889         struct disklabel dl;
  890         int error;
  891 
  892         rrootdev = blktochr(rootdev);
  893         rawdev = MAKEDISKDEV(major(rrootdev), DISKUNIT(rootdev), RAW_PART);
  894 #ifdef DEBUG
  895         printf("rootdev=0x%x rrootdev=0x%x rawdev=0x%x\n", rootdev,
  896             rrootdev, rawdev);
  897 #endif
  898 
  899         /*
  900          * open device, ioctl for the disklabel, and close it.
  901          */
  902         error = (cdevsw[major(rrootdev)].d_open)(rawdev, FREAD,
  903             S_IFCHR, curproc);
  904         if (error)
  905                 panic("cannot open disk, 0x%x/0x%x, error %d",
  906                     rootdev, rrootdev, error);
  907         error = (cdevsw[major(rrootdev)].d_ioctl)(rawdev, DIOCGDINFO,
  908             (caddr_t)&dl, FREAD, curproc);
  909         if (error)
  910                 panic("cannot read disk label, 0x%x/0x%x, error %d",
  911                     rootdev, rrootdev, error);
  912         (void) (cdevsw[major(rrootdev)].d_close)(rawdev, FREAD,
  913             S_IFCHR, curproc);
  914 
  915         if (DL_GETPSIZE(&dl.d_partitions[part]) == 0)
  916                 panic("root filesystem has size 0");
  917         switch (dl.d_partitions[part].p_fstype) {
  918 #ifdef EXT2FS
  919         case FS_EXT2FS:
  920                 {
  921                 extern int ext2fs_mountroot(void);
  922                 mountrootfn = ext2fs_mountroot;
  923                 }
  924                 break;
  925 #endif
  926 #ifdef FFS
  927         case FS_BSDFFS:
  928                 {
  929                 extern int ffs_mountroot(void);
  930                 mountrootfn = ffs_mountroot;
  931                 }
  932                 break;
  933 #endif
  934 #ifdef CD9660
  935         case FS_ISO9660:
  936                 {
  937                 extern int cd9660_mountroot(void);
  938                 mountrootfn = cd9660_mountroot;
  939                 }
  940                 break;
  941 #endif
  942         default:
  943 #ifdef FFS
  944                 { 
  945                 extern int ffs_mountroot(void);
  946 
  947                 printf("filesystem type %d not known.. assuming ffs\n",
  948                     dl.d_partitions[part].p_fstype);
  949                 mountrootfn = ffs_mountroot;
  950                 }
  951 #else
  952                 panic("disk 0x%x/0x%x filesystem type %d not known", 
  953                     rootdev, rrootdev, dl.d_partitions[part].p_fstype);
  954 #endif
  955         }
  956         return (*mountrootfn)();
  957 }
  958 
  959 struct bufq *
  960 bufq_default_alloc(void)
  961 {
  962         struct bufq_default *bq;
  963 
  964         bq = malloc(sizeof(*bq), M_DEVBUF, M_NOWAIT|M_ZERO);
  965         if (bq == NULL)
  966                 panic("bufq_default_alloc: no memory");
  967 
  968         bq->bufq.bufq_free = bufq_default_free;
  969         bq->bufq.bufq_add = bufq_default_add;
  970         bq->bufq.bufq_get = bufq_default_get;
  971 
  972         return ((struct bufq *)bq);
  973 }
  974 
  975 void
  976 bufq_default_free(struct bufq *bq)
  977 {
  978         free(bq, M_DEVBUF);
  979 }
  980 
  981 void
  982 bufq_default_add(struct bufq *bq, struct buf *bp)
  983 {
  984         struct bufq_default *bufq = (struct bufq_default *)bq;
  985         struct proc *p = bp->b_proc;
  986         struct buf *head;
  987 
  988         if (p == NULL || p->p_nice < NZERO)
  989                 head = &bufq->bufq_head[0];
  990         else if (p->p_nice == NZERO)
  991                 head = &bufq->bufq_head[1];
  992         else
  993                 head = &bufq->bufq_head[2];
  994 
  995         disksort(head, bp);
  996 }
  997 
  998 struct buf *
  999 bufq_default_get(struct bufq *bq)
 1000 {
 1001         struct bufq_default *bufq = (struct bufq_default *)bq;
 1002         struct buf *bp, *head;
 1003         int i;
 1004 
 1005         for (i = 0; i < 3; i++) {
 1006                 head = &bufq->bufq_head[i];
 1007                 if ((bp = head->b_actf))
 1008                         break;
 1009         }
 1010         if (bp == NULL)
 1011                 return (NULL);
 1012         head->b_actf = bp->b_actf;
 1013         return (bp);
 1014 }
 1015 
 1016 struct device *
 1017 getdisk(char *str, int len, int defpart, dev_t *devp)
 1018 {
 1019         struct device *dv;
 1020 
 1021         if ((dv = parsedisk(str, len, defpart, devp)) == NULL) {
 1022                 printf("use one of: exit");
 1023                 TAILQ_FOREACH(dv, &alldevs, dv_list) {
 1024                         if (dv->dv_class == DV_DISK)
 1025                                 printf(" %s[a-p]", dv->dv_xname);
 1026 #if defined(NFSCLIENT)
 1027                         if (dv->dv_class == DV_IFNET)
 1028                                 printf(" %s", dv->dv_xname);
 1029 #endif
 1030                 }
 1031                 printf("\n");
 1032         }
 1033         return (dv);
 1034 }
 1035 
 1036 struct device *
 1037 parsedisk(char *str, int len, int defpart, dev_t *devp)
 1038 {
 1039         struct device *dv;
 1040         int majdev, part = defpart;
 1041         char c;
 1042 
 1043         if (len == 0)
 1044                 return (NULL);
 1045         c = str[len-1];
 1046         if (c >= 'a' && (c - 'a') < MAXPARTITIONS) {
 1047                 part = c - 'a';
 1048                 len -= 1;
 1049         }
 1050 
 1051         TAILQ_FOREACH(dv, &alldevs, dv_list) {
 1052                 if (dv->dv_class == DV_DISK &&
 1053                     strncmp(str, dv->dv_xname, len) == 0 &&
 1054                     dv->dv_xname[len] == '\0') {
 1055                         majdev = findblkmajor(dv);
 1056                         if (majdev < 0)
 1057                                 panic("parsedisk");
 1058                         *devp = MAKEDISKDEV(majdev, dv->dv_unit, part);
 1059                         break;
 1060                 }
 1061 #if defined(NFSCLIENT)
 1062                 if (dv->dv_class == DV_IFNET &&
 1063                     strncmp(str, dv->dv_xname, len) == 0 &&
 1064                     dv->dv_xname[len] == '\0') {
 1065                         *devp = NODEV;
 1066                         break;
 1067                 }
 1068 #endif
 1069         }
 1070 
 1071         return (dv);
 1072 }
 1073 
 1074 void
 1075 setroot(struct device *bootdv, int part, int exitflags)
 1076 {
 1077         int majdev, unit, len, s;
 1078         struct swdevt *swp;
 1079         struct device *rootdv, *dv;
 1080         dev_t nrootdev, nswapdev = NODEV, temp = NODEV;
 1081         struct ifnet *ifp = NULL;
 1082         char buf[128];
 1083 #if defined(NFSCLIENT)
 1084         extern char *nfsbootdevname;
 1085 #endif
 1086 
 1087         /*
 1088          * If `swap generic' and we couldn't determine boot device,
 1089          * ask the user.
 1090          */
 1091         if (mountroot == NULL && bootdv == NULL)
 1092                 boothowto |= RB_ASKNAME;
 1093         if (boothowto & RB_ASKNAME) {
 1094                 while (1) {
 1095                         printf("root device");
 1096                         if (bootdv != NULL) {
 1097                                 printf(" (default %s", bootdv->dv_xname);
 1098                                 if (bootdv->dv_class == DV_DISK)
 1099                                         printf("%c", 'a' + part);
 1100                                 printf(")");
 1101                         }
 1102                         printf(": ");
 1103                         s = splhigh();
 1104                         cnpollc(TRUE);
 1105                         len = getsn(buf, sizeof(buf));
 1106                         cnpollc(FALSE);
 1107                         splx(s);
 1108                         if (strcmp(buf, "exit") == 0)
 1109                                 boot(exitflags);
 1110                         if (len == 0 && bootdv != NULL) {
 1111                                 strlcpy(buf, bootdv->dv_xname, sizeof buf);
 1112                                 len = strlen(buf);
 1113                         }
 1114                         if (len > 0 && buf[len - 1] == '*') {
 1115                                 buf[--len] = '\0';
 1116                                 dv = getdisk(buf, len, part, &nrootdev);
 1117                                 if (dv != NULL) {
 1118                                         rootdv = dv;
 1119                                         nswapdev = nrootdev;
 1120                                         goto gotswap;
 1121                                 }
 1122                         }
 1123                         dv = getdisk(buf, len, part, &nrootdev);
 1124                         if (dv != NULL) {
 1125                                 rootdv = dv;
 1126                                 break;
 1127                         }
 1128                 }
 1129 
 1130                 if (rootdv->dv_class == DV_IFNET)
 1131                         goto gotswap;
 1132 
 1133                 /* try to build swap device out of new root device */
 1134                 while (1) {
 1135                         printf("swap device");
 1136                         if (rootdv != NULL)
 1137                                 printf(" (default %s%s)", rootdv->dv_xname,
 1138                                     rootdv->dv_class == DV_DISK ? "b" : "");
 1139                         printf(": ");
 1140                         s = splhigh();
 1141                         cnpollc(TRUE);
 1142                         len = getsn(buf, sizeof(buf));
 1143                         cnpollc(FALSE);
 1144                         splx(s);
 1145                         if (strcmp(buf, "exit") == 0)
 1146                                 boot(exitflags);
 1147                         if (len == 0 && rootdv != NULL) {
 1148                                 switch (rootdv->dv_class) {
 1149                                 case DV_IFNET:
 1150                                         nswapdev = NODEV;
 1151                                         break;
 1152                                 case DV_DISK:
 1153                                         nswapdev = MAKEDISKDEV(major(nrootdev),
 1154                                             DISKUNIT(nrootdev), 1);
 1155                                         if (nswapdev == nrootdev)
 1156                                                 continue;
 1157                                         break;
 1158                                 default:
 1159                                         break;
 1160                                 }
 1161                                 break;
 1162                         }
 1163                         dv = getdisk(buf, len, 1, &nswapdev);
 1164                         if (dv) {
 1165                                 if (dv->dv_class == DV_IFNET)
 1166                                         nswapdev = NODEV;
 1167                                 if (nswapdev == nrootdev)
 1168                                         continue;
 1169                                 break;
 1170                         }
 1171                 }
 1172 gotswap:
 1173                 rootdev = nrootdev;
 1174                 dumpdev = nswapdev;
 1175                 swdevt[0].sw_dev = nswapdev;
 1176                 swdevt[1].sw_dev = NODEV;
 1177 #if defined(NFSCLIENT)
 1178         } else if (mountroot == nfs_mountroot) {
 1179                 rootdv = bootdv;
 1180                 rootdev = dumpdev = swapdev = NODEV;
 1181 #endif
 1182         } else if (mountroot == NULL && rootdev == NODEV) {
 1183                 /*
 1184                  * `swap generic'
 1185                  */
 1186                 rootdv = bootdv;
 1187                 majdev = findblkmajor(rootdv);
 1188                 if (majdev >= 0) {
 1189                         /*
 1190                          * Root and swap are on the disk.
 1191                          * Assume swap is on partition b.
 1192                          */
 1193                         rootdev = MAKEDISKDEV(majdev, rootdv->dv_unit, part);
 1194                         nswapdev = MAKEDISKDEV(majdev, rootdv->dv_unit, 1);
 1195                 } else {
 1196                         /*
 1197                          * Root and swap are on a net.
 1198                          */
 1199                         nswapdev = NODEV;
 1200                 }
 1201                 dumpdev = nswapdev;
 1202                 swdevt[0].sw_dev = nswapdev;
 1203                 /* swdevt[1].sw_dev = NODEV; */
 1204         } else {
 1205                 /* Completely pre-configured, but we want rootdv .. */
 1206                 majdev = major(rootdev);
 1207                 if (findblkname(majdev) == NULL)
 1208                         return;
 1209                 unit = DISKUNIT(rootdev);
 1210                 part = DISKPART(rootdev);
 1211                 snprintf(buf, sizeof buf, "%s%d%c",
 1212                     findblkname(majdev), unit, 'a' + part);
 1213                 rootdv = parsedisk(buf, strlen(buf), 0, &nrootdev);
 1214                 if (rootdv == NULL)
 1215                         panic("root device (%s) not found", buf);
 1216         }
 1217 
 1218         if (rootdv && rootdv == bootdv && rootdv->dv_class == DV_IFNET)
 1219                 ifp = ifunit(rootdv->dv_xname);
 1220         else if (bootdv && bootdv->dv_class == DV_IFNET)
 1221                 ifp = ifunit(bootdv->dv_xname);
 1222 
 1223         if (ifp)
 1224                 if_addgroup(ifp, "netboot");
 1225 
 1226         switch (rootdv->dv_class) {
 1227 #if defined(NFSCLIENT)
 1228         case DV_IFNET:
 1229                 mountroot = nfs_mountroot;
 1230                 nfsbootdevname = rootdv->dv_xname;
 1231                 return;
 1232 #endif
 1233         case DV_DISK:
 1234                 mountroot = dk_mountroot;
 1235                 part = DISKPART(rootdev);
 1236                 break;
 1237         default:
 1238                 printf("can't figure root, hope your kernel is right\n");
 1239                 return;
 1240         }
 1241 
 1242         printf("root on %s%c", rootdv->dv_xname, 'a' + part);
 1243 
 1244         /*
 1245          * Make the swap partition on the root drive the primary swap.
 1246          */
 1247         for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
 1248                 if (major(rootdev) == major(swp->sw_dev) &&
 1249                     DISKUNIT(rootdev) == DISKUNIT(swp->sw_dev)) {
 1250                         temp = swdevt[0].sw_dev;
 1251                         swdevt[0].sw_dev = swp->sw_dev;
 1252                         swp->sw_dev = temp;
 1253                         break;
 1254                 }
 1255         }
 1256         if (swp->sw_dev != NODEV) {
 1257                 /*
 1258                  * If dumpdev was the same as the old primary swap device,
 1259                  * move it to the new primary swap device.
 1260                  */
 1261                 if (temp == dumpdev)
 1262                         dumpdev = swdevt[0].sw_dev;
 1263         }
 1264         if (swdevt[0].sw_dev != NODEV)
 1265                 printf(" swap on %s%d%c", findblkname(major(swdevt[0].sw_dev)),
 1266                     DISKUNIT(swdevt[0].sw_dev),
 1267                     'a' + DISKPART(swdevt[0].sw_dev));
 1268         if (dumpdev != NODEV)
 1269                 printf(" dump on %s%d%c", findblkname(major(dumpdev)),
 1270                     DISKUNIT(dumpdev), 'a' + DISKPART(dumpdev));
 1271         printf("\n");
 1272 }
 1273 
 1274 extern struct nam2blk nam2blk[];
 1275 
 1276 int
 1277 findblkmajor(struct device *dv)
 1278 {
 1279         char buf[16], *p;
 1280         int i;
 1281 
 1282         if (strlcpy(buf, dv->dv_xname, sizeof buf) >= sizeof buf)
 1283                 return (-1);
 1284         for (p = buf; *p; p++)
 1285                 if (*p >= '' && *p <= '9')
 1286                         *p = '\0';
 1287 
 1288         for (i = 0; nam2blk[i].name; i++)
 1289                 if (!strcmp(buf, nam2blk[i].name))
 1290                         return (nam2blk[i].maj);
 1291         return (-1);
 1292 }
 1293 
 1294 char *
 1295 findblkname(int maj)
 1296 {
 1297         int i;
 1298 
 1299         for (i = 0; nam2blk[i].name; i++)
 1300                 if (nam2blk[i].maj == maj)
 1301                         return (nam2blk[i].name);
 1302         return (NULL);
 1303 }

Cache object: ddf9b224d8c18483460ef91f64dd4e7a


[ 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.