brintos

brintos / linux-shallow public Read only

0
0
Text · 21.3 KiB · 073be78 Raw
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, &sect);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, &sect);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, &sect);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, &sect);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, &sect);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, &sect);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, &sect);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