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