summaryrefslogtreecommitdiff
path: root/usr/src/lib/libfdisk/common/libfdisk.h
blob: c94e2ddf897f9da9de59074dcce68b1131f65e00 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */


#ifndef _LIBFDISK_H_
#define	_LIBFDISK_H_

#include <limits.h>
#include <sys/dktp/fdisk.h>

#ifdef	__cplusplus
extern "C" {
#endif

#define	MAX_LOGDRIVE_OFFSET 63

#define	FDISK_ERRNO		200
#define	FDISK_ETOOLONG		(FDISK_ERRNO + 0)
#define	FDISK_EOOBOUND		(FDISK_ERRNO + 1)
#define	FDISK_EZERO		(FDISK_ERRNO + 2)
#define	FDISK_EOVERLAP		(FDISK_ERRNO + 3)
#define	FDISK_ENOVGEOM		(FDISK_ERRNO + 4)
#define	FDISK_ENOPGEOM		(FDISK_ERRNO + 5)
#define	FDISK_ENOLGEOM		(FDISK_ERRNO + 6)
#define	FDISK_ENOLOGDRIVE	(FDISK_ERRNO + 7)
#define	FDISK_EBADLOGDRIVE	(FDISK_ERRNO + 8)
#define	FDISK_ENOEXTPART	(FDISK_ERRNO + 9)
#define	FDISK_EBADMAGIC		(FDISK_ERRNO + 10)
#define	FDISK_EMOUNTED		(FDISK_ERRNO + 11)

#define	FDISK_SUCCESS 0

#define	FDISK_READ_DISK		0x00000001

#define	LINUX_SWAP_MAGIC_LENGTH	10
enum {
	PHYSGEOM = 0,
	VIRTGEOM,
	NCYL,
	NHEADS,
	NSECTPT,
	SSIZE,
	ACYL
};

enum {
	FDISK_MINOR_WRITE = 1,
	FDISK_MAJOR_WRITE
};

#define	FDISK_SECTS_PER_CYL(epp) \
	(epp->disk_geom.phys_heads * epp->disk_geom.phys_sec)
#define	FDISK_SECT_TO_CYL(epp, x)	((x) / (FDISK_SECTS_PER_CYL(epp)))
#define	FDISK_CYL_TO_SECT(epp, x)	((x) * (FDISK_SECTS_PER_CYL(epp)))
#define	FDISK_ABS_CYL_NUM(epp, x)	(FDISK_SECT_TO_CYL(x) +\
    epp->ext_beg_cyl)

#define	FDISK_CYL_BNDRY_ALIGN(epp, x)	(((x) % (FDISK_SECTS_PER_CYL(epp))) ? \
	(((x)/(FDISK_SECTS_PER_CYL(epp))) + 1) :\
	((x)/(FDISK_SECTS_PER_CYL(epp))))

/*
 * Extended partition structure :
 *  +--------------+
 *  |+--+          |
 *  ||  |----------+---> structure at the beginning of the extended partition
 *  ||--|          |     ( Lets call it the EBR - Extended Boot Record )
 *  ||  |      +---+--->
 *  |+--+      |   |     Logical drive within the extended partition
 *  |+---------+--+|     ( We will plainly call this a logical drive )
 *  ||            ||
 *  ||            ||
 *  ||            ||
 *  |+------------+|
 *  +--------------+
 *
 *
 * EBR is effectively "struct ipart parts[2]".
 * The picture below shows what the EBR contains. The EBR has
 * two important pieces of information. The first is the offset and the size
 * of the logical drive in this extended partition. The second is the offset
 * and size of the next extended partition. The offsets are relative to
 * beginning of the first extended partition. These extended partitions are
 * arranged like a linked list.
 * Note that (currently) only one extended partition can exist in the MBR.
 * The system ID of a logical drive within the extended partition cannot be
 * that of an extended partition.
 *
 *                   +------+
 *                   |      |
 *  +--------------+ |    +-v------------+
 *  |+--+          | |    |+--+          |
 *  ||  |---+      | |    ||  |          |
 *  ||--|   |      | |    ||--|          |
 *  ||  |---|------+-+    ||  |          |
 *  |+--+   |      |      |+--+          |
 *  |+------v-----+|      |+------------+|
 *  ||            ||      ||            ||
 *  ||            ||      ||            ||
 *  ||            ||      ||            ||
 *  |+------------+|      |+------------+|
 *  +--------------+      +--------------+
 *
 */

/*
 * Main structure used to record changes to the partitions made.
 * Changes are not written to disk everytime, but maintained in this structure.
 * This information is used when the user chooses to commit the changes.
 * A linked list of this structure represents the ondisk partitions.
 */
typedef struct logical_drive {

	/* structure holding the EBR data */
	struct ipart parts[2];

	/*
	 * Absolute beginning sector of the extended partition, and hence an
	 * indicator of where the EBR for this logical drive would go on disk.
	 * NOTE : In case the first logical drive in this extended partition is
	 * out of (disk) order, this indicates the beginning of the logical
	 * drive. The EBR will anyway be at the first sector of the extended
	 * partition, for the first logical drive.
	 */
	uint32_t abs_secnum;

	/*
	 * Offset of the logical drive from the beginning of its extended
	 * partition
	 */
	uint32_t logdrive_offset;

	/* Size of the logical drive in sectors */
	uint32_t numsect;

	/* Beginning and ending cylinders of the extended partition */
	uint32_t begcyl, endcyl;

	/*
	 * Flag to indicate if this record is to be sync'ed to disk.
	 * It takes two values : FDISK_MAJOR_WRITE and FDISK_MINOR_WRITE
	 * If it is a minor write, there is no need to update the information
	 * in the kernel structures. Example of a minor write is correction of
	 * a corrupt boot signature.
	 */
	int modified;

	/*
	 * This pointer points to the next extended partition in the order
	 * found on disk.
	 */
	struct logical_drive *next;

	/*
	 * This pointer points to the next extended partition in a sorted list
	 * sorted in the ascending order of their beginning cylinders.
	 */
	struct logical_drive *sorted_next;

} logical_drive_t;

typedef struct fdisk_disk_geom {
	ushort_t phys_cyl;
	ushort_t phys_sec;
	ushort_t phys_heads;
	ushort_t alt_cyl;
	ushort_t virt_cyl;
	ushort_t virt_sec;
	ushort_t virt_heads;
	ushort_t sectsize;
} fdisk_disk_geom_t;

typedef struct ext_part
{
	/* Structure holding geometry information about the device */
	fdisk_disk_geom_t disk_geom;

	struct ipart *mtable;

	char device_name[PATH_MAX];

	int dev_fd;

	int op_flag;

	/*
	 * Head of the in memory structure (singly linked list) of extended
	 * partition information.
	 */
	logical_drive_t *ld_head;
	logical_drive_t *sorted_ld_head;

	/* Beginning cylinder of the extended partition */
	uint32_t ext_beg_cyl;

	/* Ending cylinder of the extended partition */
	uint32_t ext_end_cyl;

	/* Beginning sector of the extended partition */
	uint32_t ext_beg_sec;

	/* Ending sector of the extended partition */
	uint32_t ext_end_sec;

	/* Count of the number of logical drives in the extended partition */
	int logical_drive_count;

	/*
	 * Flag to keep track of the update to be made to the Extended Boot
	 * Record (EBR) when all logical drives are deleted. The EBR is filled
	 * with zeroes in such a case.
	 */
	int first_ebr_is_null;

	/*
	 * Flag to indicate corrupt logical drives. Can happen when a partition
	 * manager creates an extended partition and does not null the first EBR
	 * or when important ondisk structures are overwritten by a bad program
	 */
	int corrupt_logical_drives;

	/*
	 * The boot block signature 0xAA55 might not be found on some of the
	 * EBRs. ( Even though the rest of the data might be good )
	 * The following array is used to store the list of such logical drive
	 * numbers.
	 */
	uchar_t invalid_bb_sig[MAX_EXT_PARTS];

	/*
	 * Can add  a "next" pointer here in case support for multiple
	 * extended partitions becomes the standard someday.
	 *
	 * struct ext_part *next;
	 */
} ext_part_t;

#define	fdisk_get_logical_drive_count(epp) ((epp)->logical_drive_count)
#define	fdisk_corrupt_logical_drives(epp) ((epp)->corrupt_logical_drives)
#define	fdisk_get_ext_beg_cyl(epp) ((epp)->ext_beg_cyl)
#define	fdisk_get_ext_end_cyl(epp) ((epp)->ext_end_cyl)
#define	fdisk_get_ext_beg_sec(epp) ((epp)->ext_beg_sec)
#define	fdisk_get_ext_end_sec(epp) ((epp)->ext_end_sec)
#define	fdisk_get_ld_head(epp) ((epp)->ld_head)
#define	fdisk_is_solaris_part(id) (((id) == SUNIXOS) || ((id) == SUNIXOS2))
#define	fdisk_is_dos_extended(id) (((id) == EXTDOS) || ((id) == FDISK_EXTLBA))

extern int fdisk_is_linux_swap(ext_part_t *epp, uint32_t part_start,
    uint64_t *lsm_offset);
extern int libfdisk_init(ext_part_t **epp, char *devstr, struct ipart *parttab,
    int opflag);
extern int libfdisk_reset(ext_part_t *epp);
extern void libfdisk_fini(ext_part_t **epp);
extern int fdisk_ext_find_first_free_sec(ext_part_t *epp,
    uint32_t *first_free_sec);
extern uint32_t fdisk_ext_find_last_free_sec(ext_part_t *epp, uint32_t begsec);
extern int fdisk_ext_part_exists(ext_part_t *epp);
extern int fdisk_validate_logical_drive(ext_part_t *epp, uint32_t begsec,
    uint32_t offset, uint32_t numsec);
extern int fdisk_ext_validate_part_start(ext_part_t *epp, uint32_t begcyl,
    uint32_t *begsec);
extern int fdisk_get_solaris_part(ext_part_t *epp, int *pnum, uint32_t *begsec,
    uint32_t *numsec);
extern int fdisk_get_part_info(ext_part_t *epp, int pnum, uchar_t *sysid,
    uint32_t *begsec, uint32_t *numsec);
extern int fdisk_commit_ext_part(ext_part_t *epp);
extern void fdisk_change_logical_drive_id(ext_part_t *epp, int pno,
    uchar_t partid);
extern void fdisk_add_logical_drive(ext_part_t *epp, uint32_t begsec,
    uint32_t endsec, uchar_t partid);
extern void fdisk_delete_logical_drive(ext_part_t *epp, int pno);
extern int fdisk_init_ext_part(ext_part_t *epp, uint32_t rsect, uint32_t nsect);
extern int fdisk_delete_ext_part(ext_part_t *epp);
extern int fdisk_get_disk_geom(ext_part_t *epp, int type, int what);
extern int fdisk_invalid_bb_sig(ext_part_t *epp, uchar_t **bbsig_arr);
extern int fdisk_mounted_logical_drives(ext_part_t *epp);

#ifdef	__cplusplus
}
#endif

#endif /* _LIBFDISK_H_ */