5 * Copyright (C) 1991, 1992 Linus Torvalds
9 * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
10 * in the early extended-partition checks and added DM partitions
13 #include <linux/config.h>
15 #include <linux/genhd.h>
16 #include <linux/kernel.h>
18 struct gendisk
*gendisk_head
= NULL
;
20 static int current_minor
= 0;
21 extern int *blk_size
[];
22 extern void rd_load(void);
23 extern int ramdisk_size
;
26 * Create devices for each logical partition in an extended partition.
27 * The logical partitions form a linked list, with each entry being
28 * a partition table with two entries. The first entry
29 * is the real data partition (with a start relative to the partition
30 * table start). The second is a pointer to the next logical partition
31 * (with a start relative to the entire extended partition).
32 * We do not create a Linux partition for the partition tables, but
33 * only for the actual data partitions.
36 static void extended_partition(struct gendisk
*hd
, int dev
)
38 struct buffer_head
*bh
;
40 unsigned long first_sector
, this_sector
;
41 int mask
= (1 << hd
->minor_shift
) - 1;
43 first_sector
= hd
->part
[MINOR(dev
)].start_sect
;
44 this_sector
= first_sector
;
47 if ((current_minor
& mask
) >= (4 + hd
->max_p
))
49 if (!(bh
= bread(dev
,0,1024)))
52 * This block is from a device that we're about to stomp on.
53 * So make sure nobody thinks this block is usable.
57 if (*(unsigned short *) (bh
->b_data
+510) == 0xAA55) {
58 p
= (struct partition
*) (0x1BE + bh
->b_data
);
60 * Process the first entry, which should be the real
63 if (p
->sys_ind
== EXTENDED_PARTITION
||
64 !(hd
->part
[current_minor
].nr_sects
= p
->nr_sects
))
65 goto done
; /* shouldn't happen */
66 hd
->part
[current_minor
].start_sect
= this_sector
+ p
->start_sect
;
67 printk(" %s%c%d", hd
->major_name
,
68 'a'+(current_minor
>> hd
->minor_shift
),
69 mask
& current_minor
);
73 * Process the second entry, which should be a link
74 * to the next logical partition. Create a minor
75 * for this just long enough to get the next partition
76 * table. The minor will be reused for the real
79 if (p
->sys_ind
!= EXTENDED_PARTITION
||
80 !(hd
->part
[current_minor
].nr_sects
= p
->nr_sects
))
81 goto done
; /* no more logicals in this partition */
82 hd
->part
[current_minor
].start_sect
= first_sector
+ p
->start_sect
;
83 this_sector
= first_sector
+ p
->start_sect
;
84 dev
= ((hd
->major
) << 8) | current_minor
;
93 static void check_partition(struct gendisk
*hd
, unsigned int dev
)
95 static int first_time
= 1;
96 int i
, minor
= current_minor
;
97 struct buffer_head
*bh
;
99 unsigned long first_sector
;
100 int mask
= (1 << hd
->minor_shift
) - 1;
103 printk("Partition check:\n");
105 first_sector
= hd
->part
[MINOR(dev
)].start_sect
;
106 if (!(bh
= bread(dev
,0,1024))) {
107 printk(" unable to read partition table of device %04x\n",dev
);
110 printk(" %s%c:", hd
->major_name
, 'a'+(minor
>> hd
->minor_shift
));
111 current_minor
+= 4; /* first "extra" minor */
112 if (*(unsigned short *) (bh
->b_data
+510) == 0xAA55) {
113 p
= (struct partition
*) (0x1BE + bh
->b_data
);
114 for (i
=1 ; i
<=4 ; minor
++,i
++,p
++) {
115 if (!(hd
->part
[minor
].nr_sects
= p
->nr_sects
))
117 hd
->part
[minor
].start_sect
= first_sector
+ p
->start_sect
;
118 printk(" %s%c%d", hd
->major_name
,'a'+(minor
>> hd
->minor_shift
), i
);
119 if ((current_minor
& 0x3f) >= 60)
121 if (p
->sys_ind
== EXTENDED_PARTITION
) {
123 extended_partition(hd
, (hd
->major
<< 8) | minor
);
128 * check for Disk Manager partition table
130 if (*(unsigned short *) (bh
->b_data
+0xfc) == 0x55AA) {
131 p
= (struct partition
*) (0x1BE + bh
->b_data
);
132 for (i
= 4 ; i
< 16 ; i
++, current_minor
++) {
134 if ((current_minor
& mask
) >= mask
-2)
136 if (!(p
->start_sect
&& p
->nr_sects
))
138 hd
->part
[current_minor
].start_sect
= p
->start_sect
;
139 hd
->part
[current_minor
].nr_sects
= p
->nr_sects
;
140 printk(" %s%c%d", hd
->major_name
,
141 'a'+(current_minor
>> hd
->minor_shift
),
142 current_minor
& mask
);
146 printk(" bad partition table");
151 /* This function is used to re-read partition tables for removable disks.
152 Much of the cleanup from the old partition tables should have already been
155 /* This function will re-read the partition tables for a given device,
156 and set things back up again. There are some important caveats,
157 however. You must ensure that no one is using the device, and no one
158 can start using the device while this function is being executed. */
160 void resetup_one_dev(struct gendisk
*dev
, int drive
)
163 int start
= drive
<<dev
->minor_shift
;
164 int j
= start
+ dev
->max_p
;
165 int major
= dev
->major
<< 8;
167 current_minor
= 1+(drive
<<dev
->minor_shift
);
168 check_partition(dev
, major
+(drive
<<dev
->minor_shift
));
170 for (i
=start
; i
< j
; i
++)
171 dev
->sizes
[i
] = dev
->part
[i
].nr_sects
>> (BLOCK_SIZE_BITS
- 9);
174 static void setup_dev(struct gendisk
*dev
)
177 int j
= dev
->max_nr
* dev
->max_p
;
178 int major
= dev
->major
<< 8;
182 for (i
= 0 ; i
< j
; i
++) {
183 dev
->part
[i
].start_sect
= 0;
184 dev
->part
[i
].nr_sects
= 0;
187 for (drive
=0 ; drive
<dev
->nr_real
; drive
++) {
188 current_minor
= 1+(drive
<<dev
->minor_shift
);
189 check_partition(dev
, major
+(drive
<<dev
->minor_shift
));
191 for (i
=0 ; i
< j
; i
++)
192 dev
->sizes
[i
] = dev
->part
[i
].nr_sects
>> (BLOCK_SIZE_BITS
- 9);
193 blk_size
[dev
->major
] = dev
->sizes
;
196 /* This may be used only once, enforced by 'static int callable' */
197 asmlinkage
int sys_setup(void * BIOS
)
199 static int callable
= 1;
207 for (p
= gendisk_head
; p
; p
=p
->next
) {