This source file includes following definitions.
- disk_name
- add_partition
- is_extended_partition
- extended_partition
- bsd_disklabel_partition
- msdos_partition
- osf_partition
- sun_partition
- check_partition
- resetup_one_dev
- setup_dev
- device_setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 #ifdef CONFIG_BLK_DEV_INITRD
28 #include <linux/blk.h>
29 #endif
30
31 #include <asm/system.h>
32
33 #ifdef __alpha__
34
35
36
37
38
39
40
41 #include <asm/unaligned.h>
42 #define NR_SECTS(p) ldl_u(&p->nr_sects)
43 #define START_SECT(p) ldl_u(&p->start_sect)
44 #else
45 #define NR_SECTS(p) p->nr_sects
46 #define START_SECT(p) p->start_sect
47 #endif
48
49 struct gendisk *gendisk_head = NULL;
50
51 static int current_minor = 0;
52 extern int *blk_size[];
53 extern void rd_load(void);
54 extern void initrd_load(void);
55
56 extern int chr_dev_init(void);
57 extern int blk_dev_init(void);
58 extern int scsi_dev_init(void);
59 extern int net_dev_init(void);
60
61
62
63
64
65
66
67 char *disk_name (struct gendisk *hd, int minor, char *buf)
68 {
69 unsigned int part;
70 const char *maj = hd->major_name;
71 char unit = (minor >> hd->minor_shift) + 'a';
72
73 #ifdef CONFIG_BLK_DEV_IDE
74
75
76
77
78
79 switch (hd->major) {
80 case IDE3_MAJOR:
81 unit += 2;
82 case IDE2_MAJOR:
83 unit += 2;
84 case IDE1_MAJOR:
85 unit += 2;
86 case IDE0_MAJOR:
87 maj = "hd";
88 }
89 #endif
90 part = minor & ((1 << hd->minor_shift) - 1);
91 if (part)
92 sprintf(buf, "%s%c%d", maj, unit, part);
93 else
94 sprintf(buf, "%s%c", maj, unit);
95 return buf;
96 }
97
98 static void add_partition (struct gendisk *hd, int minor, int start, int size)
99 {
100 char buf[8];
101 hd->part[minor].start_sect = start;
102 hd->part[minor].nr_sects = size;
103 printk(" %s", disk_name(hd, minor, buf));
104 }
105
106 static inline int is_extended_partition(struct partition *p)
107 {
108 return (p->sys_ind == DOS_EXTENDED_PARTITION ||
109 p->sys_ind == LINUX_EXTENDED_PARTITION);
110 }
111
112 #ifdef CONFIG_MSDOS_PARTITION
113
114
115
116
117
118
119
120
121
122
123
124 static void extended_partition(struct gendisk *hd, kdev_t dev)
125 {
126 struct buffer_head *bh;
127 struct partition *p;
128 unsigned long first_sector, first_size, this_sector, this_size;
129 int mask = (1 << hd->minor_shift) - 1;
130 int i;
131
132 first_sector = hd->part[MINOR(dev)].start_sect;
133 first_size = hd->part[MINOR(dev)].nr_sects;
134 this_sector = first_sector;
135
136 while (1) {
137 if ((current_minor & mask) == 0)
138 return;
139 if (!(bh = bread(dev,0,1024)))
140 return;
141
142
143
144
145 bh->b_state = 0;
146
147 if (*(unsigned short *) (bh->b_data+510) != 0xAA55)
148 goto done;
149
150 p = (struct partition *) (0x1BE + bh->b_data);
151
152 this_size = hd->part[MINOR(dev)].nr_sects;
153
154
155
156
157
158
159
160
161
162
163
164
165
166 for (i=0; i<4; i++, p++) {
167 if (!NR_SECTS(p) || is_extended_partition(p))
168 continue;
169
170
171
172 if (i >= 2
173 && START_SECT(p) + NR_SECTS(p) > this_size
174 && (this_sector + START_SECT(p) < first_sector ||
175 this_sector + START_SECT(p) + NR_SECTS(p) >
176 first_sector + first_size))
177 continue;
178
179 add_partition(hd, current_minor, this_sector+START_SECT(p), NR_SECTS(p));
180 current_minor++;
181 if ((current_minor & mask) == 0)
182 goto done;
183 }
184
185
186
187
188
189
190
191
192
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;
200
201 hd->part[current_minor].nr_sects = NR_SECTS(p);
202 hd->part[current_minor].start_sect = first_sector + START_SECT(p);
203 this_sector = first_sector + START_SECT(p);
204 dev = MKDEV(hd->major, current_minor);
205 brelse(bh);
206 }
207 done:
208 brelse(bh);
209 }
210
211 #ifdef CONFIG_BSD_DISKLABEL
212
213
214
215
216 static void bsd_disklabel_partition(struct gendisk *hd, int dev)
217 {
218 struct buffer_head *bh;
219 struct bsd_disklabel *l;
220 struct bsd_partition *p;
221 int mask = (1 << hd->minor_shift) - 1;
222
223 if (!(bh = bread(dev,0,1024)))
224 return;
225 bh->b_state = 0;
226 l = (struct bsd_disklabel *) (bh->b_data+512);
227 if (l->d_magic != BSD_DISKMAGIC) {
228 brelse(bh);
229 return;
230 }
231
232 p = &l->d_partitions[0];
233 while (p - &l->d_partitions[0] <= BSD_MAXPARTITIONS) {
234 if ((current_minor & mask) >= (4 + hd->max_p))
235 break;
236
237 if (p->p_fstype != BSD_FS_UNUSED) {
238 add_partition(hd, current_minor, p->p_offset, p->p_size);
239 current_minor++;
240 }
241 p++;
242 }
243 brelse(bh);
244
245 }
246 #endif
247
248 static int msdos_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector)
249 {
250 int i, minor = current_minor;
251 struct buffer_head *bh;
252 struct partition *p;
253 unsigned char *data;
254 int mask = (1 << hd->minor_shift) - 1;
255 #ifdef CONFIG_BLK_DEV_IDE
256 int tested_for_xlate = 0;
257
258 read_mbr:
259 #endif
260 if (!(bh = bread(dev,0,1024))) {
261 printk(" unable to read partition table\n");
262 return -1;
263 }
264 data = bh->b_data;
265
266
267
268 bh->b_state = 0;
269 #ifdef CONFIG_BLK_DEV_IDE
270 check_table:
271 #endif
272 if (*(unsigned short *) (0x1fe + data) != 0xAA55) {
273 brelse(bh);
274 return 0;
275 }
276 p = (struct partition *) (0x1be + data);
277
278 #ifdef CONFIG_BLK_DEV_IDE
279 if (!tested_for_xlate++) {
280
281
282
283 extern int ide_xlate_1024(kdev_t, int, const char *);
284 unsigned int sig = *(unsigned short *)(data + 2);
285 if (p->sys_ind == EZD_PARTITION) {
286
287
288
289
290
291
292
293
294 if (ide_xlate_1024(dev, -1, " [EZD]")) {
295 data += 512;
296 goto check_table;
297 }
298 } else if (p->sys_ind == DM6_PARTITION) {
299
300
301
302
303
304
305
306
307
308
309
310 if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) {
311 brelse(bh);
312 goto read_mbr;
313 }
314 } else if (sig <= 0x1ae && *(unsigned short *)(data + sig) == 0x55AA
315 && (1 & *(unsigned char *)(data + sig + 2)) )
316 {
317
318
319
320 (void) ide_xlate_1024 (dev, 0, " [DM6:MBR]");
321 } else if (p->sys_ind == DM6_AUX1PARTITION || p->sys_ind == DM6_AUX3PARTITION) {
322
323
324
325 (void) ide_xlate_1024(dev, 0, " [DM6:AUX]");
326 } else {
327
328
329
330
331
332 for (i = 0; i < 4 ; i++) {
333 struct partition *q = &p[i];
334 if (NR_SECTS(q) && q->sector == 1 && q->end_sector == 63) {
335 unsigned int heads = q->end_head + 1;
336 if (heads == 32 || heads == 64 || heads == 128) {
337
338 (void) ide_xlate_1024(dev, heads, " [PTBL]");
339 break;
340 }
341 }
342 }
343 }
344 }
345 #endif
346
347 current_minor += 4;
348 for (i=1 ; i<=4 ; minor++,i++,p++) {
349 if (!NR_SECTS(p))
350 continue;
351 add_partition(hd, minor, first_sector+START_SECT(p), NR_SECTS(p));
352 if (is_extended_partition(p)) {
353 printk(" <");
354
355
356
357
358
359
360 hd->sizes[minor] = hd->part[minor].nr_sects
361 >> (BLOCK_SIZE_BITS - 9);
362 extended_partition(hd, MKDEV(hd->major, minor));
363 printk(" >");
364
365
366 if (hd->part[minor].nr_sects > 2)
367 hd->part[minor].nr_sects = 2;
368 }
369 #ifdef CONFIG_BSD_DISKLABEL
370 if (p->sys_ind == BSD_PARTITION) {
371 printk(" <");
372 bsd_disklabel_partition(hd, MKDEV(hd->major, minor));
373 printk(" >");
374 }
375 #endif
376 }
377
378
379
380 if (*(unsigned short *) (data+0xfc) == 0x55AA) {
381 p = (struct partition *) (0x1be + data);
382 for (i = 4 ; i < 16 ; i++, current_minor++) {
383 p--;
384 if ((current_minor & mask) == 0)
385 break;
386 if (!(START_SECT(p) && NR_SECTS(p)))
387 continue;
388 add_partition(hd, current_minor, START_SECT(p), NR_SECTS(p));
389 }
390 }
391 printk("\n");
392 brelse(bh);
393 return 1;
394 }
395
396 #endif
397
398 #ifdef CONFIG_OSF_PARTITION
399
400 static int osf_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
401 {
402 int i;
403 int mask = (1 << hd->minor_shift) - 1;
404 struct buffer_head *bh;
405 struct disklabel {
406 u32 d_magic;
407 u16 d_type,d_subtype;
408 u8 d_typename[16];
409 u8 d_packname[16];
410 u32 d_secsize;
411 u32 d_nsectors;
412 u32 d_ntracks;
413 u32 d_ncylinders;
414 u32 d_secpercyl;
415 u32 d_secprtunit;
416 u16 d_sparespertrack;
417 u16 d_sparespercyl;
418 u32 d_acylinders;
419 u16 d_rpm, d_interleave, d_trackskew, d_cylskew;
420 u32 d_headswitch, d_trkseek, d_flags;
421 u32 d_drivedata[5];
422 u32 d_spare[5];
423 u32 d_magic2;
424 u16 d_checksum;
425 u16 d_npartitions;
426 u32 d_bbsize, d_sbsize;
427 struct d_partition {
428 u32 p_size;
429 u32 p_offset;
430 u32 p_fsize;
431 u8 p_fstype;
432 u8 p_frag;
433 u16 p_cpg;
434 } d_partitions[8];
435 } * label;
436 struct d_partition * partition;
437 #define DISKLABELMAGIC (0x82564557UL)
438
439 if (!(bh = bread(dev,0,1024))) {
440 printk("unable to read partition table\n");
441 return -1;
442 }
443 label = (struct disklabel *) (bh->b_data+64);
444 partition = label->d_partitions;
445 if (label->d_magic != DISKLABELMAGIC) {
446 printk("magic: %08x\n", label->d_magic);
447 brelse(bh);
448 return 0;
449 }
450 if (label->d_magic2 != DISKLABELMAGIC) {
451 printk("magic2: %08x\n", label->d_magic2);
452 brelse(bh);
453 return 0;
454 }
455 for (i = 0 ; i < label->d_npartitions; i++, partition++) {
456 if ((current_minor & mask) == 0)
457 break;
458 if (partition->p_size)
459 add_partition(hd, current_minor,
460 first_sector+partition->p_offset,
461 partition->p_size);
462 current_minor++;
463 }
464 printk("\n");
465 brelse(bh);
466 return 1;
467 }
468
469 #endif
470
471 #ifdef CONFIG_SUN_PARTITION
472
473 static int sun_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
474 {
475 int i, csum;
476 unsigned short *ush;
477 struct buffer_head *bh;
478 struct sun_disklabel {
479 unsigned char info[128];
480 unsigned char spare[292];
481 unsigned short rspeed;
482 unsigned short pcylcount;
483 unsigned short sparecyl;
484 unsigned char spare2[4];
485 unsigned short ilfact;
486 unsigned short ncyl;
487 unsigned short nacyl;
488 unsigned short ntrks;
489 unsigned short nsect;
490 unsigned char spare3[4];
491 struct sun_partition {
492 __u32 start_cylinder;
493 __u32 num_sectors;
494 } partitions[8];
495 unsigned short magic;
496 unsigned short csum;
497 } * label;
498 struct sun_partition *p;
499 int other_endian;
500 unsigned long spc;
501 #define SUN_LABEL_MAGIC 0xDABE
502 #define SUN_LABEL_MAGIC_SWAPPED 0xBEDA
503
504
505 #define SWAP16(x) (other_endian ? (((__u16)(x) & 0xFF) << 8) \
506 | (((__u16)(x) & 0xFF00) >> 8) \
507 : (__u16)(x))
508 #define SWAP32(x) (other_endian ? (((__u32)(x) & 0xFF) << 24) \
509 | (((__u32)(x) & 0xFF00) << 8) \
510 | (((__u32)(x) & 0xFF0000) >> 8) \
511 | (((__u32)(x) & 0xFF000000) >> 24) \
512 : (__u32)(x))
513
514 if(!(bh = bread(dev, 0, 1024))) {
515 printk("Dev %d: unable to read partition table\n", dev);
516 return -1;
517 }
518 label = (struct sun_disklabel *) bh->b_data;
519 p = label->partitions;
520 if (label->magic != SUN_LABEL_MAGIC && label->magic != SUN_LABEL_MAGIC_SWAPPED) {
521 printk("Dev %d Sun disklabel: bad magic %04x\n", dev, label->magic);
522 brelse(bh);
523 return 0;
524 }
525 other_endian = (label->magic == SUN_LABEL_MAGIC_SWAPPED);
526
527 ush = ((unsigned short *) (label+1)) - 1;
528 for(csum = 0; ush >= ((unsigned short *) label);)
529 csum ^= *ush--;
530 if(csum) {
531 printk("Dev %d Sun disklabel: Csum bad, label corrupted\n", dev);
532 brelse(bh);
533 return 0;
534 }
535
536 spc = SWAP16(label->ntrks) * SWAP16(label->nsect);
537 for(i=0; i < 8; i++, p++) {
538 unsigned long st_sector;
539
540
541
542
543 st_sector = first_sector + SWAP32(p->start_cylinder) * spc;
544 add_partition(hd, current_minor, st_sector, SWAP32(p->num_sectors));
545 current_minor++;
546 }
547 printk("\n");
548 brelse(bh);
549 return 1;
550 #undef SWAP16
551 #undef SWAP32
552 }
553
554 #endif
555
556 static void check_partition(struct gendisk *hd, kdev_t dev)
557 {
558 static int first_time = 1;
559 unsigned long first_sector;
560 char buf[8];
561
562 if (first_time)
563 printk("Partition check:\n");
564 first_time = 0;
565 first_sector = hd->part[MINOR(dev)].start_sect;
566
567
568
569
570
571 if ((int)first_sector == -1) {
572 hd->part[MINOR(dev)].start_sect = 0;
573 return;
574 }
575
576 printk(" %s:", disk_name(hd, MINOR(dev), buf));
577 #ifdef CONFIG_MSDOS_PARTITION
578 if (msdos_partition(hd, dev, first_sector))
579 return;
580 #endif
581 #ifdef CONFIG_OSF_PARTITION
582 if (osf_partition(hd, dev, first_sector))
583 return;
584 #endif
585 #ifdef CONFIG_SUN_PARTITION
586 if(sun_partition(hd, dev, first_sector))
587 return;
588 #endif
589 printk(" unknown partition table\n");
590 }
591
592
593
594
595
596
597
598
599
600
601 void resetup_one_dev(struct gendisk *dev, int drive)
602 {
603 int i;
604 int first_minor = drive << dev->minor_shift;
605 int end_minor = first_minor + dev->max_p;
606
607 blk_size[dev->major] = NULL;
608 current_minor = 1 + first_minor;
609 check_partition(dev, MKDEV(dev->major, first_minor));
610
611
612
613
614
615 if (dev->sizes != NULL) {
616 for (i = first_minor; i < end_minor; i++)
617 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
618 blk_size[dev->major] = dev->sizes;
619 }
620 }
621
622 static void setup_dev(struct gendisk *dev)
623 {
624 int i, drive;
625 int end_minor = dev->max_nr * dev->max_p;
626
627 blk_size[dev->major] = NULL;
628 for (i = 0 ; i < end_minor; i++) {
629 dev->part[i].start_sect = 0;
630 dev->part[i].nr_sects = 0;
631 }
632 dev->init(dev);
633 for (drive = 0 ; drive < dev->nr_real ; drive++) {
634 int first_minor = drive << dev->minor_shift;
635 current_minor = 1 + first_minor;
636 check_partition(dev, MKDEV(dev->major, first_minor));
637 }
638 if (dev->sizes != NULL) {
639 for (i = 0; i < end_minor; i++)
640 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
641 blk_size[dev->major] = dev->sizes;
642 }
643 }
644
645 void device_setup(void)
646 {
647 extern void console_map_init(void);
648 struct gendisk *p;
649 int nr=0;
650
651 chr_dev_init();
652 blk_dev_init();
653 sti();
654 #ifdef CONFIG_SCSI
655 scsi_dev_init();
656 #endif
657 #ifdef CONFIG_INET
658 net_dev_init();
659 #endif
660 console_map_init();
661
662 for (p = gendisk_head ; p ; p=p->next) {
663 setup_dev(p);
664 nr += p->nr_real;
665 }
666 #ifdef CONFIG_BLK_DEV_RAM
667 #ifdef CONFIG_BLK_DEV_INITRD
668 if (initrd_start && mount_initrd) initrd_load();
669 else
670 #endif
671 rd_load();
672 #endif
673 }