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