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