718 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * fs/partitions/msdos.c4 *5 * Code extracted from drivers/block/genhd.c6 * Copyright (C) 1991-1998 Linus Torvalds7 *8 * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug9 * in the early extended-partition checks and added DM partitions10 *11 * Support for DiskManager v6.0x added by Mark Lord,12 * with information provided by OnTrack. This now works for linux fdisk13 * and LILO, as well as loadlin and bootln. Note that disks other than14 * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).15 *16 * More flexible handling of extended partitions - aeb, 95083117 *18 * Check partition table on IDE disks for common CHS translations19 *20 * Re-organised Feb 1998 Russell King21 *22 * BSD disklabel support by Yossi Gottlieb <yogo@math.tau.ac.il>23 * updated by Marc Espie <Marc.Espie@openbsd.org>24 *25 * Unixware slices support by Andrzej Krzysztofowicz <ankry@mif.pg.gda.pl>26 * and Krzysztof G. Baranowski <kgb@knm.org.pl>27 */28#include <linux/msdos_fs.h>29#include <linux/msdos_partition.h>30 31#include "check.h"32#include "efi.h"33 34/*35 * Many architectures don't like unaligned accesses, while36 * the nr_sects and start_sect partition table entries are37 * at a 2 (mod 4) address.38 */39#include <linux/unaligned.h>40 41static inline sector_t nr_sects(struct msdos_partition *p)42{43 return (sector_t)get_unaligned_le32(&p->nr_sects);44}45 46static inline sector_t start_sect(struct msdos_partition *p)47{48 return (sector_t)get_unaligned_le32(&p->start_sect);49}50 51static inline int is_extended_partition(struct msdos_partition *p)52{53 return (p->sys_ind == DOS_EXTENDED_PARTITION ||54 p->sys_ind == WIN98_EXTENDED_PARTITION ||55 p->sys_ind == LINUX_EXTENDED_PARTITION);56}57 58#define MSDOS_LABEL_MAGIC1 0x5559#define MSDOS_LABEL_MAGIC2 0xAA60 61static inline int62msdos_magic_present(unsigned char *p)63{64 return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);65}66 67/* Value is EBCDIC 'IBMA' */68#define AIX_LABEL_MAGIC1 0xC969#define AIX_LABEL_MAGIC2 0xC270#define AIX_LABEL_MAGIC3 0xD471#define AIX_LABEL_MAGIC4 0xC172static int aix_magic_present(struct parsed_partitions *state, unsigned char *p)73{74 struct msdos_partition *pt = (struct msdos_partition *) (p + 0x1be);75 Sector sect;76 unsigned char *d;77 int slot, ret = 0;78 79 if (!(p[0] == AIX_LABEL_MAGIC1 &&80 p[1] == AIX_LABEL_MAGIC2 &&81 p[2] == AIX_LABEL_MAGIC3 &&82 p[3] == AIX_LABEL_MAGIC4))83 return 0;84 85 /*86 * Assume the partition table is valid if Linux partitions exists.87 * Note that old Solaris/x86 partitions use the same indicator as88 * Linux swap partitions, so we consider that a Linux partition as89 * well.90 */91 for (slot = 1; slot <= 4; slot++, pt++) {92 if (pt->sys_ind == SOLARIS_X86_PARTITION ||93 pt->sys_ind == LINUX_RAID_PARTITION ||94 pt->sys_ind == LINUX_DATA_PARTITION ||95 pt->sys_ind == LINUX_LVM_PARTITION ||96 is_extended_partition(pt))97 return 0;98 }99 d = read_part_sector(state, 7, §);100 if (d) {101 if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M')102 ret = 1;103 put_dev_sector(sect);104 }105 return ret;106}107 108static void set_info(struct parsed_partitions *state, int slot,109 u32 disksig)110{111 struct partition_meta_info *info = &state->parts[slot].info;112 113 snprintf(info->uuid, sizeof(info->uuid), "%08x-%02x", disksig,114 slot);115 info->volname[0] = 0;116 state->parts[slot].has_info = true;117}118 119/*120 * Create devices for each logical partition in an extended partition.121 * The logical partitions form a linked list, with each entry being122 * a partition table with two entries. The first entry123 * is the real data partition (with a start relative to the partition124 * table start). The second is a pointer to the next logical partition125 * (with a start relative to the entire extended partition).126 * We do not create a Linux partition for the partition tables, but127 * only for the actual data partitions.128 */129 130static void parse_extended(struct parsed_partitions *state,131 sector_t first_sector, sector_t first_size,132 u32 disksig)133{134 struct msdos_partition *p;135 Sector sect;136 unsigned char *data;137 sector_t this_sector, this_size;138 sector_t sector_size;139 int loopct = 0; /* number of links followed140 without finding a data partition */141 int i;142 143 sector_size = queue_logical_block_size(state->disk->queue) / 512;144 this_sector = first_sector;145 this_size = first_size;146 147 while (1) {148 if (++loopct > 100)149 return;150 if (state->next == state->limit)151 return;152 data = read_part_sector(state, this_sector, §);153 if (!data)154 return;155 156 if (!msdos_magic_present(data + 510))157 goto done;158 159 p = (struct msdos_partition *) (data + 0x1be);160 161 /*162 * Usually, the first entry is the real data partition,163 * the 2nd entry is the next extended partition, or empty,164 * and the 3rd and 4th entries are unused.165 * However, DRDOS sometimes has the extended partition as166 * the first entry (when the data partition is empty),167 * and OS/2 seems to use all four entries.168 */169 170 /*171 * First process the data partition(s)172 */173 for (i = 0; i < 4; i++, p++) {174 sector_t offs, size, next;175 176 if (!nr_sects(p) || is_extended_partition(p))177 continue;178 179 /* Check the 3rd and 4th entries -180 these sometimes contain random garbage */181 offs = start_sect(p)*sector_size;182 size = nr_sects(p)*sector_size;183 next = this_sector + offs;184 if (i >= 2) {185 if (offs + size > this_size)186 continue;187 if (next < first_sector)188 continue;189 if (next + size > first_sector + first_size)190 continue;191 }192 193 put_partition(state, state->next, next, size);194 set_info(state, state->next, disksig);195 if (p->sys_ind == LINUX_RAID_PARTITION)196 state->parts[state->next].flags = ADDPART_FLAG_RAID;197 loopct = 0;198 if (++state->next == state->limit)199 goto done;200 }201 /*202 * Next, process the (first) extended partition, if present.203 * (So far, there seems to be no reason to make204 * parse_extended() recursive and allow a tree205 * of extended partitions.)206 * It should be a link to the next logical partition.207 */208 p -= 4;209 for (i = 0; i < 4; i++, p++)210 if (nr_sects(p) && is_extended_partition(p))211 break;212 if (i == 4)213 goto done; /* nothing left to do */214 215 this_sector = first_sector + start_sect(p) * sector_size;216 this_size = nr_sects(p) * sector_size;217 put_dev_sector(sect);218 }219done:220 put_dev_sector(sect);221}222 223#define SOLARIS_X86_NUMSLICE 16224#define SOLARIS_X86_VTOC_SANE (0x600DDEEEUL)225 226struct solaris_x86_slice {227 __le16 s_tag; /* ID tag of partition */228 __le16 s_flag; /* permission flags */229 __le32 s_start; /* start sector no of partition */230 __le32 s_size; /* # of blocks in partition */231};232 233struct solaris_x86_vtoc {234 unsigned int v_bootinfo[3]; /* info needed by mboot */235 __le32 v_sanity; /* to verify vtoc sanity */236 __le32 v_version; /* layout version */237 char v_volume[8]; /* volume name */238 __le16 v_sectorsz; /* sector size in bytes */239 __le16 v_nparts; /* number of partitions */240 unsigned int v_reserved[10]; /* free space */241 struct solaris_x86_slice242 v_slice[SOLARIS_X86_NUMSLICE]; /* slice headers */243 unsigned int timestamp[SOLARIS_X86_NUMSLICE]; /* timestamp */244 char v_asciilabel[128]; /* for compatibility */245};246 247/* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also248 indicates linux swap. Be careful before believing this is Solaris. */249 250static void parse_solaris_x86(struct parsed_partitions *state,251 sector_t offset, sector_t size, int origin)252{253#ifdef CONFIG_SOLARIS_X86_PARTITION254 Sector sect;255 struct solaris_x86_vtoc *v;256 int i;257 short max_nparts;258 259 v = read_part_sector(state, offset + 1, §);260 if (!v)261 return;262 if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {263 put_dev_sector(sect);264 return;265 }266 {267 char tmp[1 + BDEVNAME_SIZE + 10 + 11 + 1];268 269 snprintf(tmp, sizeof(tmp), " %s%d: <solaris:", state->name, origin);270 strlcat(state->pp_buf, tmp, PAGE_SIZE);271 }272 if (le32_to_cpu(v->v_version) != 1) {273 char tmp[64];274 275 snprintf(tmp, sizeof(tmp), " cannot handle version %d vtoc>\n",276 le32_to_cpu(v->v_version));277 strlcat(state->pp_buf, tmp, PAGE_SIZE);278 put_dev_sector(sect);279 return;280 }281 /* Ensure we can handle previous case of VTOC with 8 entries gracefully */282 max_nparts = le16_to_cpu(v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;283 for (i = 0; i < max_nparts && state->next < state->limit; i++) {284 struct solaris_x86_slice *s = &v->v_slice[i];285 char tmp[3 + 10 + 1 + 1];286 287 if (s->s_size == 0)288 continue;289 snprintf(tmp, sizeof(tmp), " [s%d]", i);290 strlcat(state->pp_buf, tmp, PAGE_SIZE);291 /* solaris partitions are relative to current MS-DOS292 * one; must add the offset of the current partition */293 put_partition(state, state->next++,294 le32_to_cpu(s->s_start)+offset,295 le32_to_cpu(s->s_size));296 }297 put_dev_sector(sect);298 strlcat(state->pp_buf, " >\n", PAGE_SIZE);299#endif300}301 302/* check against BSD src/sys/sys/disklabel.h for consistency */303#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */304#define BSD_MAXPARTITIONS 16305#define OPENBSD_MAXPARTITIONS 16306#define BSD_FS_UNUSED 0 /* disklabel unused partition entry ID */307struct bsd_disklabel {308 __le32 d_magic; /* the magic number */309 __s16 d_type; /* drive type */310 __s16 d_subtype; /* controller/d_type specific */311 char d_typename[16]; /* type name, e.g. "eagle" */312 char d_packname[16]; /* pack identifier */313 __u32 d_secsize; /* # of bytes per sector */314 __u32 d_nsectors; /* # of data sectors per track */315 __u32 d_ntracks; /* # of tracks per cylinder */316 __u32 d_ncylinders; /* # of data cylinders per unit */317 __u32 d_secpercyl; /* # of data sectors per cylinder */318 __u32 d_secperunit; /* # of data sectors per unit */319 __u16 d_sparespertrack; /* # of spare sectors per track */320 __u16 d_sparespercyl; /* # of spare sectors per cylinder */321 __u32 d_acylinders; /* # of alt. cylinders per unit */322 __u16 d_rpm; /* rotational speed */323 __u16 d_interleave; /* hardware sector interleave */324 __u16 d_trackskew; /* sector 0 skew, per track */325 __u16 d_cylskew; /* sector 0 skew, per cylinder */326 __u32 d_headswitch; /* head switch time, usec */327 __u32 d_trkseek; /* track-to-track seek, usec */328 __u32 d_flags; /* generic flags */329#define NDDATA 5330 __u32 d_drivedata[NDDATA]; /* drive-type specific information */331#define NSPARE 5332 __u32 d_spare[NSPARE]; /* reserved for future use */333 __le32 d_magic2; /* the magic number (again) */334 __le16 d_checksum; /* xor of data incl. partitions */335 336 /* filesystem and partition information: */337 __le16 d_npartitions; /* number of partitions in following */338 __le32 d_bbsize; /* size of boot area at sn0, bytes */339 __le32 d_sbsize; /* max size of fs superblock, bytes */340 struct bsd_partition { /* the partition table */341 __le32 p_size; /* number of sectors in partition */342 __le32 p_offset; /* starting sector */343 __le32 p_fsize; /* filesystem basic fragment size */344 __u8 p_fstype; /* filesystem type, see below */345 __u8 p_frag; /* filesystem fragments per block */346 __le16 p_cpg; /* filesystem cylinders per group */347 } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */348};349 350#if defined(CONFIG_BSD_DISKLABEL)351/*352 * Create devices for BSD partitions listed in a disklabel, under a353 * dos-like partition. See parse_extended() for more information.354 */355static void parse_bsd(struct parsed_partitions *state,356 sector_t offset, sector_t size, int origin, char *flavour,357 int max_partitions)358{359 Sector sect;360 struct bsd_disklabel *l;361 struct bsd_partition *p;362 char tmp[64];363 364 l = read_part_sector(state, offset + 1, §);365 if (!l)366 return;367 if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {368 put_dev_sector(sect);369 return;370 }371 372 snprintf(tmp, sizeof(tmp), " %s%d: <%s:", state->name, origin, flavour);373 strlcat(state->pp_buf, tmp, PAGE_SIZE);374 375 if (le16_to_cpu(l->d_npartitions) < max_partitions)376 max_partitions = le16_to_cpu(l->d_npartitions);377 for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {378 sector_t bsd_start, bsd_size;379 380 if (state->next == state->limit)381 break;382 if (p->p_fstype == BSD_FS_UNUSED)383 continue;384 bsd_start = le32_to_cpu(p->p_offset);385 bsd_size = le32_to_cpu(p->p_size);386 /* FreeBSD has relative offset if C partition offset is zero */387 if (memcmp(flavour, "bsd\0", 4) == 0 &&388 le32_to_cpu(l->d_partitions[2].p_offset) == 0)389 bsd_start += offset;390 if (offset == bsd_start && size == bsd_size)391 /* full parent partition, we have it already */392 continue;393 if (offset > bsd_start || offset+size < bsd_start+bsd_size) {394 strlcat(state->pp_buf, "bad subpartition - ignored\n", PAGE_SIZE);395 continue;396 }397 put_partition(state, state->next++, bsd_start, bsd_size);398 }399 put_dev_sector(sect);400 if (le16_to_cpu(l->d_npartitions) > max_partitions) {401 snprintf(tmp, sizeof(tmp), " (ignored %d more)",402 le16_to_cpu(l->d_npartitions) - max_partitions);403 strlcat(state->pp_buf, tmp, PAGE_SIZE);404 }405 strlcat(state->pp_buf, " >\n", PAGE_SIZE);406}407#endif408 409static void parse_freebsd(struct parsed_partitions *state,410 sector_t offset, sector_t size, int origin)411{412#ifdef CONFIG_BSD_DISKLABEL413 parse_bsd(state, offset, size, origin, "bsd", BSD_MAXPARTITIONS);414#endif415}416 417static void parse_netbsd(struct parsed_partitions *state,418 sector_t offset, sector_t size, int origin)419{420#ifdef CONFIG_BSD_DISKLABEL421 parse_bsd(state, offset, size, origin, "netbsd", BSD_MAXPARTITIONS);422#endif423}424 425static void parse_openbsd(struct parsed_partitions *state,426 sector_t offset, sector_t size, int origin)427{428#ifdef CONFIG_BSD_DISKLABEL429 parse_bsd(state, offset, size, origin, "openbsd",430 OPENBSD_MAXPARTITIONS);431#endif432}433 434#define UNIXWARE_DISKMAGIC (0xCA5E600DUL) /* The disk magic number */435#define UNIXWARE_DISKMAGIC2 (0x600DDEEEUL) /* The slice table magic nr */436#define UNIXWARE_NUMSLICE 16437#define UNIXWARE_FS_UNUSED 0 /* Unused slice entry ID */438 439struct unixware_slice {440 __le16 s_label; /* label */441 __le16 s_flags; /* permission flags */442 __le32 start_sect; /* starting sector */443 __le32 nr_sects; /* number of sectors in slice */444};445 446struct unixware_disklabel {447 __le32 d_type; /* drive type */448 __le32 d_magic; /* the magic number */449 __le32 d_version; /* version number */450 char d_serial[12]; /* serial number of the device */451 __le32 d_ncylinders; /* # of data cylinders per device */452 __le32 d_ntracks; /* # of tracks per cylinder */453 __le32 d_nsectors; /* # of data sectors per track */454 __le32 d_secsize; /* # of bytes per sector */455 __le32 d_part_start; /* # of first sector of this partition*/456 __le32 d_unknown1[12]; /* ? */457 __le32 d_alt_tbl; /* byte offset of alternate table */458 __le32 d_alt_len; /* byte length of alternate table */459 __le32 d_phys_cyl; /* # of physical cylinders per device */460 __le32 d_phys_trk; /* # of physical tracks per cylinder */461 __le32 d_phys_sec; /* # of physical sectors per track */462 __le32 d_phys_bytes; /* # of physical bytes per sector */463 __le32 d_unknown2; /* ? */464 __le32 d_unknown3; /* ? */465 __le32 d_pad[8]; /* pad */466 467 struct unixware_vtoc {468 __le32 v_magic; /* the magic number */469 __le32 v_version; /* version number */470 char v_name[8]; /* volume name */471 __le16 v_nslices; /* # of slices */472 __le16 v_unknown1; /* ? */473 __le32 v_reserved[10]; /* reserved */474 struct unixware_slice475 v_slice[UNIXWARE_NUMSLICE]; /* slice headers */476 } vtoc;477}; /* 408 */478 479/*480 * Create devices for Unixware partitions listed in a disklabel, under a481 * dos-like partition. See parse_extended() for more information.482 */483static void parse_unixware(struct parsed_partitions *state,484 sector_t offset, sector_t size, int origin)485{486#ifdef CONFIG_UNIXWARE_DISKLABEL487 Sector sect;488 struct unixware_disklabel *l;489 struct unixware_slice *p;490 491 l = read_part_sector(state, offset + 29, §);492 if (!l)493 return;494 if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||495 le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {496 put_dev_sector(sect);497 return;498 }499 {500 char tmp[1 + BDEVNAME_SIZE + 10 + 12 + 1];501 502 snprintf(tmp, sizeof(tmp), " %s%d: <unixware:", state->name, origin);503 strlcat(state->pp_buf, tmp, PAGE_SIZE);504 }505 p = &l->vtoc.v_slice[1];506 /* I omit the 0th slice as it is the same as whole disk. */507 while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {508 if (state->next == state->limit)509 break;510 511 if (p->s_label != UNIXWARE_FS_UNUSED)512 put_partition(state, state->next++,513 le32_to_cpu(p->start_sect),514 le32_to_cpu(p->nr_sects));515 p++;516 }517 put_dev_sector(sect);518 strlcat(state->pp_buf, " >\n", PAGE_SIZE);519#endif520}521 522#define MINIX_NR_SUBPARTITIONS 4523 524/*525 * Minix 2.0.0/2.0.2 subpartition support.526 * Anand Krishnamurthy <anandk@wiproge.med.ge.com>527 * Rajeev V. Pillai <rajeevvp@yahoo.com>528 */529static void parse_minix(struct parsed_partitions *state,530 sector_t offset, sector_t size, int origin)531{532#ifdef CONFIG_MINIX_SUBPARTITION533 Sector sect;534 unsigned char *data;535 struct msdos_partition *p;536 int i;537 538 data = read_part_sector(state, offset, §);539 if (!data)540 return;541 542 p = (struct msdos_partition *)(data + 0x1be);543 544 /* The first sector of a Minix partition can have either545 * a secondary MBR describing its subpartitions, or546 * the normal boot sector. */547 if (msdos_magic_present(data + 510) &&548 p->sys_ind == MINIX_PARTITION) { /* subpartition table present */549 char tmp[1 + BDEVNAME_SIZE + 10 + 9 + 1];550 551 snprintf(tmp, sizeof(tmp), " %s%d: <minix:", state->name, origin);552 strlcat(state->pp_buf, tmp, PAGE_SIZE);553 for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {554 if (state->next == state->limit)555 break;556 /* add each partition in use */557 if (p->sys_ind == MINIX_PARTITION)558 put_partition(state, state->next++,559 start_sect(p), nr_sects(p));560 }561 strlcat(state->pp_buf, " >\n", PAGE_SIZE);562 }563 put_dev_sector(sect);564#endif /* CONFIG_MINIX_SUBPARTITION */565}566 567static struct {568 unsigned char id;569 void (*parse)(struct parsed_partitions *, sector_t, sector_t, int);570} subtypes[] = {571 {FREEBSD_PARTITION, parse_freebsd},572 {NETBSD_PARTITION, parse_netbsd},573 {OPENBSD_PARTITION, parse_openbsd},574 {MINIX_PARTITION, parse_minix},575 {UNIXWARE_PARTITION, parse_unixware},576 {SOLARIS_X86_PARTITION, parse_solaris_x86},577 {NEW_SOLARIS_X86_PARTITION, parse_solaris_x86},578 {0, NULL},579};580 581int msdos_partition(struct parsed_partitions *state)582{583 sector_t sector_size;584 Sector sect;585 unsigned char *data;586 struct msdos_partition *p;587 struct fat_boot_sector *fb;588 int slot;589 u32 disksig;590 591 sector_size = queue_logical_block_size(state->disk->queue) / 512;592 data = read_part_sector(state, 0, §);593 if (!data)594 return -1;595 596 /*597 * Note order! (some AIX disks, e.g. unbootable kind,598 * have no MSDOS 55aa)599 */600 if (aix_magic_present(state, data)) {601 put_dev_sector(sect);602#ifdef CONFIG_AIX_PARTITION603 return aix_partition(state);604#else605 strlcat(state->pp_buf, " [AIX]", PAGE_SIZE);606 return 0;607#endif608 }609 610 if (!msdos_magic_present(data + 510)) {611 put_dev_sector(sect);612 return 0;613 }614 615 /*616 * Now that the 55aa signature is present, this is probably617 * either the boot sector of a FAT filesystem or a DOS-type618 * partition table. Reject this in case the boot indicator619 * is not 0 or 0x80.620 */621 p = (struct msdos_partition *) (data + 0x1be);622 for (slot = 1; slot <= 4; slot++, p++) {623 if (p->boot_ind != 0 && p->boot_ind != 0x80) {624 /*625 * Even without a valid boot indicator value626 * its still possible this is valid FAT filesystem627 * without a partition table.628 */629 fb = (struct fat_boot_sector *) data;630 if (slot == 1 && fb->reserved && fb->fats631 && fat_valid_media(fb->media)) {632 strlcat(state->pp_buf, "\n", PAGE_SIZE);633 put_dev_sector(sect);634 return 1;635 } else {636 put_dev_sector(sect);637 return 0;638 }639 }640 }641 642#ifdef CONFIG_EFI_PARTITION643 p = (struct msdos_partition *) (data + 0x1be);644 for (slot = 1 ; slot <= 4 ; slot++, p++) {645 /* If this is an EFI GPT disk, msdos should ignore it. */646 if (p->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT) {647 put_dev_sector(sect);648 return 0;649 }650 }651#endif652 p = (struct msdos_partition *) (data + 0x1be);653 654 disksig = le32_to_cpup((__le32 *)(data + 0x1b8));655 656 /*657 * Look for partitions in two passes:658 * First find the primary and DOS-type extended partitions.659 * On the second pass look inside *BSD, Unixware and Solaris partitions.660 */661 662 state->next = 5;663 for (slot = 1 ; slot <= 4 ; slot++, p++) {664 sector_t start = start_sect(p)*sector_size;665 sector_t size = nr_sects(p)*sector_size;666 667 if (!size)668 continue;669 if (is_extended_partition(p)) {670 /*671 * prevent someone doing mkfs or mkswap on an672 * extended partition, but leave room for LILO673 * FIXME: this uses one logical sector for > 512b674 * sector, although it may not be enough/proper.675 */676 sector_t n = 2;677 678 n = min(size, max(sector_size, n));679 put_partition(state, slot, start, n);680 681 strlcat(state->pp_buf, " <", PAGE_SIZE);682 parse_extended(state, start, size, disksig);683 strlcat(state->pp_buf, " >", PAGE_SIZE);684 continue;685 }686 put_partition(state, slot, start, size);687 set_info(state, slot, disksig);688 if (p->sys_ind == LINUX_RAID_PARTITION)689 state->parts[slot].flags = ADDPART_FLAG_RAID;690 if (p->sys_ind == DM6_PARTITION)691 strlcat(state->pp_buf, "[DM]", PAGE_SIZE);692 if (p->sys_ind == EZD_PARTITION)693 strlcat(state->pp_buf, "[EZD]", PAGE_SIZE);694 }695 696 strlcat(state->pp_buf, "\n", PAGE_SIZE);697 698 /* second pass - output for each on a separate line */699 p = (struct msdos_partition *) (0x1be + data);700 for (slot = 1 ; slot <= 4 ; slot++, p++) {701 unsigned char id = p->sys_ind;702 int n;703 704 if (!nr_sects(p))705 continue;706 707 for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)708 ;709 710 if (!subtypes[n].parse)711 continue;712 subtypes[n].parse(state, start_sect(p) * sector_size,713 nr_sects(p) * sector_size, slot);714 }715 put_dev_sector(sect);716 return 1;717}718