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/pc98/pc98/diskslice_machdep.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  * Copyright (c) 1994 Bruce D. Evans.
    3  * All rights reserved.
    4  *
    5  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      from: @(#)ufs_disksubr.c        7.16 (Berkeley) 5/4/91
   37  *      from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
   38  * $FreeBSD: releng/5.0/sys/pc98/pc98/diskslice_machdep.c 104272 2002-10-01 07:24:55Z phk $
   39  */
   40 
   41 /*
   42  * PC9801 port by KATO Takenor <kato@eclogite.eps.nagoya-u.ac.jp>
   43  */
   44 
   45 #include "compat_atdisk.h"
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/bio.h>
   50 #include <sys/buf.h>
   51 #include <sys/conf.h>
   52 #include <sys/disk.h>
   53 #include <sys/disklabel.h>
   54 #ifndef PC98
   55 #define DOSPTYP_EXTENDED        5
   56 #define DOSPTYP_EXTENDEDX       15
   57 #define DOSPTYP_ONTRACK         84
   58 #endif
   59 #if defined(PC98) && !defined(PC98_ATCOMPAT)
   60 #include <sys/diskpc98.h>
   61 #else
   62 #include <sys/diskmbr.h>
   63 #endif
   64 #include <sys/diskslice.h>
   65 #include <sys/malloc.h>
   66 #include <sys/syslog.h>
   67 
   68 #define TRACE(str)      do { if (dsi_debug) printf str; } while (0)
   69 
   70 static volatile u_char dsi_debug;
   71 
   72 #ifndef PC98
   73 static struct dos_partition historical_bogus_partition_table[NDOSPART] = {
   74         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
   75         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
   76         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, },
   77         { 0x80, 0, 1, 0, DOSPTYP_386BSD, 255, 255, 255, 0, 50000, },
   78 };
   79 #endif
   80 
   81 static int check_part(char *sname, struct dos_partition *dp,
   82                            u_long offset, int nsectors, int ntracks,
   83                            u_long mbr_offset);
   84 #ifndef PC98
   85 static void mbr_extended(dev_t dev, struct disklabel *lp,
   86                               struct diskslices *ssp, u_long ext_offset,
   87                               u_long ext_size, u_long base_ext_offset,
   88                               int nsectors, int ntracks, u_long mbr_offset,
   89                               int level);
   90 #endif
   91 static int mbr_setslice(char *sname, struct disklabel *lp,
   92                              struct diskslice *sp, struct dos_partition *dp,
   93                              u_long br_offset);
   94 
   95 #ifdef PC98
   96 #define DPBLKNO(cyl,hd,sect) ((cyl)*(lp->d_secpercyl))
   97 #if     NCOMPAT_ATDISK > 0
   98 int     atcompat_dsinit(dev_t dev,
   99                  struct disklabel *lp, struct diskslices **sspp);
  100 #endif
  101 #endif
  102 
  103 static int
  104 check_part(sname, dp, offset, nsectors, ntracks, mbr_offset )
  105         char    *sname;
  106         struct dos_partition *dp;
  107         u_long  offset;
  108         int     nsectors;
  109         int     ntracks;
  110         u_long  mbr_offset;
  111 {
  112         int     chs_ecyl;
  113         int     chs_esect;
  114         int     chs_scyl;
  115         int     chs_ssect;
  116         int     error;
  117         u_long  esector;
  118         u_long  esector1;
  119         u_long  secpercyl;
  120         u_long  ssector;
  121         u_long  ssector1;
  122 #ifdef PC98
  123         u_long  pc98_start;
  124         u_long  pc98_size;
  125 #endif
  126 
  127         secpercyl = (u_long)nsectors * ntracks;
  128 #ifdef PC98
  129         chs_scyl = dp->dp_scyl;
  130         chs_ssect = dp->dp_ssect;
  131         ssector = chs_ssect + dp->dp_shd * nsectors + 
  132                 chs_scyl * secpercyl + mbr_offset;
  133 #else
  134         chs_scyl = DPCYL(dp->dp_scyl, dp->dp_ssect);
  135         chs_ssect = DPSECT(dp->dp_ssect);
  136         ssector = chs_ssect - 1 + dp->dp_shd * nsectors + chs_scyl * secpercyl
  137                   + mbr_offset;
  138 #endif
  139 #ifdef PC98
  140         pc98_start = dp->dp_scyl * secpercyl;
  141         pc98_size = dp->dp_ecyl ?
  142                 (dp->dp_ecyl + 1) * secpercyl - pc98_start : 0;
  143         ssector1 = offset + pc98_start;
  144 #else
  145         ssector1 = offset + dp->dp_start;
  146 #endif
  147 
  148         /*
  149          * If ssector1 is on a cylinder >= 1024, then ssector can't be right.
  150          * Allow the C/H/S for it to be 1023/ntracks-1/nsectors, or correct
  151          * apart from the cylinder being reduced modulo 1024.  Always allow
  152          * 1023/255/63.
  153          */
  154         if ((ssector < ssector1
  155              && ((chs_ssect == nsectors && dp->dp_shd == ntracks - 1
  156                   && chs_scyl == 1023)
  157                  || (secpercyl != 0
  158                      && (ssector1 - ssector) % (1024 * secpercyl) == 0)))
  159             || (dp->dp_scyl == 255 && dp->dp_shd == 255
  160                 && dp->dp_ssect == 255)) {
  161                 TRACE(("%s: C/H/S start %d/%d/%d, start %lu: allow\n",
  162                        sname, chs_scyl, dp->dp_shd, chs_ssect, ssector1));
  163                 ssector = ssector1;
  164         }
  165 
  166 #ifdef PC98
  167         chs_ecyl = dp->dp_ecyl;
  168         chs_esect = nsectors - 1;
  169         esector = chs_esect + (ntracks - 1) * nsectors +
  170                 chs_ecyl * secpercyl + mbr_offset;
  171         esector1 = ssector1 + pc98_size - 1;
  172 #else
  173         chs_ecyl = DPCYL(dp->dp_ecyl, dp->dp_esect);
  174         chs_esect = DPSECT(dp->dp_esect);
  175         esector = chs_esect - 1 + dp->dp_ehd * nsectors + chs_ecyl * secpercyl
  176                   + mbr_offset;
  177         esector1 = ssector1 + dp->dp_size - 1;
  178 #endif
  179 
  180         /* Allow certain bogus C/H/S values for esector, as above. */
  181         if ((esector < esector1
  182              && ((chs_esect == nsectors && dp->dp_ehd == ntracks - 1
  183                   && chs_ecyl == 1023)
  184                  || (secpercyl != 0
  185                      && (esector1 - esector) % (1024 * secpercyl) == 0)))
  186             || (dp->dp_ecyl == 255 && dp->dp_ehd == 255
  187                 && dp->dp_esect == 255)) {
  188                 TRACE(("%s: C/H/S end %d/%d/%d, end %lu: allow\n",
  189                        sname, chs_ecyl, dp->dp_ehd, chs_esect, esector1));
  190                 esector = esector1;
  191         }
  192 
  193         error = (ssector == ssector1 && esector == esector1) ? 0 : EINVAL;
  194         if (bootverbose)
  195 #ifdef PC98
  196                 printf("%s: mid 0x%x, start %lu, end = %lu, size %lu%s\n",
  197                        sname, dp->dp_mid, ssector1, esector1, pc98_size,
  198                         error ? "" : ": OK");
  199 #else
  200                 printf("%s: type 0x%x, start %lu, end = %lu, size %lu %s\n",
  201                        sname, dp->dp_typ, ssector1, esector1,
  202                        (u_long)dp->dp_size, error ? "" : ": OK");
  203 #endif
  204         if (ssector != ssector1 && bootverbose)
  205                 printf("%s: C/H/S start %d/%d/%d (%lu) != start %lu: invalid\n",
  206                        sname, chs_scyl, dp->dp_shd, chs_ssect,
  207                        ssector, ssector1);
  208         if (esector != esector1 && bootverbose)
  209                 printf("%s: C/H/S end %d/%d/%d (%lu) != end %lu: invalid\n",
  210                        sname, chs_ecyl, dp->dp_ehd, chs_esect,
  211                        esector, esector1);
  212         return (error);
  213 }
  214 
  215 int
  216 dsinit(dev, lp, sspp)
  217         dev_t   dev;
  218         struct disklabel *lp;
  219         struct diskslices **sspp;
  220 {
  221         struct buf *bp;
  222         u_char  *cp;
  223         int     dospart;
  224         struct dos_partition *dp;
  225         struct dos_partition *dp0;
  226         int     error;
  227         int     max_ncyls;
  228         int     max_nsectors;
  229         int     max_ntracks;
  230         u_long  mbr_offset;
  231         char    partname[2];
  232         u_long  secpercyl;
  233         char    *sname;
  234         struct diskslice *sp;
  235         struct diskslices *ssp;
  236 
  237         mbr_offset = DOSBBSECTOR;
  238 #ifdef PC98
  239         /* Read master boot record. */
  240         if ((int)lp->d_secsize < 1024)
  241                 bp = geteblk((int)1024);
  242         else
  243                 bp = geteblk((int)lp->d_secsize);
  244 #else
  245 reread_mbr:
  246         /* Read master boot record. */
  247         bp = geteblk((int)lp->d_secsize);
  248 #endif
  249         bp->b_dev = dkmodpart(dkmodslice(dev, WHOLE_DISK_SLICE), RAW_PART);
  250         bp->b_blkno = mbr_offset;
  251         bp->b_bcount = lp->d_secsize;
  252         bp->b_iocmd = BIO_READ;
  253 #ifdef PC98
  254         if (bp->b_bcount < 1024)
  255                 bp->b_bcount = 1024;
  256 #endif
  257         DEV_STRATEGY(bp, 1);
  258         if (bufwait(bp) != 0) {
  259                 disk_err(&bp->b_io, "reading primary partition table: error",
  260                     0, 1);
  261                 error = EIO;
  262                 goto done;
  263         }
  264 
  265         /* Weakly verify it. */
  266         cp = bp->b_data;
  267         sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART, partname);
  268         if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
  269                 if (bootverbose)
  270                         printf("%s: invalid primary partition table: no magic\n",
  271                                sname);
  272                 error = EINVAL;
  273                 goto done;
  274         }
  275 #ifdef PC98
  276         /*
  277          * entire disk for FreeBSD
  278          */
  279         if ((*(cp + 512) == 0x57) && (*(cp + 513) == 0x45) &&
  280                 (*(cp + 514) == 0x56) && (*(cp + 515) == 0x82)) {
  281                 sname = dsname(dev, dkunit(dev), BASE_SLICE,
  282                         RAW_PART, partname);
  283                 free(*sspp, M_DEVBUF);
  284                 ssp = dsmakeslicestruct(MAX_SLICES, lp);
  285                 *sspp = ssp;
  286 
  287                 /* Initialize normal slices. */
  288                 sp = &ssp->dss_slices[BASE_SLICE];
  289                 sp->ds_offset = 0;
  290                 sp->ds_size = lp->d_secperunit;
  291                 sp->ds_type = DOSPTYP_386BSD;
  292                 sp->ds_subtype = 0xc4;
  293                 error = 0;
  294                 ssp->dss_nslices = BASE_SLICE + 1;
  295                 goto done;
  296         }
  297 
  298         /*
  299          * XXX --- MS-DOG MO
  300          */
  301         if ((*(cp + 0x0e) == 1) && (*(cp + 0x15) == 0xf0) &&
  302             (*(cp + 0x1c) == 0x0) && 
  303                 ((*(cp + 512) == 0xf0) || (*(cp + 512) == 0xf8)) &&
  304             (*(cp + 513) == 0xff) && (*(cp + 514) == 0xff)) {
  305                 sname = dsname(dev, dkunit(dev), BASE_SLICE,
  306                         RAW_PART, partname);
  307                 free(*sspp, M_DEVBUF);
  308                 ssp = dsmakeslicestruct(MAX_SLICES, lp);
  309                 *sspp = ssp;
  310 
  311                 /* Initialize normal slices. */
  312                 sp = &ssp->dss_slices[BASE_SLICE];
  313                 sp->ds_offset = 0;
  314                 sp->ds_size = lp->d_secperunit;
  315                 sp->ds_type = 0xa0;  /* XXX */
  316                 sp->ds_subtype = 0x81;  /* XXX */
  317                 error = 0;
  318                 ssp->dss_nslices = BASE_SLICE + 1;
  319                 goto done;
  320         }
  321 #if NCOMPAT_ATDISK > 0
  322         /* 
  323          * Check magic number of 'extended format' for PC-9801.
  324          * If no magic, it may be formatted on IBM-PC.
  325          */
  326         if (((cp[4] != 'I') || (cp[5] != 'P') || (cp[6] != 'L') ||
  327                  (cp[7] != '1')) &&
  328                 ((strncmp(devtoname(bp->b_dev), "da", 2) == 0) ||
  329                  (strncmp(devtoname(bp->b_dev), "wd", 2) == 0) ||
  330             (strncmp(devtoname(bp->b_dev), "ad", 2) == 0))) {
  331                 /* IBM-PC HDD */
  332                 bp->b_flags |= B_INVAL | B_AGE;
  333                 brelse(bp);
  334                 return atcompat_dsinit(dev, lp, sspp);
  335         }
  336 #endif
  337         dp0 = (struct dos_partition *)(cp + 512);
  338 #else
  339         dp0 = (struct dos_partition *)(cp + DOSPARTOFF);
  340 
  341         /* Check for "Ontrack Diskmanager". */
  342         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
  343                 if (dp->dp_typ == DOSPTYP_ONTRACK) {
  344                         if (bootverbose)
  345                                 printf(
  346             "%s: Found \"Ontrack Disk Manager\" on this disk.\n", sname);
  347                         bp->b_flags |= B_INVAL | B_AGE;
  348                         brelse(bp);
  349                         mbr_offset = 63;
  350                         goto reread_mbr;
  351                 }
  352         }
  353 
  354         if (bcmp(dp0, historical_bogus_partition_table,
  355                  sizeof historical_bogus_partition_table) == 0) {
  356                 TRACE(("%s: invalid primary partition table: historical\n",
  357                        sname));
  358                 error = EINVAL;
  359                 goto done;
  360         }
  361 #endif
  362 
  363         /* Guess the geometry. */
  364         /*
  365          * TODO:
  366          * Perhaps skip entries with 0 size.
  367          * Perhaps only look at entries of type DOSPTYP_386BSD.
  368          */
  369         max_ncyls = 0;
  370         max_nsectors = 0;
  371         max_ntracks = 0;
  372         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
  373                 int     ncyls;
  374                 int     nsectors;
  375                 int     ntracks;
  376 
  377 
  378 #ifdef PC98
  379                 ncyls = lp->d_ncylinders;
  380 #else
  381                 ncyls = DPCYL(dp->dp_ecyl, dp->dp_esect) + 1;
  382 #endif
  383                 if (max_ncyls < ncyls)
  384                         max_ncyls = ncyls;
  385 #ifdef PC98
  386                 nsectors = lp->d_nsectors;
  387 #else
  388                 nsectors = DPSECT(dp->dp_esect);
  389 #endif
  390                 if (max_nsectors < nsectors)
  391                         max_nsectors = nsectors;
  392 #ifdef PC98
  393                 ntracks = lp->d_ntracks;
  394 #else
  395                 ntracks = dp->dp_ehd + 1;
  396 #endif
  397                 if (max_ntracks < ntracks)
  398                         max_ntracks = ntracks;
  399         }
  400 
  401         /*
  402          * Check that we have guessed the geometry right by checking the
  403          * partition entries.
  404          */
  405         /*
  406          * TODO:
  407          * As above.
  408          * Check for overlaps.
  409          * Check against d_secperunit if the latter is reliable.
  410          */
  411         error = 0;
  412 #ifdef PC98
  413         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
  414                 if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0)
  415                         continue;
  416                 sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
  417                                 RAW_PART, partname);
  418 #else
  419         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++) {
  420                 if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
  421                     && dp->dp_start == 0 && dp->dp_size == 0)
  422                         continue;
  423                 sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
  424                                RAW_PART, partname);
  425 #endif
  426                 /*
  427                  * Temporarily ignore errors from this check.  We could
  428                  * simplify things by accepting the table eariler if we
  429                  * always ignore errors here.  Perhaps we should always
  430                  * accept the table if the magic is right but not let
  431                  * bad entries affect the geometry.
  432                  */
  433                 check_part(sname, dp, mbr_offset, max_nsectors, max_ntracks,
  434                            mbr_offset);
  435         }
  436         if (error != 0)
  437                 goto done;
  438 
  439         /*
  440          * Accept the DOS partition table.
  441          * First adjust the label (we have been careful not to change it
  442          * before we can guarantee success).
  443          */
  444         secpercyl = (u_long)max_nsectors * max_ntracks;
  445         if (secpercyl != 0) {
  446                 lp->d_nsectors = max_nsectors;
  447                 lp->d_ntracks = max_ntracks;
  448                 lp->d_secpercyl = secpercyl;
  449                 lp->d_ncylinders = lp->d_secperunit / secpercyl;
  450         }
  451 
  452         /*
  453          * We are passed a pointer to a suitably initialized minimal
  454          * slices "struct" with no dangling pointers in it.  Replace it
  455          * by a maximal one.  This usually oversizes the "struct", but
  456          * enlarging it while searching for logical drives would be
  457          * inconvenient.
  458          */
  459         free(*sspp, M_DEVBUF);
  460         ssp = dsmakeslicestruct(MAX_SLICES, lp);
  461         *sspp = ssp;
  462 
  463         /* Initialize normal slices. */
  464         sp = &ssp->dss_slices[BASE_SLICE];
  465         for (dospart = 0, dp = dp0; dospart < NDOSPART; dospart++, dp++, sp++) {
  466                 sname = dsname(dev, dkunit(dev), BASE_SLICE + dospart,
  467                                RAW_PART, partname);
  468                 (void)mbr_setslice(sname, lp, sp, dp, mbr_offset);
  469         }
  470         ssp->dss_nslices = BASE_SLICE + NDOSPART;
  471 
  472 #ifndef PC98
  473         /* Handle extended partitions. */
  474         sp -= NDOSPART;
  475         for (dospart = 0; dospart < NDOSPART; dospart++, sp++)
  476                 if (sp->ds_type == DOSPTYP_EXTENDED ||
  477                     sp->ds_type == DOSPTYP_EXTENDEDX)
  478                         mbr_extended(bp->b_dev, lp, ssp,
  479                                      sp->ds_offset, sp->ds_size, sp->ds_offset,
  480                                      max_nsectors, max_ntracks, mbr_offset, 1);
  481 
  482         /*
  483          * mbr_extended() abuses ssp->dss_nslices for the number of slices
  484          * that would be found if there were no limit on the number of slices
  485          * in *ssp.  Cut it back now.
  486          */
  487         if (ssp->dss_nslices > MAX_SLICES)
  488                 ssp->dss_nslices = MAX_SLICES;
  489 #endif
  490 
  491 done:
  492         bp->b_flags |= B_INVAL | B_AGE;
  493         brelse(bp);
  494         if (error == EINVAL)
  495                 error = 0;
  496         return (error);
  497 }
  498 
  499 #ifndef PC98
  500 void
  501 mbr_extended(dev, lp, ssp, ext_offset, ext_size, base_ext_offset, nsectors,
  502              ntracks, mbr_offset, level)
  503         dev_t   dev;
  504         struct disklabel *lp;
  505         struct diskslices *ssp;
  506         u_long  ext_offset;
  507         u_long  ext_size;
  508         u_long  base_ext_offset;
  509         int     nsectors;
  510         int     ntracks;
  511         u_long  mbr_offset;
  512         int     level;
  513 {
  514         struct buf *bp;
  515         u_char  *cp;
  516         int     dospart;
  517         struct dos_partition *dp;
  518         struct dos_partition dpcopy[NDOSPART];
  519         u_long  ext_offsets[NDOSPART];
  520         u_long  ext_sizes[NDOSPART];
  521         char    partname[2];
  522         int     slice;
  523         char    *sname;
  524         struct diskslice *sp;
  525 
  526         if (level >= 16) {
  527                 printf(
  528         "%s: excessive recursion in search for slices; aborting search\n",
  529                        devtoname(dev));
  530                 return;
  531         }
  532 
  533         /* Read extended boot record. */
  534         bp = geteblk((int)lp->d_secsize);
  535         bp->b_dev = dev;
  536         bp->b_blkno = ext_offset;
  537         bp->b_bcount = lp->d_secsize;
  538         bp->b_iocmd = BIO_READ;
  539         DEV_STRATEGY(bp, 1);
  540         if (bufwait(bp) != 0) {
  541                 disk_err(&bp->b_io, "reading extended partition table: error",
  542                     0, 1);
  543                 goto done;
  544         }
  545 
  546         /* Weakly verify it. */
  547         cp = bp->b_data;
  548         if (cp[0x1FE] != 0x55 || cp[0x1FF] != 0xAA) {
  549                 sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE, RAW_PART,
  550                                partname);
  551                 if (bootverbose)
  552                         printf("%s: invalid extended partition table: no magic\n",
  553                                sname);
  554                 goto done;
  555         }
  556 
  557         /* Make a copy of the partition table to avoid alignment problems. */
  558         memcpy(&dpcopy[0], cp + DOSPARTOFF, sizeof(dpcopy));
  559 
  560         slice = ssp->dss_nslices;
  561         for (dospart = 0, dp = &dpcopy[0]; dospart < NDOSPART;
  562             dospart++, dp++) {
  563                 ext_sizes[dospart] = 0;
  564                 if (dp->dp_scyl == 0 && dp->dp_shd == 0 && dp->dp_ssect == 0
  565                     && dp->dp_start == 0 && dp->dp_size == 0)
  566                         continue;
  567                 if (dp->dp_typ == DOSPTYP_EXTENDED ||
  568                     dp->dp_typ == DOSPTYP_EXTENDEDX) {
  569                         static char buf[32];
  570 
  571                         sname = dsname(dev, dkunit(dev), WHOLE_DISK_SLICE,
  572                                        RAW_PART, partname);
  573                         snprintf(buf, sizeof(buf), "%s", sname);
  574                         if (strlen(buf) < sizeof buf - 11)
  575                                 strcat(buf, "<extended>");
  576                         check_part(buf, dp, base_ext_offset, nsectors,
  577                                    ntracks, mbr_offset);
  578                         ext_offsets[dospart] = base_ext_offset + dp->dp_start;
  579                         ext_sizes[dospart] = dp->dp_size;
  580                 } else {
  581                         sname = dsname(dev, dkunit(dev), slice, RAW_PART,
  582                                        partname);
  583                         check_part(sname, dp, ext_offset, nsectors, ntracks,
  584                                    mbr_offset);
  585                         if (slice >= MAX_SLICES) {
  586                                 printf("%s: too many slices\n", sname);
  587                                 slice++;
  588                                 continue;
  589                         }
  590                         sp = &ssp->dss_slices[slice];
  591                         if (mbr_setslice(sname, lp, sp, dp, ext_offset) != 0)
  592                                 continue;
  593                         slice++;
  594                 }
  595         }
  596         ssp->dss_nslices = slice;
  597 
  598         /* If we found any more slices, recursively find all the subslices. */
  599         for (dospart = 0; dospart < NDOSPART; dospart++)
  600                 if (ext_sizes[dospart] != 0)
  601                         mbr_extended(dev, lp, ssp, ext_offsets[dospart],
  602                                      ext_sizes[dospart], base_ext_offset,
  603                                      nsectors, ntracks, mbr_offset, ++level);
  604 
  605 done:
  606         bp->b_flags |= B_INVAL | B_AGE;
  607         brelse(bp);
  608 }
  609 #endif
  610 
  611 static int
  612 mbr_setslice(sname, lp, sp, dp, br_offset)
  613         char    *sname;
  614         struct disklabel *lp;
  615         struct diskslice *sp;
  616         struct dos_partition *dp;
  617         u_long  br_offset;
  618 {
  619         u_long  offset;
  620         u_long  size;
  621 
  622 #ifdef PC98
  623         offset = DPBLKNO(dp->dp_scyl, dp->dp_shd, dp->dp_ssect);
  624         size = dp->dp_ecyl ?
  625             DPBLKNO(dp->dp_ecyl + 1, dp->dp_ehd, dp->dp_esect) - offset : 0;
  626 #else
  627         offset = br_offset + dp->dp_start;
  628         if (offset > lp->d_secperunit || offset < br_offset) {
  629                 printf(
  630                 "%s: slice starts beyond end of the disk: rejecting it\n",
  631                        sname);
  632                 return (1);
  633         }
  634         size = lp->d_secperunit - offset;
  635         if (size >= dp->dp_size)
  636                 size = dp->dp_size;
  637         else
  638                 printf(
  639 "%s: slice extends beyond end of disk: truncating from %lu to %lu sectors\n",
  640                        sname, (u_long)dp->dp_size, size);
  641 #endif
  642         sp->ds_offset = offset;
  643         sp->ds_size = size;
  644 #ifdef PC98
  645         sp->ds_type = dp->dp_mid;
  646         sp->ds_subtype = dp->dp_sid;
  647         strncpy(sp->ds_name, dp->dp_name, sizeof(sp->ds_name));
  648 #else
  649         sp->ds_type = dp->dp_typ;
  650 #ifdef PC98_ATCOMPAT
  651         /* Fake FreeBSD(98). */
  652         if (sp->ds_type == DOSPTYP_386BSD)
  653                 sp->ds_type = 0x94;
  654 #endif
  655 #endif /* PC98 */
  656 #if 0
  657         lp->d_subtype |= (lp->d_subtype & 3) | dospart | DSTYPE_INDOSPART;
  658 #endif
  659         return (0);
  660 }
  661 
  662 #ifdef __alpha__
  663 void
  664 alpha_fix_srm_checksum(bp)
  665         struct buf *bp;
  666 {
  667         u_int64_t *p;
  668         u_int64_t sum;
  669         int i;
  670 
  671         p = (u_int64_t *) bp->b_data;
  672         sum = 0;
  673         for (i = 0; i < 63; i++)
  674                 sum += p[i];
  675         p[63] = sum;
  676 }
  677 #endif

Cache object: 83b9dbf62983d935195c53cd74639e75


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