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