1 /*
2 * Code extracted from
3 * linux/kernel/hd.c
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 *
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 (mlord@bnr.ca)
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
21 #include <linux/config.h>
22 #include <linux/fs.h>
23 #include <linux/genhd.h>
24 #include <linux/kernel.h>
25 #include <linux/major.h>
26 #include <linux/string.h>
27
28 #include <asm/system.h>
29
30 #ifdef __alpha__
31 /*
32 * On the Alpha, we get unaligned access exceptions on
33 * p->nr_sects and p->start_sect, when the partition table
34 * is not on a 4-byte boundary, which is frequently the case.
35 * This code uses unaligned load instructions to prevent
36 * such exceptions.
37 */
38 #include <asm/unaligned.h>
39 #define NR_SECTS(p) ldl_u(&p->nr_sects)
40 #define START_SECT(p) ldl_u(&p->start_sect)
41 #else /* __alpha__ */
42 #define NR_SECTS(p) p->nr_sects
43 #define START_SECT(p) p->start_sect
44 #endif /* __alpha__ */
45
46 struct gendisk *gendisk_head = NULL;
47
48 static int current_minor = 0;
49 extern int *blk_size[];
50 extern void rd_load(void);
51
52 extern int chr_dev_init(void);
53 extern int blk_dev_init(void);
54 extern int scsi_dev_init(void);
55 extern int net_dev_init(void);
56
57 static void print_minor_name (struct gendisk *hd, int minor)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
58 {
59 unsigned int unit = minor >> hd->minor_shift;
60 unsigned int part = minor & ((1 << hd->minor_shift) - 1);
61
62 #ifdef CONFIG_BLK_DEV_IDE
63 /*
64 * IDE devices use multiple major numbers, but the drives
65 * are named as: {hda,hdb}, {hdc,hdd}, {hde,hdf}, {hdg,hdh}..
66 * This requires some creative handling here to find the
67 * correct name to use, with some help from ide.c
68 */
69 if (!strcmp(hd->major_name,"ide")) {
70 char name[16]; /* more than large enough */
71 strcpy(name, hd->real_devices); /* courtesy ide.c */
72 name[strlen(name)-1] += unit;
73 printk(" %s", name);
74 } else
75 #endif
76 printk(" %s%c", hd->major_name, 'a' + unit);
77 if (part)
78 printk("%d", part);
79 else
80 printk(":");
81 }
82
83 static void add_partition (struct gendisk *hd, int minor, int start, int size)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
84 {
85 hd->part[minor].start_sect = start;
86 hd->part[minor].nr_sects = size;
87 print_minor_name(hd, minor);
88 }
89
90 static inline int is_extended_partition(struct partition *p)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
91 {
92 return (p->sys_ind == DOS_EXTENDED_PARTITION ||
93 p->sys_ind == LINUX_EXTENDED_PARTITION);
94 }
95
96 #ifdef CONFIG_MSDOS_PARTITION
97 /*
98 * Create devices for each logical partition in an extended partition.
99 * The logical partitions form a linked list, with each entry being
100 * a partition table with two entries. The first entry
101 * is the real data partition (with a start relative to the partition
102 * table start). The second is a pointer to the next logical partition
103 * (with a start relative to the entire extended partition).
104 * We do not create a Linux partition for the partition tables, but
105 * only for the actual data partitions.
106 */
107
108 static void extended_partition(struct gendisk *hd, kdev_t dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
109 {
110 struct buffer_head *bh;
111 struct partition *p;
112 unsigned long first_sector, first_size, this_sector, this_size;
113 int mask = (1 << hd->minor_shift) - 1;
114 int i;
115
116 first_sector = hd->part[MINOR(dev)].start_sect;
117 first_size = hd->part[MINOR(dev)].nr_sects;
118 this_sector = first_sector;
119
120 while (1) {
121 if ((current_minor & mask) == 0)
122 return;
123 if (!(bh = bread(dev,0,1024)))
124 return;
125 /*
126 * This block is from a device that we're about to stomp on.
127 * So make sure nobody thinks this block is usable.
128 */
129 bh->b_state = 0;
130
131 if (*(unsigned short *) (bh->b_data+510) != 0xAA55)
132 goto done;
133
134 p = (struct partition *) (0x1BE + bh->b_data);
135
136 this_size = hd->part[MINOR(dev)].nr_sects;
137
138 /*
139 * Usually, the first entry is the real data partition,
140 * the 2nd entry is the next extended partition, or empty,
141 * and the 3rd and 4th entries are unused.
142 * However, DRDOS sometimes has the extended partition as
143 * the first entry (when the data partition is empty),
144 * and OS/2 seems to use all four entries.
145 */
146
147 /*
148 * First process the data partition(s)
149 */
150 for (i=0; i<4; i++, p++) {
151 if (!NR_SECTS(p) || is_extended_partition(p))
152 continue;
153
154 /* Check the 3rd and 4th entries -
155 these sometimes contain random garbage */
156 if (i >= 2
157 && START_SECT(p) + NR_SECTS(p) > this_size
158 && (this_sector + START_SECT(p) < first_sector ||
159 this_sector + START_SECT(p) + NR_SECTS(p) >
160 first_sector + first_size))
161 continue;
162
163 add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
164 current_minor++;
165 if ((current_minor & mask) == 0)
166 goto done;
167 }
168 /*
169 * Next, process the (first) extended partition, if present.
170 * (So far, there seems to be no reason to make
171 * extended_partition() recursive and allow a tree
172 * of extended partitions.)
173 * It should be a link to the next logical partition.
174 * Create a minor for this just long enough to get the next
175 * partition table. The minor will be reused for the next
176 * data partition.
177 */
178 p -= 4;
179 for (i=0; i<4; i++, p++)
180 if(NR_SECTS(p) && is_extended_partition(p))
181 break;
182 if (i == 4)
183 goto done; /* nothing left to do */
184
185 hd->part[current_minor].nr_sects = NR_SECTS(p);
186 hd->part[current_minor].start_sect = first_sector + START_SECT(p);
187 this_sector = first_sector + START_SECT(p);
188 dev = MKDEV(hd->major, current_minor);
189 brelse(bh);
190 }
191 done:
192 brelse(bh);
193 }
194
195 static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
196 {
197 int i, minor = current_minor;
198 struct buffer_head *bh;
199 struct partition *p;
200 unsigned char *data;
201 int mask = (1 << hd->minor_shift) - 1;
202 #ifdef CONFIG_BLK_DEV_IDE
203 int tested_for_xlate = 0;
204
205 read_mbr:
206 #endif
207 if (!(bh = bread(dev,0,1024))) {
208 printk(" unable to read partition table\n");
209 return -1;
210 }
211 data = bh->b_data;
212 /* In some cases we modify the geometry */
213 /* of the drive (below), so ensure that */
214 /* nobody else tries to re-use this data. */
215 bh->b_state = 0;
216 #ifdef CONFIG_BLK_DEV_IDE
217 check_table:
218 #endif
219 if (*(unsigned short *) (0x1fe + data) != 0xAA55) {
220 brelse(bh);
221 return 0;
222 }
223 p = (struct partition *) (0x1be + data);
224
225 #ifdef CONFIG_BLK_DEV_IDE
226 if (!tested_for_xlate++) { /* Do this only once per disk */
227 /*
228 * Look for various forms of IDE disk geometry translation
229 */
230 extern int ide_xlate_1024(kdev_t, int, const char *);
231 unsigned int sig = *(unsigned short *)(data + 2);
232 if (p->sys_ind == EZD_PARTITION) {
233 /*
234 * The remainder of the disk must be accessed using
235 * a translated geometry that reduces the number of
236 * apparent cylinders to less than 1024 if possible.
237 *
238 * ide_xlate_1024() will take care of the necessary
239 * adjustments to fool fdisk/LILO and partition check.
240 */
241 if (ide_xlate_1024(dev, -1, " [EZD]")) {
242 data += 512;
243 goto check_table;
244 }
245 } else if (p->sys_ind == DM6_PARTITION) {
246
247 /*
248 * Everything on the disk is offset by 63 sectors,
249 * including a "new" MBR with its own partition table,
250 * and the remainder of the disk must be accessed using
251 * a translated geometry that reduces the number of
252 * apparent cylinders to less than 1024 if possible.
253 *
254 * ide_xlate_1024() will take care of the necessary
255 * adjustments to fool fdisk/LILO and partition check.
256 */
257 if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
258 brelse(bh);
259 goto read_mbr; /* start over with new MBR */
260 }
261 } else if (sig <= 0x1ae && *(unsigned short *)(data + sig) == 0x55AA
262 && (1 & *(unsigned char *)(data + sig + 2)) )
263 {
264 /*
265 * DM6 signature in MBR, courtesy of OnTrack
266 */
267 (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
268 } else if (p->sys_ind == DM6_AUX1PARTITION || p->sys_ind == DM6_AUX3PARTITION) {
269 /*
270 * DM6 on other than the first (boot) drive
271 */
272 (void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
273 } else {
274 /*
275 * Examine the partition table for common translations.
276 * This is necessary for drives for situations where
277 * the translated geometry is unavailable from the BIOS.
278 */
279 for (i = 0; i < 4 ; i++) {
280 struct partition *q = &p[i];
281 if (NR_SECTS(q) && q->sector == 1 && q->end_sector == 63) {
282 unsigned int heads = q->end_head + 1;
283 if (heads == 32 || heads == 64 || heads == 128) {
284
285 (void) ide_xlate_1024(dev, heads, " [PTBL]");
286 break;
287 }
288 }
289 }
290 }
291 }
292 #endif /* CONFIG_BLK_DEV_IDE */
293
294 current_minor += 4; /* first "extra" minor (for extended partitions) */
295 for (i=1 ; i<=4 ; minor++,i++,p++) {
296 if (!NR_SECTS(p))
297 continue;
298 add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
299 if (is_extended_partition(p)) {
300 printk(" <");
301 /*
302 * If we are rereading the partition table, we need
303 * to set the size of the partition so that we will
304 * be able to bread the block containing the extended
305 * partition info.
306 */
307 hd->sizes[minor] = hd->part[minor].nr_sects
308 >> (BLOCK_SIZE_BITS - 9);
309 extended_partition(hd, MKDEV(hd->major, minor));
310 printk(" >");
311 /* prevent someone doing mkfs or mkswap on an
312 extended partition, but leave room for LILO */
313 if (hd->part[minor].nr_sects > 2)
314 hd->part[minor].nr_sects = 2;
315 }
316 }
317 /*
318 * Check for old-style Disk Manager partition table
319 */
320 if (*(unsigned short *) (data+0xfc) == 0x55AA) {
321 p = (struct partition *) (0x1be + data);
322 for (i = 4 ; i < 16 ; i++, current_minor++) {
323 p--;
324 if ((current_minor & mask) == 0)
325 break;
326 if (!(START_SECT(p) && NR_SECTS(p)))
327 continue;
328 add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
329 }
330 }
331 printk("\n");
332 brelse(bh);
333 return 1;
334 }
335
336 #endif /* CONFIG_MSDOS_PARTITION */
337
338 #ifdef CONFIG_OSF_PARTITION
339
340 static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
341 {
342 int i;
343 int mask = (1 << hd->minor_shift) - 1;
344 struct buffer_head *bh;
345 struct disklabel {
346 u32 d_magic;
347 u16 d_type,d_subtype;
348 u8 d_typename[16];
349 u8 d_packname[16];
350 u32 d_secsize;
351 u32 d_nsectors;
352 u32 d_ntracks;
353 u32 d_ncylinders;
354 u32 d_secpercyl;
355 u32 d_secprtunit;
356 u16 d_sparespertrack;
357 u16 d_sparespercyl;
358 u32 d_acylinders;
359 u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
360 u32 d_headswitch, d_trkseek, d_flags;
361 u32 d_drivedata[5];
362 u32 d_spare[5];
363 u32 d_magic2;
364 u16 d_checksum;
365 u16 d_npartitions;
366 u32 d_bbsize, d_sbsize;
367 struct d_partition {
368 u32 p_size;
369 u32 p_offset;
370 u32 p_fsize;
371 u8 p_fstype;
372 u8 p_frag;
373 u16 p_cpg;
374 } d_partitions[8];
375 } * label;
376 struct d_partition * partition;
377 #define DISKLABELMAGIC (0x82564557UL)
378
379 if (!(bh = bread(dev,0,1024))) {
380 printk("unable to read partition table\n");
381 return -1;
382 }
383 label = (struct disklabel *) (bh->b_data+64);
384 partition = label->d_partitions;
385 if (label->d_magic != DISKLABELMAGIC) {
386 printk("magic: %08x\n", label->d_magic);
387 brelse(bh);
388 return 0;
389 }
390 if (label->d_magic2 != DISKLABELMAGIC) {
391 printk("magic2: %08x\n", label->d_magic2);
392 brelse(bh);
393 return 0;
394 }
395 for (i = 0 ; i < label->d_npartitions; i++, partition++) {
396 if ((current_minor & mask) == 0)
397 break;
398 if (partition->p_size)
399 add_partition(hd, current_minor,
400 first_sector+partition->p_offset,
401 partition->p_size);
402 current_minor++;
403 }
404 printk("\n");
405 brelse(bh);
406 return 1;
407 }
408
409 #endif /* CONFIG_OSF_PARTITION */
410
411 #ifdef CONFIG_SUN_PARTITION
412
413 static int sun_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
414 {
415 int i, csum;
416 unsigned short *ush;
417 struct buffer_head *bh;
418 struct sun_disklabel {
419 unsigned char info[128]; /* Informative text string */
420 unsigned char spare[292]; /* Boot information etc. */
421 unsigned short rspeed; /* Disk rotational speed */
422 unsigned short pcylcount; /* Physical cylinder count */
423 unsigned short sparecyl; /* extra sects per cylinder */
424 unsigned char spare2[4]; /* More magic... */
425 unsigned short ilfact; /* Interleave factor */
426 unsigned short ncyl; /* Data cylinder count */
427 unsigned short nacyl; /* Alt. cylinder count */
428 unsigned short ntrks; /* Tracks per cylinder */
429 unsigned short nsect; /* Sectors per track */
430 unsigned char spare3[4]; /* Even more magic... */
431 struct sun_partition {
432 unsigned long start_cylinder;
433 unsigned long num_sectors;
434 } partitions[8];
435 unsigned short magic; /* Magic number */
436 unsigned short csum; /* Label xor'd checksum */
437 } * label;
438 struct sun_partition *p;
439 unsigned long spc;
440 #define SUN_LABEL_MAGIC 0xDABE
441
442 if(!(bh = bread(dev, 0, 1024))) {
443 printk("Dev %d: unable to read partition table\n", dev);
444 return -1;
445 }
446 label = (struct sun_disklabel *) bh->b_data;
447 p = label->partitions;
448 if(label->magic != SUN_LABEL_MAGIC) {
449 printk("Dev %d Sun disklabel: bad magic %08x\n", dev, label->magic);
450 brelse(bh);
451 return 0;
452 }
453 /* Look at the checksum */
454 ush = ((unsigned short *) (label+1)) - 1;
455 for(csum = 0; ush >= ((unsigned short *) label);)
456 csum ^= *ush--;
457 if(csum) {
458 printk("Dev %d Sun disklabel: Csum bad, label corrupted\n", dev);
459 brelse(bh);
460 return 0;
461 }
462 /* All Sun disks have 8 partition entries */
463 spc = (label->ntrks * label->nsect);
464 for(i=0; i < 8; i++, p++) {
465 unsigned long st_sector;
466
467 /* We register all partitions, even if zero size, so that
468 * the minor numbers end up ok as per SunOS interpretation.
469 */
470 st_sector = first_sector + (p->start_cylinder * spc);
471 add_partition(hd, current_minor, st_sector, p->num_sectors);
472 current_minor++;
473 }
474 printk("\n");
475 brelse(bh);
476 return 1;
477 }
478
479 #endif /* CONFIG_SUN_PARTITION */
480
481 static void check_partition(struct gendisk *hd, kdev_t dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
482 {
483 static int first_time = 1;
484 unsigned long first_sector;
485
486 if (first_time)
487 printk("Partition check:\n");
488 first_time = 0;
489 first_sector = hd->part[MINOR(dev)].start_sect;
490
491 /*
492 * This is a kludge to allow the partition check to be
493 * skipped for specific drives (e.g. IDE cd-rom drives)
494 */
495 if ((int)first_sector == -1) {
496 hd->part[MINOR(dev)].start_sect = 0;
497 return;
498 }
499
500 printk(" ");
501 print_minor_name(hd, MINOR(dev));
502 #ifdef CONFIG_MSDOS_PARTITION
503 if (msdos_partition(hd, dev, first_sector))
504 return;
505 #endif
506 #ifdef CONFIG_OSF_PARTITION
507 if (osf_partition(hd, dev, first_sector))
508 return;
509 #endif
510 #ifdef CONFIG_SUN_PARTITION
511 if(sun_partition(hd, dev, first_sector))
512 return;
513 #endif
514 printk(" unknown partition table\n");
515 }
516
517 /* This function is used to re-read partition tables for removable disks.
518 Much of the cleanup from the old partition tables should have already been
519 done */
520
521 /* This function will re-read the partition tables for a given device,
522 and set things back up again. There are some important caveats,
523 however. You must ensure that no one is using the device, and no one
524 can start using the device while this function is being executed. */
525
526 void resetup_one_dev(struct gendisk *dev, int drive)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
527 {
528 int i;
529 int first_minor = drive << dev->minor_shift;
530 int end_minor = first_minor + dev->max_p;
531
532 blk_size[dev->major] = NULL;
533 current_minor = 1 + first_minor;
534 check_partition(dev, MKDEV(dev->major, first_minor));
535
536 /*
537 * We need to set the sizes array before we will be able to access
538 * any of the partitions on this device.
539 */
540 if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
541 for (i = first_minor; i < end_minor; i++)
542 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
543 blk_size[dev->major] = dev->sizes;
544 }
545 }
546
547 static void setup_dev(struct gendisk *dev)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
548 {
549 int i, drive;
550 int end_minor = dev->max_nr * dev->max_p;
551
552 blk_size[dev->major] = NULL;
553 for (i = 0 ; i < end_minor; i++) {
554 dev->part[i].start_sect = 0;
555 dev->part[i].nr_sects = 0;
556 }
557 dev->init(dev);
558 for (drive = 0 ; drive < dev->nr_real ; drive++) {
559 int first_minor = drive << dev->minor_shift;
560 current_minor = 1 + first_minor;
561 check_partition(dev, MKDEV(dev->major, first_minor));
562 }
563 if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
564 for (i = 0; i < end_minor; i++)
565 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
566 blk_size[dev->major] = dev->sizes;
567 }
568 }
569
570 void device_setup(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
571 {
572 extern void console_map_init(void);
573 struct gendisk *p;
574 int nr=0;
575
576 chr_dev_init();
577 blk_dev_init();
578 sti();
579 #ifdef CONFIG_SCSI
580 scsi_dev_init();
581 #endif
582 #ifdef CONFIG_INET
583 net_dev_init();
584 #endif
585 console_map_init();
586
587 for (p = gendisk_head ; p ; p=p->next) {
588 setup_dev(p);
589 nr += p->nr_real;
590 }
591 #ifdef CONFIG_BLK_DEV_RAM
592 rd_load();
593 #endif
594 }