1 /* IBM device driver utility functions. Author: Kees J. Bot
4 * partition: partition a disk to the partition table(s) on it.
7 #include <minix/blockdriver.h>
8 #include <minix/drvlib.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 /*============================================================================*
27 *============================================================================*/
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
40 if ((*bdp
->bdr_part
)(device
) == NULL
)
43 /* For multithreaded drivers, multiple partition() calls may be made on
44 * different devices in parallel. Hence we need a separate temporary buffer
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 /*============================================================================*
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
;
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
)) {
89 /* Compute the device number of the first partition. */
92 device
+= MINOR_fd0p0
;
95 sort(table
); /* sort a primary partition table */
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. */
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
,
126 /* An extended partition has logical partitions. */
127 if (ext_part(pe
->sysind
))
128 extpartition(bdp
, device
+ par
, pe
->lowsec
, tmp_buf
);
133 /*============================================================================*
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
;
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
;
157 if (!get_part_table(bdp
, extdev
, offset
, table
, tmp_buf
)) return;
160 /* The table should contain one logical partition and optionally
161 * another extended partition. (It's a linked list.)
164 for (par
= 0; par
< NR_PARTITIONS
; par
++) {
166 if (ext_part(pe
->sysind
)) {
167 nextoffset
= pe
->lowsec
;
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
) *
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 /*============================================================================*
185 *============================================================================*/
186 static int get_part_table(
187 struct blockdriver
*bdp
,
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
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
) {
208 if (tmp_buf
[510] != 0x55 || tmp_buf
[511] != 0xAA) {
209 /* Invalid partition table. */
212 memcpy(table
, (tmp_buf
+ PART_TABLE_OFF
), NR_PARTITIONS
* sizeof(table
[0]));
216 /*===========================================================================*
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
;
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
;