linux/block/partitions/msdos.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  fs/partitions/msdos.c
   4 *
   5 *  Code extracted from drivers/block/genhd.c
   6 *  Copyright (C) 1991-1998  Linus Torvalds
   7 *
   8 *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
   9 *  in the early extended-partition checks and added DM partitions
  10 *
  11 *  Support for DiskManager v6.0x added by Mark Lord,
  12 *  with information provided by OnTrack.  This now works for linux fdisk
  13 *  and LILO, as well as loadlin and bootln.  Note that disks other than
  14 *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
  15 *
  16 *  More flexible handling of extended partitions - aeb, 950831
  17 *
  18 *  Check partition table on IDE disks for common CHS translations
  19 *
  20 *  Re-organised Feb 1998 Russell King
  21 */
  22#include <linux/msdos_fs.h>
  23
  24#include "check.h"
  25#include "msdos.h"
  26#include "efi.h"
  27#include "aix.h"
  28
  29/*
  30 * Many architectures don't like unaligned accesses, while
  31 * the nr_sects and start_sect partition table entries are
  32 * at a 2 (mod 4) address.
  33 */
  34#include <asm/unaligned.h>
  35
  36#define SYS_IND(p)      get_unaligned(&p->sys_ind)
  37
  38static inline sector_t nr_sects(struct partition *p)
  39{
  40        return (sector_t)get_unaligned_le32(&p->nr_sects);
  41}
  42
  43static inline sector_t start_sect(struct partition *p)
  44{
  45        return (sector_t)get_unaligned_le32(&p->start_sect);
  46}
  47
  48static inline int is_extended_partition(struct partition *p)
  49{
  50        return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
  51                SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
  52                SYS_IND(p) == LINUX_EXTENDED_PARTITION);
  53}
  54
  55#define MSDOS_LABEL_MAGIC1      0x55
  56#define MSDOS_LABEL_MAGIC2      0xAA
  57
  58static inline int
  59msdos_magic_present(unsigned char *p)
  60{
  61        return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
  62}
  63
  64/* Value is EBCDIC 'IBMA' */
  65#define AIX_LABEL_MAGIC1        0xC9
  66#define AIX_LABEL_MAGIC2        0xC2
  67#define AIX_LABEL_MAGIC3        0xD4
  68#define AIX_LABEL_MAGIC4        0xC1
  69static int aix_magic_present(struct parsed_partitions *state, unsigned char *p)
  70{
  71        struct partition *pt = (struct partition *) (p + 0x1be);
  72        Sector sect;
  73        unsigned char *d;
  74        int slot, ret = 0;
  75
  76        if (!(p[0] == AIX_LABEL_MAGIC1 &&
  77                p[1] == AIX_LABEL_MAGIC2 &&
  78                p[2] == AIX_LABEL_MAGIC3 &&
  79                p[3] == AIX_LABEL_MAGIC4))
  80                return 0;
  81        /* Assume the partition table is valid if Linux partitions exists */
  82        for (slot = 1; slot <= 4; slot++, pt++) {
  83                if (pt->sys_ind == LINUX_SWAP_PARTITION ||
  84                        pt->sys_ind == LINUX_RAID_PARTITION ||
  85                        pt->sys_ind == LINUX_DATA_PARTITION ||
  86                        pt->sys_ind == LINUX_LVM_PARTITION ||
  87                        is_extended_partition(pt))
  88                        return 0;
  89        }
  90        d = read_part_sector(state, 7, &sect);
  91        if (d) {
  92                if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M')
  93                        ret = 1;
  94                put_dev_sector(sect);
  95        }
  96        return ret;
  97}
  98
  99static void set_info(struct parsed_partitions *state, int slot,
 100                     u32 disksig)
 101{
 102        struct partition_meta_info *info = &state->parts[slot].info;
 103
 104        snprintf(info->uuid, sizeof(info->uuid), "%08x-%02x", disksig,
 105                 slot);
 106        info->volname[0] = 0;
 107        state->parts[slot].has_info = true;
 108}
 109
 110/*
 111 * Create devices for each logical partition in an extended partition.
 112 * The logical partitions form a linked list, with each entry being
 113 * a partition table with two entries.  The first entry
 114 * is the real data partition (with a start relative to the partition
 115 * table start).  The second is a pointer to the next logical partition
 116 * (with a start relative to the entire extended partition).
 117 * We do not create a Linux partition for the partition tables, but
 118 * only for the actual data partitions.
 119 */
 120
 121static void parse_extended(struct parsed_partitions *state,
 122                           sector_t first_sector, sector_t first_size,
 123                           u32 disksig)
 124{
 125        struct partition *p;
 126        Sector sect;
 127        unsigned char *data;
 128        sector_t this_sector, this_size;
 129        sector_t sector_size = bdev_logical_block_size(state->bdev) / 512;
 130        int loopct = 0;         /* number of links followed
 131                                   without finding a data partition */
 132        int i;
 133
 134        this_sector = first_sector;
 135        this_size = first_size;
 136
 137        while (1) {
 138                if (++loopct > 100)
 139                        return;
 140                if (state->next == state->limit)
 141                        return;
 142                data = read_part_sector(state, this_sector, &sect);
 143                if (!data)
 144                        return;
 145
 146                if (!msdos_magic_present(data + 510))
 147                        goto done;
 148
 149                p = (struct partition *) (data + 0x1be);
 150
 151                /*
 152                 * Usually, the first entry is the real data partition,
 153                 * the 2nd entry is the next extended partition, or empty,
 154                 * and the 3rd and 4th entries are unused.
 155                 * However, DRDOS sometimes has the extended partition as
 156                 * the first entry (when the data partition is empty),
 157                 * and OS/2 seems to use all four entries.
 158                 */
 159
 160                /*
 161                 * First process the data partition(s)
 162                 */
 163                for (i = 0; i < 4; i++, p++) {
 164                        sector_t offs, size, next;
 165
 166                        if (!nr_sects(p) || is_extended_partition(p))
 167                                continue;
 168
 169                        /* Check the 3rd and 4th entries -
 170                           these sometimes contain random garbage */
 171                        offs = start_sect(p)*sector_size;
 172                        size = nr_sects(p)*sector_size;
 173                        next = this_sector + offs;
 174                        if (i >= 2) {
 175                                if (offs + size > this_size)
 176                                        continue;
 177                                if (next < first_sector)
 178                                        continue;
 179                                if (next + size > first_sector + first_size)
 180                                        continue;
 181                        }
 182
 183                        put_partition(state, state->next, next, size);
 184                        set_info(state, state->next, disksig);
 185                        if (SYS_IND(p) == LINUX_RAID_PARTITION)
 186                                state->parts[state->next].flags = ADDPART_FLAG_RAID;
 187                        loopct = 0;
 188                        if (++state->next == state->limit)
 189                                goto done;
 190                }
 191                /*
 192                 * Next, process the (first) extended partition, if present.
 193                 * (So far, there seems to be no reason to make
 194                 *  parse_extended()  recursive and allow a tree
 195                 *  of extended partitions.)
 196                 * It should be a link to the next logical partition.
 197                 */
 198                p -= 4;
 199                for (i = 0; i < 4; i++, p++)
 200                        if (nr_sects(p) && is_extended_partition(p))
 201                                break;
 202                if (i == 4)
 203                        goto done;       /* nothing left to do */
 204
 205                this_sector = first_sector + start_sect(p) * sector_size;
 206                this_size = nr_sects(p) * sector_size;
 207                put_dev_sector(sect);
 208        }
 209done:
 210        put_dev_sector(sect);
 211}
 212
 213/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
 214   indicates linux swap.  Be careful before believing this is Solaris. */
 215
 216static void parse_solaris_x86(struct parsed_partitions *state,
 217                              sector_t offset, sector_t size, int origin)
 218{
 219#ifdef CONFIG_SOLARIS_X86_PARTITION
 220        Sector sect;
 221        struct solaris_x86_vtoc *v;
 222        int i;
 223        short max_nparts;
 224
 225        v = read_part_sector(state, offset + 1, &sect);
 226        if (!v)
 227                return;
 228        if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
 229                put_dev_sector(sect);
 230                return;
 231        }
 232        {
 233                char tmp[1 + BDEVNAME_SIZE + 10 + 11 + 1];
 234
 235                snprintf(tmp, sizeof(tmp), " %s%d: <solaris:", state->name, origin);
 236                strlcat(state->pp_buf, tmp, PAGE_SIZE);
 237        }
 238        if (le32_to_cpu(v->v_version) != 1) {
 239                char tmp[64];
 240
 241                snprintf(tmp, sizeof(tmp), "  cannot handle version %d vtoc>\n",
 242                         le32_to_cpu(v->v_version));
 243                strlcat(state->pp_buf, tmp, PAGE_SIZE);
 244                put_dev_sector(sect);
 245                return;
 246        }
 247        /* Ensure we can handle previous case of VTOC with 8 entries gracefully */
 248        max_nparts = le16_to_cpu(v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
 249        for (i = 0; i < max_nparts && state->next < state->limit; i++) {
 250                struct solaris_x86_slice *s = &v->v_slice[i];
 251                char tmp[3 + 10 + 1 + 1];
 252
 253                if (s->s_size == 0)
 254                        continue;
 255                snprintf(tmp, sizeof(tmp), " [s%d]", i);
 256                strlcat(state->pp_buf, tmp, PAGE_SIZE);
 257                /* solaris partitions are relative to current MS-DOS
 258                 * one; must add the offset of the current partition */
 259                put_partition(state, state->next++,
 260                                 le32_to_cpu(s->s_start)+offset,
 261                                 le32_to_cpu(s->s_size));
 262        }
 263        put_dev_sector(sect);
 264        strlcat(state->pp_buf, " >\n", PAGE_SIZE);
 265#endif
 266}
 267
 268#if defined(CONFIG_BSD_DISKLABEL)
 269/*
 270 * Create devices for BSD partitions listed in a disklabel, under a
 271 * dos-like partition. See parse_extended() for more information.
 272 */
 273static void parse_bsd(struct parsed_partitions *state,
 274                      sector_t offset, sector_t size, int origin, char *flavour,
 275                      int max_partitions)
 276{
 277        Sector sect;
 278        struct bsd_disklabel *l;
 279        struct bsd_partition *p;
 280        char tmp[64];
 281
 282        l = read_part_sector(state, offset + 1, &sect);
 283        if (!l)
 284                return;
 285        if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
 286                put_dev_sector(sect);
 287                return;
 288        }
 289
 290        snprintf(tmp, sizeof(tmp), " %s%d: <%s:", state->name, origin, flavour);
 291        strlcat(state->pp_buf, tmp, PAGE_SIZE);
 292
 293        if (le16_to_cpu(l->d_npartitions) < max_partitions)
 294                max_partitions = le16_to_cpu(l->d_npartitions);
 295        for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
 296                sector_t bsd_start, bsd_size;
 297
 298                if (state->next == state->limit)
 299                        break;
 300                if (p->p_fstype == BSD_FS_UNUSED)
 301                        continue;
 302                bsd_start = le32_to_cpu(p->p_offset);
 303                bsd_size = le32_to_cpu(p->p_size);
 304                /* FreeBSD has relative offset if C partition offset is zero */
 305                if (memcmp(flavour, "bsd\0", 4) == 0 &&
 306                    le32_to_cpu(l->d_partitions[2].p_offset) == 0)
 307                        bsd_start += offset;
 308                if (offset == bsd_start && size == bsd_size)
 309                        /* full parent partition, we have it already */
 310                        continue;
 311                if (offset > bsd_start || offset+size < bsd_start+bsd_size) {
 312                        strlcat(state->pp_buf, "bad subpartition - ignored\n", PAGE_SIZE);
 313                        continue;
 314                }
 315                put_partition(state, state->next++, bsd_start, bsd_size);
 316        }
 317        put_dev_sector(sect);
 318        if (le16_to_cpu(l->d_npartitions) > max_partitions) {
 319                snprintf(tmp, sizeof(tmp), " (ignored %d more)",
 320                         le16_to_cpu(l->d_npartitions) - max_partitions);
 321                strlcat(state->pp_buf, tmp, PAGE_SIZE);
 322        }
 323        strlcat(state->pp_buf, " >\n", PAGE_SIZE);
 324}
 325#endif
 326
 327static void parse_freebsd(struct parsed_partitions *state,
 328                          sector_t offset, sector_t size, int origin)
 329{
 330#ifdef CONFIG_BSD_DISKLABEL
 331        parse_bsd(state, offset, size, origin, "bsd", BSD_MAXPARTITIONS);
 332#endif
 333}
 334
 335static void parse_netbsd(struct parsed_partitions *state,
 336                         sector_t offset, sector_t size, int origin)
 337{
 338#ifdef CONFIG_BSD_DISKLABEL
 339        parse_bsd(state, offset, size, origin, "netbsd", BSD_MAXPARTITIONS);
 340#endif
 341}
 342
 343static void parse_openbsd(struct parsed_partitions *state,
 344                          sector_t offset, sector_t size, int origin)
 345{
 346#ifdef CONFIG_BSD_DISKLABEL
 347        parse_bsd(state, offset, size, origin, "openbsd",
 348                  OPENBSD_MAXPARTITIONS);
 349#endif
 350}
 351
 352/*
 353 * Create devices for Unixware partitions listed in a disklabel, under a
 354 * dos-like partition. See parse_extended() for more information.
 355 */
 356static void parse_unixware(struct parsed_partitions *state,
 357                           sector_t offset, sector_t size, int origin)
 358{
 359#ifdef CONFIG_UNIXWARE_DISKLABEL
 360        Sector sect;
 361        struct unixware_disklabel *l;
 362        struct unixware_slice *p;
 363
 364        l = read_part_sector(state, offset + 29, &sect);
 365        if (!l)
 366                return;
 367        if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
 368            le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
 369                put_dev_sector(sect);
 370                return;
 371        }
 372        {
 373                char tmp[1 + BDEVNAME_SIZE + 10 + 12 + 1];
 374
 375                snprintf(tmp, sizeof(tmp), " %s%d: <unixware:", state->name, origin);
 376                strlcat(state->pp_buf, tmp, PAGE_SIZE);
 377        }
 378        p = &l->vtoc.v_slice[1];
 379        /* I omit the 0th slice as it is the same as whole disk. */
 380        while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
 381                if (state->next == state->limit)
 382                        break;
 383
 384                if (p->s_label != UNIXWARE_FS_UNUSED)
 385                        put_partition(state, state->next++,
 386                                      le32_to_cpu(p->start_sect),
 387                                      le32_to_cpu(p->nr_sects));
 388                p++;
 389        }
 390        put_dev_sector(sect);
 391        strlcat(state->pp_buf, " >\n", PAGE_SIZE);
 392#endif
 393}
 394
 395/*
 396 * Minix 2.0.0/2.0.2 subpartition support.
 397 * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
 398 * Rajeev V. Pillai    <rajeevvp@yahoo.com>
 399 */
 400static void parse_minix(struct parsed_partitions *state,
 401                        sector_t offset, sector_t size, int origin)
 402{
 403#ifdef CONFIG_MINIX_SUBPARTITION
 404        Sector sect;
 405        unsigned char *data;
 406        struct partition *p;
 407        int i;
 408
 409        data = read_part_sector(state, offset, &sect);
 410        if (!data)
 411                return;
 412
 413        p = (struct partition *)(data + 0x1be);
 414
 415        /* The first sector of a Minix partition can have either
 416         * a secondary MBR describing its subpartitions, or
 417         * the normal boot sector. */
 418        if (msdos_magic_present(data + 510) &&
 419            SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
 420                char tmp[1 + BDEVNAME_SIZE + 10 + 9 + 1];
 421
 422                snprintf(tmp, sizeof(tmp), " %s%d: <minix:", state->name, origin);
 423                strlcat(state->pp_buf, tmp, PAGE_SIZE);
 424                for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
 425                        if (state->next == state->limit)
 426                                break;
 427                        /* add each partition in use */
 428                        if (SYS_IND(p) == MINIX_PARTITION)
 429                                put_partition(state, state->next++,
 430                                              start_sect(p), nr_sects(p));
 431                }
 432                strlcat(state->pp_buf, " >\n", PAGE_SIZE);
 433        }
 434        put_dev_sector(sect);
 435#endif /* CONFIG_MINIX_SUBPARTITION */
 436}
 437
 438static struct {
 439        unsigned char id;
 440        void (*parse)(struct parsed_partitions *, sector_t, sector_t, int);
 441} subtypes[] = {
 442        {FREEBSD_PARTITION, parse_freebsd},
 443        {NETBSD_PARTITION, parse_netbsd},
 444        {OPENBSD_PARTITION, parse_openbsd},
 445        {MINIX_PARTITION, parse_minix},
 446        {UNIXWARE_PARTITION, parse_unixware},
 447        {SOLARIS_X86_PARTITION, parse_solaris_x86},
 448        {NEW_SOLARIS_X86_PARTITION, parse_solaris_x86},
 449        {0, NULL},
 450};
 451
 452int msdos_partition(struct parsed_partitions *state)
 453{
 454        sector_t sector_size = bdev_logical_block_size(state->bdev) / 512;
 455        Sector sect;
 456        unsigned char *data;
 457        struct partition *p;
 458        struct fat_boot_sector *fb;
 459        int slot;
 460        u32 disksig;
 461
 462        data = read_part_sector(state, 0, &sect);
 463        if (!data)
 464                return -1;
 465
 466        /*
 467         * Note order! (some AIX disks, e.g. unbootable kind,
 468         * have no MSDOS 55aa)
 469         */
 470        if (aix_magic_present(state, data)) {
 471                put_dev_sector(sect);
 472#ifdef CONFIG_AIX_PARTITION
 473                return aix_partition(state);
 474#else
 475                strlcat(state->pp_buf, " [AIX]", PAGE_SIZE);
 476                return 0;
 477#endif
 478        }
 479
 480        if (!msdos_magic_present(data + 510)) {
 481                put_dev_sector(sect);
 482                return 0;
 483        }
 484
 485        /*
 486         * Now that the 55aa signature is present, this is probably
 487         * either the boot sector of a FAT filesystem or a DOS-type
 488         * partition table. Reject this in case the boot indicator
 489         * is not 0 or 0x80.
 490         */
 491        p = (struct partition *) (data + 0x1be);
 492        for (slot = 1; slot <= 4; slot++, p++) {
 493                if (p->boot_ind != 0 && p->boot_ind != 0x80) {
 494                        /*
 495                         * Even without a valid boot inidicator value
 496                         * its still possible this is valid FAT filesystem
 497                         * without a partition table.
 498                         */
 499                        fb = (struct fat_boot_sector *) data;
 500                        if (slot == 1 && fb->reserved && fb->fats
 501                                && fat_valid_media(fb->media)) {
 502                                strlcat(state->pp_buf, "\n", PAGE_SIZE);
 503                                put_dev_sector(sect);
 504                                return 1;
 505                        } else {
 506                                put_dev_sector(sect);
 507                                return 0;
 508                        }
 509                }
 510        }
 511
 512#ifdef CONFIG_EFI_PARTITION
 513        p = (struct partition *) (data + 0x1be);
 514        for (slot = 1 ; slot <= 4 ; slot++, p++) {
 515                /* If this is an EFI GPT disk, msdos should ignore it. */
 516                if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) {
 517                        put_dev_sector(sect);
 518                        return 0;
 519                }
 520        }
 521#endif
 522        p = (struct partition *) (data + 0x1be);
 523
 524        disksig = le32_to_cpup((__le32 *)(data + 0x1b8));
 525
 526        /*
 527         * Look for partitions in two passes:
 528         * First find the primary and DOS-type extended partitions.
 529         * On the second pass look inside *BSD, Unixware and Solaris partitions.
 530         */
 531
 532        state->next = 5;
 533        for (slot = 1 ; slot <= 4 ; slot++, p++) {
 534                sector_t start = start_sect(p)*sector_size;
 535                sector_t size = nr_sects(p)*sector_size;
 536
 537                if (!size)
 538                        continue;
 539                if (is_extended_partition(p)) {
 540                        /*
 541                         * prevent someone doing mkfs or mkswap on an
 542                         * extended partition, but leave room for LILO
 543                         * FIXME: this uses one logical sector for > 512b
 544                         * sector, although it may not be enough/proper.
 545                         */
 546                        sector_t n = 2;
 547
 548                        n = min(size, max(sector_size, n));
 549                        put_partition(state, slot, start, n);
 550
 551                        strlcat(state->pp_buf, " <", PAGE_SIZE);
 552                        parse_extended(state, start, size, disksig);
 553                        strlcat(state->pp_buf, " >", PAGE_SIZE);
 554                        continue;
 555                }
 556                put_partition(state, slot, start, size);
 557                set_info(state, slot, disksig);
 558                if (SYS_IND(p) == LINUX_RAID_PARTITION)
 559                        state->parts[slot].flags = ADDPART_FLAG_RAID;
 560                if (SYS_IND(p) == DM6_PARTITION)
 561                        strlcat(state->pp_buf, "[DM]", PAGE_SIZE);
 562                if (SYS_IND(p) == EZD_PARTITION)
 563                        strlcat(state->pp_buf, "[EZD]", PAGE_SIZE);
 564        }
 565
 566        strlcat(state->pp_buf, "\n", PAGE_SIZE);
 567
 568        /* second pass - output for each on a separate line */
 569        p = (struct partition *) (0x1be + data);
 570        for (slot = 1 ; slot <= 4 ; slot++, p++) {
 571                unsigned char id = SYS_IND(p);
 572                int n;
 573
 574                if (!nr_sects(p))
 575                        continue;
 576
 577                for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
 578                        ;
 579
 580                if (!subtypes[n].parse)
 581                        continue;
 582                subtypes[n].parse(state, start_sect(p) * sector_size,
 583                                  nr_sects(p) * sector_size, slot);
 584        }
 585        put_dev_sector(sect);
 586        return 1;
 587}
 588