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