Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  fs/partitions/msdos.c
0004  *
0005  *  Code extracted from drivers/block/genhd.c
0006  *  Copyright (C) 1991-1998  Linus Torvalds
0007  *
0008  *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
0009  *  in the early extended-partition checks and added DM partitions
0010  *
0011  *  Support for DiskManager v6.0x added by Mark Lord,
0012  *  with information provided by OnTrack.  This now works for linux fdisk
0013  *  and LILO, as well as loadlin and bootln.  Note that disks other than
0014  *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
0015  *
0016  *  More flexible handling of extended partitions - aeb, 950831
0017  *
0018  *  Check partition table on IDE disks for common CHS translations
0019  *
0020  *  Re-organised Feb 1998 Russell King
0021  *
0022  *  BSD disklabel support by Yossi Gottlieb <yogo@math.tau.ac.il>
0023  *  updated by Marc Espie <Marc.Espie@openbsd.org>
0024  *
0025  *  Unixware slices support by Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>
0026  *  and Krzysztof G. Baranowski <kgb@knm.org.pl>
0027  */
0028 #include <linux/msdos_fs.h>
0029 #include <linux/msdos_partition.h>
0030 
0031 #include "check.h"
0032 #include "efi.h"
0033 
0034 /*
0035  * Many architectures don't like unaligned accesses, while
0036  * the nr_sects and start_sect partition table entries are
0037  * at a 2 (mod 4) address.
0038  */
0039 #include <asm/unaligned.h>
0040 
0041 static inline sector_t nr_sects(struct msdos_partition *p)
0042 {
0043     return (sector_t)get_unaligned_le32(&p->nr_sects);
0044 }
0045 
0046 static inline sector_t start_sect(struct msdos_partition *p)
0047 {
0048     return (sector_t)get_unaligned_le32(&p->start_sect);
0049 }
0050 
0051 static inline int is_extended_partition(struct msdos_partition *p)
0052 {
0053     return (p->sys_ind == DOS_EXTENDED_PARTITION ||
0054         p->sys_ind == WIN98_EXTENDED_PARTITION ||
0055         p->sys_ind == LINUX_EXTENDED_PARTITION);
0056 }
0057 
0058 #define MSDOS_LABEL_MAGIC1  0x55
0059 #define MSDOS_LABEL_MAGIC2  0xAA
0060 
0061 static inline int
0062 msdos_magic_present(unsigned char *p)
0063 {
0064     return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
0065 }
0066 
0067 /* Value is EBCDIC 'IBMA' */
0068 #define AIX_LABEL_MAGIC1    0xC9
0069 #define AIX_LABEL_MAGIC2    0xC2
0070 #define AIX_LABEL_MAGIC3    0xD4
0071 #define AIX_LABEL_MAGIC4    0xC1
0072 static int aix_magic_present(struct parsed_partitions *state, unsigned char *p)
0073 {
0074     struct msdos_partition *pt = (struct msdos_partition *) (p + 0x1be);
0075     Sector sect;
0076     unsigned char *d;
0077     int slot, ret = 0;
0078 
0079     if (!(p[0] == AIX_LABEL_MAGIC1 &&
0080         p[1] == AIX_LABEL_MAGIC2 &&
0081         p[2] == AIX_LABEL_MAGIC3 &&
0082         p[3] == AIX_LABEL_MAGIC4))
0083         return 0;
0084 
0085     /*
0086      * Assume the partition table is valid if Linux partitions exists.
0087      * Note that old Solaris/x86 partitions use the same indicator as
0088      * Linux swap partitions, so we consider that a Linux partition as
0089      * well.
0090      */
0091     for (slot = 1; slot <= 4; slot++, pt++) {
0092         if (pt->sys_ind == SOLARIS_X86_PARTITION ||
0093             pt->sys_ind == LINUX_RAID_PARTITION ||
0094             pt->sys_ind == LINUX_DATA_PARTITION ||
0095             pt->sys_ind == LINUX_LVM_PARTITION ||
0096             is_extended_partition(pt))
0097             return 0;
0098     }
0099     d = read_part_sector(state, 7, &sect);
0100     if (d) {
0101         if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M')
0102             ret = 1;
0103         put_dev_sector(sect);
0104     }
0105     return ret;
0106 }
0107 
0108 static void set_info(struct parsed_partitions *state, int slot,
0109              u32 disksig)
0110 {
0111     struct partition_meta_info *info = &state->parts[slot].info;
0112 
0113     snprintf(info->uuid, sizeof(info->uuid), "%08x-%02x", disksig,
0114          slot);
0115     info->volname[0] = 0;
0116     state->parts[slot].has_info = true;
0117 }
0118 
0119 /*
0120  * Create devices for each logical partition in an extended partition.
0121  * The logical partitions form a linked list, with each entry being
0122  * a partition table with two entries.  The first entry
0123  * is the real data partition (with a start relative to the partition
0124  * table start).  The second is a pointer to the next logical partition
0125  * (with a start relative to the entire extended partition).
0126  * We do not create a Linux partition for the partition tables, but
0127  * only for the actual data partitions.
0128  */
0129 
0130 static void parse_extended(struct parsed_partitions *state,
0131                sector_t first_sector, sector_t first_size,
0132                u32 disksig)
0133 {
0134     struct msdos_partition *p;
0135     Sector sect;
0136     unsigned char *data;
0137     sector_t this_sector, this_size;
0138     sector_t sector_size;
0139     int loopct = 0;     /* number of links followed
0140                    without finding a data partition */
0141     int i;
0142 
0143     sector_size = queue_logical_block_size(state->disk->queue) / 512;
0144     this_sector = first_sector;
0145     this_size = first_size;
0146 
0147     while (1) {
0148         if (++loopct > 100)
0149             return;
0150         if (state->next == state->limit)
0151             return;
0152         data = read_part_sector(state, this_sector, &sect);
0153         if (!data)
0154             return;
0155 
0156         if (!msdos_magic_present(data + 510))
0157             goto done;
0158 
0159         p = (struct msdos_partition *) (data + 0x1be);
0160 
0161         /*
0162          * Usually, the first entry is the real data partition,
0163          * the 2nd entry is the next extended partition, or empty,
0164          * and the 3rd and 4th entries are unused.
0165          * However, DRDOS sometimes has the extended partition as
0166          * the first entry (when the data partition is empty),
0167          * and OS/2 seems to use all four entries.
0168          */
0169 
0170         /*
0171          * First process the data partition(s)
0172          */
0173         for (i = 0; i < 4; i++, p++) {
0174             sector_t offs, size, next;
0175 
0176             if (!nr_sects(p) || is_extended_partition(p))
0177                 continue;
0178 
0179             /* Check the 3rd and 4th entries -
0180                these sometimes contain random garbage */
0181             offs = start_sect(p)*sector_size;
0182             size = nr_sects(p)*sector_size;
0183             next = this_sector + offs;
0184             if (i >= 2) {
0185                 if (offs + size > this_size)
0186                     continue;
0187                 if (next < first_sector)
0188                     continue;
0189                 if (next + size > first_sector + first_size)
0190                     continue;
0191             }
0192 
0193             put_partition(state, state->next, next, size);
0194             set_info(state, state->next, disksig);
0195             if (p->sys_ind == LINUX_RAID_PARTITION)
0196                 state->parts[state->next].flags = ADDPART_FLAG_RAID;
0197             loopct = 0;
0198             if (++state->next == state->limit)
0199                 goto done;
0200         }
0201         /*
0202          * Next, process the (first) extended partition, if present.
0203          * (So far, there seems to be no reason to make
0204          *  parse_extended()  recursive and allow a tree
0205          *  of extended partitions.)
0206          * It should be a link to the next logical partition.
0207          */
0208         p -= 4;
0209         for (i = 0; i < 4; i++, p++)
0210             if (nr_sects(p) && is_extended_partition(p))
0211                 break;
0212         if (i == 4)
0213             goto done;   /* nothing left to do */
0214 
0215         this_sector = first_sector + start_sect(p) * sector_size;
0216         this_size = nr_sects(p) * sector_size;
0217         put_dev_sector(sect);
0218     }
0219 done:
0220     put_dev_sector(sect);
0221 }
0222 
0223 #define SOLARIS_X86_NUMSLICE    16
0224 #define SOLARIS_X86_VTOC_SANE   (0x600DDEEEUL)
0225 
0226 struct solaris_x86_slice {
0227     __le16 s_tag;       /* ID tag of partition */
0228     __le16 s_flag;      /* permission flags */
0229     __le32 s_start;     /* start sector no of partition */
0230     __le32 s_size;      /* # of blocks in partition */
0231 };
0232 
0233 struct solaris_x86_vtoc {
0234     unsigned int v_bootinfo[3]; /* info needed by mboot */
0235     __le32 v_sanity;        /* to verify vtoc sanity */
0236     __le32 v_version;       /* layout version */
0237     char    v_volume[8];        /* volume name */
0238     __le16  v_sectorsz;     /* sector size in bytes */
0239     __le16  v_nparts;       /* number of partitions */
0240     unsigned int v_reserved[10];    /* free space */
0241     struct solaris_x86_slice
0242         v_slice[SOLARIS_X86_NUMSLICE]; /* slice headers */
0243     unsigned int timestamp[SOLARIS_X86_NUMSLICE]; /* timestamp */
0244     char    v_asciilabel[128];  /* for compatibility */
0245 };
0246 
0247 /* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
0248    indicates linux swap.  Be careful before believing this is Solaris. */
0249 
0250 static void parse_solaris_x86(struct parsed_partitions *state,
0251                   sector_t offset, sector_t size, int origin)
0252 {
0253 #ifdef CONFIG_SOLARIS_X86_PARTITION
0254     Sector sect;
0255     struct solaris_x86_vtoc *v;
0256     int i;
0257     short max_nparts;
0258 
0259     v = read_part_sector(state, offset + 1, &sect);
0260     if (!v)
0261         return;
0262     if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
0263         put_dev_sector(sect);
0264         return;
0265     }
0266     {
0267         char tmp[1 + BDEVNAME_SIZE + 10 + 11 + 1];
0268 
0269         snprintf(tmp, sizeof(tmp), " %s%d: <solaris:", state->name, origin);
0270         strlcat(state->pp_buf, tmp, PAGE_SIZE);
0271     }
0272     if (le32_to_cpu(v->v_version) != 1) {
0273         char tmp[64];
0274 
0275         snprintf(tmp, sizeof(tmp), "  cannot handle version %d vtoc>\n",
0276              le32_to_cpu(v->v_version));
0277         strlcat(state->pp_buf, tmp, PAGE_SIZE);
0278         put_dev_sector(sect);
0279         return;
0280     }
0281     /* Ensure we can handle previous case of VTOC with 8 entries gracefully */
0282     max_nparts = le16_to_cpu(v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
0283     for (i = 0; i < max_nparts && state->next < state->limit; i++) {
0284         struct solaris_x86_slice *s = &v->v_slice[i];
0285         char tmp[3 + 10 + 1 + 1];
0286 
0287         if (s->s_size == 0)
0288             continue;
0289         snprintf(tmp, sizeof(tmp), " [s%d]", i);
0290         strlcat(state->pp_buf, tmp, PAGE_SIZE);
0291         /* solaris partitions are relative to current MS-DOS
0292          * one; must add the offset of the current partition */
0293         put_partition(state, state->next++,
0294                  le32_to_cpu(s->s_start)+offset,
0295                  le32_to_cpu(s->s_size));
0296     }
0297     put_dev_sector(sect);
0298     strlcat(state->pp_buf, " >\n", PAGE_SIZE);
0299 #endif
0300 }
0301 
0302 /* check against BSD src/sys/sys/disklabel.h for consistency */
0303 #define BSD_DISKMAGIC   (0x82564557UL)  /* The disk magic number */
0304 #define BSD_MAXPARTITIONS   16
0305 #define OPENBSD_MAXPARTITIONS   16
0306 #define BSD_FS_UNUSED       0 /* disklabel unused partition entry ID */
0307 struct bsd_disklabel {
0308     __le32  d_magic;        /* the magic number */
0309     __s16   d_type;         /* drive type */
0310     __s16   d_subtype;      /* controller/d_type specific */
0311     char    d_typename[16];     /* type name, e.g. "eagle" */
0312     char    d_packname[16];     /* pack identifier */
0313     __u32   d_secsize;      /* # of bytes per sector */
0314     __u32   d_nsectors;     /* # of data sectors per track */
0315     __u32   d_ntracks;      /* # of tracks per cylinder */
0316     __u32   d_ncylinders;       /* # of data cylinders per unit */
0317     __u32   d_secpercyl;        /* # of data sectors per cylinder */
0318     __u32   d_secperunit;       /* # of data sectors per unit */
0319     __u16   d_sparespertrack;   /* # of spare sectors per track */
0320     __u16   d_sparespercyl;     /* # of spare sectors per cylinder */
0321     __u32   d_acylinders;       /* # of alt. cylinders per unit */
0322     __u16   d_rpm;          /* rotational speed */
0323     __u16   d_interleave;       /* hardware sector interleave */
0324     __u16   d_trackskew;        /* sector 0 skew, per track */
0325     __u16   d_cylskew;      /* sector 0 skew, per cylinder */
0326     __u32   d_headswitch;       /* head switch time, usec */
0327     __u32   d_trkseek;      /* track-to-track seek, usec */
0328     __u32   d_flags;        /* generic flags */
0329 #define NDDATA 5
0330     __u32   d_drivedata[NDDATA];    /* drive-type specific information */
0331 #define NSPARE 5
0332     __u32   d_spare[NSPARE];    /* reserved for future use */
0333     __le32  d_magic2;       /* the magic number (again) */
0334     __le16  d_checksum;     /* xor of data incl. partitions */
0335 
0336             /* filesystem and partition information: */
0337     __le16  d_npartitions;      /* number of partitions in following */
0338     __le32  d_bbsize;       /* size of boot area at sn0, bytes */
0339     __le32  d_sbsize;       /* max size of fs superblock, bytes */
0340     struct  bsd_partition {     /* the partition table */
0341         __le32  p_size;     /* number of sectors in partition */
0342         __le32  p_offset;   /* starting sector */
0343         __le32  p_fsize;    /* filesystem basic fragment size */
0344         __u8    p_fstype;   /* filesystem type, see below */
0345         __u8    p_frag;     /* filesystem fragments per block */
0346         __le16  p_cpg;      /* filesystem cylinders per group */
0347     } d_partitions[BSD_MAXPARTITIONS];  /* actually may be more */
0348 };
0349 
0350 #if defined(CONFIG_BSD_DISKLABEL)
0351 /*
0352  * Create devices for BSD partitions listed in a disklabel, under a
0353  * dos-like partition. See parse_extended() for more information.
0354  */
0355 static void parse_bsd(struct parsed_partitions *state,
0356               sector_t offset, sector_t size, int origin, char *flavour,
0357               int max_partitions)
0358 {
0359     Sector sect;
0360     struct bsd_disklabel *l;
0361     struct bsd_partition *p;
0362     char tmp[64];
0363 
0364     l = read_part_sector(state, offset + 1, &sect);
0365     if (!l)
0366         return;
0367     if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
0368         put_dev_sector(sect);
0369         return;
0370     }
0371 
0372     snprintf(tmp, sizeof(tmp), " %s%d: <%s:", state->name, origin, flavour);
0373     strlcat(state->pp_buf, tmp, PAGE_SIZE);
0374 
0375     if (le16_to_cpu(l->d_npartitions) < max_partitions)
0376         max_partitions = le16_to_cpu(l->d_npartitions);
0377     for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
0378         sector_t bsd_start, bsd_size;
0379 
0380         if (state->next == state->limit)
0381             break;
0382         if (p->p_fstype == BSD_FS_UNUSED)
0383             continue;
0384         bsd_start = le32_to_cpu(p->p_offset);
0385         bsd_size = le32_to_cpu(p->p_size);
0386         /* FreeBSD has relative offset if C partition offset is zero */
0387         if (memcmp(flavour, "bsd\0", 4) == 0 &&
0388             le32_to_cpu(l->d_partitions[2].p_offset) == 0)
0389             bsd_start += offset;
0390         if (offset == bsd_start && size == bsd_size)
0391             /* full parent partition, we have it already */
0392             continue;
0393         if (offset > bsd_start || offset+size < bsd_start+bsd_size) {
0394             strlcat(state->pp_buf, "bad subpartition - ignored\n", PAGE_SIZE);
0395             continue;
0396         }
0397         put_partition(state, state->next++, bsd_start, bsd_size);
0398     }
0399     put_dev_sector(sect);
0400     if (le16_to_cpu(l->d_npartitions) > max_partitions) {
0401         snprintf(tmp, sizeof(tmp), " (ignored %d more)",
0402              le16_to_cpu(l->d_npartitions) - max_partitions);
0403         strlcat(state->pp_buf, tmp, PAGE_SIZE);
0404     }
0405     strlcat(state->pp_buf, " >\n", PAGE_SIZE);
0406 }
0407 #endif
0408 
0409 static void parse_freebsd(struct parsed_partitions *state,
0410               sector_t offset, sector_t size, int origin)
0411 {
0412 #ifdef CONFIG_BSD_DISKLABEL
0413     parse_bsd(state, offset, size, origin, "bsd", BSD_MAXPARTITIONS);
0414 #endif
0415 }
0416 
0417 static void parse_netbsd(struct parsed_partitions *state,
0418              sector_t offset, sector_t size, int origin)
0419 {
0420 #ifdef CONFIG_BSD_DISKLABEL
0421     parse_bsd(state, offset, size, origin, "netbsd", BSD_MAXPARTITIONS);
0422 #endif
0423 }
0424 
0425 static void parse_openbsd(struct parsed_partitions *state,
0426               sector_t offset, sector_t size, int origin)
0427 {
0428 #ifdef CONFIG_BSD_DISKLABEL
0429     parse_bsd(state, offset, size, origin, "openbsd",
0430           OPENBSD_MAXPARTITIONS);
0431 #endif
0432 }
0433 
0434 #define UNIXWARE_DISKMAGIC     (0xCA5E600DUL)   /* The disk magic number */
0435 #define UNIXWARE_DISKMAGIC2    (0x600DDEEEUL)   /* The slice table magic nr */
0436 #define UNIXWARE_NUMSLICE      16
0437 #define UNIXWARE_FS_UNUSED     0        /* Unused slice entry ID */
0438 
0439 struct unixware_slice {
0440     __le16   s_label;   /* label */
0441     __le16   s_flags;   /* permission flags */
0442     __le32   start_sect;    /* starting sector */
0443     __le32   nr_sects;  /* number of sectors in slice */
0444 };
0445 
0446 struct unixware_disklabel {
0447     __le32  d_type;         /* drive type */
0448     __le32  d_magic;        /* the magic number */
0449     __le32  d_version;      /* version number */
0450     char    d_serial[12];       /* serial number of the device */
0451     __le32  d_ncylinders;       /* # of data cylinders per device */
0452     __le32  d_ntracks;      /* # of tracks per cylinder */
0453     __le32  d_nsectors;     /* # of data sectors per track */
0454     __le32  d_secsize;      /* # of bytes per sector */
0455     __le32  d_part_start;       /* # of first sector of this partition*/
0456     __le32  d_unknown1[12];     /* ? */
0457     __le32  d_alt_tbl;      /* byte offset of alternate table */
0458     __le32  d_alt_len;      /* byte length of alternate table */
0459     __le32  d_phys_cyl;     /* # of physical cylinders per device */
0460     __le32  d_phys_trk;     /* # of physical tracks per cylinder */
0461     __le32  d_phys_sec;     /* # of physical sectors per track */
0462     __le32  d_phys_bytes;       /* # of physical bytes per sector */
0463     __le32  d_unknown2;     /* ? */
0464     __le32  d_unknown3;     /* ? */
0465     __le32  d_pad[8];       /* pad */
0466 
0467     struct unixware_vtoc {
0468         __le32  v_magic;        /* the magic number */
0469         __le32  v_version;      /* version number */
0470         char    v_name[8];      /* volume name */
0471         __le16  v_nslices;      /* # of slices */
0472         __le16  v_unknown1;     /* ? */
0473         __le32  v_reserved[10];     /* reserved */
0474         struct unixware_slice
0475             v_slice[UNIXWARE_NUMSLICE]; /* slice headers */
0476     } vtoc;
0477 };  /* 408 */
0478 
0479 /*
0480  * Create devices for Unixware partitions listed in a disklabel, under a
0481  * dos-like partition. See parse_extended() for more information.
0482  */
0483 static void parse_unixware(struct parsed_partitions *state,
0484                sector_t offset, sector_t size, int origin)
0485 {
0486 #ifdef CONFIG_UNIXWARE_DISKLABEL
0487     Sector sect;
0488     struct unixware_disklabel *l;
0489     struct unixware_slice *p;
0490 
0491     l = read_part_sector(state, offset + 29, &sect);
0492     if (!l)
0493         return;
0494     if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
0495         le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
0496         put_dev_sector(sect);
0497         return;
0498     }
0499     {
0500         char tmp[1 + BDEVNAME_SIZE + 10 + 12 + 1];
0501 
0502         snprintf(tmp, sizeof(tmp), " %s%d: <unixware:", state->name, origin);
0503         strlcat(state->pp_buf, tmp, PAGE_SIZE);
0504     }
0505     p = &l->vtoc.v_slice[1];
0506     /* I omit the 0th slice as it is the same as whole disk. */
0507     while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
0508         if (state->next == state->limit)
0509             break;
0510 
0511         if (p->s_label != UNIXWARE_FS_UNUSED)
0512             put_partition(state, state->next++,
0513                       le32_to_cpu(p->start_sect),
0514                       le32_to_cpu(p->nr_sects));
0515         p++;
0516     }
0517     put_dev_sector(sect);
0518     strlcat(state->pp_buf, " >\n", PAGE_SIZE);
0519 #endif
0520 }
0521 
0522 #define MINIX_NR_SUBPARTITIONS  4
0523 
0524 /*
0525  * Minix 2.0.0/2.0.2 subpartition support.
0526  * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
0527  * Rajeev V. Pillai    <rajeevvp@yahoo.com>
0528  */
0529 static void parse_minix(struct parsed_partitions *state,
0530             sector_t offset, sector_t size, int origin)
0531 {
0532 #ifdef CONFIG_MINIX_SUBPARTITION
0533     Sector sect;
0534     unsigned char *data;
0535     struct msdos_partition *p;
0536     int i;
0537 
0538     data = read_part_sector(state, offset, &sect);
0539     if (!data)
0540         return;
0541 
0542     p = (struct msdos_partition *)(data + 0x1be);
0543 
0544     /* The first sector of a Minix partition can have either
0545      * a secondary MBR describing its subpartitions, or
0546      * the normal boot sector. */
0547     if (msdos_magic_present(data + 510) &&
0548         p->sys_ind == MINIX_PARTITION) { /* subpartition table present */
0549         char tmp[1 + BDEVNAME_SIZE + 10 + 9 + 1];
0550 
0551         snprintf(tmp, sizeof(tmp), " %s%d: <minix:", state->name, origin);
0552         strlcat(state->pp_buf, tmp, PAGE_SIZE);
0553         for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
0554             if (state->next == state->limit)
0555                 break;
0556             /* add each partition in use */
0557             if (p->sys_ind == MINIX_PARTITION)
0558                 put_partition(state, state->next++,
0559                           start_sect(p), nr_sects(p));
0560         }
0561         strlcat(state->pp_buf, " >\n", PAGE_SIZE);
0562     }
0563     put_dev_sector(sect);
0564 #endif /* CONFIG_MINIX_SUBPARTITION */
0565 }
0566 
0567 static struct {
0568     unsigned char id;
0569     void (*parse)(struct parsed_partitions *, sector_t, sector_t, int);
0570 } subtypes[] = {
0571     {FREEBSD_PARTITION, parse_freebsd},
0572     {NETBSD_PARTITION, parse_netbsd},
0573     {OPENBSD_PARTITION, parse_openbsd},
0574     {MINIX_PARTITION, parse_minix},
0575     {UNIXWARE_PARTITION, parse_unixware},
0576     {SOLARIS_X86_PARTITION, parse_solaris_x86},
0577     {NEW_SOLARIS_X86_PARTITION, parse_solaris_x86},
0578     {0, NULL},
0579 };
0580 
0581 int msdos_partition(struct parsed_partitions *state)
0582 {
0583     sector_t sector_size;
0584     Sector sect;
0585     unsigned char *data;
0586     struct msdos_partition *p;
0587     struct fat_boot_sector *fb;
0588     int slot;
0589     u32 disksig;
0590 
0591     sector_size = queue_logical_block_size(state->disk->queue) / 512;
0592     data = read_part_sector(state, 0, &sect);
0593     if (!data)
0594         return -1;
0595 
0596     /*
0597      * Note order! (some AIX disks, e.g. unbootable kind,
0598      * have no MSDOS 55aa)
0599      */
0600     if (aix_magic_present(state, data)) {
0601         put_dev_sector(sect);
0602 #ifdef CONFIG_AIX_PARTITION
0603         return aix_partition(state);
0604 #else
0605         strlcat(state->pp_buf, " [AIX]", PAGE_SIZE);
0606         return 0;
0607 #endif
0608     }
0609 
0610     if (!msdos_magic_present(data + 510)) {
0611         put_dev_sector(sect);
0612         return 0;
0613     }
0614 
0615     /*
0616      * Now that the 55aa signature is present, this is probably
0617      * either the boot sector of a FAT filesystem or a DOS-type
0618      * partition table. Reject this in case the boot indicator
0619      * is not 0 or 0x80.
0620      */
0621     p = (struct msdos_partition *) (data + 0x1be);
0622     for (slot = 1; slot <= 4; slot++, p++) {
0623         if (p->boot_ind != 0 && p->boot_ind != 0x80) {
0624             /*
0625              * Even without a valid boot indicator value
0626              * its still possible this is valid FAT filesystem
0627              * without a partition table.
0628              */
0629             fb = (struct fat_boot_sector *) data;
0630             if (slot == 1 && fb->reserved && fb->fats
0631                 && fat_valid_media(fb->media)) {
0632                 strlcat(state->pp_buf, "\n", PAGE_SIZE);
0633                 put_dev_sector(sect);
0634                 return 1;
0635             } else {
0636                 put_dev_sector(sect);
0637                 return 0;
0638             }
0639         }
0640     }
0641 
0642 #ifdef CONFIG_EFI_PARTITION
0643     p = (struct msdos_partition *) (data + 0x1be);
0644     for (slot = 1 ; slot <= 4 ; slot++, p++) {
0645         /* If this is an EFI GPT disk, msdos should ignore it. */
0646         if (p->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT) {
0647             put_dev_sector(sect);
0648             return 0;
0649         }
0650     }
0651 #endif
0652     p = (struct msdos_partition *) (data + 0x1be);
0653 
0654     disksig = le32_to_cpup((__le32 *)(data + 0x1b8));
0655 
0656     /*
0657      * Look for partitions in two passes:
0658      * First find the primary and DOS-type extended partitions.
0659      * On the second pass look inside *BSD, Unixware and Solaris partitions.
0660      */
0661 
0662     state->next = 5;
0663     for (slot = 1 ; slot <= 4 ; slot++, p++) {
0664         sector_t start = start_sect(p)*sector_size;
0665         sector_t size = nr_sects(p)*sector_size;
0666 
0667         if (!size)
0668             continue;
0669         if (is_extended_partition(p)) {
0670             /*
0671              * prevent someone doing mkfs or mkswap on an
0672              * extended partition, but leave room for LILO
0673              * FIXME: this uses one logical sector for > 512b
0674              * sector, although it may not be enough/proper.
0675              */
0676             sector_t n = 2;
0677 
0678             n = min(size, max(sector_size, n));
0679             put_partition(state, slot, start, n);
0680 
0681             strlcat(state->pp_buf, " <", PAGE_SIZE);
0682             parse_extended(state, start, size, disksig);
0683             strlcat(state->pp_buf, " >", PAGE_SIZE);
0684             continue;
0685         }
0686         put_partition(state, slot, start, size);
0687         set_info(state, slot, disksig);
0688         if (p->sys_ind == LINUX_RAID_PARTITION)
0689             state->parts[slot].flags = ADDPART_FLAG_RAID;
0690         if (p->sys_ind == DM6_PARTITION)
0691             strlcat(state->pp_buf, "[DM]", PAGE_SIZE);
0692         if (p->sys_ind == EZD_PARTITION)
0693             strlcat(state->pp_buf, "[EZD]", PAGE_SIZE);
0694     }
0695 
0696     strlcat(state->pp_buf, "\n", PAGE_SIZE);
0697 
0698     /* second pass - output for each on a separate line */
0699     p = (struct msdos_partition *) (0x1be + data);
0700     for (slot = 1 ; slot <= 4 ; slot++, p++) {
0701         unsigned char id = p->sys_ind;
0702         int n;
0703 
0704         if (!nr_sects(p))
0705             continue;
0706 
0707         for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
0708             ;
0709 
0710         if (!subtypes[n].parse)
0711             continue;
0712         subtypes[n].parse(state, start_sect(p) * sector_size,
0713                   nr_sects(p) * sector_size, slot);
0714     }
0715     put_dev_sector(sect);
0716     return 1;
0717 }