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