xref: /openbsd/sbin/fdisk/part.c (revision eb4cb19d)
1*eb4cb19dSkjell /*	$OpenBSD: part.c,v 1.22 2001/06/23 01:54:38 kjell Exp $	*/
2a1705421Sweingart 
3a1705421Sweingart /*
4a1705421Sweingart  * Copyright (c) 1997 Tobias Weingartner
5a1705421Sweingart  * All rights reserved.
6a1705421Sweingart  *
7a1705421Sweingart  * Redistribution and use in source and binary forms, with or without
8a1705421Sweingart  * modification, are permitted provided that the following conditions
9a1705421Sweingart  * are met:
10a1705421Sweingart  * 1. Redistributions of source code must retain the above copyright
11a1705421Sweingart  *    notice, this list of conditions and the following disclaimer.
12a1705421Sweingart  * 2. Redistributions in binary form must reproduce the above copyright
13a1705421Sweingart  *    notice, this list of conditions and the following disclaimer in the
14a1705421Sweingart  *    documentation and/or other materials provided with the distribution.
15a1705421Sweingart  * 3. All advertising materials mentioning features or use of this software
16a1705421Sweingart  *    must display the following acknowledgement:
17a1705421Sweingart  *    This product includes software developed by Tobias Weingartner.
18a1705421Sweingart  * 4. The name of the author may not be used to endorse or promote products
19a1705421Sweingart  *    derived from this software without specific prior written permission.
20a1705421Sweingart  *
21a1705421Sweingart  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22a1705421Sweingart  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23a1705421Sweingart  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24a1705421Sweingart  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25a1705421Sweingart  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26a1705421Sweingart  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27a1705421Sweingart  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28a1705421Sweingart  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29a1705421Sweingart  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30a1705421Sweingart  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31a1705421Sweingart  */
32a1705421Sweingart 
33a1705421Sweingart #include <err.h>
34a1705421Sweingart #include <util.h>
35a1705421Sweingart #include <stdio.h>
36a1705421Sweingart #include <unistd.h>
37a1705421Sweingart #include <sys/fcntl.h>
38a1705421Sweingart #include <sys/types.h>
39a1705421Sweingart #include <sys/stat.h>
40a1705421Sweingart #include <sys/disklabel.h>
41a1705421Sweingart #include <machine/param.h>
42a1705421Sweingart #include "disk.h"
43a1705421Sweingart #include "misc.h"
44a1705421Sweingart #include "mbr.h"
45a1705421Sweingart 
46a1705421Sweingart 
476c2b1c19Smickey static const struct part_type {
48a1705421Sweingart 	int	type;
496c2b1c19Smickey 	char	sname[14];
504b464610Sderaadt 	char	*lname;
51a1705421Sweingart } part_types[] = {
524b464610Sderaadt 	{ 0x00, "unused      ", "unused"},
534b464610Sderaadt 	{ 0x01, "DOS FAT-12  ", "Primary DOS with 12 bit FAT"},
544b464610Sderaadt 	{ 0x02, "XENIX /     ", "XENIX / filesystem"},
554b464610Sderaadt 	{ 0x03, "XENIX /usr  ", "XENIX /usr filesystem"},
564b464610Sderaadt 	{ 0x04, "DOS FAT-16  ", "Primary DOS with 16 bit FAT"},
574b464610Sderaadt 	{ 0x05, "Extended DOS", "Extended DOS"},
584b464610Sderaadt 	{ 0x06, "DOS > 32MB  ", "Primary 'big' DOS (> 32MB)"},
59f3f2107eSderaadt 	{ 0x07, "HPFS/QNX/AUX", "OS/2 HPFS, QNX-2 or Advanced UNIX"},
604b464610Sderaadt 	{ 0x08, "AIX fs      ", "AIX filesystem"},
614b464610Sderaadt 	{ 0x09, "AIX/Coherent", "AIX boot partition or Coherent"},
624b464610Sderaadt 	{ 0x0A, "OS/2 Bootmgr", "OS/2 Boot Manager or OPUS"},
634b464610Sderaadt 	{ 0x0B, "Win95 FAT-32", "Primary Win95 w/ 32-bit FAT"},
64c3e3230dSderaadt 	{ 0x0C, "Win95 FAT32L", "Primary Win95 w/ 32-bit FAT LBA-mapped"},
654b464610Sderaadt 	{ 0x0E, "DOS FAT-16  ", "Primary DOS w/ 16-bit FAT, CHS-mapped"},
66c3e3230dSderaadt 	{ 0x0F, "Extended LBA", "Extended DOS LBA-mapped"},
674b464610Sderaadt 	{ 0x10, "OPUS        ", "OPUS"},
684b464610Sderaadt 	{ 0x12, "Compaq Diag.", "Compaq Diagnostics"},
69a34f1fa7Smarkus 	{ 0x39, "Plan 9      ",	"Plan 9"},
704b464610Sderaadt 	{ 0x40, "VENIX 286   ", "VENIX 286"},
71f3f2107eSderaadt 	{ 0x4d, "QNX 4.2 Pri ", "QNX 4.2 Primary"},
72f3f2107eSderaadt 	{ 0x4e, "QNX 4.2 Sec ", "QNX 4.2 Secondary"},
73f3f2107eSderaadt 	{ 0x4f, "QNX 4.2 Ter ", "QNX 4.2 Tertiary"},
744b464610Sderaadt 	{ 0x50, "DM          ", "DM"},
754b464610Sderaadt 	{ 0x51, "DM          ", "DM"},
764b464610Sderaadt 	{ 0x52, "CP/M or SysV", "CP/M or Microport SysV/AT"},
774b464610Sderaadt 	{ 0x54, "Ontrack     ", "Ontrack"},
784b464610Sderaadt 	{ 0x56, "GB          ", "GB"},
794b464610Sderaadt 	{ 0x61, "Speed       ", "Speed"},
804b464610Sderaadt 	{ 0x63, "ISC, HURD, *", "ISC, System V/386, GNU HURD or Mach"},
814b464610Sderaadt 	{ 0x64, "Netware 2.xx", "Novell Netware 2.xx"},
824b464610Sderaadt 	{ 0x65, "Netware 3.xx", "Novell Netware 3.xx"},
834b464610Sderaadt 	{ 0x75, "PCIX        ", "PCIX"},
844b464610Sderaadt 	{ 0x80, "Minix (old) ", "Minix 1.1 ... 1.4a"},
854b464610Sderaadt 	{ 0x81, "Minix (new) ", "Minix 1.4b ... 1.5.10"},
864b464610Sderaadt 	{ 0x82, "Linux swap  ", "Linux swap"},
874b464610Sderaadt 	{ 0x83, "Linux files*", "Linux filesystem"},
884b464610Sderaadt 	{ 0x93, "Amoeba file*", "Amoeba filesystem"},
894b464610Sderaadt 	{ 0x94, "Amoeba BBT  ", "Amoeba bad block table"},
90bdb6a33cSmarkus 	{ 0x9f, "BSDI        ", "BSDI BSD/OS"},
913addffc7Sian 	{ 0xA0, "NotebookSave", "Phoenix NoteBIOS save-to-disk"},
9258fe3b3aSderaadt 	{ 0xA5, "FreeBSD     ",	"FreeBSD"},
934b464610Sderaadt 	{ 0xA6, "OpenBSD     ", "OpenBSD"},
944b464610Sderaadt 	{ 0xA7, "NEXTSTEP    ", "NEXTSTEP"},
9558fe3b3aSderaadt 	{ 0xA9, "NetBSD      ",	"NetBSD"},
964b464610Sderaadt 	{ 0xB7, "BSDI filesy*", "BSDI BSD/386 filesystem"},
974b464610Sderaadt 	{ 0xB8, "BSDI swap   ", "BSDI BSD/386 swap"},
984b464610Sderaadt 	{ 0xDB, "CPM/C.DOS/C*", "Concurrent CPM or C.DOS or CTOS"},
994b464610Sderaadt 	{ 0xE1, "Speed       ", "Speed"},
1004b464610Sderaadt 	{ 0xE3, "Speed       ", "Speed"},
1014b464610Sderaadt 	{ 0xE4, "Speed       ", "Speed"},
102092b495fSderaadt 	{ 0xEB, "BeOS/i386   ", "BeOS for Intel"},
1034b464610Sderaadt 	{ 0xF1, "Speed       ", "Speed"},
1044b464610Sderaadt 	{ 0xF2, "DOS 3.3+ Sec", "DOS 3.3+ Secondary"},
1054b464610Sderaadt 	{ 0xF4, "Speed       ", "Speed"},
1064b464610Sderaadt 	{ 0xFF, "BBT         ", "BBT (Bad Blocks Table)"},
107a1705421Sweingart };
108a1705421Sweingart 
1094b464610Sderaadt void
1104b464610Sderaadt PRT_printall()
1114b464610Sderaadt {
112d20bdfc6Skrw 	int i, idrows;
113d20bdfc6Skrw 
114d20bdfc6Skrw         idrows = ((sizeof(part_types)/sizeof(struct part_type))+3)/4;
1154b464610Sderaadt 
116c2ad5584Sderaadt 	printf("Choose from the following Partition id values:\n");
117d20bdfc6Skrw 	for (i = 0; i < idrows; i++) {
118d20bdfc6Skrw 		printf("%02X %s   %02X %s   %02X %s"
119d20bdfc6Skrw                       , part_types[i         ].type, part_types[i         ].sname
120d20bdfc6Skrw                       , part_types[i+idrows  ].type, part_types[i+idrows  ].sname
121d20bdfc6Skrw                       , part_types[i+idrows*2].type, part_types[i+idrows*2].sname
122d20bdfc6Skrw                       );
123d20bdfc6Skrw                 if ((i+idrows*3) < (sizeof(part_types)/sizeof(struct part_type))) {
124d20bdfc6Skrw 		       printf("   %02X %s\n"
125d20bdfc6Skrw                              , part_types[i+idrows*3].type, part_types[i+idrows*3].sname );
1264b464610Sderaadt                 }
127d20bdfc6Skrw 		else
1284b464610Sderaadt 		        printf( "\n" );
1294b464610Sderaadt 	}
130d20bdfc6Skrw }
131a1705421Sweingart 
1326c2b1c19Smickey const char *
133a1705421Sweingart PRT_ascii_id(id)
134a1705421Sweingart 	int id;
135a1705421Sweingart {
136a1705421Sweingart 	static char unknown[] = "<Unknown ID>";
137a1705421Sweingart 	int i;
138a1705421Sweingart 
139a1705421Sweingart 	for (i = 0; i < sizeof(part_types)/sizeof(struct part_type); i++) {
140a1705421Sweingart 		if (part_types[i].type == id)
1414b464610Sderaadt 			return (part_types[i].sname);
142a1705421Sweingart 	}
143a1705421Sweingart 
144a1705421Sweingart 	return (unknown);
145a1705421Sweingart }
146a1705421Sweingart 
147a1705421Sweingart void
1480d5049c6Smickey PRT_parse(disk, prt, offset, reloff, partn, pn)
1494ed7cd7eSrahnds 	disk_t *disk;
150a1705421Sweingart 	void *prt;
151ca2e86e1Sprovos 	off_t offset;
152ca2e86e1Sprovos 	off_t reloff;
153a1705421Sweingart 	prt_t *partn;
1540d5049c6Smickey 	int pn;
155a1705421Sweingart {
156a1705421Sweingart 	unsigned char *p = prt;
157ca2e86e1Sprovos 	off_t off;
158a1705421Sweingart 
159a1705421Sweingart 	partn->flag = *p++;
160a1705421Sweingart 	partn->shead = *p++;
161ca2e86e1Sprovos 
162a1705421Sweingart 	partn->ssect = (*p) & 0x3F;
163a1705421Sweingart 	partn->scyl = ((*p << 2) & 0xFF00) | (*(p+1));
164a1705421Sweingart 	p += 2;
165a1705421Sweingart 
166a1705421Sweingart 	partn->id = *p++;
167a1705421Sweingart 	partn->ehead = *p++;
168a1705421Sweingart 	partn->esect = (*p) & 0x3F;
169a1705421Sweingart 	partn->ecyl = ((*p << 2) & 0xFF00) | (*(p+1));
170a1705421Sweingart 	p += 2;
171a1705421Sweingart 
172c3e3230dSderaadt 	if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL))
173c3e3230dSderaadt 		off = reloff;
174c3e3230dSderaadt 	else
175c3e3230dSderaadt 		off = offset;
176ca2e86e1Sprovos 
177ca2e86e1Sprovos 	partn->bs = getlong(p) + off;
178a1705421Sweingart 	partn->ns = getlong(p+4);
1794ed7cd7eSrahnds 
1800d5049c6Smickey 	PRT_fix_CHS(disk, partn, pn);
1814ed7cd7eSrahnds }
182a1705421Sweingart 
1834ed7cd7eSrahnds int
1844ed7cd7eSrahnds PRT_check_chs(partn)
1854ed7cd7eSrahnds 	prt_t *partn;
1864ed7cd7eSrahnds {
1874ed7cd7eSrahnds 	if ( (partn->shead > 255) ||
1884ed7cd7eSrahnds 		(partn->ssect >63) ||
1894ed7cd7eSrahnds 		(partn->scyl > 1023) ||
1904ed7cd7eSrahnds 		(partn->ehead >255) ||
1914ed7cd7eSrahnds 		(partn->esect >63) ||
1924ed7cd7eSrahnds 		(partn->ecyl > 1023) )
1934ed7cd7eSrahnds 	{
1944ed7cd7eSrahnds 		return 0;
1954ed7cd7eSrahnds 	}
1964ed7cd7eSrahnds 	return 1;
1974ed7cd7eSrahnds }
198a1705421Sweingart void
199ca2e86e1Sprovos PRT_make(partn, offset, reloff, prt)
200a1705421Sweingart 	prt_t *partn;
201ca2e86e1Sprovos 	off_t offset;
202ca2e86e1Sprovos 	off_t reloff;
203a1705421Sweingart 	void *prt;
204a1705421Sweingart {
205a1705421Sweingart 	unsigned char *p = prt;
206c3e3230dSderaadt 	prt_t tmp;
207c3e3230dSderaadt 	off_t off;
208c3e3230dSderaadt 
209c3e3230dSderaadt 	tmp.shead = partn->shead;
210c3e3230dSderaadt 	tmp.ssect = partn->ssect;
211*eb4cb19dSkjell 	tmp.scyl = (partn->scyl > 1023)? 1023: partn->scyl;
212c3e3230dSderaadt 	tmp.ehead = partn->ehead;
213c3e3230dSderaadt 	tmp.esect = partn->ssect;
214*eb4cb19dSkjell 	tmp.ecyl = (partn->ecyl > 1023)? 1023: partn->ecyl;
215c3e3230dSderaadt 	if (!PRT_check_chs(partn) && PRT_check_chs(&tmp)) {
216c3e3230dSderaadt 		partn->shead = tmp.shead;
217c3e3230dSderaadt 		partn->ssect = tmp.ssect;
218c3e3230dSderaadt 		partn->scyl = tmp.scyl;
219c3e3230dSderaadt 		partn->ehead = tmp.ehead;
220c3e3230dSderaadt 		partn->esect = tmp.esect;
221c3e3230dSderaadt 		partn->ecyl = tmp.ecyl;
222c3e3230dSderaadt 		printf("Cylinder values are modified to fit in CHS.\n");
223c3e3230dSderaadt 	}
224c3e3230dSderaadt 	if ((partn->id == DOSPTYP_EXTEND) || (partn->id == DOSPTYP_EXTENDL))
225c3e3230dSderaadt 		off = reloff;
226c3e3230dSderaadt 	else
227c3e3230dSderaadt 		off = offset;
228a1705421Sweingart 
2294ed7cd7eSrahnds 	if (PRT_check_chs(partn)) {
230a1705421Sweingart 		*p++ = partn->flag & 0xFF;
2314ed7cd7eSrahnds 
232a1705421Sweingart 		*p++ = partn->shead & 0xFF;
233a1705421Sweingart 		*p++ = (partn->ssect & 0x3F) | ((partn->scyl & 0x300) >> 2);
234a1705421Sweingart 		*p++ = partn->scyl & 0xFF;
235a1705421Sweingart 
236a1705421Sweingart 		*p++ = partn->id & 0xFF;
237a1705421Sweingart 
238a1705421Sweingart 		*p++ = partn->ehead & 0xFF;
239a1705421Sweingart 		*p++ = (partn->esect & 0x3F) | ((partn->ecyl & 0x300) >> 2);
240a1705421Sweingart 		*p++ = partn->ecyl & 0xFF;
2414ed7cd7eSrahnds 	} else {
2424ed7cd7eSrahnds 		/* should this really keep flag, id and set others to 0xff? */
2434ed7cd7eSrahnds 		*p++ = partn->flag & 0xFF;
2444ed7cd7eSrahnds 		*p++ = 0xFF;
2454ed7cd7eSrahnds 		*p++ = 0xFF;
2464ed7cd7eSrahnds 		*p++ = 0xFF;
2474ed7cd7eSrahnds 		*p++ = partn->id & 0xFF;
2484ed7cd7eSrahnds 		*p++ = 0xFF;
2494ed7cd7eSrahnds 		*p++ = 0xFF;
2504ed7cd7eSrahnds 		*p++ = 0xFF;
2514ed7cd7eSrahnds 		printf("Warning CHS values out of bounds only saving LBA values\n");
2524ed7cd7eSrahnds 	}
253a1705421Sweingart 
254ca2e86e1Sprovos 	putlong(p, partn->bs - off);
255a1705421Sweingart 	putlong(p+4, partn->ns);
256a1705421Sweingart }
257a1705421Sweingart 
258a1705421Sweingart void
259a1705421Sweingart PRT_print(num, partn)
260a1705421Sweingart 	int num;
261a1705421Sweingart 	prt_t *partn;
262a1705421Sweingart {
263a1705421Sweingart 
264a1705421Sweingart 	if (partn == NULL) {
265a1705421Sweingart 		printf("         Starting       Ending\n");
266a1705421Sweingart 		printf(" #: id  cyl  hd sec -  cyl  hd sec [     start -       size]\n");
2676c2b1c19Smickey 		printf("------------------------------------------------------------------------\n");
268a1705421Sweingart 	} else {
2696c2b1c19Smickey 		printf("%c%1d: %.2X %4d %3d %3d - %4d %3d %3d [%10d - %10d] %s\n",
270a1705421Sweingart 			(partn->flag == 0x80)?'*':' ',
271a1705421Sweingart 			num, partn->id,
272a1705421Sweingart 			partn->scyl, partn->shead, partn->ssect,
273a1705421Sweingart 			partn->ecyl, partn->ehead, partn->esect,
274a1705421Sweingart 			partn->bs, partn->ns,
275a1705421Sweingart 			PRT_ascii_id(partn->id));
276a1705421Sweingart 	}
277a1705421Sweingart }
278a1705421Sweingart 
279a1705421Sweingart void
2800d5049c6Smickey PRT_fix_BN(disk, part, pn)
281a1705421Sweingart 	disk_t *disk;
282a1705421Sweingart 	prt_t *part;
2830d5049c6Smickey 	int pn;
284a1705421Sweingart {
285a1705421Sweingart 	int spt, tpc, spc;
286a1705421Sweingart 	int start = 0;
287a1705421Sweingart 	int end = 0;
288a1705421Sweingart 
289*eb4cb19dSkjell 	/* Zero out entry if not used */
290*eb4cb19dSkjell 	if (part->id == DOSPTYP_UNUSED ) {
291*eb4cb19dSkjell 		memset(part, 0, sizeof(*part));
292*eb4cb19dSkjell 		return;
293*eb4cb19dSkjell 	}
294*eb4cb19dSkjell 
295a1705421Sweingart 	/* Disk metrics */
2964b464610Sderaadt 	spt = disk->real->sectors;
2974b464610Sderaadt 	tpc = disk->real->heads;
298a1705421Sweingart 	spc = spt * tpc;
299a1705421Sweingart 
300a1705421Sweingart 	start += part->scyl * spc;
301a1705421Sweingart 	start += part->shead * spt;
302a1705421Sweingart 	start += part->ssect - 1;
303a1705421Sweingart 
304a1705421Sweingart 	end += part->ecyl * spc;
305a1705421Sweingart 	end += part->ehead * spt;
306a1705421Sweingart 	end += part->esect - 1;
307a1705421Sweingart 
308a1705421Sweingart 	/* XXX - Should handle this... */
309a1705421Sweingart 	if (start > end)
3100d5049c6Smickey 		warn("Start of partition #%d after end!", pn);
311a1705421Sweingart 
312a1705421Sweingart 	part->bs = start;
313a1705421Sweingart 	part->ns = (end - start) + 1;
314a1705421Sweingart }
315a1705421Sweingart 
316a1705421Sweingart void
3170d5049c6Smickey PRT_fix_CHS(disk, part, pn)
318a1705421Sweingart 	disk_t *disk;
319a1705421Sweingart 	prt_t *part;
3200d5049c6Smickey 	int pn;
321a1705421Sweingart {
322a1705421Sweingart 	int spt, tpc, spc;
323a1705421Sweingart 	int start, end, size;
324a1705421Sweingart 	int cyl, head, sect;
325a1705421Sweingart 
326*eb4cb19dSkjell 	/* Zero out entry if not used */
327*eb4cb19dSkjell 	if (part->id == DOSPTYP_UNUSED ) {
328*eb4cb19dSkjell 		memset(part, 0, sizeof(*part));
329*eb4cb19dSkjell 		return;
330*eb4cb19dSkjell 	}
331*eb4cb19dSkjell 
332a1705421Sweingart 	/* Disk metrics */
3334b464610Sderaadt 	spt = disk->real->sectors;
3344b464610Sderaadt 	tpc = disk->real->heads;
335a1705421Sweingart 	spc = spt * tpc;
336a1705421Sweingart 
337a1705421Sweingart 	start = part->bs;
338a1705421Sweingart 	size = part->ns;
339a1705421Sweingart 	end = (start + size) - 1;
340a1705421Sweingart 
341a1705421Sweingart 	/* Figure out starting CHS values */
342a1705421Sweingart 	cyl = (start / spc); start -= (cyl * spc);
343a1705421Sweingart 	head = (start / spt); start -= (head * spt);
344a1705421Sweingart 	sect = (start + 1);
345a1705421Sweingart 
346c3e3230dSderaadt 	if (cyl > 1023) {
347c3e3230dSderaadt 		cyl = 1023;
3480d5049c6Smickey 		printf("Only LBA values are valid in starting cylinder for partition #%d.\n", pn);
349c3e3230dSderaadt 	}
350a1705421Sweingart 	part->scyl = cyl;
351a1705421Sweingart 	part->shead = head;
352a1705421Sweingart 	part->ssect = sect;
353a1705421Sweingart 
354a1705421Sweingart 	/* Figure out ending CHS values */
355a1705421Sweingart 	cyl = (end / spc); end -= (cyl * spc);
356a1705421Sweingart 	head = (end / spt); end -= (head * spt);
357a1705421Sweingart 	sect = (end + 1);
358a1705421Sweingart 
359c3e3230dSderaadt 	if (cyl > 1023) {
360c3e3230dSderaadt 		cyl = 1023;
3610d5049c6Smickey 		printf("Only LBA values are valid in ending cylinder for partition #%d.\n", pn);
362c3e3230dSderaadt 	}
363a1705421Sweingart 	part->ecyl = cyl;
364a1705421Sweingart 	part->ehead = head;
365a1705421Sweingart 	part->esect = sect;
366a1705421Sweingart }
367a1705421Sweingart 
368