📄 genhd.c.txt
字号:
1 /*
2 * Code extracted from
3 * linux/kernel/hd.c
4 *
5 * Copyright (C) 1991, 1992 Linus Torvalds
6 */
7
8 /*
9 * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
10 * in the early extended-partition checks and added DM partitions
11 */
12
13 #include <linux/config.h>
14 #include <linux/fs.h>
15 #include <linux/genhd.h>
16 #include <linux/kernel.h>
17
18 struct gendisk *gendisk_head = NULL;
19
20 static int current_minor = 0;
21 extern int *blk_size[];
22 extern void rd_load(void);
23 extern int ramdisk_size;
24
25 /*
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.
34 */
35
36 static void extended_partition(struct gendisk *hd, int dev)
37 {
38 struct buffer_head *bh;
39 struct partition *p;
40 unsigned long first_sector, this_sector;
41 int mask = (1 << hd->minor_shift) - 1;
42
43 first_sector = hd->part[MINOR(dev)].start_sect;
44 this_sector = first_sector;
45
46 while (1) {
47 if ((current_minor & mask) >= (4 + hd->max_p))
48 return;
49 if (!(bh = bread(dev,0,1024)))
50 return;
51 /*
52 * This block is from a device that we're about to stomp on.
53 * So make sure nobody thinks this block is usable.
54 */
55 bh->b_dirt=0;
56 bh->b_uptodate=0;
57 if (*(unsigned short *) (bh->b_data+510) == 0xAA55) {
58 p = (struct partition *) (0x1BE + bh->b_data);
59 /*
60 * Process the first entry, which should be the real
61 * data partition.
62 */
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);
70 current_minor++;
71 p++;
72 /*
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
77 * data partition.
78 */
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;
85 brelse(bh);
86 } else
87 goto done;
88 }
89 done:
90 brelse(bh);
91 }
92
93 static void check_partition(struct gendisk *hd, unsigned int dev)
94 {
95 static int first_time = 1;
96 int i, minor = current_minor;
97 struct buffer_head *bh;
98 struct partition *p;
99 unsigned long first_sector;
100 int mask = (1 << hd->minor_shift) - 1;
101
102 if (first_time)
103 printk("Partition check:\n");
104 first_time = 0;
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);
108 return;
109 }
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))
116 continue;
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)
120 continue;
121 if (p->sys_ind == EXTENDED_PARTITION) {
122 printk(" <");
123 extended_partition(hd, (hd->major << 8) | minor);
124 printk(" >");
125 }
126 }
127 /*
128 * check for Disk Manager partition table
129 */
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++) {
133 p--;
134 if ((current_minor & mask) >= mask-2)
135 break;
136 if (!(p->start_sect && p->nr_sects))
137 continue;
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);
143 }
144 }
145 } else
146 printk(" bad partition table");
147 printk("\n");
148 brelse(bh);
149 }
150
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
153 done */
154
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. */
159
160 void resetup_one_dev(struct gendisk *dev, int drive)
161 {
162 int i;
163 int start = drive<<dev->minor_shift;
164 int j = start + dev->max_p;
165 int major = dev->major << 8;
166
167 current_minor = 1+(drive<<dev->minor_shift);
168 check_partition(dev, major+(drive<<dev->minor_shift));
169
170 for (i=start ; i < j ; i++)
171 dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
172 }
173
174 static void setup_dev(struct gendisk *dev)
175 {
176 int i;
177 int j = dev->max_nr * dev->max_p;
178 int major = dev->major << 8;
179 int drive;
180
181
182 for (i = 0 ; i < j; i++) {
183 dev->part[i].start_sect = 0;
184 dev->part[i].nr_sects = 0;
185 }
186 dev->init();
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));
190 }
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;
194 }
195
196 /* This may be used only once, enforced by 'static int callable' */
197 asmlinkage int sys_setup(void * BIOS)
198 {
199 static int callable = 1;
200 struct gendisk *p;
201 int nr=0;
202
203 if (!callable)
204 return -1;
205 callable = 0;
206
207 for (p = gendisk_head ; p ; p=p->next) {
208 setup_dev(p);
209 nr += p->nr_real;
210 }
211
212 if (ramdisk_size)
213 rd_load();
214 mount_root();
215 return (0);
216 }
217
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -