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/i386/pc_hd_label.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 /* 
    2  * Mach Operating System
    3  * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University
    4  * All Rights Reserved.
    5  * 
    6  * Permission to use, copy, modify and distribute this software and its
    7  * documentation is hereby granted, provided that both the copyright
    8  * notice and this permission notice appear in all copies of the
    9  * software, derivative works or modified versions, and any portions
   10  * thereof, and that both notices appear in supporting documentation.
   11  * 
   12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   15  * 
   16  * Carnegie Mellon requests users of this software to return to
   17  * 
   18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   19  *  School of Computer Science
   20  *  Carnegie Mellon University
   21  *  Pittsburgh PA 15213-3890
   22  * 
   23  * any improvements or extensions that they make and grant Carnegie Mellon
   24  * the rights to redistribute these changes.
   25  */
   26 /*
   27  * HISTORY
   28  * $Log:        pc_hd_label.c,v $
   29  * Revision 2.2  93/08/10  15:56:36  mrt
   30  *      Created by Robert Baron from hc.c
   31  * 
   32  */
   33 
   34 #include <hd.h>
   35 
   36 #include <sys/types.h>
   37 #define PRIBIO 20
   38 #include <device/buf.h>
   39 #include <device/errno.h>
   40 #include <device/device_types.h>
   41 #include <device/disk_status.h>
   42 #include <sys/ioctl.h>
   43 #include <i386/pio.h>
   44 #include <i386/ipl.h>
   45 #include <i386at/disk.h>
   46 #include <chips/busses.h>
   47 #include <i386at/hdreg.h>
   48 
   49 /* From sys/systm.h */
   50 struct buf *geteblk();
   51 
   52 extern int hdgotvtoc[NHD];
   53 extern struct alt_info alt_info[NHD];
   54 extern struct disklabel label[NHD];
   55 extern int         labeloffset[NHD];
   56 extern int         labelsector[NHD];
   57 
   58 extern int label_flag;
   59 extern int allow_bsd_label;
   60 
   61 #define LABEL_DEBUG(x,y) if (label_flag&x) y
   62 unsigned dkcksum();
   63 
   64 
   65 hdreadlabel(unit, badblocks)
   66 unsigned char unit;
   67 {
   68         struct disklabel        *lp = &label[unit];
   69         struct evtoc            *evp;
   70         struct buf              *bp;
   71         struct ipart            part[FD_NUMPART];
   72         struct ipart            *bpart,
   73                                 *ospart = (struct ipart *)0;
   74         u_int                   i, n;
   75 
   76         if (hdgotvtoc[unit]) {
   77                 if (hdgotvtoc[unit] == -1)
   78                         sleep(&hdgotvtoc[unit],PRIBIO);
   79                 return;
   80         }
   81         setcontroller(unit);            /* start sane */
   82         hdgotvtoc[unit] = -1;
   83         bp = geteblk(SECSIZE);          /* for evtoc */
   84         /* make partition 0 the whole disk in case of failure then get pdinfo*/
   85         lp->d_partitions[PART_DISK].p_offset = 0;
   86         lp->d_partitions[PART_DISK].p_size = lp->d_secperunit;
   87         /* get active partition */
   88         bp->b_flags = B_READ | B_MD1;
   89         bp->b_blkno = 0;
   90         bp->b_dev = WHOLE_DISK(unit);   /* C partition */
   91         bp->b_bcount = SECSIZE;
   92         hdstrategy(bp);
   93         biowait(bp);
   94         if (bp->b_flags & B_ERROR) {
   95                 printf("hd%d: can't read sector 0 boot record\n",unit);
   96                 goto done;
   97         }
   98         if (((struct mboot *)bp->b_un.b_addr)->signature != 0xaa55) {
   99                 printf("hd%d: sector 0 corrupt, can't read boot record\n",unit);
  100                 goto done;
  101         }
  102         bcopy(((struct mboot *)bp->b_un.b_addr)->parts,
  103               part, FD_NUMPART * sizeof (struct ipart));
  104         /*
  105          * In search of the bios partition
  106          */
  107         bpart = part;
  108 #ifdef  old
  109         {
  110                 int nmach = 0;
  111                 struct ipart            *mabr = (struct ipart *) 0,
  112                                         *mbr = (struct ipart *) 0;
  113                 for (i = 0; i < 4; i++, bpart++) {
  114                         if (bpart->sys_ind == UNIXOS) {
  115                                 if (!nmach++)
  116                                         mabr = bpart;
  117                                 if (bpart->boot_ind == ACTIVE)
  118                                         mbr = bpart;
  119                         }
  120                 }
  121                 if ((int)mabr)
  122                         bpart = mabr;
  123                 else if (nmach == 1)
  124                         bpart = mbr;
  125                 else if (!nmach)
  126                         bpart = &mempty;
  127                 else {
  128                         printf("More than one mach partition and none active.\n");
  129                         printf("Try to fix this from floppies or DOS.\n");
  130                         for (;;);
  131                 }
  132         }
  133 #else   /* old */
  134         for (i = 0; i < 4; i++, bpart++) {
  135                 LABEL_DEBUG(1,print_dos_partition(i, bpart));
  136                 if (bpart->systid == UNIXOS || bpart->systid == BSDOS) {
  137                         if ((int)ospart) {
  138                                 if (bpart->bootid == ACTIVE)
  139                                         ospart = bpart;
  140                         } else
  141                                 ospart = bpart;
  142                 }
  143 
  144         }
  145         if (!ospart)
  146                 goto done;
  147 #endif  /* old */
  148         OS = ospart->systid;
  149         if (OS == UNIXOS)
  150                 printf("hd%d: MACH OS ", unit);
  151         if (OS == BSDOS)
  152                 printf("hd%d: XXXBSD OS ", unit);
  153         /* set correct partition information */
  154         lp->d_partitions[PART_DISK].p_offset = ospart->relsect;
  155         lp->d_partitions[PART_DISK].p_size = ospart->numsect;
  156         if (hd_bios_bsd_label(unit, bp, lp, ospart))
  157                 goto done;
  158         /* get evtoc out of active unix partition */
  159         bp->b_flags = B_READ;
  160         bp->b_blkno = PDLOCATION;
  161         hdstrategy(bp);
  162         biowait(bp);
  163         if (bp->b_flags & B_ERROR) {
  164                 printf("hd%d: can't read evtoc\n", unit);
  165                 goto done;
  166         }
  167         if ((evp = (struct evtoc *)bp->b_un.b_addr)->sanity != VTOC_SANE) {
  168                 printf("hd%d: evtoc corrupt\n",unit);
  169                 goto done;
  170         }
  171         printf("LOCAL LABEL\n");
  172         LABEL_DEBUG(0x40,print_local_label(evp, "ev:"));
  173 
  174         /* pd info from disk must be more accurate than that in cmos thus
  175            override hdparm and re- setcontroller() */
  176         n = evp->nparts;
  177         if (n >= MAXPARTITIONS)
  178                 n = MAXPARTITIONS;
  179         fudge_bsd_label(lp, DTYPE_ESDI, evp->cyls, evp->tracks, evp->sectors, n);
  180         setcontroller(unit);
  181 
  182         /* copy info on all valid partition, zero the others */
  183         for (i = 0; i < n; i++) {
  184                 if (i == PART_DISK)
  185                         continue;
  186                 bzero(&(lp->d_partitions[i]), sizeof (struct partition));
  187                 lp->d_partitions[i].p_size   = evp->part[i].p_size;
  188                 lp->d_partitions[i].p_offset = evp->part[i].p_start;
  189                 lp->d_partitions[i].p_fstype = FS_BSDFFS;
  190         }
  191         for ( ; i < MAXPARTITIONS; i++) {
  192                 if (i == PART_DISK)
  193                         continue;
  194                 bzero(&(lp->d_partitions[i]), sizeof (struct partition));
  195         }
  196         if (badblocks) {
  197                 /* get alternate sectors out of active unix partition */
  198                 bp->b_blkno = evp->alt_ptr/SECSIZE;
  199                 for (i = 0; i < 4; i++) {
  200                         bp->b_flags = B_READ;
  201                         hdstrategy(bp);
  202                         biowait(bp);
  203                         if (bp->b_flags & B_ERROR) {
  204                                 printf("hd%d: can't read alternate sectors\n", unit);
  205                                 goto done;
  206                         }
  207                         bcopy(bp->b_un.b_addr,(char *)&alt_info[unit]+i*SECSIZE,
  208                               SECSIZE);
  209                         bp->b_blkno++;
  210                 }
  211                 if (alt_info[unit].alt_sanity != ALT_SANITY)
  212                         printf("hd%d: alternate sectors corrupt\n", unit);
  213         }
  214         /*
  215          * Just in case
  216          */
  217         labeloffset[unit] = 0;
  218         labelsector[unit] = (ospart->relsect + LBLLOC);
  219         lp->d_checksum = dkcksum(lp);
  220         LABEL_DEBUG(2,print_bsd_label(lp, "   "));
  221 
  222 done:
  223         brelse(bp);
  224         hdgotvtoc[unit]=1;
  225         wakeup(&hdgotvtoc[unit]);
  226 }
  227 
  228 hd_bios_bsd_label(unit, bp, label, ospart)
  229         int                     unit;
  230         struct buf               *bp;
  231         struct disklabel        *label;
  232         struct ipart            *ospart;
  233 {
  234         struct disklabel        *dlp;
  235         int                     i;
  236 
  237         bp->b_flags = B_READ;
  238         bp->b_blkno = LBLLOC;
  239         hdstrategy(bp);
  240         biowait(bp);
  241         if (bp->b_flags & B_ERROR) {
  242                 printf("hd%d: can't read bsd label\n", unit);
  243                 return FALSE;
  244         }
  245         dlp = (struct disklabel *) bp->b_un.b_addr;
  246         if (dlp->d_magic  != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
  247                 if (ospart->systid == BSDOS) {
  248                         printf("NO BSD LABEL!!\n");
  249                 }
  250                 return FALSE;
  251         }
  252         printf("BSD LABEL\n");
  253         LABEL_DEBUG(2,print_bsd_label(dlp, "dk:"));
  254         if (dlp->d_flags & D_BADSECT) {
  255                 printf("hd%d: DISK NEEDS BAD144 SUPPORT.  WILL TRY FOR LOCAL LABEL.\n",
  256                         unit);
  257                 return FALSE;
  258         }
  259 
  260         /*
  261          * here's were we dump label
  262          */
  263         if (allow_bsd_label == 0)
  264                 return FALSE;
  265 
  266         *label = *dlp;
  267         setcontroller(unit);
  268         bzero(&alt_info[unit], sizeof (struct alt_info));
  269 
  270         labeloffset[unit] = 0;
  271         labelsector[unit] = (ospart->relsect + LBLLOC);
  272 
  273         LABEL_DEBUG(0x20,print_bsd_label(label, "   "));
  274         return TRUE;
  275 }
  276 
  277 hdwritelabel(unit)
  278 {
  279         struct buf              *bp;
  280 
  281         if (alt_info[unit].alt_trk.alt_used || alt_info[unit].alt_sec.alt_used) {
  282                 printf("hd%x: can not write label: alt trk = %d, alt sec = %d\n",
  283                         unit, alt_info[unit].alt_trk.alt_used, alt_info[unit].alt_sec.alt_used);
  284                 return (EINVAL);
  285         }
  286         printf("hd%x: hdwritelabel replacing label at %d\n", unit, labelsector[unit]);
  287 
  288         bp = geteblk(SECSIZE);
  289         bp->b_flags = B_READ | B_MD1;   /* MD1 is be absolute */
  290         bp->b_blkno = labelsector[unit];
  291         bp->b_dev = WHOLE_DISK(unit);   /* C partition */
  292         bp->b_bcount = SECSIZE;
  293         hdstrategy(bp);
  294         biowait(bp);
  295         if (bp->b_flags & B_ERROR) {
  296                 printf("hd%d hdwritelabel(): read failure\n", unit);
  297                 brelse(bp);
  298                 return (ENXIO);
  299         }
  300 
  301         *((struct disklabel *) &(((char *)bp->b_un.b_addr)[labeloffset[unit]]))
  302                 = label[unit];
  303 
  304         bp->b_flags = B_WRITE | B_MD1;  /* MD1 is be absolute */
  305         bp->b_blkno = labelsector[unit];
  306         bp->b_dev = WHOLE_DISK(unit);   /* C partition */
  307         bp->b_bcount = SECSIZE;
  308         hdstrategy(bp);
  309         biowait(bp);
  310         if (bp->b_flags & B_ERROR) {
  311                 printf("hd%d: hdwritelabel() write failure\n", unit);
  312                 brelse(bp);
  313                 return ENXIO;
  314         }
  315         brelse(bp);
  316 
  317         return D_SUCCESS;
  318 }
  319 
  320 io_return_t
  321 hdsetlabel(dev_t dev, int flavor, int *data, unsigned int count)
  322 {
  323         io_return_t     errcode = D_SUCCESS;
  324         int             unit = UNIT(dev);
  325         struct disklabel*lp = &label[unit];
  326 
  327         switch (flavor) {
  328         /* set */
  329         case DIOCWLABEL:
  330         case DIOCWLABEL - (0x10<<16):
  331                 if (*(int*)data)
  332 /*
  333                         tgt->flags |= TGT_WRITE_LABEL;
  334                 else
  335                         tgt->flags &= ~TGT_WRITE_LABEL;
  336 */              break;
  337         case DIOCSDINFO:
  338         case DIOCSDINFO - (0x10<<16):
  339         case DIOCWDINFO:
  340         case DIOCWDINFO - (0x10<<16):
  341                 if (count != sizeof(struct disklabel) / sizeof(int))
  342                         return D_INVALID_SIZE;
  343                 /*
  344                  * setdisklabel is in scsi/rz_disk.c; but is generic
  345                  */
  346                 errcode = setdisklabel(lp, (struct disklabel*) data);
  347                 if (errcode || (flavor == DIOCSDINFO) || (flavor == DIOCSDINFO - (0x10<<16)))
  348                         return errcode;
  349                 errcode = hdwritelabel(unit);
  350                 break;
  351         }
  352         return errcode;
  353 }

Cache object: 1174f1e3887df9f039b767bae693efc5


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