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
, int
15 style
, int atapi
, u8_t
*tmp_buf
);
16 static void extpartition(struct blockdriver
*bdp
, int extdev
, unsigned
17 long extbase
, u8_t
*tmp_buf
);
18 static int get_part_table(struct blockdriver
*bdp
, int device
, unsigned
19 long offset
, struct part_entry
*table
, u8_t
*tmp_buf
);
20 static void sort(struct part_entry
*table
);
22 /*============================================================================*
24 *============================================================================*/
25 void partition(bdp
, device
, style
, atapi
)
26 struct blockdriver
*bdp
; /* device dependent entry points */
27 int device
; /* device to partition */
28 int style
; /* partitioning style: floppy, primary, sub. */
29 int atapi
; /* atapi device */
31 /* This routine is called on first open to initialize the partition tables
36 if ((*bdp
->bdr_part
)(device
) == NULL
)
39 /* For multithreaded drivers, multiple partition() calls may be made on
40 * different devices in parallel. Hence we need a separate temporary buffer
43 if (!(tmp_buf
= alloc_contig(CD_SECTOR_SIZE
, AC_ALIGN4K
, NULL
)))
44 panic("partition: unable to allocate temporary buffer");
46 parse_part_table(bdp
, device
, style
, atapi
, tmp_buf
);
48 free_contig(tmp_buf
, CD_SECTOR_SIZE
);
51 /*============================================================================*
53 *============================================================================*/
54 static void parse_part_table(bdp
, device
, style
, atapi
, tmp_buf
)
55 struct blockdriver
*bdp
; /* device dependent entry points */
56 int device
; /* device to partition */
57 int style
; /* partitioning style: floppy, primary, sub. */
58 int atapi
; /* atapi device */
59 u8_t
*tmp_buf
; /* temporary buffer */
61 /* This routine reads and parses a partition table. It may be called
62 * recursively. It makes sure that each partition falls safely within the
63 * device's limits. Depending on the partition style we are either making
64 * floppy partitions, primary partitions or subpartitions. Only primary
65 * partitions are sorted, because they are shared with other operating
66 * systems that expect this.
68 struct part_entry table
[NR_PARTITIONS
], *pe
;
71 unsigned long base
, limit
, part_limit
;
73 /* Get the geometry of the device to partition */
74 if ((dv
= (*bdp
->bdr_part
)(device
)) == NULL
75 || cmp64u(dv
->dv_size
, 0) == 0) return;
76 base
= div64u(dv
->dv_base
, SECTOR_SIZE
);
77 limit
= base
+ div64u(dv
->dv_size
, SECTOR_SIZE
);
79 /* Read the partition table for the device. */
80 if(!get_part_table(bdp
, device
, 0L, table
, tmp_buf
)) {
84 /* Compute the device number of the first partition. */
87 device
+= MINOR_fd0p0
;
90 sort(table
); /* sort a primary partition table */
94 disk
= device
/ DEV_PER_DRIVE
;
95 par
= device
% DEV_PER_DRIVE
- 1;
96 device
= MINOR_d0p0s0
+ (disk
* NR_PARTITIONS
+ par
) * NR_PARTITIONS
;
99 /* Find an array of devices. */
100 if ((dv
= (*bdp
->bdr_part
)(device
)) == NULL
) return;
102 /* Set the geometry of the partitions from the partition table. */
103 for (par
= 0; par
< NR_PARTITIONS
; par
++, dv
++) {
104 /* Shrink the partition to fit within the device. */
106 part_limit
= pe
->lowsec
+ pe
->size
;
107 if (part_limit
< pe
->lowsec
) part_limit
= limit
;
108 if (part_limit
> limit
) part_limit
= limit
;
109 if (pe
->lowsec
< base
) pe
->lowsec
= base
;
110 if (part_limit
< pe
->lowsec
) part_limit
= pe
->lowsec
;
112 dv
->dv_base
= mul64u(pe
->lowsec
, SECTOR_SIZE
);
113 dv
->dv_size
= mul64u(part_limit
- pe
->lowsec
, SECTOR_SIZE
);
115 if (style
== P_PRIMARY
) {
116 /* Each Minix primary partition can be subpartitioned. */
117 if (pe
->sysind
== MINIX_PART
)
118 parse_part_table(bdp
, device
+ par
, P_SUB
, atapi
,
121 /* An extended partition has logical partitions. */
122 if (ext_part(pe
->sysind
))
123 extpartition(bdp
, device
+ par
, pe
->lowsec
, tmp_buf
);
128 /*============================================================================*
130 *============================================================================*/
131 static void extpartition(bdp
, extdev
, extbase
, tmp_buf
)
132 struct blockdriver
*bdp
; /* device dependent entry points */
133 int extdev
; /* extended partition to scan */
134 unsigned long extbase
; /* sector offset of the base ext. partition */
135 u8_t
*tmp_buf
; /* temporary buffer */
137 /* Extended partitions cannot be ignored alas, because people like to move
138 * files to and from DOS partitions. Avoid reading this code, it's no fun.
140 struct part_entry table
[NR_PARTITIONS
], *pe
;
141 int subdev
, disk
, par
;
143 unsigned long offset
, nextoffset
;
145 disk
= extdev
/ DEV_PER_DRIVE
;
146 par
= extdev
% DEV_PER_DRIVE
- 1;
147 subdev
= MINOR_d0p0s0
+ (disk
* NR_PARTITIONS
+ par
) * NR_PARTITIONS
;
151 if (!get_part_table(bdp
, extdev
, offset
, table
, tmp_buf
)) return;
154 /* The table should contain one logical partition and optionally
155 * another extended partition. (It's a linked list.)
158 for (par
= 0; par
< NR_PARTITIONS
; par
++) {
160 if (ext_part(pe
->sysind
)) {
161 nextoffset
= pe
->lowsec
;
163 if (pe
->sysind
!= NO_PART
) {
164 if ((dv
= (*bdp
->bdr_part
)(subdev
)) == NULL
) return;
166 dv
->dv_base
= mul64u(extbase
+ offset
+ pe
->lowsec
,
168 dv
->dv_size
= mul64u(pe
->size
, SECTOR_SIZE
);
170 /* Out of devices? */
171 if (++subdev
% NR_PARTITIONS
== 0) return;
174 } while ((offset
= nextoffset
) != 0);
177 /*============================================================================*
179 *============================================================================*/
180 static int get_part_table(bdp
, device
, offset
, table
, tmp_buf
)
181 struct blockdriver
*bdp
;
183 unsigned long offset
; /* sector offset to the table */
184 struct part_entry
*table
; /* four entries */
185 u8_t
*tmp_buf
; /* temporary buffer */
187 /* Read the partition table for the device, return true iff there were no
194 position
= mul64u(offset
, SECTOR_SIZE
);
195 iovec1
.iov_addr
= (vir_bytes
) tmp_buf
;
196 iovec1
.iov_size
= CD_SECTOR_SIZE
;
197 r
= (*bdp
->bdr_transfer
)(device
, FALSE
/*do_write*/, position
, SELF
,
198 &iovec1
, 1, BDEV_NOFLAGS
);
199 if (r
!= CD_SECTOR_SIZE
) {
202 if (tmp_buf
[510] != 0x55 || tmp_buf
[511] != 0xAA) {
203 /* Invalid partition table. */
206 memcpy(table
, (tmp_buf
+ PART_TABLE_OFF
), NR_PARTITIONS
* sizeof(table
[0]));
210 /*===========================================================================*
212 *===========================================================================*/
213 static void sort(table
)
214 struct part_entry
*table
;
216 /* Sort a partition table. */
217 struct part_entry
*pe
, tmp
;
218 int n
= NR_PARTITIONS
;
221 for (pe
= table
; pe
< table
+ NR_PARTITIONS
-1; pe
++) {
222 if (pe
[0].sysind
== NO_PART
223 || (pe
[0].lowsec
> pe
[1].lowsec
224 && pe
[1].sysind
!= NO_PART
)) {
225 tmp
= pe
[0]; pe
[0] = pe
[1]; pe
[1] = tmp
;