1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27#ifndef _LIBFDISK_H_
28#define	_LIBFDISK_H_
29
30#include <limits.h>
31#include <sys/dktp/fdisk.h>
32
33#ifdef	__cplusplus
34extern "C" {
35#endif
36
37#define	MAX_LOGDRIVE_OFFSET 63
38
39#define	FDISK_ERRNO		200
40#define	FDISK_ETOOLONG		(FDISK_ERRNO + 0)
41#define	FDISK_EOOBOUND		(FDISK_ERRNO + 1)
42#define	FDISK_EZERO		(FDISK_ERRNO + 2)
43#define	FDISK_EOVERLAP		(FDISK_ERRNO + 3)
44#define	FDISK_ENOVGEOM		(FDISK_ERRNO + 4)
45#define	FDISK_ENOPGEOM		(FDISK_ERRNO + 5)
46#define	FDISK_ENOLGEOM		(FDISK_ERRNO + 6)
47#define	FDISK_ENOLOGDRIVE	(FDISK_ERRNO + 7)
48#define	FDISK_EBADLOGDRIVE	(FDISK_ERRNO + 8)
49#define	FDISK_ENOEXTPART	(FDISK_ERRNO + 9)
50#define	FDISK_EBADMAGIC		(FDISK_ERRNO + 10)
51#define	FDISK_EMOUNTED		(FDISK_ERRNO + 11)
52
53#define	FDISK_SUCCESS 0
54
55#define	FDISK_READ_DISK		0x00000001
56
57#define	LINUX_SWAP_MAGIC_LENGTH	10
58enum {
59	PHYSGEOM = 0,
60	VIRTGEOM,
61	NCYL,
62	NHEADS,
63	NSECTPT,
64	SSIZE,
65	ACYL
66};
67
68enum {
69	FDISK_MINOR_WRITE = 1,
70	FDISK_MAJOR_WRITE
71};
72
73#define	FDISK_SECTS_PER_CYL(epp) \
74	(epp->disk_geom.phys_heads * epp->disk_geom.phys_sec)
75#define	FDISK_SECT_TO_CYL(epp, x)	((x) / (FDISK_SECTS_PER_CYL(epp)))
76#define	FDISK_CYL_TO_SECT(epp, x)	((x) * (FDISK_SECTS_PER_CYL(epp)))
77#define	FDISK_ABS_CYL_NUM(epp, x)	(FDISK_SECT_TO_CYL(x) +\
78    epp->ext_beg_cyl)
79
80#define	FDISK_CYL_BNDRY_ALIGN(epp, x)	(((x) % (FDISK_SECTS_PER_CYL(epp))) ? \
81	(((x)/(FDISK_SECTS_PER_CYL(epp))) + 1) :\
82	((x)/(FDISK_SECTS_PER_CYL(epp))))
83
84/*
85 * Extended partition structure :
86 *  +--------------+
87 *  |+--+          |
88 *  ||  |----------+---> structure at the beginning of the extended partition
89 *  ||--|          |     ( Lets call it the EBR - Extended Boot Record )
90 *  ||  |      +---+--->
91 *  |+--+      |   |     Logical drive within the extended partition
92 *  |+---------+--+|     ( We will plainly call this a logical drive )
93 *  ||            ||
94 *  ||            ||
95 *  ||            ||
96 *  |+------------+|
97 *  +--------------+
98 *
99 *
100 * EBR is effectively "struct ipart parts[2]".
101 * The picture below shows what the EBR contains. The EBR has
102 * two important pieces of information. The first is the offset and the size
103 * of the logical drive in this extended partition. The second is the offset
104 * and size of the next extended partition. The offsets are relative to
105 * beginning of the first extended partition. These extended partitions are
106 * arranged like a linked list.
107 * Note that (currently) only one extended partition can exist in the MBR.
108 * The system ID of a logical drive within the extended partition cannot be
109 * that of an extended partition.
110 *
111 *                   +------+
112 *                   |      |
113 *  +--------------+ |    +-v------------+
114 *  |+--+          | |    |+--+          |
115 *  ||  |---+      | |    ||  |          |
116 *  ||--|   |      | |    ||--|          |
117 *  ||  |---|------+-+    ||  |          |
118 *  |+--+   |      |      |+--+          |
119 *  |+------v-----+|      |+------------+|
120 *  ||            ||      ||            ||
121 *  ||            ||      ||            ||
122 *  ||            ||      ||            ||
123 *  |+------------+|      |+------------+|
124 *  +--------------+      +--------------+
125 *
126 */
127
128/*
129 * Main structure used to record changes to the partitions made.
130 * Changes are not written to disk everytime, but maintained in this structure.
131 * This information is used when the user chooses to commit the changes.
132 * A linked list of this structure represents the ondisk partitions.
133 */
134typedef struct logical_drive {
135
136	/* structure holding the EBR data */
137	struct ipart parts[2];
138
139	/*
140	 * Absolute beginning sector of the extended partition, and hence an
141	 * indicator of where the EBR for this logical drive would go on disk.
142	 * NOTE : In case the first logical drive in this extended partition is
143	 * out of (disk) order, this indicates the beginning of the logical
144	 * drive. The EBR will anyway be at the first sector of the extended
145	 * partition, for the first logical drive.
146	 */
147	uint32_t abs_secnum;
148
149	/*
150	 * Offset of the logical drive from the beginning of its extended
151	 * partition
152	 */
153	uint32_t logdrive_offset;
154
155	/* Size of the logical drive in sectors */
156	uint32_t numsect;
157
158	/* Beginning and ending cylinders of the extended partition */
159	uint32_t begcyl, endcyl;
160
161	/*
162	 * Flag to indicate if this record is to be sync'ed to disk.
163	 * It takes two values : FDISK_MAJOR_WRITE and FDISK_MINOR_WRITE
164	 * If it is a minor write, there is no need to update the information
165	 * in the kernel structures. Example of a minor write is correction of
166	 * a corrupt boot signature.
167	 */
168	int modified;
169
170	/*
171	 * This pointer points to the next extended partition in the order
172	 * found on disk.
173	 */
174	struct logical_drive *next;
175
176	/*
177	 * This pointer points to the next extended partition in a sorted list
178	 * sorted in the ascending order of their beginning cylinders.
179	 */
180	struct logical_drive *sorted_next;
181
182} logical_drive_t;
183
184typedef struct fdisk_disk_geom {
185	ushort_t phys_cyl;
186	ushort_t phys_sec;
187	ushort_t phys_heads;
188	ushort_t alt_cyl;
189	ushort_t virt_cyl;
190	ushort_t virt_sec;
191	ushort_t virt_heads;
192	ushort_t sectsize;
193} fdisk_disk_geom_t;
194
195typedef struct ext_part
196{
197	/* Structure holding geometry information about the device */
198	fdisk_disk_geom_t disk_geom;
199
200	struct ipart *mtable;
201
202	char device_name[PATH_MAX];
203
204	int dev_fd;
205
206	int op_flag;
207
208	/*
209	 * Head of the in memory structure (singly linked list) of extended
210	 * partition information.
211	 */
212	logical_drive_t *ld_head;
213	logical_drive_t *sorted_ld_head;
214
215	/* Beginning cylinder of the extended partition */
216	uint32_t ext_beg_cyl;
217
218	/* Ending cylinder of the extended partition */
219	uint32_t ext_end_cyl;
220
221	/* Beginning sector of the extended partition */
222	uint32_t ext_beg_sec;
223
224	/* Ending sector of the extended partition */
225	uint32_t ext_end_sec;
226
227	/* Count of the number of logical drives in the extended partition */
228	int logical_drive_count;
229
230	/*
231	 * Flag to keep track of the update to be made to the Extended Boot
232	 * Record (EBR) when all logical drives are deleted. The EBR is filled
233	 * with zeroes in such a case.
234	 */
235	int first_ebr_is_null;
236
237	/*
238	 * Flag to indicate corrupt logical drives. Can happen when a partition
239	 * manager creates an extended partition and does not null the first EBR
240	 * or when important ondisk structures are overwritten by a bad program
241	 */
242	int corrupt_logical_drives;
243
244	/*
245	 * The boot block signature 0xAA55 might not be found on some of the
246	 * EBRs. ( Even though the rest of the data might be good )
247	 * The following array is used to store the list of such logical drive
248	 * numbers.
249	 */
250	uchar_t invalid_bb_sig[MAX_EXT_PARTS];
251
252	/*
253	 * Can add  a "next" pointer here in case support for multiple
254	 * extended partitions becomes the standard someday.
255	 *
256	 * struct ext_part *next;
257	 */
258} ext_part_t;
259
260#define	fdisk_get_logical_drive_count(epp) ((epp)->logical_drive_count)
261#define	fdisk_corrupt_logical_drives(epp) ((epp)->corrupt_logical_drives)
262#define	fdisk_get_ext_beg_cyl(epp) ((epp)->ext_beg_cyl)
263#define	fdisk_get_ext_end_cyl(epp) ((epp)->ext_end_cyl)
264#define	fdisk_get_ext_beg_sec(epp) ((epp)->ext_beg_sec)
265#define	fdisk_get_ext_end_sec(epp) ((epp)->ext_end_sec)
266#define	fdisk_get_ld_head(epp) ((epp)->ld_head)
267#define	fdisk_is_solaris_part(id) (((id) == SUNIXOS) || ((id) == SUNIXOS2))
268#define	fdisk_is_dos_extended(id) (((id) == EXTDOS) || ((id) == FDISK_EXTLBA))
269
270extern int fdisk_is_linux_swap(ext_part_t *epp, uint32_t part_start,
271    uint64_t *lsm_offset);
272extern int libfdisk_init(ext_part_t **epp, char *devstr, struct ipart *parttab,
273    int opflag);
274extern int libfdisk_reset(ext_part_t *epp);
275extern void libfdisk_fini(ext_part_t **epp);
276extern int fdisk_ext_find_first_free_sec(ext_part_t *epp,
277    uint32_t *first_free_sec);
278extern uint32_t fdisk_ext_find_last_free_sec(ext_part_t *epp, uint32_t begsec);
279extern int fdisk_ext_part_exists(ext_part_t *epp);
280extern int fdisk_validate_logical_drive(ext_part_t *epp, uint32_t begsec,
281    uint32_t offset, uint32_t numsec);
282extern int fdisk_ext_validate_part_start(ext_part_t *epp, uint32_t begcyl,
283    uint32_t *begsec);
284extern int fdisk_get_solaris_part(ext_part_t *epp, int *pnum, uint32_t *begsec,
285    uint32_t *numsec);
286extern int fdisk_get_part_info(ext_part_t *epp, int pnum, uchar_t *sysid,
287    uint32_t *begsec, uint32_t *numsec);
288extern int fdisk_commit_ext_part(ext_part_t *epp);
289extern void fdisk_change_logical_drive_id(ext_part_t *epp, int pno,
290    uchar_t partid);
291extern void fdisk_add_logical_drive(ext_part_t *epp, uint32_t begsec,
292    uint32_t endsec, uchar_t partid);
293extern void fdisk_delete_logical_drive(ext_part_t *epp, int pno);
294extern int fdisk_init_ext_part(ext_part_t *epp, uint32_t rsect, uint32_t nsect);
295extern int fdisk_delete_ext_part(ext_part_t *epp);
296extern int fdisk_get_disk_geom(ext_part_t *epp, int type, int what);
297extern int fdisk_invalid_bb_sig(ext_part_t *epp, uchar_t **bbsig_arr);
298extern int fdisk_mounted_logical_drives(ext_part_t *epp);
299
300#ifdef	__cplusplus
301}
302#endif
303
304#endif /* _LIBFDISK_H_ */
305