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/fs/partitions/msdos.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  *  fs/partitions/msdos.c
    3  *
    4  *  Code extracted from drivers/block/genhd.c
    5  *  Copyright (C) 1991-1998  Linus Torvalds
    6  *
    7  *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
    8  *  in the early extended-partition checks and added DM partitions
    9  *
   10  *  Support for DiskManager v6.0x added by Mark Lord,
   11  *  with information provided by OnTrack.  This now works for linux fdisk
   12  *  and LILO, as well as loadlin and bootln.  Note that disks other than
   13  *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
   14  *
   15  *  More flexible handling of extended partitions - aeb, 950831
   16  *
   17  *  Check partition table on IDE disks for common CHS translations
   18  *
   19  *  Re-organised Feb 1998 Russell King
   20  */
   21 
   22 #include <linux/config.h>
   23 #include <linux/fs.h>
   24 #include <linux/genhd.h>
   25 #include <linux/kernel.h>
   26 #include <linux/major.h>
   27 #include <linux/string.h>
   28 #include <linux/blk.h>
   29 
   30 #ifdef CONFIG_BLK_DEV_IDE
   31 #include <linux/ide.h>  /* IDE xlate */
   32 #elif defined(CONFIG_BLK_DEV_IDE_MODULE)
   33 #include <linux/module.h>
   34 
   35 int (*ide_xlate_1024_hook)(kdev_t, int, int, const char *);
   36 EXPORT_SYMBOL(ide_xlate_1024_hook);
   37 #define ide_xlate_1024 ide_xlate_1024_hook
   38 #endif
   39 
   40 #include <asm/system.h>
   41 
   42 #include "check.h"
   43 #include "msdos.h"
   44 
   45 #if CONFIG_BLK_DEV_MD
   46 extern void md_autodetect_dev(kdev_t dev);
   47 #endif
   48 
   49 /*
   50  * Many architectures don't like unaligned accesses, which is
   51  * frequently the case with the nr_sects and start_sect partition
   52  * table entries.
   53  */
   54 #include <asm/unaligned.h>
   55 
   56 #define SYS_IND(p)      (get_unaligned(&p->sys_ind))
   57 #define NR_SECTS(p)     ({ __typeof__(p->nr_sects) __a =        \
   58                                 get_unaligned(&p->nr_sects);    \
   59                                 le32_to_cpu(__a); \
   60                         })
   61 
   62 #define START_SECT(p)   ({ __typeof__(p->start_sect) __a =      \
   63                                 get_unaligned(&p->start_sect);  \
   64                                 le32_to_cpu(__a); \
   65                         })
   66 
   67 static inline int is_extended_partition(struct partition *p)
   68 {
   69         return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
   70                 SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
   71                 SYS_IND(p) == LINUX_EXTENDED_PARTITION);
   72 }
   73 
   74 /*
   75  * msdos_partition_name() formats the short partition name into the supplied
   76  * buffer, and returns a pointer to that buffer.
   77  * Used by several partition types which makes conditional inclusion messy,
   78  * use __attribute__ ((unused)) instead.
   79  */
   80 static char __attribute__ ((unused))
   81         *msdos_partition_name (struct gendisk *hd, int minor, char *buf)
   82 {
   83 #ifdef CONFIG_DEVFS_FS
   84         sprintf(buf, "p%d", (minor & ((1 << hd->minor_shift) - 1)));
   85         return buf;
   86 #else
   87         return disk_name(hd, minor, buf);
   88 #endif
   89 }
   90 
   91 #define MSDOS_LABEL_MAGIC1      0x55
   92 #define MSDOS_LABEL_MAGIC2      0xAA
   93 
   94 static inline int
   95 msdos_magic_present(unsigned char *p)
   96 {
   97         return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
   98 }
   99 
  100 /*
  101  * Create devices for each logical partition in an extended partition.
  102  * The logical partitions form a linked list, with each entry being
  103  * a partition table with two entries.  The first entry
  104  * is the real data partition (with a start relative to the partition
  105  * table start).  The second is a pointer to the next logical partition
  106  * (with a start relative to the entire extended partition).
  107  * We do not create a Linux partition for the partition tables, but
  108  * only for the actual data partitions.
  109  */
  110 
  111 static void extended_partition(struct gendisk *hd, struct block_device *bdev,
  112                         int minor, unsigned long first_size, int *current_minor)
  113 {
  114         struct partition *p;
  115         Sector sect;
  116         unsigned char *data;
  117         unsigned long first_sector, this_sector, this_size;
  118         int mask = (1 << hd->minor_shift) - 1;
  119         int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
  120         int loopct = 0;         /* number of links followed
  121                                    without finding a data partition */
  122         int i;
  123 
  124         this_sector = first_sector = hd->part[minor].start_sect;
  125         this_size = first_size;
  126 
  127         while (1) {
  128                 if (++loopct > 100)
  129                         return;
  130                 if ((*current_minor & mask) == 0)
  131                         return;
  132                 data = read_dev_sector(bdev, this_sector, &sect);
  133                 if (!data)
  134                         return;
  135 
  136                 if (!msdos_magic_present(data + 510))
  137                         goto done; 
  138 
  139                 p = (struct partition *) (data + 0x1be);
  140 
  141                 /*
  142                  * Usually, the first entry is the real data partition,
  143                  * the 2nd entry is the next extended partition, or empty,
  144                  * and the 3rd and 4th entries are unused.
  145                  * However, DRDOS sometimes has the extended partition as
  146                  * the first entry (when the data partition is empty),
  147                  * and OS/2 seems to use all four entries.
  148                  */
  149 
  150                 /* 
  151                  * First process the data partition(s)
  152                  */
  153                 for (i=0; i<4; i++, p++) {
  154                         unsigned long offs, size, next;
  155                         if (!NR_SECTS(p) || is_extended_partition(p))
  156                                 continue;
  157 
  158                         /* Check the 3rd and 4th entries -
  159                            these sometimes contain random garbage */
  160                         offs = START_SECT(p)*sector_size;
  161                         size = NR_SECTS(p)*sector_size;
  162                         next = this_sector + offs;
  163                         if (i >= 2) {
  164                                 if (offs + size > this_size)
  165                                         continue;
  166                                 if (next < first_sector)
  167                                         continue;
  168                                 if (next + size > first_sector + first_size)
  169                                         continue;
  170                         }
  171 
  172                         add_gd_partition(hd, *current_minor, next, size);
  173 #if CONFIG_BLK_DEV_MD
  174                         if (SYS_IND(p) == LINUX_RAID_PARTITION) {
  175                             md_autodetect_dev(MKDEV(hd->major,*current_minor));
  176                         }
  177 #endif
  178 
  179                         (*current_minor)++;
  180                         loopct = 0;
  181                         if ((*current_minor & mask) == 0)
  182                                 goto done;
  183                 }
  184                 /*
  185                  * Next, process the (first) extended partition, if present.
  186                  * (So far, there seems to be no reason to make
  187                  *  extended_partition()  recursive and allow a tree
  188                  *  of extended partitions.)
  189                  * It should be a link to the next logical partition.
  190                  * Create a minor for this just long enough to get the next
  191                  * partition table.  The minor will be reused for the next
  192                  * data partition.
  193                  */
  194                 p -= 4;
  195                 for (i=0; i<4; i++, p++)
  196                         if (NR_SECTS(p) && is_extended_partition(p))
  197                                 break;
  198                 if (i == 4)
  199                         goto done;       /* nothing left to do */
  200 
  201                 this_sector = first_sector + START_SECT(p) * sector_size;
  202                 this_size = NR_SECTS(p) * sector_size;
  203                 minor = *current_minor;
  204                 put_dev_sector(sect);
  205         }
  206 done:
  207         put_dev_sector(sect);
  208 }
  209 
  210 /* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
  211    indicates linux swap.  Be careful before believing this is Solaris. */
  212 
  213 static void
  214 solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
  215                 int minor, int *current_minor)
  216 {
  217 
  218 #ifdef CONFIG_SOLARIS_X86_PARTITION
  219         long offset = hd->part[minor].start_sect;
  220         Sector sect;
  221         struct solaris_x86_vtoc *v;
  222         struct solaris_x86_slice *s;
  223         int mask = (1 << hd->minor_shift) - 1;
  224         int i;
  225         char buf[40];
  226 
  227         v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
  228         if (!v)
  229                 return;
  230         if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
  231                 put_dev_sector(sect);
  232                 return;
  233         }
  234         printk(" %s: <solaris:", msdos_partition_name(hd, minor, buf));
  235         if (le32_to_cpu(v->v_version) != 1) {
  236                 printk("  cannot handle version %d vtoc>\n",
  237                         le32_to_cpu(v->v_version));
  238                 put_dev_sector(sect);
  239                 return;
  240         }
  241         for (i=0; i<SOLARIS_X86_NUMSLICE; i++) {
  242                 if ((*current_minor & mask) == 0)
  243                         break;
  244                 s = &v->v_slice[i];
  245 
  246                 if (s->s_size == 0)
  247                         continue;
  248                 printk(" [s%d]", i);
  249                 /* solaris partitions are relative to current MS-DOS
  250                  * one but add_gd_partition starts relative to sector
  251                  * zero of the disk.  Therefore, must add the offset
  252                  * of the current partition */
  253                 add_gd_partition(hd, *current_minor,
  254                                  le32_to_cpu(s->s_start)+offset,
  255                                  le32_to_cpu(s->s_size));
  256                 (*current_minor)++;
  257         }
  258         put_dev_sector(sect);
  259         printk(" >\n");
  260 #endif
  261 }
  262 
  263 #ifdef CONFIG_BSD_DISKLABEL
  264 static void
  265 check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
  266         int baseminor, int *current_minor)
  267 {
  268         int i, bsd_start, bsd_size;
  269 
  270         bsd_start = le32_to_cpu(bsd_p->p_offset);
  271         bsd_size = le32_to_cpu(bsd_p->p_size);
  272 
  273         /* check relative position of already allocated partitions */
  274         for (i = baseminor+1; i < *current_minor; i++) {
  275                 int start = hd->part[i].start_sect;
  276                 int size = hd->part[i].nr_sects;
  277 
  278                 if (start+size <= bsd_start || start >= bsd_start+bsd_size)
  279                         continue;       /* no overlap */
  280 
  281                 if (start == bsd_start && size == bsd_size)
  282                         return;         /* equal -> no need to add */
  283 
  284                 if (start <= bsd_start && start+size >= bsd_start+bsd_size) {
  285                         /* bsd living within dos partition */
  286 #ifdef DEBUG_BSD_DISKLABEL
  287                         printk("w: %d %ld+%ld,%d+%d", 
  288                                i, start, size, bsd_start, bsd_size);
  289 #endif
  290                         break;          /* ok */
  291                 }
  292 
  293                 /* ouch: bsd and linux overlap */
  294 #ifdef DEBUG_BSD_DISKLABEL
  295                 printk("???: %d %ld+%ld,%d+%d",
  296                        i, start, size, bsd_start, bsd_size);
  297 #endif
  298                 printk("???");
  299                 return;
  300         }
  301 
  302         add_gd_partition(hd, *current_minor, bsd_start, bsd_size);
  303         (*current_minor)++;
  304 }
  305 
  306 /* 
  307  * Create devices for BSD partitions listed in a disklabel, under a
  308  * dos-like partition. See extended_partition() for more information.
  309  */
  310 static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
  311         int minor, int *current_minor, char *name, int max_partitions)
  312 {
  313         long offset = hd->part[minor].start_sect;
  314         Sector sect;
  315         struct bsd_disklabel *l;
  316         struct bsd_partition *p;
  317         int mask = (1 << hd->minor_shift) - 1;
  318         int baseminor = (minor & ~mask);
  319         char buf[40];
  320 
  321         l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect);
  322         if (!l)
  323                 return;
  324         if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
  325                 put_dev_sector(sect);
  326                 return;
  327         }
  328         printk(" %s: <%s:", msdos_partition_name(hd, minor, buf), name);
  329 
  330         if (le16_to_cpu(l->d_npartitions) < max_partitions)
  331                 max_partitions = le16_to_cpu(l->d_npartitions);
  332         for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
  333                 if ((*current_minor & mask) == 0)
  334                         break;
  335                 if (p->p_fstype == BSD_FS_UNUSED) 
  336                         continue;
  337                 check_and_add_bsd_partition(hd, p, baseminor, current_minor);
  338         }
  339         put_dev_sector(sect);
  340         printk(" >\n");
  341 }
  342 #endif
  343 
  344 static void bsd_partition(struct gendisk *hd, struct block_device *bdev,
  345         int minor, int *current_minor)
  346 {
  347 #ifdef CONFIG_BSD_DISKLABEL
  348         do_bsd_partition(hd, bdev, minor, current_minor, "bsd",
  349                 BSD_MAXPARTITIONS);
  350 #endif
  351 }
  352 
  353 static void netbsd_partition(struct gendisk *hd, struct block_device *bdev,
  354                 int minor, int *current_minor)
  355 {
  356 #ifdef CONFIG_BSD_DISKLABEL
  357         do_bsd_partition(hd, bdev, minor, current_minor, "netbsd",
  358                         BSD_MAXPARTITIONS);
  359 #endif
  360 }
  361 
  362 static void openbsd_partition(struct gendisk *hd, struct block_device *bdev,
  363                 int minor, int *current_minor)
  364 {
  365 #ifdef CONFIG_BSD_DISKLABEL
  366         do_bsd_partition(hd, bdev, minor, current_minor,
  367                         "openbsd", OPENBSD_MAXPARTITIONS);
  368 #endif
  369 }
  370 
  371 /*
  372  * Create devices for Unixware partitions listed in a disklabel, under a
  373  * dos-like partition. See extended_partition() for more information.
  374  */
  375 static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
  376                 int minor, int *current_minor)
  377 {
  378 #ifdef CONFIG_UNIXWARE_DISKLABEL
  379         long offset = hd->part[minor].start_sect;
  380         Sector sect;
  381         struct unixware_disklabel *l;
  382         struct unixware_slice *p;
  383         int mask = (1 << hd->minor_shift) - 1;
  384         char buf[40];
  385 
  386         l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, &sect);
  387         if (!l)
  388                 return;
  389         if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
  390             le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
  391                 put_dev_sector(sect);
  392                 return;
  393         }
  394         printk(" %s: <unixware:", msdos_partition_name(hd, minor, buf));
  395         p = &l->vtoc.v_slice[1];
  396         /* I omit the 0th slice as it is the same as whole disk. */
  397         while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
  398                 if ((*current_minor & mask) == 0)
  399                         break;
  400 
  401                 if (p->s_label != UNIXWARE_FS_UNUSED) {
  402                         add_gd_partition(hd, *current_minor, START_SECT(p),
  403                                          NR_SECTS(p));
  404                         (*current_minor)++;
  405                 }
  406                 p++;
  407         }
  408         put_dev_sector(sect);
  409         printk(" >\n");
  410 #endif
  411 }
  412 
  413 /*
  414  * Minix 2.0.0/2.0.2 subpartition support.
  415  * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
  416  * Rajeev V. Pillai    <rajeevvp@yahoo.com>
  417  */
  418 static void minix_partition(struct gendisk *hd, struct block_device *bdev,
  419                 int minor, int *current_minor)
  420 {
  421 #ifdef CONFIG_MINIX_SUBPARTITION
  422         long offset = hd->part[minor].start_sect;
  423         Sector sect;
  424         unsigned char *data;
  425         struct partition *p;
  426         int mask = (1 << hd->minor_shift) - 1;
  427         int i;
  428         char buf[40];
  429 
  430         data = read_dev_sector(bdev, offset, &sect);
  431         if (!data)
  432                 return;
  433 
  434         p = (struct partition *)(data + 0x1be);
  435 
  436         /* The first sector of a Minix partition can have either
  437          * a secondary MBR describing its subpartitions, or
  438          * the normal boot sector. */
  439         if (msdos_magic_present (data + 510) &&
  440             SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
  441 
  442                 printk(" %s: <minix:", msdos_partition_name(hd, minor, buf));
  443                 for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
  444                         if ((*current_minor & mask) == 0)
  445                                 break;
  446                         /* add each partition in use */
  447                         if (SYS_IND(p) == MINIX_PARTITION) {
  448                                 add_gd_partition(hd, *current_minor,
  449                                               START_SECT(p), NR_SECTS(p));
  450                                 (*current_minor)++;
  451                         }
  452                 }
  453                 printk(" >\n");
  454         }
  455         put_dev_sector(sect);
  456 #endif /* CONFIG_MINIX_SUBPARTITION */
  457 }
  458 
  459 static struct {
  460         unsigned char id;
  461         void (*parse)(struct gendisk *, struct block_device *, int, int *);
  462 } subtypes[] = {
  463         {BSD_PARTITION, bsd_partition},
  464         {NETBSD_PARTITION, netbsd_partition},
  465         {OPENBSD_PARTITION, openbsd_partition},
  466         {MINIX_PARTITION, minix_partition},
  467         {UNIXWARE_PARTITION, unixware_partition},
  468         {SOLARIS_X86_PARTITION, solaris_x86_partition},
  469         {0, NULL},
  470 };
  471 /*
  472  * Look for various forms of IDE disk geometry translation
  473  */
  474 static int handle_ide_mess(struct block_device *bdev)
  475 {
  476 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
  477         Sector sect;
  478         unsigned char *data;
  479         kdev_t dev = to_kdev_t(bdev->bd_dev);
  480         unsigned int sig;
  481         int heads = 0;
  482         struct partition *p;
  483         int i;
  484 #ifdef CONFIG_BLK_DEV_IDE_MODULE
  485         if (!ide_xlate_1024)
  486                 return 1;
  487 #endif
  488         /*
  489          * The i386 partition handling programs very often
  490          * make partitions end on cylinder boundaries.
  491          * There is no need to do so, and Linux fdisk doesn't always
  492          * do this, and Windows NT on Alpha doesn't do this either,
  493          * but still, this helps to guess #heads.
  494          */
  495         data = read_dev_sector(bdev, 0, &sect);
  496         if (!data)
  497                 return -1;
  498         if (!msdos_magic_present(data + 510)) {
  499                 put_dev_sector(sect);
  500                 return 0;
  501         }
  502         sig = le16_to_cpu(*(unsigned short *)(data + 2));
  503         p = (struct partition *) (data + 0x1be);
  504         for (i = 0; i < 4; i++) {
  505                 struct partition *q = &p[i];
  506                 if (NR_SECTS(q)) {
  507                         if ((q->sector & 63) == 1 &&
  508                             (q->end_sector & 63) == 63)
  509                                 heads = q->end_head + 1;
  510                         break;
  511                 }
  512         }
  513         if (SYS_IND(p) == EZD_PARTITION) {
  514                 /*
  515                  * Accesses to sector 0 must go to sector 1 instead.
  516                  */
  517                 if (ide_xlate_1024(dev, -1, heads, " [EZD]"))
  518                         goto reread;
  519         } else if (SYS_IND(p) == DM6_PARTITION) {
  520 
  521                 /*
  522                  * Everything on the disk is offset by 63 sectors,
  523                  * including a "new" MBR with its own partition table.
  524                  */
  525                 if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]"))
  526                         goto reread;
  527         } else if (sig <= 0x1ae &&
  528                    data[sig] == 0xAA && data[sig+1] == 0x55 &&
  529                    (data[sig+2] & 1)) {
  530                 /* DM6 signature in MBR, courtesy of OnTrack */
  531                 (void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
  532         } else if (SYS_IND(p) == DM6_AUX1PARTITION ||
  533                    SYS_IND(p) == DM6_AUX3PARTITION) {
  534                 /*
  535                  * DM6 on other than the first (boot) drive
  536                  */
  537                 (void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
  538         } else {
  539                 (void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
  540         }
  541         put_dev_sector(sect);
  542         return 1;
  543 
  544 reread:
  545         put_dev_sector(sect);
  546         /* Flush the cache */
  547         invalidate_bdev(bdev, 1);
  548         truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
  549 #endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
  550         return 1;
  551 }
  552  
  553 int msdos_partition(struct gendisk *hd, struct block_device *bdev,
  554                     unsigned long first_sector, int first_part_minor)
  555 {
  556         int i, minor = first_part_minor;
  557         Sector sect;
  558         struct partition *p;
  559         unsigned char *data;
  560         int mask = (1 << hd->minor_shift) - 1;
  561         int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
  562         int current_minor = first_part_minor;
  563         int err;
  564 
  565         err = handle_ide_mess(bdev);
  566         if (err <= 0)
  567                 return err;
  568         data = read_dev_sector(bdev, 0, &sect);
  569         if (!data)
  570                 return -1;
  571         if (!msdos_magic_present(data + 510)) {
  572                 put_dev_sector(sect);
  573                 return 0;
  574         }
  575         p = (struct partition *) (data + 0x1be);
  576 
  577         /*
  578          * Look for partitions in two passes:
  579          * First find the primary and DOS-type extended partitions.
  580          * On the second pass look inside *BSD, Unixware and Solaris partitions.
  581          */
  582 
  583         current_minor += 4;
  584         for (i=1 ; i<=4 ; minor++,i++,p++) {
  585                 if (!NR_SECTS(p))
  586                         continue;
  587                 add_gd_partition(hd, minor,
  588                                 first_sector+START_SECT(p)*sector_size,
  589                                 NR_SECTS(p)*sector_size);
  590 #if CONFIG_BLK_DEV_MD
  591                 if (SYS_IND(p) == LINUX_RAID_PARTITION) {
  592                         md_autodetect_dev(MKDEV(hd->major,minor));
  593                 }
  594 #endif
  595                 if (is_extended_partition(p)) {
  596                         unsigned long size = hd->part[minor].nr_sects;
  597                         printk(" <");
  598                         /* prevent someone doing mkfs or mkswap on an
  599                            extended partition, but leave room for LILO */
  600                         if (size > 2)
  601                                 hd->part[minor].nr_sects = 2;
  602                         extended_partition(hd, bdev, minor, size, &current_minor);
  603                         printk(" >");
  604                 }
  605         }
  606 
  607         /*
  608          *  Check for old-style Disk Manager partition table
  609          */
  610         if (msdos_magic_present(data + 0xfc)) {
  611                 p = (struct partition *) (0x1be + data);
  612                 for (i = 4 ; i < 16 ; i++, current_minor++) {
  613                         p--;
  614                         if ((current_minor & mask) == 0)
  615                                 break;
  616                         if (!(START_SECT(p) && NR_SECTS(p)))
  617                                 continue;
  618                         add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
  619                 }
  620         }
  621         printk("\n");
  622 
  623         /* second pass - output for each on a separate line */
  624         minor -= 4;
  625         p = (struct partition *) (0x1be + data);
  626         for (i=1 ; i<=4 ; minor++,i++,p++) {
  627                 unsigned char id = SYS_IND(p);
  628                 int n;
  629 
  630                 if (!NR_SECTS(p))
  631                         continue;
  632 
  633                 for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
  634                         ;
  635 
  636                 if (subtypes[n].parse)
  637                         subtypes[n].parse(hd, bdev, minor, &current_minor);
  638         }
  639         put_dev_sector(sect);
  640         return 1;
  641 }

Cache object: 9e295818de114e09131c5f697540a49b


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