Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * fs/partitions/msdos.c
4 : *
5 : * Code extracted from drivers/block/genhd.c
6 : * Copyright (C) 1991-1998 Linus Torvalds
7 : *
8 : * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
9 : * in the early extended-partition checks and added DM partitions
10 : *
11 : * Support for DiskManager v6.0x added by Mark Lord,
12 : * with information provided by OnTrack. This now works for linux fdisk
13 : * and LILO, as well as loadlin and bootln. Note that disks other than
14 : * /dev/hda *must* have a "DOS" type 0x51 partition in the first slot (hda1).
15 : *
16 : * More flexible handling of extended partitions - aeb, 950831
17 : *
18 : * Check partition table on IDE disks for common CHS translations
19 : *
20 : * Re-organised Feb 1998 Russell King
21 : *
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, while
36 : * the nr_sects and start_sect partition table entries are
37 : * at a 2 (mod 4) address.
38 : */
39 : #include <asm/unaligned.h>
40 :
41 : static inline sector_t nr_sects(struct msdos_partition *p)
42 : {
43 0 : return (sector_t)get_unaligned_le32(&p->nr_sects);
44 : }
45 :
46 : static inline sector_t start_sect(struct msdos_partition *p)
47 : {
48 0 : return (sector_t)get_unaligned_le32(&p->start_sect);
49 : }
50 :
51 : static inline int is_extended_partition(struct msdos_partition *p)
52 : {
53 0 : return (p->sys_ind == DOS_EXTENDED_PARTITION ||
54 0 : p->sys_ind == WIN98_EXTENDED_PARTITION ||
55 : p->sys_ind == LINUX_EXTENDED_PARTITION);
56 : }
57 :
58 : #define MSDOS_LABEL_MAGIC1 0x55
59 : #define MSDOS_LABEL_MAGIC2 0xAA
60 :
61 : static inline int
62 : msdos_magic_present(unsigned char *p)
63 : {
64 0 : return (p[0] == MSDOS_LABEL_MAGIC1 && p[1] == MSDOS_LABEL_MAGIC2);
65 : }
66 :
67 : /* Value is EBCDIC 'IBMA' */
68 : #define AIX_LABEL_MAGIC1 0xC9
69 : #define AIX_LABEL_MAGIC2 0xC2
70 : #define AIX_LABEL_MAGIC3 0xD4
71 : #define AIX_LABEL_MAGIC4 0xC1
72 0 : static int aix_magic_present(struct parsed_partitions *state, unsigned char *p)
73 : {
74 0 : struct msdos_partition *pt = (struct msdos_partition *) (p + 0x1be);
75 : Sector sect;
76 : unsigned char *d;
77 0 : int slot, ret = 0;
78 :
79 0 : if (!(p[0] == AIX_LABEL_MAGIC1 &&
80 0 : p[1] == AIX_LABEL_MAGIC2 &&
81 0 : p[2] == AIX_LABEL_MAGIC3 &&
82 0 : 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 as
88 : * Linux swap partitions, so we consider that a Linux partition as
89 : * well.
90 : */
91 0 : for (slot = 1; slot <= 4; slot++, pt++) {
92 0 : if (pt->sys_ind == SOLARIS_X86_PARTITION ||
93 0 : pt->sys_ind == LINUX_RAID_PARTITION ||
94 0 : pt->sys_ind == LINUX_DATA_PARTITION ||
95 0 : pt->sys_ind == LINUX_LVM_PARTITION ||
96 0 : is_extended_partition(pt))
97 : return 0;
98 : }
99 0 : d = read_part_sector(state, 7, §);
100 0 : if (d) {
101 0 : if (d[0] == '_' && d[1] == 'L' && d[2] == 'V' && d[3] == 'M')
102 0 : ret = 1;
103 : put_dev_sector(sect);
104 : }
105 : return ret;
106 : }
107 :
108 0 : static void set_info(struct parsed_partitions *state, int slot,
109 : u32 disksig)
110 : {
111 0 : struct partition_meta_info *info = &state->parts[slot].info;
112 :
113 0 : snprintf(info->uuid, sizeof(info->uuid), "%08x-%02x", disksig,
114 : slot);
115 0 : info->volname[0] = 0;
116 0 : state->parts[slot].has_info = true;
117 0 : }
118 :
119 : /*
120 : * Create devices for each logical partition in an extended partition.
121 : * The logical partitions form a linked list, with each entry being
122 : * a partition table with two entries. The first entry
123 : * is the real data partition (with a start relative to the partition
124 : * table start). The second is a pointer to the next logical partition
125 : * (with a start relative to the entire extended partition).
126 : * We do not create a Linux partition for the partition tables, but
127 : * only for the actual data partitions.
128 : */
129 :
130 0 : static 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 0 : int loopct = 0; /* number of links followed
140 : without finding a data partition */
141 : int i;
142 :
143 0 : sector_size = queue_logical_block_size(state->disk->queue) / 512;
144 0 : this_sector = first_sector;
145 0 : this_size = first_size;
146 :
147 : while (1) {
148 0 : if (++loopct > 100)
149 0 : return;
150 0 : if (state->next == state->limit)
151 : return;
152 0 : data = read_part_sector(state, this_sector, §);
153 0 : if (!data)
154 : return;
155 :
156 0 : if (!msdos_magic_present(data + 510))
157 : goto done;
158 :
159 0 : 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 as
166 : * 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 0 : for (i = 0; i < 4; i++, p++) {
174 : sector_t offs, size, next;
175 :
176 0 : if (!nr_sects(p) || is_extended_partition(p))
177 0 : continue;
178 :
179 : /* Check the 3rd and 4th entries -
180 : these sometimes contain random garbage */
181 0 : offs = start_sect(p)*sector_size;
182 0 : size = nr_sects(p)*sector_size;
183 0 : next = this_sector + offs;
184 0 : if (i >= 2) {
185 0 : if (offs + size > this_size)
186 0 : continue;
187 0 : if (next < first_sector)
188 0 : continue;
189 0 : if (next + size > first_sector + first_size)
190 0 : continue;
191 : }
192 :
193 0 : put_partition(state, state->next, next, size);
194 0 : set_info(state, state->next, disksig);
195 0 : if (p->sys_ind == LINUX_RAID_PARTITION)
196 0 : state->parts[state->next].flags = ADDPART_FLAG_RAID;
197 0 : loopct = 0;
198 0 : 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 make
204 : * parse_extended() recursive and allow a tree
205 : * of extended partitions.)
206 : * It should be a link to the next logical partition.
207 : */
208 0 : p -= 4;
209 0 : for (i = 0; i < 4; i++, p++)
210 0 : if (nr_sects(p) && is_extended_partition(p))
211 : break;
212 0 : if (i == 4)
213 : goto done; /* nothing left to do */
214 :
215 0 : this_sector = first_sector + start_sect(p) * sector_size;
216 0 : this_size = nr_sects(p) * sector_size;
217 : put_dev_sector(sect);
218 : }
219 : done:
220 0 : put_dev_sector(sect);
221 : }
222 :
223 : #define SOLARIS_X86_NUMSLICE 16
224 : #define SOLARIS_X86_VTOC_SANE (0x600DDEEEUL)
225 :
226 : struct 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 :
233 : struct 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_slice
242 : 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 also
248 : indicates linux swap. Be careful before believing this is Solaris. */
249 :
250 0 : static void parse_solaris_x86(struct parsed_partitions *state,
251 : sector_t offset, sector_t size, int origin)
252 : {
253 : #ifdef CONFIG_SOLARIS_X86_PARTITION
254 : Sector sect;
255 : struct solaris_x86_vtoc *v;
256 : int i;
257 : short max_nparts;
258 :
259 : v = read_part_sector(state, offset + 1, §);
260 : if (!v)
261 : return;
262 : if (le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
263 : put_dev_sector(sect);
264 : return;
265 : }
266 : {
267 : char tmp[1 + BDEVNAME_SIZE + 10 + 11 + 1];
268 :
269 : snprintf(tmp, sizeof(tmp), " %s%d: <solaris:", state->name, origin);
270 : strlcat(state->pp_buf, tmp, PAGE_SIZE);
271 : }
272 : if (le32_to_cpu(v->v_version) != 1) {
273 : char tmp[64];
274 :
275 : snprintf(tmp, sizeof(tmp), " cannot handle version %d vtoc>\n",
276 : le32_to_cpu(v->v_version));
277 : strlcat(state->pp_buf, tmp, PAGE_SIZE);
278 : put_dev_sector(sect);
279 : return;
280 : }
281 : /* Ensure we can handle previous case of VTOC with 8 entries gracefully */
282 : max_nparts = le16_to_cpu(v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
283 : for (i = 0; i < max_nparts && state->next < state->limit; i++) {
284 : struct solaris_x86_slice *s = &v->v_slice[i];
285 : char tmp[3 + 10 + 1 + 1];
286 :
287 : if (s->s_size == 0)
288 : continue;
289 : snprintf(tmp, sizeof(tmp), " [s%d]", i);
290 : strlcat(state->pp_buf, tmp, PAGE_SIZE);
291 : /* solaris partitions are relative to current MS-DOS
292 : * 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 : #endif
300 0 : }
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 16
305 : #define OPENBSD_MAXPARTITIONS 16
306 : #define BSD_FS_UNUSED 0 /* disklabel unused partition entry ID */
307 : struct 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 5
330 : __u32 d_drivedata[NDDATA]; /* drive-type specific information */
331 : #define NSPARE 5
332 : __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 a
353 : * dos-like partition. See parse_extended() for more information.
354 : */
355 : static void parse_bsd(struct parsed_partitions *state,
356 : sector_t offset, sector_t size, int origin, char *flavour,
357 : int max_partitions)
358 : {
359 : Sector sect;
360 : struct bsd_disklabel *l;
361 : struct bsd_partition *p;
362 : char tmp[64];
363 :
364 : l = read_part_sector(state, offset + 1, §);
365 : if (!l)
366 : return;
367 : if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
368 : put_dev_sector(sect);
369 : return;
370 : }
371 :
372 : snprintf(tmp, sizeof(tmp), " %s%d: <%s:", state->name, origin, flavour);
373 : strlcat(state->pp_buf, tmp, PAGE_SIZE);
374 :
375 : if (le16_to_cpu(l->d_npartitions) < max_partitions)
376 : max_partitions = le16_to_cpu(l->d_npartitions);
377 : for (p = l->d_partitions; p - l->d_partitions < max_partitions; p++) {
378 : sector_t bsd_start, bsd_size;
379 :
380 : if (state->next == state->limit)
381 : break;
382 : if (p->p_fstype == BSD_FS_UNUSED)
383 : continue;
384 : bsd_start = le32_to_cpu(p->p_offset);
385 : bsd_size = le32_to_cpu(p->p_size);
386 : /* FreeBSD has relative offset if C partition offset is zero */
387 : if (memcmp(flavour, "bsd\0", 4) == 0 &&
388 : le32_to_cpu(l->d_partitions[2].p_offset) == 0)
389 : bsd_start += offset;
390 : if (offset == bsd_start && size == bsd_size)
391 : /* full parent partition, we have it already */
392 : continue;
393 : if (offset > bsd_start || offset+size < bsd_start+bsd_size) {
394 : strlcat(state->pp_buf, "bad subpartition - ignored\n", PAGE_SIZE);
395 : continue;
396 : }
397 : put_partition(state, state->next++, bsd_start, bsd_size);
398 : }
399 : put_dev_sector(sect);
400 : if (le16_to_cpu(l->d_npartitions) > max_partitions) {
401 : snprintf(tmp, sizeof(tmp), " (ignored %d more)",
402 : le16_to_cpu(l->d_npartitions) - max_partitions);
403 : strlcat(state->pp_buf, tmp, PAGE_SIZE);
404 : }
405 : strlcat(state->pp_buf, " >\n", PAGE_SIZE);
406 : }
407 : #endif
408 :
409 0 : static void parse_freebsd(struct parsed_partitions *state,
410 : sector_t offset, sector_t size, int origin)
411 : {
412 : #ifdef CONFIG_BSD_DISKLABEL
413 : parse_bsd(state, offset, size, origin, "bsd", BSD_MAXPARTITIONS);
414 : #endif
415 0 : }
416 :
417 0 : static void parse_netbsd(struct parsed_partitions *state,
418 : sector_t offset, sector_t size, int origin)
419 : {
420 : #ifdef CONFIG_BSD_DISKLABEL
421 : parse_bsd(state, offset, size, origin, "netbsd", BSD_MAXPARTITIONS);
422 : #endif
423 0 : }
424 :
425 0 : static void parse_openbsd(struct parsed_partitions *state,
426 : sector_t offset, sector_t size, int origin)
427 : {
428 : #ifdef CONFIG_BSD_DISKLABEL
429 : parse_bsd(state, offset, size, origin, "openbsd",
430 : OPENBSD_MAXPARTITIONS);
431 : #endif
432 0 : }
433 :
434 : #define UNIXWARE_DISKMAGIC (0xCA5E600DUL) /* The disk magic number */
435 : #define UNIXWARE_DISKMAGIC2 (0x600DDEEEUL) /* The slice table magic nr */
436 : #define UNIXWARE_NUMSLICE 16
437 : #define UNIXWARE_FS_UNUSED 0 /* Unused slice entry ID */
438 :
439 : struct 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 :
446 : struct 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_slice
475 : v_slice[UNIXWARE_NUMSLICE]; /* slice headers */
476 : } vtoc;
477 : }; /* 408 */
478 :
479 : /*
480 : * Create devices for Unixware partitions listed in a disklabel, under a
481 : * dos-like partition. See parse_extended() for more information.
482 : */
483 0 : static void parse_unixware(struct parsed_partitions *state,
484 : sector_t offset, sector_t size, int origin)
485 : {
486 : #ifdef CONFIG_UNIXWARE_DISKLABEL
487 : Sector sect;
488 : struct unixware_disklabel *l;
489 : struct unixware_slice *p;
490 :
491 : l = read_part_sector(state, offset + 29, §);
492 : if (!l)
493 : return;
494 : if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC ||
495 : le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) {
496 : put_dev_sector(sect);
497 : return;
498 : }
499 : {
500 : char tmp[1 + BDEVNAME_SIZE + 10 + 12 + 1];
501 :
502 : snprintf(tmp, sizeof(tmp), " %s%d: <unixware:", state->name, origin);
503 : strlcat(state->pp_buf, tmp, PAGE_SIZE);
504 : }
505 : p = &l->vtoc.v_slice[1];
506 : /* I omit the 0th slice as it is the same as whole disk. */
507 : while (p - &l->vtoc.v_slice[0] < UNIXWARE_NUMSLICE) {
508 : if (state->next == state->limit)
509 : break;
510 :
511 : if (p->s_label != UNIXWARE_FS_UNUSED)
512 : put_partition(state, state->next++,
513 : le32_to_cpu(p->start_sect),
514 : le32_to_cpu(p->nr_sects));
515 : p++;
516 : }
517 : put_dev_sector(sect);
518 : strlcat(state->pp_buf, " >\n", PAGE_SIZE);
519 : #endif
520 0 : }
521 :
522 : #define MINIX_NR_SUBPARTITIONS 4
523 :
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 : */
529 0 : static void parse_minix(struct parsed_partitions *state,
530 : sector_t offset, sector_t size, int origin)
531 : {
532 : #ifdef CONFIG_MINIX_SUBPARTITION
533 : Sector sect;
534 : unsigned char *data;
535 : struct msdos_partition *p;
536 : int i;
537 :
538 : data = read_part_sector(state, offset, §);
539 : if (!data)
540 : return;
541 :
542 : p = (struct msdos_partition *)(data + 0x1be);
543 :
544 : /* The first sector of a Minix partition can have either
545 : * a secondary MBR describing its subpartitions, or
546 : * 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 0 : }
566 :
567 : static 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 :
581 0 : int 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 0 : sector_size = queue_logical_block_size(state->disk->queue) / 512;
592 0 : data = read_part_sector(state, 0, §);
593 0 : if (!data)
594 : return -1;
595 :
596 : /*
597 : * Note order! (some AIX disks, e.g. unbootable kind,
598 : * have no MSDOS 55aa)
599 : */
600 0 : if (aix_magic_present(state, data)) {
601 0 : put_dev_sector(sect);
602 : #ifdef CONFIG_AIX_PARTITION
603 : return aix_partition(state);
604 : #else
605 0 : strlcat(state->pp_buf, " [AIX]", PAGE_SIZE);
606 0 : return 0;
607 : #endif
608 : }
609 :
610 0 : 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 probably
617 : * either the boot sector of a FAT filesystem or a DOS-type
618 : * partition table. Reject this in case the boot indicator
619 : * is not 0 or 0x80.
620 : */
621 0 : p = (struct msdos_partition *) (data + 0x1be);
622 0 : for (slot = 1; slot <= 4; slot++, p++) {
623 0 : if (p->boot_ind != 0 && p->boot_ind != 0x80) {
624 : /*
625 : * Even without a valid boot indicator value
626 : * its still possible this is valid FAT filesystem
627 : * without a partition table.
628 : */
629 0 : fb = (struct fat_boot_sector *) data;
630 0 : if (slot == 1 && fb->reserved && fb->fats
631 0 : && fat_valid_media(fb->media)) {
632 0 : 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_PARTITION
643 : p = (struct msdos_partition *) (data + 0x1be);
644 0 : for (slot = 1 ; slot <= 4 ; slot++, p++) {
645 : /* If this is an EFI GPT disk, msdos should ignore it. */
646 0 : if (p->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT) {
647 : put_dev_sector(sect);
648 : return 0;
649 : }
650 : }
651 : #endif
652 0 : p = (struct msdos_partition *) (data + 0x1be);
653 :
654 0 : 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 0 : state->next = 5;
663 0 : for (slot = 1 ; slot <= 4 ; slot++, p++) {
664 0 : sector_t start = start_sect(p)*sector_size;
665 0 : sector_t size = nr_sects(p)*sector_size;
666 :
667 0 : if (!size)
668 0 : continue;
669 0 : if (is_extended_partition(p)) {
670 : /*
671 : * prevent someone doing mkfs or mkswap on an
672 : * extended partition, but leave room for LILO
673 : * FIXME: this uses one logical sector for > 512b
674 : * sector, although it may not be enough/proper.
675 : */
676 0 : sector_t n = 2;
677 :
678 0 : n = min(size, max(sector_size, n));
679 0 : put_partition(state, slot, start, n);
680 :
681 0 : strlcat(state->pp_buf, " <", PAGE_SIZE);
682 0 : parse_extended(state, start, size, disksig);
683 0 : strlcat(state->pp_buf, " >", PAGE_SIZE);
684 0 : continue;
685 : }
686 0 : put_partition(state, slot, start, size);
687 0 : set_info(state, slot, disksig);
688 0 : if (p->sys_ind == LINUX_RAID_PARTITION)
689 0 : state->parts[slot].flags = ADDPART_FLAG_RAID;
690 0 : if (p->sys_ind == DM6_PARTITION)
691 0 : strlcat(state->pp_buf, "[DM]", PAGE_SIZE);
692 0 : if (p->sys_ind == EZD_PARTITION)
693 0 : strlcat(state->pp_buf, "[EZD]", PAGE_SIZE);
694 : }
695 :
696 0 : strlcat(state->pp_buf, "\n", PAGE_SIZE);
697 :
698 : /* second pass - output for each on a separate line */
699 0 : p = (struct msdos_partition *) (0x1be + data);
700 0 : for (slot = 1 ; slot <= 4 ; slot++, p++) {
701 0 : unsigned char id = p->sys_ind;
702 : int n;
703 :
704 0 : if (!nr_sects(p))
705 0 : continue;
706 :
707 0 : for (n = 0; subtypes[n].parse && id != subtypes[n].id; n++)
708 : ;
709 :
710 0 : if (!subtypes[n].parse)
711 0 : continue;
712 0 : subtypes[n].parse(state, start_sect(p) * sector_size,
713 0 : nr_sects(p) * sector_size, slot);
714 : }
715 : put_dev_sector(sect);
716 : return 1;
717 : }
|