1 /*
2  *  fs/partitions/msdos.c
3  *
4  *  Code extracted from drivers/block/genhd.c
5  *  Copyright (C) 1991-1998  Linus Torvalds
6  *
7  *  Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
8  *  in the early extended-partition checks and added DM partitions
9  *
10  *  Support for DiskManager v6.0x added by Mark Lord,
11  *  with information provided by OnTrack.  This now works for linux fdisk
12  *  and LILO, as well as loadlin and bootln.  Note that disks other than
13  *  /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
14  *
15  *  More flexible handling of extended partitions - aeb, 950831
16  *
17  *  Check partition table on IDE disks for common CHS translations
18  *
19  *  Re-organised Feb 1998 Russell King
20  */
21 
22 #include <linux/config.h>
23 #include <linux/fs.h>
24 #include <linux/genhd.h>
25 #include <linux/kernel.h>
26 #include <linux/major.h>
27 #include <linux/string.h>
28 #include <linux/blk.h>
29 
30 #ifdef CONFIG_BLK_DEV_IDE
31 #include <linux/ide.h>	/* IDE xlate */
32 #elif defined(CONFIG_BLK_DEV_IDE_MODULE)
33 #include <linux/module.h>
34 
35 int (*ide_xlate_1024_hook)(kdev_t, int, int, const char *);
36 EXPORT_SYMBOL(ide_xlate_1024_hook);
37 #define ide_xlate_1024 ide_xlate_1024_hook
38 #endif
39 
40 #include <asm/system.h>
41 
42 #include "check.h"
43 #include "msdos.h"
44 
45 #if CONFIG_BLK_DEV_MD
46 extern void md_autodetect_dev(kdev_t dev);
47 #endif
48 
49 /*
50  * Many architectures don't like unaligned accesses, which is
51  * frequently the case with the nr_sects and start_sect partition
52  * table entries.
53  */
54 #include <asm/unaligned.h>
55 
56 #define SYS_IND(p)	(get_unaligned(&p->sys_ind))
57 #define NR_SECTS(p)	({ __typeof__(p->nr_sects) __a =	\
58 				get_unaligned(&p->nr_sects);	\
59 				le32_to_cpu(__a); \
60 			})
61 
62 #define START_SECT(p)	({ __typeof__(p->start_sect) __a =	\
63 				get_unaligned(&p->start_sect);	\
64 				le32_to_cpu(__a); \
65 			})
66 
is_extended_partition(struct partition * p)67 static inline int is_extended_partition(struct partition *p)
68 {
69 	return (SYS_IND(p) == DOS_EXTENDED_PARTITION ||
70 		SYS_IND(p) == WIN98_EXTENDED_PARTITION ||
71 		SYS_IND(p) == LINUX_EXTENDED_PARTITION);
72 }
73 
74 /*
75  * msdos_partition_name() formats the short partition name into the supplied
76  * buffer, and returns a pointer to that buffer.
77  * Used by several partition types which makes conditional inclusion messy,
78  * use __attribute__ ((unused)) instead.
79  */
80 static char __attribute__ ((unused))
msdos_partition_name(struct gendisk * hd,int minor,char * buf)81 	*msdos_partition_name (struct gendisk *hd, int minor, char *buf)
82 {
83 #ifdef CONFIG_DEVFS_FS
84 	sprintf(buf, "p%d", (minor & ((1 << hd->minor_shift) - 1)));
85 	return buf;
86 #else
87 	return disk_name(hd, minor, buf);
88 #endif
89 }
90 
91 #define MSDOS_LABEL_MAGIC1	0x55
92 #define MSDOS_LABEL_MAGIC2	0xAA
93 
94 static inline int
msdos_magic_present(unsigned char * p)95 msdos_magic_present(unsigned char *p)
96 {
97 	return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
98 }
99 
100 /*
101  * Create devices for each logical partition in an extended partition.
102  * The logical partitions form a linked list, with each entry being
103  * a partition table with two entries.  The first entry
104  * is the real data partition (with a start relative to the partition
105  * table start).  The second is a pointer to the next logical partition
106  * (with a start relative to the entire extended partition).
107  * We do not create a Linux partition for the partition tables, but
108  * only for the actual data partitions.
109  */
110 
extended_partition(struct gendisk * hd,struct block_device * bdev,int minor,unsigned long first_size,int * current_minor)111 static void extended_partition(struct gendisk *hd, struct block_device *bdev,
112 			int minor, unsigned long first_size, int *current_minor)
113 {
114 	struct partition *p;
115 	Sector sect;
116 	unsigned char *data;
117 	unsigned long first_sector, this_sector, this_size;
118 	int mask = (1 << hd->minor_shift) - 1;
119 	int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
120 	int loopct = 0;		/* number of links followed
121 				   without finding a data partition */
122 	int i;
123 
124 	this_sector = first_sector = hd->part[minor].start_sect;
125 	this_size = first_size;
126 
127 	while (1) {
128 		if (++loopct > 100)
129 			return;
130 		if ((*current_minor & mask) == 0)
131 			return;
132 		data = read_dev_sector(bdev, this_sector, &sect);
133 		if (!data)
134 			return;
135 
136 		if (!msdos_magic_present(data + 510))
137 			goto done;
138 
139 		p = (struct partition *) (data + 0x1be);
140 
141 		/*
142 		 * Usually, the first entry is the real data partition,
143 		 * the 2nd entry is the next extended partition, or empty,
144 		 * and the 3rd and 4th entries are unused.
145 		 * However, DRDOS sometimes has the extended partition as
146 		 * the first entry (when the data partition is empty),
147 		 * and OS/2 seems to use all four entries.
148 		 */
149 
150 		/*
151 		 * First process the data partition(s)
152 		 */
153 		for (i=0; i<4; i++, p++) {
154 			unsigned long offs, size, next;
155 			if (!NR_SECTS(p) || is_extended_partition(p))
156 				continue;
157 
158 			/* Check the 3rd and 4th entries -
159 			   these sometimes contain random garbage */
160 			offs = START_SECT(p)*sector_size;
161 			size = NR_SECTS(p)*sector_size;
162 			next = this_sector + offs;
163 			if (i >= 2) {
164 				if (offs + size > this_size)
165 					continue;
166 				if (next < first_sector)
167 					continue;
168 				if (next + size > first_sector + first_size)
169 					continue;
170 			}
171 
172 			add_gd_partition(hd, *current_minor, next, size);
173 #if CONFIG_BLK_DEV_MD
174 			if (SYS_IND(p) == LINUX_RAID_PARTITION) {
175 			    md_autodetect_dev(MKDEV(hd->major,*current_minor));
176 			}
177 #endif
178 
179 			(*current_minor)++;
180 			loopct = 0;
181 			if ((*current_minor & mask) == 0)
182 				goto done;
183 		}
184 		/*
185 		 * Next, process the (first) extended partition, if present.
186 		 * (So far, there seems to be no reason to make
187 		 *  extended_partition()  recursive and allow a tree
188 		 *  of extended partitions.)
189 		 * It should be a link to the next logical partition.
190 		 * Create a minor for this just long enough to get the next
191 		 * partition table.  The minor will be reused for the next
192 		 * data partition.
193 		 */
194 		p -= 4;
195 		for (i=0; i<4; i++, p++)
196 			if (NR_SECTS(p) && is_extended_partition(p))
197 				break;
198 		if (i == 4)
199 			goto done;	 /* nothing left to do */
200 
201 		this_sector = first_sector + START_SECT(p) * sector_size;
202 		this_size = NR_SECTS(p) * sector_size;
203 		minor = *current_minor;
204 		put_dev_sector(sect);
205 	}
206 done:
207 	put_dev_sector(sect);
208 }
209 
210 /* james@bpgc.com: Solaris has a nasty indicator: 0x82 which also
211    indicates linux swap.  Be careful before believing this is Solaris. */
212 
213 static void
solaris_x86_partition(struct gendisk * hd,struct block_device * bdev,int minor,int * current_minor)214 solaris_x86_partition(struct gendisk *hd, struct block_device *bdev,
215 		int minor, int *current_minor)
216 {
217 
218 #ifdef CONFIG_SOLARIS_X86_PARTITION
219 	long offset = hd->part[minor].start_sect;
220 	Sector sect;
221 	struct solaris_x86_vtoc *v;
222 	struct solaris_x86_slice *s;
223 	int mask = (1 << hd->minor_shift) - 1;
224 	int i;
225 	char buf[40];
226 
227 	v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
228 	if (!v)
229 		return;
230 	if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
231 		put_dev_sector(sect);
232 		return;
233 	}
234 	printk(" %s: <solaris:", msdos_partition_name(hd, minor, buf));
235 	if (le32_to_cpu(v->v_version) != 1) {
236 		printk("  cannot handle version %d vtoc>\n",
237 			le32_to_cpu(v->v_version));
238 		put_dev_sector(sect);
239 		return;
240 	}
241 	for (i=0; i<SOLARIS_X86_NUMSLICE; i++) {
242 		if ((*current_minor & mask) == 0)
243 			break;
244 		s = &v->v_slice[i];
245 
246 		if (s->s_size == 0)
247 			continue;
248 		printk(" [s%d]", i);
249 		/* solaris partitions are relative to current MS-DOS
250 		 * one but add_gd_partition starts relative to sector
251 		 * zero of the disk.  Therefore, must add the offset
252 		 * of the current partition */
253 		add_gd_partition(hd, *current_minor,
254 				 le32_to_cpu(s->s_start)+offset,
255 				 le32_to_cpu(s->s_size));
256 		(*current_minor)++;
257 	}
258 	put_dev_sector(sect);
259 	printk(" >\n");
260 #endif
261 }
262 
263 #ifdef CONFIG_BSD_DISKLABEL
264 static void
check_and_add_bsd_partition(struct gendisk * hd,struct bsd_partition * bsd_p,int baseminor,int * current_minor)265 check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
266 	int baseminor, int *current_minor)
267 {
268 	int i, bsd_start, bsd_size;
269 
270 	bsd_start = le32_to_cpu(bsd_p->p_offset);
271 	bsd_size = le32_to_cpu(bsd_p->p_size);
272 
273 	/* check relative position of already allocated partitions */
274 	for (i = baseminor+1; i < *current_minor; i++) {
275 		int start = hd->part[i].start_sect;
276 		int size = hd->part[i].nr_sects;
277 
278 		if (start+size <= bsd_start || start >= bsd_start+bsd_size)
279 			continue;	/* no overlap */
280 
281 		if (start == bsd_start && size == bsd_size)
282 			return;		/* equal -> no need to add */
283 
284 		if (start <= bsd_start && start+size >= bsd_start+bsd_size) {
285 			/* bsd living within dos partition */
286 #ifdef DEBUG_BSD_DISKLABEL
287 			printk("w: %d %ld+%ld,%d+%d",
288 			       i, start, size, bsd_start, bsd_size);
289 #endif
290 			break;		/* ok */
291 		}
292 
293 		/* ouch: bsd and linux overlap */
294 #ifdef DEBUG_BSD_DISKLABEL
295 		printk("???: %d %ld+%ld,%d+%d",
296 		       i, start, size, bsd_start, bsd_size);
297 #endif
298 		printk("???");
299 		return;
300 	}
301 
302 	add_gd_partition(hd, *current_minor, bsd_start, bsd_size);
303 	(*current_minor)++;
304 }
305 
306 /*
307  * Create devices for BSD partitions listed in a disklabel, under a
308  * dos-like partition. See extended_partition() for more information.
309  */
do_bsd_partition(struct gendisk * hd,struct block_device * bdev,int minor,int * current_minor,char * name,int max_partitions)310 static void do_bsd_partition(struct gendisk *hd, struct block_device *bdev,
311 	int minor, int *current_minor, char *name, int max_partitions)
312 {
313 	long offset = hd->part[minor].start_sect;
314 	Sector sect;
315 	struct bsd_disklabel *l;
316 	struct bsd_partition *p;
317 	int mask = (1 << hd->minor_shift) - 1;
318 	int baseminor = (minor & ~mask);
319 	char buf[40];
320 
321 	l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect);
322 	if (!l)
323 		return;
324 	if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
325 		put_dev_sector(sect);
326 		return;
327 	}
328 	printk(" %s: <%s:", msdos_partition_name(hd, minor, buf), name);
329 
330 	if (le16_to_cpu(l->d_npartitions) < max_partitions)
331 		max_partitions = le16_to_cpu(l->d_npartitions);
332 	for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
333 		if ((*current_minor & mask) == 0)
334 			break;
335 		if (p->p_fstype == BSD_FS_UNUSED)
336 			continue;
337 		check_and_add_bsd_partition(hd, p, baseminor, current_minor);
338 	}
339 	put_dev_sector(sect);
340 	printk(" >\n");
341 }
342 #endif
343 
bsd_partition(struct gendisk * hd,struct block_device * bdev,int minor,int * current_minor)344 static void bsd_partition(struct gendisk *hd, struct block_device *bdev,
345 	int minor, int *current_minor)
346 {
347 #ifdef CONFIG_BSD_DISKLABEL
348 	do_bsd_partition(hd, bdev, minor, current_minor, "bsd",
349 		BSD_MAXPARTITIONS);
350 #endif
351 }
352 
netbsd_partition(struct gendisk * hd,struct block_device * bdev,int minor,int * current_minor)353 static void netbsd_partition(struct gendisk *hd, struct block_device *bdev,
354 		int minor, int *current_minor)
355 {
356 #ifdef CONFIG_BSD_DISKLABEL
357 	do_bsd_partition(hd, bdev, minor, current_minor, "netbsd",
358 			BSD_MAXPARTITIONS);
359 #endif
360 }
361 
openbsd_partition(struct gendisk * hd,struct block_device * bdev,int minor,int * current_minor)362 static void openbsd_partition(struct gendisk *hd, struct block_device *bdev,
363 		int minor, int *current_minor)
364 {
365 #ifdef CONFIG_BSD_DISKLABEL
366 	do_bsd_partition(hd, bdev, minor, current_minor,
367 			"openbsd", OPENBSD_MAXPARTITIONS);
368 #endif
369 }
370 
371 /*
372  * Create devices for Unixware partitions listed in a disklabel, under a
373  * dos-like partition. See extended_partition() for more information.
374  */
unixware_partition(struct gendisk * hd,struct block_device * bdev,int minor,int * current_minor)375 static void unixware_partition(struct gendisk *hd, struct block_device *bdev,
376 		int minor, int *current_minor)
377 {
378 #ifdef CONFIG_UNIXWARE_DISKLABEL
379 	long offset = hd->part[minor].start_sect;
380 	Sector sect;
381 	struct unixware_disklabel *l;
382 	struct unixware_slice *p;
383 	int mask = (1 << hd->minor_shift) - 1;
384 	char buf[40];
385 
386 	l = (struct unixware_disklabel *)read_dev_sector(bdev, offset+29, &sect);
387 	if (!l)
388 		return;
389 	if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
390 	    le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
391 		put_dev_sector(sect);
392 		return;
393 	}
394 	printk(" %s: <unixware:", msdos_partition_name(hd, minor, buf));
395 	p = &l->vtoc.v_slice[1];
396 	/* I omit the 0th slice as it is the same as whole disk. */
397 	while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
398 		if ((*current_minor & mask) == 0)
399 			break;
400 
401 		if (p->s_label != UNIXWARE_FS_UNUSED) {
402 			add_gd_partition(hd, *current_minor, START_SECT(p),
403 					 NR_SECTS(p));
404 			(*current_minor)++;
405 		}
406 		p++;
407 	}
408 	put_dev_sector(sect);
409 	printk(" >\n");
410 #endif
411 }
412 
413 /*
414  * Minix 2.0.0/2.0.2 subpartition support.
415  * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
416  * Rajeev V. Pillai    <rajeevvp@yahoo.com>
417  */
minix_partition(struct gendisk * hd,struct block_device * bdev,int minor,int * current_minor)418 static void minix_partition(struct gendisk *hd, struct block_device *bdev,
419 		int minor, int *current_minor)
420 {
421 #ifdef CONFIG_MINIX_SUBPARTITION
422 	long offset = hd->part[minor].start_sect;
423 	Sector sect;
424 	unsigned char *data;
425 	struct partition *p;
426 	int mask = (1 << hd->minor_shift) - 1;
427 	int i;
428 	char buf[40];
429 
430 	data = read_dev_sector(bdev, offset, &sect);
431 	if (!data)
432 		return;
433 
434 	p = (struct partition *)(data + 0x1be);
435 
436 	/* The first sector of a Minix partition can have either
437 	 * a secondary MBR describing its subpartitions, or
438 	 * the normal boot sector. */
439 	if (msdos_magic_present (data + 510) &&
440 	    SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
441 
442 		printk(" %s: <minix:", msdos_partition_name(hd, minor, buf));
443 		for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
444 			if ((*current_minor & mask) == 0)
445 				break;
446 			/* add each partition in use */
447 			if (SYS_IND(p) == MINIX_PARTITION) {
448 				add_gd_partition(hd, *current_minor,
449 					      START_SECT(p), NR_SECTS(p));
450 				(*current_minor)++;
451 			}
452 		}
453 		printk(" >\n");
454 	}
455 	put_dev_sector(sect);
456 #endif /* CONFIG_MINIX_SUBPARTITION */
457 }
458 
459 static struct {
460 	unsigned char id;
461 	void (*parse)(struct gendisk *, struct block_device *, int, int *);
462 } subtypes[] = {
463 	{BSD_PARTITION, bsd_partition},
464 	{NETBSD_PARTITION, netbsd_partition},
465 	{OPENBSD_PARTITION, openbsd_partition},
466 	{MINIX_PARTITION, minix_partition},
467 	{UNIXWARE_PARTITION, unixware_partition},
468 	{SOLARIS_X86_PARTITION, solaris_x86_partition},
469 	{0, NULL},
470 };
471 /*
472  * Look for various forms of IDE disk geometry translation
473  */
handle_ide_mess(struct block_device * bdev)474 static int handle_ide_mess(struct block_device *bdev)
475 {
476 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
477 	Sector sect;
478 	unsigned char *data;
479 	kdev_t dev = to_kdev_t(bdev->bd_dev);
480 	unsigned int sig;
481 	int heads = 0;
482 	struct partition *p;
483 	int i;
484 #ifdef CONFIG_BLK_DEV_IDE_MODULE
485 	if (!ide_xlate_1024)
486 		return 1;
487 #endif
488 	/*
489 	 * The i386 partition handling programs very often
490 	 * make partitions end on cylinder boundaries.
491 	 * There is no need to do so, and Linux fdisk doesn't always
492 	 * do this, and Windows NT on Alpha doesn't do this either,
493 	 * but still, this helps to guess #heads.
494 	 */
495 	data = read_dev_sector(bdev, 0, &sect);
496 	if (!data)
497 		return -1;
498 	if (!msdos_magic_present(data + 510)) {
499 		put_dev_sector(sect);
500 		return 0;
501 	}
502 	sig = le16_to_cpu(*(unsigned short *)(data + 2));
503 	p = (struct partition *) (data + 0x1be);
504 	for (i = 0; i < 4; i++) {
505 		struct partition *q = &p[i];
506 		if (NR_SECTS(q)) {
507 			if ((q->sector & 63) == 1 &&
508 			    (q->end_sector & 63) == 63)
509 				heads = q->end_head + 1;
510 			break;
511 		}
512 	}
513 	if (SYS_IND(p) == EZD_PARTITION) {
514 		/*
515 		 * Accesses to sector 0 must go to sector 1 instead.
516 		 */
517 		if (ide_xlate_1024(dev, -1, heads, " [EZD]"))
518 			goto reread;
519 	} else if (SYS_IND(p) == DM6_PARTITION) {
520 
521 		/*
522 		 * Everything on the disk is offset by 63 sectors,
523 		 * including a "new" MBR with its own partition table.
524 		 */
525 		if (ide_xlate_1024(dev, 1, heads, " [DM6:DDO]"))
526 			goto reread;
527 	} else if (sig <= 0x1ae &&
528 		   data[sig] == 0xAA && data[sig+1] == 0x55 &&
529 		   (data[sig+2] & 1)) {
530 		/* DM6 signature in MBR, courtesy of OnTrack */
531 		(void) ide_xlate_1024 (dev, 0, heads, " [DM6:MBR]");
532 	} else if (SYS_IND(p) == DM6_AUX1PARTITION ||
533 		   SYS_IND(p) == DM6_AUX3PARTITION) {
534 		/*
535 		 * DM6 on other than the first (boot) drive
536 		 */
537 		(void) ide_xlate_1024(dev, 0, heads, " [DM6:AUX]");
538 	} else {
539 		(void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
540 	}
541 	put_dev_sector(sect);
542 	return 1;
543 
544 reread:
545 	put_dev_sector(sect);
546 	/* Flush the cache */
547 	invalidate_bdev(bdev, 1);
548 	truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
549 #endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
550 	return 1;
551 }
552 
msdos_partition(struct gendisk * hd,struct block_device * bdev,unsigned long first_sector,int first_part_minor)553 int msdos_partition(struct gendisk *hd, struct block_device *bdev,
554 		    unsigned long first_sector, int first_part_minor)
555 {
556 	int i, minor = first_part_minor;
557 	Sector sect;
558 	struct partition *p;
559 	unsigned char *data;
560 	int mask = (1 << hd->minor_shift) - 1;
561 	int sector_size = get_hardsect_size(to_kdev_t(bdev->bd_dev)) / 512;
562 	int current_minor = first_part_minor;
563 	int err;
564 
565 	err = handle_ide_mess(bdev);
566 	if (err <= 0)
567 		return err;
568 	data = read_dev_sector(bdev, 0, &sect);
569 	if (!data)
570 		return -1;
571 	if (!msdos_magic_present(data + 510)) {
572 		put_dev_sector(sect);
573 		return 0;
574 	}
575 	/*
576 	 * Now that the 55aa signature is present, this is probably
577 	 * either the boot sector of a FAT filesystem or a DOS-type
578 	 * partition table. Reject this in case the boot indicator
579 	 * is not 0 or 0x80.
580 	 */
581 	p = (struct partition *) (data + 0x1be);
582 	for (i = 1; i <= 4; i++, p++) {
583 		if (p->boot_ind != 0 && p->boot_ind != 0x80) {
584 			put_dev_sector(sect);
585 			return 0;
586 		}
587 	}
588 	p = (struct partition *) (data + 0x1be);
589 
590 	/*
591 	 * Look for partitions in two passes:
592 	 * First find the primary and DOS-type extended partitions.
593 	 * On the second pass look inside *BSD, Unixware and Solaris partitions.
594 	 */
595 
596 	current_minor += 4;
597 	for (i=1 ; i<=4 ; minor++,i++,p++) {
598 		if (!NR_SECTS(p))
599 			continue;
600 		add_gd_partition(hd, minor,
601 				first_sector+START_SECT(p)*sector_size,
602 				NR_SECTS(p)*sector_size);
603 #if CONFIG_BLK_DEV_MD
604 		if (SYS_IND(p) == LINUX_RAID_PARTITION) {
605 			md_autodetect_dev(MKDEV(hd->major,minor));
606 		}
607 #endif
608 		if (is_extended_partition(p)) {
609 			unsigned long size = hd->part[minor].nr_sects;
610 			printk(" <");
611 			/* prevent someone doing mkfs or mkswap on an
612 			   extended partition, but leave room for LILO */
613 			if (size > 2)
614 				hd->part[minor].nr_sects = 2;
615 			extended_partition(hd, bdev, minor, size, &current_minor);
616 			printk(" >");
617 		}
618 	}
619 
620 	/*
621 	 *  Check for old-style Disk Manager partition table
622 	 */
623 	if (msdos_magic_present(data + 0xfc)) {
624 		p = (struct partition *) (0x1be + data);
625 		for (i = 4 ; i < 16 ; i++, current_minor++) {
626 			p--;
627 			if ((current_minor & mask) == 0)
628 				break;
629 			if (!(START_SECT(p) && NR_SECTS(p)))
630 				continue;
631 			add_gd_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
632 		}
633 	}
634 	printk("\n");
635 
636 	/* second pass - output for each on a separate line */
637 	minor -= 4;
638 	p = (struct partition *) (0x1be + data);
639 	for (i=1 ; i<=4 ; minor++,i++,p++) {
640 		unsigned char id = SYS_IND(p);
641 		int n;
642 
643 		if (!NR_SECTS(p))
644 			continue;
645 
646 		for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
647 			;
648 
649 		if (subtypes[n].parse)
650 			subtypes[n].parse(hd, bdev, minor, &current_minor);
651 	}
652 	put_dev_sector(sect);
653 	return 1;
654 }
655