Remove building with NOCRYPTO option
[minix.git] / minix / lib / libblockdriver / drvlib.c
blob15d618ae3b5c263398c4aed54c9aac8c504c11b8
1 /* IBM device driver utility functions. Author: Kees J. Bot
2 * 7 Dec 1995
3 * Entry point:
4 * partition: partition a disk to the partition table(s) on it.
5 */
7 #include <minix/blockdriver.h>
8 #include <minix/drvlib.h>
9 #include <unistd.h>
11 /* Extended partition? */
12 #define ext_part(s) ((s) == 0x05 || (s) == 0x0F)
14 static void parse_part_table(struct blockdriver *bdp, int device,
15 int style, int atapi, u8_t *tmp_buf);
17 static void extpartition(struct blockdriver *bdp, int extdev,
18 unsigned long extbase, u8_t *tmp_buf);
20 static int get_part_table(struct blockdriver *bdp, int device,
21 unsigned long offset, struct part_entry *table, u8_t *tmp_buf);
23 static void sort(struct part_entry *table);
25 /*============================================================================*
26 * partition *
27 *============================================================================*/
28 void partition(
29 struct blockdriver *bdp, /* device dependent entry points */
30 int device, /* device to partition */
31 int style, /* partitioning style: floppy, primary, sub. */
32 int atapi /* atapi device */
35 /* This routine is called on first open to initialize the partition tables
36 * of a device.
38 u8_t *tmp_buf;
40 if ((*bdp->bdr_part)(device) == NULL)
41 return;
43 /* For multithreaded drivers, multiple partition() calls may be made on
44 * different devices in parallel. Hence we need a separate temporary buffer
45 * for each request.
47 if (!(tmp_buf = alloc_contig(CD_SECTOR_SIZE, AC_ALIGN4K, NULL)))
48 panic("partition: unable to allocate temporary buffer");
50 parse_part_table(bdp, device, style, atapi, tmp_buf);
52 free_contig(tmp_buf, CD_SECTOR_SIZE);
55 /*============================================================================*
56 * parse_part_table *
57 *============================================================================*/
58 static void parse_part_table(
59 struct blockdriver *bdp, /* device dependent entry points */
60 int device, /* device to partition */
61 int style, /* partitioning style: floppy, primary, sub. */
62 int atapi, /* atapi device */
63 u8_t *tmp_buf /* temporary buffer */
66 /* This routine reads and parses a partition table. It may be called
67 * recursively. It makes sure that each partition falls safely within the
68 * device's limits. Depending on the partition style we are either making
69 * floppy partitions, primary partitions or subpartitions. Only primary
70 * partitions are sorted, because they are shared with other operating
71 * systems that expect this.
73 struct part_entry table[NR_PARTITIONS], *pe;
74 int disk, par;
75 struct device *dv;
76 unsigned long base, limit, part_limit;
78 /* Get the geometry of the device to partition */
79 if ((dv = (*bdp->bdr_part)(device)) == NULL
80 || dv->dv_size == 0) return;
81 base = (unsigned long)(dv->dv_base / SECTOR_SIZE);
82 limit = base + (unsigned long)(dv->dv_size / SECTOR_SIZE);
84 /* Read the partition table for the device. */
85 if(!get_part_table(bdp, device, 0L, table, tmp_buf)) {
86 return;
89 /* Compute the device number of the first partition. */
90 switch (style) {
91 case P_FLOPPY:
92 device += MINOR_fd0p0;
93 break;
94 case P_PRIMARY:
95 sort(table); /* sort a primary partition table */
96 device += 1;
97 break;
98 case P_SUB:
99 disk = device / DEV_PER_DRIVE;
100 par = device % DEV_PER_DRIVE - 1;
101 device = MINOR_d0p0s0 + (disk * NR_PARTITIONS + par) * NR_PARTITIONS;
104 /* Find an array of devices. */
105 if ((dv = (*bdp->bdr_part)(device)) == NULL) return;
107 /* Set the geometry of the partitions from the partition table. */
108 for (par = 0; par < NR_PARTITIONS; par++, dv++) {
109 /* Shrink the partition to fit within the device. */
110 pe = &table[par];
111 part_limit = pe->lowsec + pe->size;
112 if (part_limit < pe->lowsec) part_limit = limit;
113 if (part_limit > limit) part_limit = limit;
114 if (pe->lowsec < base) pe->lowsec = base;
115 if (part_limit < pe->lowsec) part_limit = pe->lowsec;
117 dv->dv_base = (u64_t)pe->lowsec * SECTOR_SIZE;
118 dv->dv_size = (u64_t)(part_limit - pe->lowsec) * SECTOR_SIZE;
120 if (style == P_PRIMARY) {
121 /* Each Minix primary partition can be subpartitioned. */
122 if (pe->sysind == MINIX_PART)
123 parse_part_table(bdp, device + par, P_SUB, atapi,
124 tmp_buf);
126 /* An extended partition has logical partitions. */
127 if (ext_part(pe->sysind))
128 extpartition(bdp, device + par, pe->lowsec, tmp_buf);
133 /*============================================================================*
134 * extpartition *
135 *============================================================================*/
136 static void extpartition(
137 struct blockdriver *bdp, /* device dependent entry points */
138 int extdev, /* extended partition to scan */
139 unsigned long extbase, /* sector offset of the base ext. partition */
140 u8_t *tmp_buf /* temporary buffer */
143 /* Extended partitions cannot be ignored alas, because people like to move
144 * files to and from DOS partitions. Avoid reading this code, it's no fun.
146 struct part_entry table[NR_PARTITIONS], *pe;
147 int subdev, disk, par;
148 struct device *dv;
149 unsigned long offset, nextoffset;
151 disk = extdev / DEV_PER_DRIVE;
152 par = extdev % DEV_PER_DRIVE - 1;
153 subdev = MINOR_d0p0s0 + (disk * NR_PARTITIONS + par) * NR_PARTITIONS;
155 offset = 0;
156 do {
157 if (!get_part_table(bdp, extdev, offset, table, tmp_buf)) return;
158 sort(table);
160 /* The table should contain one logical partition and optionally
161 * another extended partition. (It's a linked list.)
163 nextoffset = 0;
164 for (par = 0; par < NR_PARTITIONS; par++) {
165 pe = &table[par];
166 if (ext_part(pe->sysind)) {
167 nextoffset = pe->lowsec;
168 } else
169 if (pe->sysind != NO_PART) {
170 if ((dv = (*bdp->bdr_part)(subdev)) == NULL) return;
172 dv->dv_base = (u64_t)(extbase + offset + pe->lowsec) *
173 SECTOR_SIZE;
174 dv->dv_size = (u64_t)pe->size * SECTOR_SIZE;
176 /* Out of devices? */
177 if (++subdev % NR_PARTITIONS == 0) return;
180 } while ((offset = nextoffset) != 0);
183 /*============================================================================*
184 * get_part_table *
185 *============================================================================*/
186 static int get_part_table(
187 struct blockdriver *bdp,
188 int device,
189 unsigned long offset, /* sector offset to the table */
190 struct part_entry *table, /* four entries */
191 u8_t *tmp_buf) /* temporary buffer */
193 /* Read the partition table for the device, return true iff there were no
194 * errors.
196 iovec_t iovec1;
197 u64_t position;
198 int r;
200 position = (u64_t)offset * SECTOR_SIZE;
201 iovec1.iov_addr = (vir_bytes) tmp_buf;
202 iovec1.iov_size = CD_SECTOR_SIZE;
203 r = (*bdp->bdr_transfer)(device, FALSE /*do_write*/, position, SELF,
204 &iovec1, 1, BDEV_NOFLAGS);
205 if (r != CD_SECTOR_SIZE) {
206 return 0;
208 if (tmp_buf[510] != 0x55 || tmp_buf[511] != 0xAA) {
209 /* Invalid partition table. */
210 return 0;
212 memcpy(table, (tmp_buf + PART_TABLE_OFF), NR_PARTITIONS * sizeof(table[0]));
213 return 1;
216 /*===========================================================================*
217 * sort *
218 *===========================================================================*/
219 static void sort(struct part_entry *table)
221 /* Sort a partition table. */
222 struct part_entry *pe, tmp;
223 int n = NR_PARTITIONS;
225 do {
226 for (pe = table; pe < table + NR_PARTITIONS-1; pe++) {
227 if (pe[0].sysind == NO_PART
228 || (pe[0].lowsec > pe[1].lowsec
229 && pe[1].sysind != NO_PART)) {
230 tmp = pe[0]; pe[0] = pe[1]; pe[1] = tmp;
233 } while (--n > 0);