xref: /plan9/sys/src/cmd/disk/prep/fdisk.c (revision 9e7327053ed393a8b0783a7612798f611e722014)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  * fdisk - edit dos disk partition table
37dd7cddfSDavid du Colombier  */
47dd7cddfSDavid du Colombier #include <u.h>
57dd7cddfSDavid du Colombier #include <libc.h>
67dd7cddfSDavid du Colombier #include <bio.h>
77dd7cddfSDavid du Colombier #include <ctype.h>
87dd7cddfSDavid du Colombier #include <disk.h>
97dd7cddfSDavid du Colombier #include "edit.h"
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier typedef struct Dospart	Dospart;
127dd7cddfSDavid du Colombier enum {
1380ee5cbfSDavid du Colombier 	NTentry = 4,
1480ee5cbfSDavid du Colombier 	Mpart = 64,
157dd7cddfSDavid du Colombier };
167dd7cddfSDavid du Colombier 
17eba00c11SDavid du Colombier static void rdpart(Edit*, uvlong, uvlong);
187dd7cddfSDavid du Colombier static void findmbr(Edit*);
197dd7cddfSDavid du Colombier static void autopart(Edit*);
207dd7cddfSDavid du Colombier static void wrpart(Edit*);
217dd7cddfSDavid du Colombier static void blankpart(Edit*);
227dd7cddfSDavid du Colombier static void cmdnamectl(Edit*);
2380ee5cbfSDavid du Colombier static void recover(Edit*);
249a747e4fSDavid du Colombier static int Dfmt(Fmt*);
257dd7cddfSDavid du Colombier static int blank;
267dd7cddfSDavid du Colombier static int dowrite;
277dd7cddfSDavid du Colombier static int file;
287dd7cddfSDavid du Colombier static int rdonly;
297dd7cddfSDavid du Colombier static int doauto;
307dd7cddfSDavid du Colombier static vlong mbroffset;
317dd7cddfSDavid du Colombier static int printflag;
327dd7cddfSDavid du Colombier static int printchs;
3380ee5cbfSDavid du Colombier static int sec2cyl;
3480ee5cbfSDavid du Colombier static int written;
357dd7cddfSDavid du Colombier 
367dd7cddfSDavid du Colombier static void 	cmdsum(Edit*, Part*, vlong, vlong);
377dd7cddfSDavid du Colombier static char 	*cmdadd(Edit*, char*, vlong, vlong);
387dd7cddfSDavid du Colombier static char 	*cmddel(Edit*, Part*);
397dd7cddfSDavid du Colombier static char 	*cmdext(Edit*, int, char**);
407dd7cddfSDavid du Colombier static char 	*cmdhelp(Edit*);
417dd7cddfSDavid du Colombier static char 	*cmdokname(Edit*, char*);
427dd7cddfSDavid du Colombier static char 	*cmdwrite(Edit*);
437dd7cddfSDavid du Colombier static void	cmdprintctl(Edit*, int);
447dd7cddfSDavid du Colombier 
4580ee5cbfSDavid du Colombier #pragma varargck type "D" uchar*
4680ee5cbfSDavid du Colombier 
477dd7cddfSDavid du Colombier Edit edit = {
487dd7cddfSDavid du Colombier 	.add=	cmdadd,
497dd7cddfSDavid du Colombier 	.del=		cmddel,
507dd7cddfSDavid du Colombier 	.ext=		cmdext,
517dd7cddfSDavid du Colombier 	.help=	cmdhelp,
527dd7cddfSDavid du Colombier 	.okname=	cmdokname,
537dd7cddfSDavid du Colombier 	.sum=	cmdsum,
547dd7cddfSDavid du Colombier 	.write=	cmdwrite,
557dd7cddfSDavid du Colombier 	.printctl=	cmdprintctl,
5680ee5cbfSDavid du Colombier 
5780ee5cbfSDavid du Colombier 	.unit=	"cylinder",
587dd7cddfSDavid du Colombier };
597dd7cddfSDavid du Colombier 
6080ee5cbfSDavid du Colombier /*
6180ee5cbfSDavid du Colombier  * Catch the obvious error routines to fix up the disk.
6280ee5cbfSDavid du Colombier  */
6380ee5cbfSDavid du Colombier void
sysfatal(char * fmt,...)6480ee5cbfSDavid du Colombier sysfatal(char *fmt, ...)
6580ee5cbfSDavid du Colombier {
6680ee5cbfSDavid du Colombier 	char buf[1024];
6780ee5cbfSDavid du Colombier 	va_list arg;
6880ee5cbfSDavid du Colombier 
6980ee5cbfSDavid du Colombier 	va_start(arg, fmt);
709a747e4fSDavid du Colombier 	vseprint(buf, buf+sizeof(buf), fmt, arg);
7180ee5cbfSDavid du Colombier 	va_end(arg);
7280ee5cbfSDavid du Colombier 	if(argv0)
7380ee5cbfSDavid du Colombier 		fprint(2, "%s: %s\n", argv0, buf);
7480ee5cbfSDavid du Colombier 	else
7580ee5cbfSDavid du Colombier 		fprint(2, "%s\n", buf);
7680ee5cbfSDavid du Colombier 
7780ee5cbfSDavid du Colombier 	if(written)
7880ee5cbfSDavid du Colombier 		recover(&edit);
7980ee5cbfSDavid du Colombier 
8080ee5cbfSDavid du Colombier 	exits(buf);
8180ee5cbfSDavid du Colombier }
8280ee5cbfSDavid du Colombier 
8380ee5cbfSDavid du Colombier void
abort(void)8480ee5cbfSDavid du Colombier abort(void)
8580ee5cbfSDavid du Colombier {
8680ee5cbfSDavid du Colombier 	fprint(2, "abort\n");
8780ee5cbfSDavid du Colombier 	recover(&edit);
8880ee5cbfSDavid du Colombier }
8980ee5cbfSDavid du Colombier 
907dd7cddfSDavid du Colombier void
usage(void)917dd7cddfSDavid du Colombier usage(void)
927dd7cddfSDavid du Colombier {
937dd7cddfSDavid du Colombier 	fprint(2, "usage: disk/fdisk [-abfprvw] [-s sectorsize] /dev/sdC0/data\n");
947dd7cddfSDavid du Colombier 	exits("usage");
957dd7cddfSDavid du Colombier }
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier void
main(int argc,char ** argv)987dd7cddfSDavid du Colombier main(int argc, char **argv)
997dd7cddfSDavid du Colombier {
1007dd7cddfSDavid du Colombier 	vlong secsize;
1017dd7cddfSDavid du Colombier 
1027dd7cddfSDavid du Colombier 	secsize = 0;
1037dd7cddfSDavid du Colombier 	ARGBEGIN{
1047dd7cddfSDavid du Colombier 	case 'a':
1057dd7cddfSDavid du Colombier 		doauto++;
1067dd7cddfSDavid du Colombier 		break;
1077dd7cddfSDavid du Colombier 	case 'b':
1087dd7cddfSDavid du Colombier 		blank++;
1097dd7cddfSDavid du Colombier 		break;
1107dd7cddfSDavid du Colombier 	case 'f':
1117dd7cddfSDavid du Colombier 		file++;
1127dd7cddfSDavid du Colombier 		break;
1137dd7cddfSDavid du Colombier 	case 'p':
1147dd7cddfSDavid du Colombier 		printflag++;
1157dd7cddfSDavid du Colombier 		break;
1167dd7cddfSDavid du Colombier 	case 'r':
1177dd7cddfSDavid du Colombier 		rdonly++;
1187dd7cddfSDavid du Colombier 		break;
1197dd7cddfSDavid du Colombier 	case 's':
1207dd7cddfSDavid du Colombier 		secsize = atoi(ARGF());
1217dd7cddfSDavid du Colombier 		break;
1227dd7cddfSDavid du Colombier 	case 'v':
1237dd7cddfSDavid du Colombier 		printchs++;
1247dd7cddfSDavid du Colombier 		break;
1257dd7cddfSDavid du Colombier 	case 'w':
1267dd7cddfSDavid du Colombier 		dowrite++;
1277dd7cddfSDavid du Colombier 		break;
1287dd7cddfSDavid du Colombier 	}ARGEND;
1297dd7cddfSDavid du Colombier 
1309a747e4fSDavid du Colombier 	fmtinstall('D', Dfmt);
13180ee5cbfSDavid du Colombier 
1327dd7cddfSDavid du Colombier 	if(argc != 1)
1337dd7cddfSDavid du Colombier 		usage();
1347dd7cddfSDavid du Colombier 
1357dd7cddfSDavid du Colombier 	edit.disk = opendisk(argv[0], rdonly, file);
1367dd7cddfSDavid du Colombier 	if(edit.disk == nil) {
1377dd7cddfSDavid du Colombier 		fprint(2, "cannot open disk: %r\n");
1387dd7cddfSDavid du Colombier 		exits("opendisk");
1397dd7cddfSDavid du Colombier 	}
1407dd7cddfSDavid du Colombier 
1417dd7cddfSDavid du Colombier 	if(secsize != 0) {
1427dd7cddfSDavid du Colombier 		edit.disk->secsize = secsize;
1437dd7cddfSDavid du Colombier 		edit.disk->secs = edit.disk->size / secsize;
1447dd7cddfSDavid du Colombier 	}
1457dd7cddfSDavid du Colombier 
14680ee5cbfSDavid du Colombier 	sec2cyl = edit.disk->h * edit.disk->s;
14780ee5cbfSDavid du Colombier 	edit.end = edit.disk->secs / sec2cyl;
14880ee5cbfSDavid du Colombier 
1497dd7cddfSDavid du Colombier 	findmbr(&edit);
1507dd7cddfSDavid du Colombier 
1517dd7cddfSDavid du Colombier 	if(blank)
1527dd7cddfSDavid du Colombier 		blankpart(&edit);
1537dd7cddfSDavid du Colombier 	else
1549a747e4fSDavid du Colombier 		rdpart(&edit, 0, 0);
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier 	if(doauto)
1577dd7cddfSDavid du Colombier 		autopart(&edit);
1587dd7cddfSDavid du Colombier 
1597dd7cddfSDavid du Colombier 	if(dowrite)
16080ee5cbfSDavid du Colombier 		runcmd(&edit, "w");
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier 	if(printflag)
1637dd7cddfSDavid du Colombier 		runcmd(&edit, "P");
1647dd7cddfSDavid du Colombier 
1657dd7cddfSDavid du Colombier 	if(dowrite || printflag)
1667dd7cddfSDavid du Colombier 		exits(0);
1677dd7cddfSDavid du Colombier 
16880ee5cbfSDavid du Colombier 	fprint(2, "cylinder = %lld bytes\n", sec2cyl*edit.disk->secsize);
1697dd7cddfSDavid du Colombier 	runcmd(&edit, "p");
1707dd7cddfSDavid du Colombier 	for(;;) {
1717dd7cddfSDavid du Colombier 		fprint(2, ">>> ");
1727dd7cddfSDavid du Colombier 		runcmd(&edit, getline(&edit));
1737dd7cddfSDavid du Colombier 	}
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier typedef struct Tentry	Tentry;
1777dd7cddfSDavid du Colombier typedef struct Table	Table;
1787dd7cddfSDavid du Colombier typedef struct Type	Type;
1797dd7cddfSDavid du Colombier typedef struct Tab	Tab;
18080ee5cbfSDavid du Colombier typedef struct Recover Recover;
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier struct Tentry {
1837dd7cddfSDavid du Colombier 	uchar	active;			/* active flag */
1847dd7cddfSDavid du Colombier 	uchar	starth;			/* starting head */
1857dd7cddfSDavid du Colombier 	uchar	starts;			/* starting sector */
1867dd7cddfSDavid du Colombier 	uchar	startc;			/* starting cylinder */
1877dd7cddfSDavid du Colombier 	uchar	type;			/* partition type */
1887dd7cddfSDavid du Colombier 	uchar	endh;			/* ending head */
1897dd7cddfSDavid du Colombier 	uchar	ends;			/* ending sector */
1907dd7cddfSDavid du Colombier 	uchar	endc;			/* ending cylinder */
19180ee5cbfSDavid du Colombier 	uchar	xlba[4];		/* starting LBA from beginning of disc or ext. partition */
1927dd7cddfSDavid du Colombier 	uchar	xsize[4];		/* size in sectors */
1937dd7cddfSDavid du Colombier };
1947dd7cddfSDavid du Colombier 
195*9e732705SDavid du Colombier struct Table {
196*9e732705SDavid du Colombier 	Tentry	entry[NTentry];
197*9e732705SDavid du Colombier 	uchar	magic[2];
198*9e732705SDavid du Colombier 	uchar	size[];
199*9e732705SDavid du Colombier };
200*9e732705SDavid du Colombier 
2017dd7cddfSDavid du Colombier enum {
2027dd7cddfSDavid du Colombier 	Active		= 0x80,		/* partition is active */
2037dd7cddfSDavid du Colombier 	Primary		= 0x01,		/* internal flag */
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier 	TypeBB		= 0xFF,
2067dd7cddfSDavid du Colombier 
2077dd7cddfSDavid du Colombier 	TypeEMPTY	= 0x00,
2087dd7cddfSDavid du Colombier 	TypeFAT12	= 0x01,
2097dd7cddfSDavid du Colombier 	TypeXENIX	= 0x02,		/* root */
2107dd7cddfSDavid du Colombier 	TypeXENIXUSR	= 0x03,		/* usr */
2117dd7cddfSDavid du Colombier 	TypeFAT16	= 0x04,
2127dd7cddfSDavid du Colombier 	TypeEXTENDED	= 0x05,
2137dd7cddfSDavid du Colombier 	TypeFATHUGE	= 0x06,
2147dd7cddfSDavid du Colombier 	TypeHPFS	= 0x07,
2157dd7cddfSDavid du Colombier 	TypeAIXBOOT	= 0x08,
2167dd7cddfSDavid du Colombier 	TypeAIXDATA	= 0x09,
2177dd7cddfSDavid du Colombier 	TypeOS2BOOT	= 0x0A,		/* OS/2 Boot Manager */
2187dd7cddfSDavid du Colombier 	TypeFAT32	= 0x0B,		/* FAT 32 */
2197dd7cddfSDavid du Colombier 	TypeFAT32LBA	= 0x0C,		/* FAT 32 needing LBA support */
2204afe124fSDavid du Colombier 	TypeFAT16X	= 0x0E,		/* FAT 16 needing LBA support */
2217dd7cddfSDavid du Colombier 	TypeEXTHUGE	= 0x0F,		/* FAT 32 extended partition */
2227dd7cddfSDavid du Colombier 	TypeUNFORMATTED	= 0x16,		/* unformatted primary partition (OS/2 FDISK)? */
2237dd7cddfSDavid du Colombier 	TypeHPFS2	= 0x17,
2246b6b9ac8SDavid du Colombier 	TypeIBMRecovery = 0x1C,		/* really hidden fat */
2257dd7cddfSDavid du Colombier 	TypeCPM0	= 0x52,
2267dd7cddfSDavid du Colombier 	TypeDMDDO	= 0x54,		/* Disk Manager Dynamic Disk Overlay */
2277dd7cddfSDavid du Colombier 	TypeGB		= 0x56,		/* ???? */
2287dd7cddfSDavid du Colombier 	TypeSPEEDSTOR	= 0x61,
2297dd7cddfSDavid du Colombier 	TypeSYSV386	= 0x63,		/* also HURD? */
2307dd7cddfSDavid du Colombier 	TypeNETWARE	= 0x64,
2317dd7cddfSDavid du Colombier 	TypePCIX	= 0x75,
2327dd7cddfSDavid du Colombier 	TypeMINIX13	= 0x80,		/* Minix v1.3 and below */
2337dd7cddfSDavid du Colombier 	TypeMINIX	= 0x81,		/* Minix v1.5+ */
2347dd7cddfSDavid du Colombier 	TypeLINUXSWAP	= 0x82,
2357dd7cddfSDavid du Colombier 	TypeLINUX	= 0x83,
2369a747e4fSDavid du Colombier 	TypeLINUXEXT	= 0x85,
237c39c2eb3SDavid du Colombier 	TypeLINUXLVM	= 0x8E,		/* logical volume manager */
2387dd7cddfSDavid du Colombier 	TypeAMOEBA	= 0x93,
2397dd7cddfSDavid du Colombier 	TypeAMOEBABB	= 0x94,
2407dd7cddfSDavid du Colombier 	TypeBSD386	= 0xA5,
241*9e732705SDavid du Colombier 	TypeNETBSD	= 0xA9,
2427dd7cddfSDavid du Colombier 	TypeBSDI	= 0xB7,
2437dd7cddfSDavid du Colombier 	TypeBSDISWAP	= 0xB8,
24480ee5cbfSDavid du Colombier 	TypeOTHER	= 0xDA,
2457dd7cddfSDavid du Colombier 	TypeCPM		= 0xDB,
24665fa3f8bSDavid du Colombier 	TypeDellRecovery= 0xDE,
2477dd7cddfSDavid du Colombier 	TypeSPEEDSTOR12	= 0xE1,
2487dd7cddfSDavid du Colombier 	TypeSPEEDSTOR16	= 0xE4,
249*9e732705SDavid du Colombier 	TypeEFIProtect	= 0xEE,
250*9e732705SDavid du Colombier 	TypeEFI		= 0xEF,
2517dd7cddfSDavid du Colombier 	TypeLANSTEP	= 0xFE,
2527dd7cddfSDavid du Colombier 
2537dd7cddfSDavid du Colombier 	Type9		= 0x39,
2547dd7cddfSDavid du Colombier 
2557dd7cddfSDavid du Colombier 	Toffset		= 446,		/* offset of partition table in sector */
2567dd7cddfSDavid du Colombier 	Magic0		= 0x55,
2577dd7cddfSDavid du Colombier 	Magic1		= 0xAA,
2587dd7cddfSDavid du Colombier 
259*9e732705SDavid du Colombier 	Tablesz		= offsetof(Table, size[0]),
2607dd7cddfSDavid du Colombier };
2617dd7cddfSDavid du Colombier 
2627dd7cddfSDavid du Colombier struct Type {
2637dd7cddfSDavid du Colombier 	char *desc;
2647dd7cddfSDavid du Colombier 	char *name;
2657dd7cddfSDavid du Colombier };
2667dd7cddfSDavid du Colombier 
26780ee5cbfSDavid du Colombier struct Dospart {
26880ee5cbfSDavid du Colombier 	Part;
2697dd7cddfSDavid du Colombier 	Tentry;
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier 	u32int	lba;
2727dd7cddfSDavid du Colombier 	u32int	size;
27380ee5cbfSDavid du Colombier 	int		primary;
2747dd7cddfSDavid du Colombier };
2757dd7cddfSDavid du Colombier 
27680ee5cbfSDavid du Colombier struct Recover {
27780ee5cbfSDavid du Colombier 	Table	table;
27880ee5cbfSDavid du Colombier 	ulong	lba;
2797dd7cddfSDavid du Colombier };
2807dd7cddfSDavid du Colombier 
2817dd7cddfSDavid du Colombier static Type types[256] = {
2827dd7cddfSDavid du Colombier 	[TypeEMPTY]		{ "EMPTY", "" },
2837dd7cddfSDavid du Colombier 	[TypeFAT12]		{ "FAT12", "dos" },
2847dd7cddfSDavid du Colombier 	[TypeFAT16]		{ "FAT16", "dos" },
2857dd7cddfSDavid du Colombier 	[TypeFAT32]		{ "FAT32", "dos" },
2867dd7cddfSDavid du Colombier 	[TypeFAT32LBA]		{ "FAT32LBA", "dos" },
2874afe124fSDavid du Colombier 	[TypeFAT16X]		{ "FAT16X", "dos" },
2887dd7cddfSDavid du Colombier 	[TypeEXTHUGE]		{ "EXTHUGE", "" },
2896b6b9ac8SDavid du Colombier 	[TypeIBMRecovery]	{ "IBMRECOVERY", "ibm" },
2907dd7cddfSDavid du Colombier 	[TypeEXTENDED]		{ "EXTENDED", "" },
2917dd7cddfSDavid du Colombier 	[TypeFATHUGE]		{ "FATHUGE", "dos" },
2927dd7cddfSDavid du Colombier 	[TypeBB]		{ "BB", "bb" },
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier 	[TypeXENIX]		{ "XENIX", "xenix" },
2957dd7cddfSDavid du Colombier 	[TypeXENIXUSR]		{ "XENIX USR", "xenixusr" },
2967dd7cddfSDavid du Colombier 	[TypeHPFS]		{ "HPFS", "ntfs" },
2977dd7cddfSDavid du Colombier 	[TypeAIXBOOT]		{ "AIXBOOT", "aixboot" },
2987dd7cddfSDavid du Colombier 	[TypeAIXDATA]		{ "AIXDATA", "aixdata" },
2997dd7cddfSDavid du Colombier 	[TypeOS2BOOT]		{ "OS/2BOOT", "os2boot" },
3007dd7cddfSDavid du Colombier 	[TypeUNFORMATTED]	{ "UNFORMATTED", "" },
3017dd7cddfSDavid du Colombier 	[TypeHPFS2]		{ "HPFS2", "hpfs2" },
3027dd7cddfSDavid du Colombier 	[TypeCPM0]		{ "CPM0", "cpm0" },
3037dd7cddfSDavid du Colombier 	[TypeDMDDO]		{ "DMDDO", "dmdd0" },
3047dd7cddfSDavid du Colombier 	[TypeGB]		{ "GB", "gb" },
3057dd7cddfSDavid du Colombier 	[TypeSPEEDSTOR]		{ "SPEEDSTOR", "speedstor" },
3067dd7cddfSDavid du Colombier 	[TypeSYSV386]		{ "SYSV386", "sysv386" },
3077dd7cddfSDavid du Colombier 	[TypeNETWARE]		{ "NETWARE", "netware" },
3087dd7cddfSDavid du Colombier 	[TypePCIX]		{ "PCIX", "pcix" },
3097dd7cddfSDavid du Colombier 	[TypeMINIX13]		{ "MINIXV1.3", "minix13" },
3107dd7cddfSDavid du Colombier 	[TypeMINIX]		{ "MINIXV1.5", "minix15" },
3117dd7cddfSDavid du Colombier 	[TypeLINUXSWAP]		{ "LINUXSWAP", "linuxswap" },
3127dd7cddfSDavid du Colombier 	[TypeLINUX]		{ "LINUX", "linux" },
3139a747e4fSDavid du Colombier 	[TypeLINUXEXT]		{ "LINUXEXTENDED", "" },
314c39c2eb3SDavid du Colombier 	[TypeLINUXLVM]		{ "LINUXLVM", "linuxlvm" },
3157dd7cddfSDavid du Colombier 	[TypeAMOEBA]		{ "AMOEBA", "amoeba" },
3167dd7cddfSDavid du Colombier 	[TypeAMOEBABB]		{ "AMOEBABB", "amoebaboot" },
3177dd7cddfSDavid du Colombier 	[TypeBSD386]		{ "BSD386", "bsd386" },
3184af5a9a1SDavid du Colombier 	[TypeNETBSD]		{ "NETBSD", "netbsd" },
3197dd7cddfSDavid du Colombier 	[TypeBSDI]		{ "BSDI", "bsdi" },
3207dd7cddfSDavid du Colombier 	[TypeBSDISWAP]		{ "BSDISWAP", "bsdiswap" },
32180ee5cbfSDavid du Colombier 	[TypeOTHER]		{ "OTHER", "other" },
3227dd7cddfSDavid du Colombier 	[TypeCPM]		{ "CPM", "cpm" },
32365fa3f8bSDavid du Colombier 	[TypeDellRecovery]	{ "DELLRECOVERY", "dell" },
3247dd7cddfSDavid du Colombier 	[TypeSPEEDSTOR12]	{ "SPEEDSTOR12", "speedstor" },
3257dd7cddfSDavid du Colombier 	[TypeSPEEDSTOR16]	{ "SPEEDSTOR16", "speedstor" },
326*9e732705SDavid du Colombier 	[TypeEFIProtect]	{ "EFIPROTECT", "efiprotect" },
327*9e732705SDavid du Colombier 	[TypeEFI]		{ "EFI", "efi" },
3287dd7cddfSDavid du Colombier 	[TypeLANSTEP]		{ "LANSTEP", "lanstep" },
3297dd7cddfSDavid du Colombier 
3307dd7cddfSDavid du Colombier 	[Type9]			{ "PLAN9", "plan9" },
3317dd7cddfSDavid du Colombier };
3327dd7cddfSDavid du Colombier 
33380ee5cbfSDavid du Colombier static Dospart	part[Mpart];
33480ee5cbfSDavid du Colombier static int		npart;
33580ee5cbfSDavid du Colombier 
3367dd7cddfSDavid du Colombier static char*
typestr0(int type)33780ee5cbfSDavid du Colombier typestr0(int type)
3387dd7cddfSDavid du Colombier {
3397dd7cddfSDavid du Colombier 	static char buf[100];
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 	sprint(buf, "type %d", type);
3427dd7cddfSDavid du Colombier 	if(type < 0 || type >= 256)
3437dd7cddfSDavid du Colombier 		return buf;
3447dd7cddfSDavid du Colombier 	if(types[type].desc == nil)
3457dd7cddfSDavid du Colombier 		return buf;
3467dd7cddfSDavid du Colombier 	return types[type].desc;
3477dd7cddfSDavid du Colombier }
3487dd7cddfSDavid du Colombier 
3497dd7cddfSDavid du Colombier static u32int
getle32(void * v)3507dd7cddfSDavid du Colombier getle32(void* v)
3517dd7cddfSDavid du Colombier {
3527dd7cddfSDavid du Colombier 	uchar *p;
3537dd7cddfSDavid du Colombier 
3547dd7cddfSDavid du Colombier 	p = v;
3557dd7cddfSDavid du Colombier 	return (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0];
3567dd7cddfSDavid du Colombier }
3577dd7cddfSDavid du Colombier 
3587dd7cddfSDavid du Colombier static void
putle32(void * v,u32int i)3597dd7cddfSDavid du Colombier putle32(void* v, u32int i)
3607dd7cddfSDavid du Colombier {
3617dd7cddfSDavid du Colombier 	uchar *p;
3627dd7cddfSDavid du Colombier 
3637dd7cddfSDavid du Colombier 	p = v;
3647dd7cddfSDavid du Colombier 	p[0] = i;
3657dd7cddfSDavid du Colombier 	p[1] = i>>8;
3667dd7cddfSDavid du Colombier 	p[2] = i>>16;
3677dd7cddfSDavid du Colombier 	p[3] = i>>24;
3687dd7cddfSDavid du Colombier }
3697dd7cddfSDavid du Colombier 
37080ee5cbfSDavid du Colombier static void
diskread(Disk * disk,void * data,int ndata,u32int sec,u32int off)37180ee5cbfSDavid du Colombier diskread(Disk *disk, void *data, int ndata, u32int sec, u32int off)
3727dd7cddfSDavid du Colombier {
3739a747e4fSDavid du Colombier 	if(seek(disk->fd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off)
37480ee5cbfSDavid du Colombier 		sysfatal("diskread seek %lud.%lud: %r", (ulong)sec, (ulong)off);
37580ee5cbfSDavid du Colombier 	if(readn(disk->fd, data, ndata) != ndata)
37680ee5cbfSDavid du Colombier 		sysfatal("diskread %lud at %lud.%lud: %r", (ulong)ndata, (ulong)sec, (ulong)off);
37780ee5cbfSDavid du Colombier }
3787dd7cddfSDavid du Colombier 
37980ee5cbfSDavid du Colombier static int
diskwrite(Disk * disk,void * data,int ndata,u32int sec,u32int off)38080ee5cbfSDavid du Colombier diskwrite(Disk *disk, void *data, int ndata, u32int sec, u32int off)
38180ee5cbfSDavid du Colombier {
38280ee5cbfSDavid du Colombier 	written = 1;
3839a747e4fSDavid du Colombier 	if(seek(disk->wfd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off)
38480ee5cbfSDavid du Colombier 		goto Error;
38580ee5cbfSDavid du Colombier 	if(write(disk->wfd, data, ndata) != ndata)
38680ee5cbfSDavid du Colombier 		goto Error;
38780ee5cbfSDavid du Colombier 	return 0;
3887dd7cddfSDavid du Colombier 
38980ee5cbfSDavid du Colombier Error:
39080ee5cbfSDavid du Colombier 	fprint(2, "write %d bytes at %lud.%lud failed: %r\n", ndata, (ulong)sec, (ulong)off);
39180ee5cbfSDavid du Colombier 	return -1;
3927dd7cddfSDavid du Colombier }
3937dd7cddfSDavid du Colombier 
3947dd7cddfSDavid du Colombier static Dospart*
mkpart(char * name,int primary,vlong lba,vlong size,Tentry * t)395eba00c11SDavid du Colombier mkpart(char *name, int primary, vlong lba, vlong size, Tentry *t)
3967dd7cddfSDavid du Colombier {
39780ee5cbfSDavid du Colombier 	static int n;
3987dd7cddfSDavid du Colombier 	Dospart *p;
3997dd7cddfSDavid du Colombier 
40080ee5cbfSDavid du Colombier 	p = emalloc(sizeof(*p));
40180ee5cbfSDavid du Colombier 	if(name)
4029a747e4fSDavid du Colombier 		p->name = estrdup(name);
4039a747e4fSDavid du Colombier 	else{
4049a747e4fSDavid du Colombier 		p->name = emalloc(20);
40580ee5cbfSDavid du Colombier 		sprint(p->name, "%c%d", primary ? 'p' : 's', ++n);
4069a747e4fSDavid du Colombier 	}
40780ee5cbfSDavid du Colombier 
40880ee5cbfSDavid du Colombier 	if(t)
40980ee5cbfSDavid du Colombier 		p->Tentry = *t;
41080ee5cbfSDavid du Colombier 	else
41180ee5cbfSDavid du Colombier 		memset(&p->Tentry, 0, sizeof(Tentry));
41280ee5cbfSDavid du Colombier 
4137dd7cddfSDavid du Colombier 	p->changed = 0;
41480ee5cbfSDavid du Colombier 	p->start = lba/sec2cyl;
41580ee5cbfSDavid du Colombier 	p->end = (lba+size)/sec2cyl;
41680ee5cbfSDavid du Colombier 	p->ctlstart = lba;
41780ee5cbfSDavid du Colombier 	p->ctlend = lba+size;
41880ee5cbfSDavid du Colombier 	p->lba = lba;
419eba00c11SDavid du Colombier 	if (p->lba != lba)
420eba00c11SDavid du Colombier 		fprint(2, "%s: start of partition (%lld) won't fit in MBR table\n", argv0, lba);
42180ee5cbfSDavid du Colombier 	p->size = size;
422eba00c11SDavid du Colombier 	if (p->size != size)
423eba00c11SDavid du Colombier 		fprint(2, "%s: size of partition (%lld) won't fit in MBR table\n", argv0, size);
42480ee5cbfSDavid du Colombier 	p->primary = primary;
4257dd7cddfSDavid du Colombier 	return p;
4267dd7cddfSDavid du Colombier }
4277dd7cddfSDavid du Colombier 
42880ee5cbfSDavid du Colombier /*
42980ee5cbfSDavid du Colombier  * Recovery takes care of remembering what the various tables
43080ee5cbfSDavid du Colombier  * looked like when we started, attempting to restore them when
43180ee5cbfSDavid du Colombier  * we are finished.
43280ee5cbfSDavid du Colombier  */
43380ee5cbfSDavid du Colombier static Recover	*rtab;
43480ee5cbfSDavid du Colombier static int		nrtab;
4357dd7cddfSDavid du Colombier 
43680ee5cbfSDavid du Colombier static void
addrecover(Table t,ulong lba)43780ee5cbfSDavid du Colombier addrecover(Table t, ulong lba)
43880ee5cbfSDavid du Colombier {
43980ee5cbfSDavid du Colombier 	if((nrtab%8) == 0) {
44080ee5cbfSDavid du Colombier 		rtab = realloc(rtab, (nrtab+8)*sizeof(rtab[0]));
44180ee5cbfSDavid du Colombier 		if(rtab == nil)
44280ee5cbfSDavid du Colombier 			sysfatal("out of memory");
4437dd7cddfSDavid du Colombier 	}
44480ee5cbfSDavid du Colombier 	rtab[nrtab] = (Recover){t, lba};
44580ee5cbfSDavid du Colombier 	nrtab++;
44680ee5cbfSDavid du Colombier }
44780ee5cbfSDavid du Colombier 
44880ee5cbfSDavid du Colombier static void
recover(Edit * edit)44980ee5cbfSDavid du Colombier recover(Edit *edit)
45080ee5cbfSDavid du Colombier {
45180ee5cbfSDavid du Colombier 	int err, i, ctlfd;
45280ee5cbfSDavid du Colombier 	vlong offset;
45380ee5cbfSDavid du Colombier 
45480ee5cbfSDavid du Colombier 	err = 0;
45580ee5cbfSDavid du Colombier 	for(i=0; i<nrtab; i++)
456*9e732705SDavid du Colombier 		if(diskwrite(edit->disk, &rtab[i].table, Tablesz, rtab[i].lba, Toffset) < 0)
45780ee5cbfSDavid du Colombier 			err = 1;
45880ee5cbfSDavid du Colombier 	if(err) {
45980ee5cbfSDavid du Colombier 		fprint(2, "warning: some writes failed during restoration of old partition tables\n");
46080ee5cbfSDavid du Colombier 		exits("inconsistent");
46180ee5cbfSDavid du Colombier 	} else {
46280ee5cbfSDavid du Colombier 		fprint(2, "restored old partition tables\n");
46380ee5cbfSDavid du Colombier 	}
46480ee5cbfSDavid du Colombier 
46580ee5cbfSDavid du Colombier 	ctlfd = edit->disk->ctlfd;
46680ee5cbfSDavid du Colombier 	offset = edit->disk->offset;
46780ee5cbfSDavid du Colombier 	if(ctlfd >= 0){
46880ee5cbfSDavid du Colombier 		for(i=0; i<edit->npart; i++)
4696b6b9ac8SDavid du Colombier 			if(edit->part[i]->ctlname && fprint(ctlfd, "delpart %s", edit->part[i]->ctlname)<0)
47080ee5cbfSDavid du Colombier 				fprint(2, "delpart failed: %s: %r", edit->part[i]->ctlname);
47180ee5cbfSDavid du Colombier 		for(i=0; i<edit->nctlpart; i++)
4726b6b9ac8SDavid du Colombier 			if(edit->part[i]->name && fprint(ctlfd, "delpart %s", edit->ctlpart[i]->name)<0)
47380ee5cbfSDavid du Colombier 				fprint(2, "delpart failed: %s: %r", edit->ctlpart[i]->name);
47480ee5cbfSDavid du Colombier 		for(i=0; i<edit->nctlpart; i++){
47580ee5cbfSDavid du Colombier 			if(fprint(ctlfd, "part %s %lld %lld", edit->ctlpart[i]->name,
47680ee5cbfSDavid du Colombier 				edit->ctlpart[i]->start+offset, edit->ctlpart[i]->end+offset) < 0){
47780ee5cbfSDavid du Colombier 				fprint(2, "restored disk partition table but not kernel; reboot\n");
47880ee5cbfSDavid du Colombier 				exits("inconsistent");
47980ee5cbfSDavid du Colombier 			}
48080ee5cbfSDavid du Colombier 		}
48180ee5cbfSDavid du Colombier 	}
48280ee5cbfSDavid du Colombier 	exits("restored");
48380ee5cbfSDavid du Colombier 
48480ee5cbfSDavid du Colombier }
48580ee5cbfSDavid du Colombier 
48680ee5cbfSDavid du Colombier /*
48780ee5cbfSDavid du Colombier  * Read the partition table (including extended partition tables)
48880ee5cbfSDavid du Colombier  * from the disk into the part array.
48980ee5cbfSDavid du Colombier  */
49080ee5cbfSDavid du Colombier static void
rdpart(Edit * edit,uvlong lba,uvlong xbase)491eba00c11SDavid du Colombier rdpart(Edit *edit, uvlong lba, uvlong xbase)
49280ee5cbfSDavid du Colombier {
49380ee5cbfSDavid du Colombier 	char *err;
49480ee5cbfSDavid du Colombier 	Table table;
49580ee5cbfSDavid du Colombier 	Tentry *tp, *ep;
49680ee5cbfSDavid du Colombier 	Dospart *p;
49780ee5cbfSDavid du Colombier 
4989a747e4fSDavid du Colombier 	if(xbase == 0)
4999a747e4fSDavid du Colombier 		xbase = lba;
5009a747e4fSDavid du Colombier 
501*9e732705SDavid du Colombier 	diskread(edit->disk, &table, Tablesz, mbroffset+lba, Toffset);
50280ee5cbfSDavid du Colombier 	addrecover(table, mbroffset+lba);
5037dd7cddfSDavid du Colombier 
5047dd7cddfSDavid du Colombier 	if(table.magic[0] != Magic0 || table.magic[1] != Magic1) {
50580ee5cbfSDavid du Colombier 		assert(lba != 0);
5067dd7cddfSDavid du Colombier 		return;
5077dd7cddfSDavid du Colombier 	}
5087dd7cddfSDavid du Colombier 
50980ee5cbfSDavid du Colombier 	for(tp=table.entry, ep=tp+NTentry; tp<ep && npart < Mpart; tp++) {
51080ee5cbfSDavid du Colombier 		switch(tp->type) {
5117dd7cddfSDavid du Colombier 		case TypeEMPTY:
5127dd7cddfSDavid du Colombier 			break;
5137dd7cddfSDavid du Colombier 		case TypeEXTENDED:
5147dd7cddfSDavid du Colombier 		case TypeEXTHUGE:
5159a747e4fSDavid du Colombier 		case TypeLINUXEXT:
5169a747e4fSDavid du Colombier 			rdpart(edit, xbase+getle32(tp->xlba), xbase);
5177dd7cddfSDavid du Colombier 			break;
5187dd7cddfSDavid du Colombier 		default:
51980ee5cbfSDavid du Colombier 			p = mkpart(nil, lba==0, lba+getle32(tp->xlba), getle32(tp->xsize), tp);
5207dd7cddfSDavid du Colombier 			if(err = addpart(edit, p))
52180ee5cbfSDavid du Colombier 				fprint(2, "adding partition: %s\n", err);
52280ee5cbfSDavid du Colombier 			break;
52380ee5cbfSDavid du Colombier 		}
5247dd7cddfSDavid du Colombier 	}
5257dd7cddfSDavid du Colombier }
5267dd7cddfSDavid du Colombier 
5277dd7cddfSDavid du Colombier static void
blankpart(Edit * edit)5287dd7cddfSDavid du Colombier blankpart(Edit *edit)
5297dd7cddfSDavid du Colombier {
5307dd7cddfSDavid du Colombier 	edit->changed = 1;
5317dd7cddfSDavid du Colombier }
5327dd7cddfSDavid du Colombier 
5337dd7cddfSDavid du Colombier static void
findmbr(Edit * edit)5347dd7cddfSDavid du Colombier findmbr(Edit *edit)
5357dd7cddfSDavid du Colombier {
5367dd7cddfSDavid du Colombier 	Table table;
5377dd7cddfSDavid du Colombier 	Tentry *tp;
5387dd7cddfSDavid du Colombier 
539*9e732705SDavid du Colombier 	diskread(edit->disk, &table, Tablesz, 0, Toffset);
5407dd7cddfSDavid du Colombier 	if(table.magic[0] != Magic0 || table.magic[1] != Magic1)
5417dd7cddfSDavid du Colombier 		sysfatal("did not find master boot record");
5427dd7cddfSDavid du Colombier 
5437dd7cddfSDavid du Colombier 	for(tp = table.entry; tp < &table.entry[NTentry]; tp++)
5447dd7cddfSDavid du Colombier 		if(tp->type == TypeDMDDO)
54580ee5cbfSDavid du Colombier 			mbroffset = edit->disk->s;
5467dd7cddfSDavid du Colombier }
5477dd7cddfSDavid du Colombier 
54880ee5cbfSDavid du Colombier static int
haveroom(Edit * edit,int primary,vlong start)54980ee5cbfSDavid du Colombier haveroom(Edit *edit, int primary, vlong start)
5507dd7cddfSDavid du Colombier {
5519a747e4fSDavid du Colombier 	int i, lastsec, n;
5529a747e4fSDavid du Colombier 	Dospart *p, *q;
5539a747e4fSDavid du Colombier 	ulong pend, qstart;
55480ee5cbfSDavid du Colombier 
55580ee5cbfSDavid du Colombier 	if(primary) {
55680ee5cbfSDavid du Colombier 		/*
55780ee5cbfSDavid du Colombier 		 * must be open primary slot.
55880ee5cbfSDavid du Colombier 		 * primary slots are taken by primary partitions
55980ee5cbfSDavid du Colombier 		 * and runs of secondary partitions.
56080ee5cbfSDavid du Colombier 		 */
56180ee5cbfSDavid du Colombier 		n = 0;
56280ee5cbfSDavid du Colombier 		lastsec = 0;
56380ee5cbfSDavid du Colombier 		for(i=0; i<edit->npart; i++) {
56480ee5cbfSDavid du Colombier 			p = (Dospart*)edit->part[i];
56580ee5cbfSDavid du Colombier 			if(p->primary)
56680ee5cbfSDavid du Colombier 				n++, lastsec=0;
5679a747e4fSDavid du Colombier 			else if(!lastsec)
56880ee5cbfSDavid du Colombier 				n++, lastsec=1;
5697dd7cddfSDavid du Colombier 		}
57080ee5cbfSDavid du Colombier 		return n<4;
5717dd7cddfSDavid du Colombier 	}
5727dd7cddfSDavid du Colombier 
57380ee5cbfSDavid du Colombier 	/*
57480ee5cbfSDavid du Colombier 	 * secondary partitions can be inserted between two primary
57580ee5cbfSDavid du Colombier 	 * partitions only if there is an empty primary slot.
57680ee5cbfSDavid du Colombier 	 * otherwise, we can put a new secondary partition next
57780ee5cbfSDavid du Colombier 	 * to a secondary partition no problem.
57880ee5cbfSDavid du Colombier 	 */
57980ee5cbfSDavid du Colombier 	n = 0;
5806b6b9ac8SDavid du Colombier 	for(i=0; i<edit->npart; i++){
58180ee5cbfSDavid du Colombier 		p = (Dospart*)edit->part[i];
58280ee5cbfSDavid du Colombier 		if(p->primary)
5839a747e4fSDavid du Colombier 			n++;
5849a747e4fSDavid du Colombier 		pend = p->end;
5859a747e4fSDavid du Colombier 		if(i+1<edit->npart){
5869a747e4fSDavid du Colombier 			q = (Dospart*)edit->part[i+1];
5879a747e4fSDavid du Colombier 			qstart = q->start;
5889a747e4fSDavid du Colombier 		}else{
5899a747e4fSDavid du Colombier 			qstart = edit->end;
5909a747e4fSDavid du Colombier 			q = nil;
5917dd7cddfSDavid du Colombier 		}
5929a747e4fSDavid du Colombier 		if(start < pend || start >= qstart)
5939a747e4fSDavid du Colombier 			continue;
5949a747e4fSDavid du Colombier 		/* we go between these two */
5959a747e4fSDavid du Colombier 		if(p->primary==0 || (q && q->primary==0))
5969a747e4fSDavid du Colombier 			return 1;
5977dd7cddfSDavid du Colombier 	}
59880ee5cbfSDavid du Colombier 	/* not next to a secondary, need a new primary */
59980ee5cbfSDavid du Colombier 	return n<4;
6007dd7cddfSDavid du Colombier }
6017dd7cddfSDavid du Colombier 
6027dd7cddfSDavid du Colombier static void
autopart(Edit * edit)6037dd7cddfSDavid du Colombier autopart(Edit *edit)
6047dd7cddfSDavid du Colombier {
60580ee5cbfSDavid du Colombier 	char *err;
60680ee5cbfSDavid du Colombier 	int active, i;
60780ee5cbfSDavid du Colombier 	vlong bigstart, bigsize, start;
60880ee5cbfSDavid du Colombier 	Dospart *p;
6097dd7cddfSDavid du Colombier 
61080ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
61180ee5cbfSDavid du Colombier 		if(((Dospart*)edit->part[i])->type == Type9)
6127dd7cddfSDavid du Colombier 			return;
6137dd7cddfSDavid du Colombier 
61480ee5cbfSDavid du Colombier 	/* look for the biggest gap in which we can put a primary partition */
61580ee5cbfSDavid du Colombier 	start = 0;
6167dd7cddfSDavid du Colombier 	bigsize = 0;
6177dd7cddfSDavid du Colombier 	SET(bigstart);
6187dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++) {
61980ee5cbfSDavid du Colombier 		p = (Dospart*)edit->part[i];
62080ee5cbfSDavid du Colombier 		if(p->start > start && p->start - start > bigsize && haveroom(edit, 1, start)) {
6217dd7cddfSDavid du Colombier 			bigsize = p->start - start;
6227dd7cddfSDavid du Colombier 			bigstart = start;
6237dd7cddfSDavid du Colombier 		}
6247dd7cddfSDavid du Colombier 		start = p->end;
6257dd7cddfSDavid du Colombier 	}
6267dd7cddfSDavid du Colombier 
62780ee5cbfSDavid du Colombier 	if(edit->end - start > bigsize && haveroom(edit, 1, start)) {
62880ee5cbfSDavid du Colombier 		bigsize = edit->end - start;
6297dd7cddfSDavid du Colombier 		bigstart = start;
6307dd7cddfSDavid du Colombier 	}
63180ee5cbfSDavid du Colombier 	if(bigsize < 1) {
63280ee5cbfSDavid du Colombier 		fprint(2, "couldn't find space or partition slot for plan 9 partition\n");
6337dd7cddfSDavid du Colombier 		return;
6347dd7cddfSDavid du Colombier 	}
6357dd7cddfSDavid du Colombier 
63680ee5cbfSDavid du Colombier 	/* set new partition active only if no others are */
6377dd7cddfSDavid du Colombier 	active = Active;
63880ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
63980ee5cbfSDavid du Colombier 		if(((Dospart*)edit->part[i])->primary && (((Dospart*)edit->part[i])->active & Active))
6407dd7cddfSDavid du Colombier 			active = 0;
6417dd7cddfSDavid du Colombier 
64280ee5cbfSDavid du Colombier 	/* add new plan 9 partition */
64380ee5cbfSDavid du Colombier 	bigsize *= sec2cyl;
64480ee5cbfSDavid du Colombier 	bigstart *= sec2cyl;
64580ee5cbfSDavid du Colombier 	if(bigstart == 0) {
64680ee5cbfSDavid du Colombier 		bigstart += edit->disk->s;
64780ee5cbfSDavid du Colombier 		bigsize -= edit->disk->s;
6487dd7cddfSDavid du Colombier 	}
64980ee5cbfSDavid du Colombier 	p = mkpart(nil, 1, bigstart, bigsize, nil);
65080ee5cbfSDavid du Colombier 	p->active = active;
65180ee5cbfSDavid du Colombier 	p->changed = 1;
65280ee5cbfSDavid du Colombier 	p->type = Type9;
65380ee5cbfSDavid du Colombier 	edit->changed = 1;
65480ee5cbfSDavid du Colombier 	if(err = addpart(edit, p)) {
65580ee5cbfSDavid du Colombier 		fprint(2, "error adding plan9 partition: %s\n", err);
6567dd7cddfSDavid du Colombier 		return;
6577dd7cddfSDavid du Colombier 	}
6587dd7cddfSDavid du Colombier }
6597dd7cddfSDavid du Colombier 
6607dd7cddfSDavid du Colombier typedef struct Name Name;
6617dd7cddfSDavid du Colombier struct Name {
6629a747e4fSDavid du Colombier 	char *name;
6637dd7cddfSDavid du Colombier 	Name *link;
6647dd7cddfSDavid du Colombier };
6657dd7cddfSDavid du Colombier Name *namelist;
6667dd7cddfSDavid du Colombier static void
plan9print(Dospart * part,int fd)66780ee5cbfSDavid du Colombier plan9print(Dospart *part, int fd)
6687dd7cddfSDavid du Colombier {
6697dd7cddfSDavid du Colombier 	int i, ok;
6709a747e4fSDavid du Colombier 	char *name, *vname;
6717dd7cddfSDavid du Colombier 	Name *n;
67280ee5cbfSDavid du Colombier 	vlong start, end;
67380ee5cbfSDavid du Colombier 	char *sep;
67480ee5cbfSDavid du Colombier 
67580ee5cbfSDavid du Colombier 	vname = types[part->type].name;
6769a747e4fSDavid du Colombier 	if(vname==nil || strcmp(vname, "")==0) {
6779a747e4fSDavid du Colombier 		part->ctlname = "";
67880ee5cbfSDavid du Colombier 		return;
67980ee5cbfSDavid du Colombier 	}
68080ee5cbfSDavid du Colombier 
68180ee5cbfSDavid du Colombier 	start = mbroffset+part->lba;
68280ee5cbfSDavid du Colombier 	end = start+part->size;
68380ee5cbfSDavid du Colombier 
68480ee5cbfSDavid du Colombier 	/* avoid names like plan90 */
68580ee5cbfSDavid du Colombier 	i = strlen(vname) - 1;
68680ee5cbfSDavid du Colombier 	if(vname[i] >= '0' && vname[i] <= '9')
68780ee5cbfSDavid du Colombier 		sep = ".";
68880ee5cbfSDavid du Colombier 	else
68980ee5cbfSDavid du Colombier 		sep = "";
6907dd7cddfSDavid du Colombier 
6917dd7cddfSDavid du Colombier 	i = 0;
6929a747e4fSDavid du Colombier 	name = emalloc(strlen(vname)+10);
6939a747e4fSDavid du Colombier 
69480ee5cbfSDavid du Colombier 	sprint(name, "%s", vname);
6957dd7cddfSDavid du Colombier 	do {
6967dd7cddfSDavid du Colombier 		ok = 1;
6977dd7cddfSDavid du Colombier 		for(n=namelist; n; n=n->link) {
6987dd7cddfSDavid du Colombier 			if(strcmp(name, n->name) == 0) {
6997dd7cddfSDavid du Colombier 				i++;
70080ee5cbfSDavid du Colombier 				sprint(name, "%s%s%d", vname, sep, i);
7017dd7cddfSDavid du Colombier 				ok = 0;
7027dd7cddfSDavid du Colombier 			}
7037dd7cddfSDavid du Colombier 		}
7047dd7cddfSDavid du Colombier 	} while(ok == 0);
7057dd7cddfSDavid du Colombier 
7069a747e4fSDavid du Colombier 	n = emalloc(sizeof(*n));
7079a747e4fSDavid du Colombier 	n->name = name;
7087dd7cddfSDavid du Colombier 	n->link = namelist;
7097dd7cddfSDavid du Colombier 	namelist = n;
7109a747e4fSDavid du Colombier 	part->ctlname = name;
7117dd7cddfSDavid du Colombier 
7127dd7cddfSDavid du Colombier 	if(fd >= 0)
7137dd7cddfSDavid du Colombier 		print("part %s %lld %lld\n", name, start, end);
7147dd7cddfSDavid du Colombier }
7157dd7cddfSDavid du Colombier 
7167dd7cddfSDavid du Colombier static void
freenamelist(void)7177dd7cddfSDavid du Colombier freenamelist(void)
7187dd7cddfSDavid du Colombier {
7197dd7cddfSDavid du Colombier 	Name *n, *next;
7207dd7cddfSDavid du Colombier 
7217dd7cddfSDavid du Colombier 	for(n=namelist; n; n=next) {
7227dd7cddfSDavid du Colombier 		next = n->link;
7237dd7cddfSDavid du Colombier 		free(n);
7247dd7cddfSDavid du Colombier 	}
7257dd7cddfSDavid du Colombier 	namelist = nil;
7267dd7cddfSDavid du Colombier }
7277dd7cddfSDavid du Colombier 
7287dd7cddfSDavid du Colombier static void
cmdprintctl(Edit * edit,int ctlfd)7297dd7cddfSDavid du Colombier cmdprintctl(Edit *edit, int ctlfd)
7307dd7cddfSDavid du Colombier {
7317dd7cddfSDavid du Colombier 	int i;
7327dd7cddfSDavid du Colombier 
7337dd7cddfSDavid du Colombier 	freenamelist();
7347dd7cddfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
73580ee5cbfSDavid du Colombier 		plan9print((Dospart*)edit->part[i], -1);
7367dd7cddfSDavid du Colombier 	ctldiff(edit, ctlfd);
7377dd7cddfSDavid du Colombier }
7387dd7cddfSDavid du Colombier 
7397dd7cddfSDavid du Colombier static char*
cmdokname(Edit *,char * name)7407dd7cddfSDavid du Colombier cmdokname(Edit*, char *name)
7417dd7cddfSDavid du Colombier {
74280ee5cbfSDavid du Colombier 	char *q;
74380ee5cbfSDavid du Colombier 
74480ee5cbfSDavid du Colombier 	if(name[0] != 'p' && name[0] != 's')
74580ee5cbfSDavid du Colombier 		return "name must be pN or sN";
74680ee5cbfSDavid du Colombier 
74780ee5cbfSDavid du Colombier 	strtol(name+1, &q, 10);
74880ee5cbfSDavid du Colombier 	if(*q != '\0')
74980ee5cbfSDavid du Colombier 		return "name must be pN or sN";
75080ee5cbfSDavid du Colombier 
7517dd7cddfSDavid du Colombier 	return nil;
7527dd7cddfSDavid du Colombier }
7537dd7cddfSDavid du Colombier 
754eba00c11SDavid du Colombier #define TB (1024LL*GB)
7557dd7cddfSDavid du Colombier #define GB (1024*1024*1024)
7567dd7cddfSDavid du Colombier #define MB (1024*1024)
7577dd7cddfSDavid du Colombier #define KB (1024)
7587dd7cddfSDavid du Colombier 
7597dd7cddfSDavid du Colombier static void
cmdsum(Edit * edit,Part * vp,vlong a,vlong b)7607dd7cddfSDavid du Colombier cmdsum(Edit *edit, Part *vp, vlong a, vlong b)
7617dd7cddfSDavid du Colombier {
7627dd7cddfSDavid du Colombier 	char *name, *ty;
7637dd7cddfSDavid du Colombier 	char buf[3];
76480ee5cbfSDavid du Colombier 	char *suf;
7657dd7cddfSDavid du Colombier 	Dospart *p;
76680ee5cbfSDavid du Colombier 	vlong sz, div;
7677dd7cddfSDavid du Colombier 
7687dd7cddfSDavid du Colombier 	p = (Dospart*)vp;
7697dd7cddfSDavid du Colombier 
7707dd7cddfSDavid du Colombier 	buf[0] = p && p->changed ? '\'' : ' ';
7717dd7cddfSDavid du Colombier 	buf[1] = p && (p->active & Active) ? '*' : ' ';
7727dd7cddfSDavid du Colombier 	buf[2] = '\0';
7737dd7cddfSDavid du Colombier 
7747dd7cddfSDavid du Colombier 	name = p ? p->name : "empty";
77580ee5cbfSDavid du Colombier 	ty = p ? typestr0(p->type) : "";
7767dd7cddfSDavid du Colombier 
77780ee5cbfSDavid du Colombier 	sz = (b-a)*edit->disk->secsize*sec2cyl;
778eba00c11SDavid du Colombier 	if(sz >= 1*TB){
779eba00c11SDavid du Colombier 		suf = "TB";
780eba00c11SDavid du Colombier 		div = TB;
781eba00c11SDavid du Colombier 	}else if(sz >= 1*GB){
78280ee5cbfSDavid du Colombier 		suf = "GB";
78380ee5cbfSDavid du Colombier 		div = GB;
78480ee5cbfSDavid du Colombier 	}else if(sz >= 1*MB){
78580ee5cbfSDavid du Colombier 		suf = "MB";
78680ee5cbfSDavid du Colombier 		div = MB;
78780ee5cbfSDavid du Colombier 	}else if(sz >= 1*KB){
78880ee5cbfSDavid du Colombier 		suf = "KB";
78980ee5cbfSDavid du Colombier 		div = KB;
79080ee5cbfSDavid du Colombier 	}else{
79180ee5cbfSDavid du Colombier 		suf = "B ";
79280ee5cbfSDavid du Colombier 		div = 1;
79380ee5cbfSDavid du Colombier 	}
79480ee5cbfSDavid du Colombier 
79580ee5cbfSDavid du Colombier 	if(div == 1)
79680ee5cbfSDavid du Colombier 		print("%s %-12s %*lld %-*lld (%lld cylinders, %lld %s) %s\n", buf, name,
79780ee5cbfSDavid du Colombier 			edit->disk->width, a, edit->disk->width, b, b-a, sz, suf, ty);
79880ee5cbfSDavid du Colombier 	else
79980ee5cbfSDavid du Colombier 		print("%s %-12s %*lld %-*lld (%lld cylinders, %lld.%.2d %s) %s\n", buf, name,
80080ee5cbfSDavid du Colombier 			edit->disk->width, a, edit->disk->width, b,  b-a,
80180ee5cbfSDavid du Colombier 			sz/div, (int)(((sz%div)*100)/div), suf, ty);
8027dd7cddfSDavid du Colombier }
8037dd7cddfSDavid du Colombier 
8047dd7cddfSDavid du Colombier static char*
cmdadd(Edit * edit,char * name,vlong start,vlong end)8057dd7cddfSDavid du Colombier cmdadd(Edit *edit, char *name, vlong start, vlong end)
8067dd7cddfSDavid du Colombier {
80780ee5cbfSDavid du Colombier 	Dospart *p;
8087dd7cddfSDavid du Colombier 
80980ee5cbfSDavid du Colombier 	if(!haveroom(edit, name[0]=='p', start))
81080ee5cbfSDavid du Colombier 		return "no room for partition";
8119a747e4fSDavid du Colombier 	start *= sec2cyl;
8129a747e4fSDavid du Colombier 	end *= sec2cyl;
8136b6b9ac8SDavid du Colombier 	if(start == 0 || name[0] != 'p')
8146b6b9ac8SDavid du Colombier 		start += edit->disk->s;
8159a747e4fSDavid du Colombier 	p = mkpart(name, name[0]=='p', start, end-start, nil);
81680ee5cbfSDavid du Colombier 	p->changed = 1;
817d9dc5dd1SDavid du Colombier 	p->type = Type9;
81880ee5cbfSDavid du Colombier 	return addpart(edit, p);
8197dd7cddfSDavid du Colombier }
8207dd7cddfSDavid du Colombier 
8217dd7cddfSDavid du Colombier static char*
cmddel(Edit * edit,Part * p)8227dd7cddfSDavid du Colombier cmddel(Edit *edit, Part *p)
8237dd7cddfSDavid du Colombier {
82480ee5cbfSDavid du Colombier 	return delpart(edit, p);
8257dd7cddfSDavid du Colombier }
8267dd7cddfSDavid du Colombier 
8277dd7cddfSDavid du Colombier static char*
cmdwrite(Edit * edit)8287dd7cddfSDavid du Colombier cmdwrite(Edit *edit)
8297dd7cddfSDavid du Colombier {
8307dd7cddfSDavid du Colombier 	wrpart(edit);
8317dd7cddfSDavid du Colombier 	return nil;
8327dd7cddfSDavid du Colombier }
8337dd7cddfSDavid du Colombier 
8347dd7cddfSDavid du Colombier static char *help =
8357dd7cddfSDavid du Colombier 	"A name - set partition active\n"
8367dd7cddfSDavid du Colombier 	"P - print table in ctl format\n"
8376b6b9ac8SDavid du Colombier 	"R - restore disk back to initial configuration and exit\n"
8387dd7cddfSDavid du Colombier 	"e - show empty dos partitions\n"
8397dd7cddfSDavid du Colombier 	"t name [type] - set partition type\n";
8407dd7cddfSDavid du Colombier 
8417dd7cddfSDavid du Colombier static char*
cmdhelp(Edit *)8427dd7cddfSDavid du Colombier cmdhelp(Edit*)
8437dd7cddfSDavid du Colombier {
8447dd7cddfSDavid du Colombier 	print("%s\n", help);
8457dd7cddfSDavid du Colombier 	return nil;
8467dd7cddfSDavid du Colombier }
8477dd7cddfSDavid du Colombier 
8487dd7cddfSDavid du Colombier static char*
cmdactive(Edit * edit,int nf,char ** f)8497dd7cddfSDavid du Colombier cmdactive(Edit *edit, int nf, char **f)
8507dd7cddfSDavid du Colombier {
8517dd7cddfSDavid du Colombier 	int i;
85280ee5cbfSDavid du Colombier 	Dospart *p, *ip;
8537dd7cddfSDavid du Colombier 
8547dd7cddfSDavid du Colombier 	if(nf != 2)
8557dd7cddfSDavid du Colombier 		return "args";
8567dd7cddfSDavid du Colombier 
8579a747e4fSDavid du Colombier 	if(f[1][0] != 'p')
8589a747e4fSDavid du Colombier 		return "cannot set secondary partition active";
8599a747e4fSDavid du Colombier 
86080ee5cbfSDavid du Colombier 	if((p = (Dospart*)findpart(edit, f[1])) == nil)
86180ee5cbfSDavid du Colombier 		return "unknown partition";
8627dd7cddfSDavid du Colombier 
86380ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart; i++) {
86480ee5cbfSDavid du Colombier 		ip = (Dospart*)edit->part[i];
86580ee5cbfSDavid du Colombier 		if(ip->active & Active) {
86680ee5cbfSDavid du Colombier 			ip->active &= ~Active;
86780ee5cbfSDavid du Colombier 			ip->changed = 1;
8687dd7cddfSDavid du Colombier 			edit->changed = 1;
8697dd7cddfSDavid du Colombier 		}
8707dd7cddfSDavid du Colombier 	}
87180ee5cbfSDavid du Colombier 
8727dd7cddfSDavid du Colombier 	if((p->active & Active) == 0) {
8737dd7cddfSDavid du Colombier 		p->active |= Active;
8747dd7cddfSDavid du Colombier 		p->changed = 1;
8757dd7cddfSDavid du Colombier 		edit->changed = 1;
8767dd7cddfSDavid du Colombier 	}
8777dd7cddfSDavid du Colombier 
8787dd7cddfSDavid du Colombier 	return nil;
8797dd7cddfSDavid du Colombier }
8807dd7cddfSDavid du Colombier 
8817dd7cddfSDavid du Colombier static char*
strupr(char * s)8827dd7cddfSDavid du Colombier strupr(char *s)
8837dd7cddfSDavid du Colombier {
8847dd7cddfSDavid du Colombier 	char *p;
8857dd7cddfSDavid du Colombier 
8867dd7cddfSDavid du Colombier 	for(p=s; *p; p++)
8877dd7cddfSDavid du Colombier 		*p = toupper(*p);
8887dd7cddfSDavid du Colombier 	return s;
8897dd7cddfSDavid du Colombier }
8907dd7cddfSDavid du Colombier 
8917dd7cddfSDavid du Colombier static void
dumplist(void)8927dd7cddfSDavid du Colombier dumplist(void)
8937dd7cddfSDavid du Colombier {
8947dd7cddfSDavid du Colombier 	int i, n;
8957dd7cddfSDavid du Colombier 
8967dd7cddfSDavid du Colombier 	n = 0;
8977dd7cddfSDavid du Colombier 	for(i=0; i<256; i++) {
8987dd7cddfSDavid du Colombier 		if(types[i].desc) {
8997dd7cddfSDavid du Colombier 			print("%-16s", types[i].desc);
9007dd7cddfSDavid du Colombier 			if(n++%4 == 3)
9017dd7cddfSDavid du Colombier 				print("\n");
9027dd7cddfSDavid du Colombier 		}
9037dd7cddfSDavid du Colombier 	}
9047dd7cddfSDavid du Colombier 	if(n%4)
9057dd7cddfSDavid du Colombier 		print("\n");
9067dd7cddfSDavid du Colombier }
9077dd7cddfSDavid du Colombier 
9087dd7cddfSDavid du Colombier static char*
cmdtype(Edit * edit,int nf,char ** f)9097dd7cddfSDavid du Colombier cmdtype(Edit *edit, int nf, char **f)
9107dd7cddfSDavid du Colombier {
9117dd7cddfSDavid du Colombier 	char *q;
9127dd7cddfSDavid du Colombier 	Dospart *p;
9137dd7cddfSDavid du Colombier 	int i;
9147dd7cddfSDavid du Colombier 
9157dd7cddfSDavid du Colombier 	if(nf < 2)
9167dd7cddfSDavid du Colombier 		return "args";
9177dd7cddfSDavid du Colombier 
9187dd7cddfSDavid du Colombier 	if((p = (Dospart*)findpart(edit, f[1])) == nil)
9197dd7cddfSDavid du Colombier 		return "unknown partition";
9207dd7cddfSDavid du Colombier 
9217dd7cddfSDavid du Colombier 	if(nf == 2) {
9227dd7cddfSDavid du Colombier 		for(;;) {
9237dd7cddfSDavid du Colombier 			fprint(2, "new partition type [? for list]: ");
9247dd7cddfSDavid du Colombier 			q = getline(edit);
9257dd7cddfSDavid du Colombier 			if(q[0] == '?')
9267dd7cddfSDavid du Colombier 				dumplist();
9277dd7cddfSDavid du Colombier 			else
9287dd7cddfSDavid du Colombier 				break;
9297dd7cddfSDavid du Colombier 		}
9307dd7cddfSDavid du Colombier 	} else
9317dd7cddfSDavid du Colombier 		q = f[2];
9327dd7cddfSDavid du Colombier 
9337dd7cddfSDavid du Colombier 	strupr(q);
9347dd7cddfSDavid du Colombier 	for(i=0; i<256; i++)
9357dd7cddfSDavid du Colombier 		if(types[i].desc && strcmp(types[i].desc, q) == 0)
9367dd7cddfSDavid du Colombier 			break;
9377dd7cddfSDavid du Colombier 	if(i < 256 && p->type != i) {
9387dd7cddfSDavid du Colombier 		p->type = i;
9397dd7cddfSDavid du Colombier 		p->changed = 1;
9407dd7cddfSDavid du Colombier 		edit->changed = 1;
9417dd7cddfSDavid du Colombier 	}
9427dd7cddfSDavid du Colombier 	return nil;
9437dd7cddfSDavid du Colombier }
9447dd7cddfSDavid du Colombier 
9457dd7cddfSDavid du Colombier static char*
cmdext(Edit * edit,int nf,char ** f)9467dd7cddfSDavid du Colombier cmdext(Edit *edit, int nf, char **f)
9477dd7cddfSDavid du Colombier {
9487dd7cddfSDavid du Colombier 	switch(f[0][0]) {
9497dd7cddfSDavid du Colombier 	case 'A':
9507dd7cddfSDavid du Colombier 		return cmdactive(edit, nf, f);
9517dd7cddfSDavid du Colombier 	case 't':
9527dd7cddfSDavid du Colombier 		return cmdtype(edit, nf, f);
95380ee5cbfSDavid du Colombier 	case 'R':
95480ee5cbfSDavid du Colombier 		recover(edit);
95580ee5cbfSDavid du Colombier 		return nil;
9567dd7cddfSDavid du Colombier 	default:
9577dd7cddfSDavid du Colombier 		return "unknown command";
9587dd7cddfSDavid du Colombier 	}
9597dd7cddfSDavid du Colombier }
9607dd7cddfSDavid du Colombier 
96180ee5cbfSDavid du Colombier static int
Dfmt(Fmt * f)9629a747e4fSDavid du Colombier Dfmt(Fmt *f)
96380ee5cbfSDavid du Colombier {
96480ee5cbfSDavid du Colombier 	char buf[60];
96580ee5cbfSDavid du Colombier 	uchar *p;
96680ee5cbfSDavid du Colombier 	int c, h, s;
96780ee5cbfSDavid du Colombier 
9689a747e4fSDavid du Colombier 	p = va_arg(f->args, uchar*);
96980ee5cbfSDavid du Colombier 	h = p[0];
97080ee5cbfSDavid du Colombier 	c = p[2];
97180ee5cbfSDavid du Colombier 	c |= (p[1]&0xC0)<<2;
97280ee5cbfSDavid du Colombier 	s = (p[1] & 0x3F);
97380ee5cbfSDavid du Colombier 
97480ee5cbfSDavid du Colombier 	sprint(buf, "%d/%d/%d", c, h, s);
9759a747e4fSDavid du Colombier 	return fmtstrcpy(f, buf);
97680ee5cbfSDavid du Colombier }
97780ee5cbfSDavid du Colombier 
97880ee5cbfSDavid du Colombier static void
writechs(Disk * disk,uchar * p,vlong lba)97980ee5cbfSDavid du Colombier writechs(Disk *disk, uchar *p, vlong lba)
98080ee5cbfSDavid du Colombier {
98180ee5cbfSDavid du Colombier 	int c, h, s;
98280ee5cbfSDavid du Colombier 
98380ee5cbfSDavid du Colombier 	s = lba % disk->s;
98480ee5cbfSDavid du Colombier 	h = (lba / disk->s) % disk->h;
98580ee5cbfSDavid du Colombier 	c = lba / (disk->s * disk->h);
98680ee5cbfSDavid du Colombier 
98780ee5cbfSDavid du Colombier 	if(c >= 1024) {
98880ee5cbfSDavid du Colombier 		c = 1023;
98980ee5cbfSDavid du Colombier 		h = disk->h - 1;
99080ee5cbfSDavid du Colombier 		s = disk->s - 1;
99180ee5cbfSDavid du Colombier 	}
99280ee5cbfSDavid du Colombier 
99380ee5cbfSDavid du Colombier 	p[0] = h;
99480ee5cbfSDavid du Colombier 	p[1] = ((s+1) & 0x3F) | ((c>>2) & 0xC0);
99580ee5cbfSDavid du Colombier 	p[2] = c;
99680ee5cbfSDavid du Colombier }
99780ee5cbfSDavid du Colombier 
99880ee5cbfSDavid du Colombier static void
wrtentry(Disk * disk,Tentry * tp,int type,u32int xbase,u32int lba,u32int end)9999a747e4fSDavid du Colombier wrtentry(Disk *disk, Tentry *tp, int type, u32int xbase, u32int lba, u32int end)
100080ee5cbfSDavid du Colombier {
100180ee5cbfSDavid du Colombier 	tp->type = type;
10029a747e4fSDavid du Colombier 	writechs(disk, &tp->starth, lba);
10039a747e4fSDavid du Colombier 	writechs(disk, &tp->endh, end-1);
10049a747e4fSDavid du Colombier 	putle32(tp->xlba, lba-xbase);
10059a747e4fSDavid du Colombier 	putle32(tp->xsize, end-lba);
100680ee5cbfSDavid du Colombier }
100780ee5cbfSDavid du Colombier 
100880ee5cbfSDavid du Colombier static int
wrextend(Edit * edit,int i,vlong xbase,vlong startlba,vlong * endlba)10099a747e4fSDavid du Colombier wrextend(Edit *edit, int i, vlong xbase, vlong startlba, vlong *endlba)
101080ee5cbfSDavid du Colombier {
101180ee5cbfSDavid du Colombier 	int ni;
101280ee5cbfSDavid du Colombier 	Table table;
101380ee5cbfSDavid du Colombier 	Tentry *tp, *ep;
101480ee5cbfSDavid du Colombier 	Dospart *p;
101580ee5cbfSDavid du Colombier 	Disk *disk;
101680ee5cbfSDavid du Colombier 
10179a747e4fSDavid du Colombier 	if(i == edit->npart){
10189a747e4fSDavid du Colombier 		*endlba = edit->disk->secs;
10199a747e4fSDavid du Colombier 	Finish:
10209a747e4fSDavid du Colombier 		if(startlba < *endlba){
10219a747e4fSDavid du Colombier 			disk = edit->disk;
1022*9e732705SDavid du Colombier 			diskread(disk, &table, Tablesz, mbroffset+startlba, Toffset);
10239a747e4fSDavid du Colombier 			tp = table.entry;
10249a747e4fSDavid du Colombier 			ep = tp+NTentry;
10259a747e4fSDavid du Colombier 			for(; tp<ep; tp++)
10269a747e4fSDavid du Colombier 				memset(tp, 0, sizeof *tp);
10279a747e4fSDavid du Colombier 			table.magic[0] = Magic0;
10289a747e4fSDavid du Colombier 			table.magic[1] = Magic1;
10299a747e4fSDavid du Colombier 
1030*9e732705SDavid du Colombier 			if(diskwrite(edit->disk, &table, Tablesz, mbroffset+startlba, Toffset) < 0)
10319a747e4fSDavid du Colombier 				recover(edit);
10329a747e4fSDavid du Colombier 		}
103380ee5cbfSDavid du Colombier 		return i;
10349a747e4fSDavid du Colombier 	}
103580ee5cbfSDavid du Colombier 
103680ee5cbfSDavid du Colombier 	p = (Dospart*)edit->part[i];
10379a747e4fSDavid du Colombier 	if(p->primary){
10389a747e4fSDavid du Colombier 		*endlba = (vlong)p->start*sec2cyl;
10399a747e4fSDavid du Colombier 		goto Finish;
10409a747e4fSDavid du Colombier 	}
104180ee5cbfSDavid du Colombier 
104280ee5cbfSDavid du Colombier 	disk = edit->disk;
1043*9e732705SDavid du Colombier 	diskread(disk, &table, Tablesz, mbroffset+startlba, Toffset);
104480ee5cbfSDavid du Colombier 	tp = table.entry;
104580ee5cbfSDavid du Colombier 	ep = tp+NTentry;
104680ee5cbfSDavid du Colombier 
10479a747e4fSDavid du Colombier 	ni = wrextend(edit, i+1, xbase, p->end*sec2cyl, endlba);
104880ee5cbfSDavid du Colombier 
104980ee5cbfSDavid du Colombier 	*tp = p->Tentry;
10509a747e4fSDavid du Colombier 	wrtentry(disk, tp, p->type, startlba, startlba+disk->s, p->end*sec2cyl);
105180ee5cbfSDavid du Colombier 	tp++;
105280ee5cbfSDavid du Colombier 
10539a747e4fSDavid du Colombier 	if(p->end*sec2cyl != *endlba){
105480ee5cbfSDavid du Colombier 		memset(tp, 0, sizeof *tp);
10559a747e4fSDavid du Colombier 		wrtentry(disk, tp, TypeEXTENDED, xbase, p->end*sec2cyl, *endlba);
105680ee5cbfSDavid du Colombier 		tp++;
105780ee5cbfSDavid du Colombier 	}
105880ee5cbfSDavid du Colombier 
105980ee5cbfSDavid du Colombier 	for(; tp<ep; tp++)
106080ee5cbfSDavid du Colombier 		memset(tp, 0, sizeof *tp);
106180ee5cbfSDavid du Colombier 
106280ee5cbfSDavid du Colombier 	table.magic[0] = Magic0;
106380ee5cbfSDavid du Colombier 	table.magic[1] = Magic1;
106480ee5cbfSDavid du Colombier 
1065*9e732705SDavid du Colombier 	if(diskwrite(edit->disk, &table, Tablesz, mbroffset+startlba, Toffset) < 0)
106680ee5cbfSDavid du Colombier 		recover(edit);
106780ee5cbfSDavid du Colombier 	return ni;
106880ee5cbfSDavid du Colombier }
106980ee5cbfSDavid du Colombier 
107080ee5cbfSDavid du Colombier static void
wrpart(Edit * edit)107180ee5cbfSDavid du Colombier wrpart(Edit *edit)
107280ee5cbfSDavid du Colombier {
10739a747e4fSDavid du Colombier 	int i, ni, t;
107480ee5cbfSDavid du Colombier 	Table table;
107580ee5cbfSDavid du Colombier 	Tentry *tp, *ep;
107680ee5cbfSDavid du Colombier 	Disk *disk;
107780ee5cbfSDavid du Colombier 	vlong s, endlba;
107880ee5cbfSDavid du Colombier 	Dospart *p;
107980ee5cbfSDavid du Colombier 
108080ee5cbfSDavid du Colombier 	disk = edit->disk;
108180ee5cbfSDavid du Colombier 
1082*9e732705SDavid du Colombier 	diskread(disk, &table, Tablesz, mbroffset, Toffset);
108380ee5cbfSDavid du Colombier 
108480ee5cbfSDavid du Colombier 	tp = table.entry;
108580ee5cbfSDavid du Colombier 	ep = tp+NTentry;
108680ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart && tp<ep; ) {
108780ee5cbfSDavid du Colombier 		p = (Dospart*)edit->part[i];
108880ee5cbfSDavid du Colombier 		if(p->start == 0)
108980ee5cbfSDavid du Colombier 			s = disk->s;
109080ee5cbfSDavid du Colombier 		else
109180ee5cbfSDavid du Colombier 			s = p->start*sec2cyl;
109280ee5cbfSDavid du Colombier 		if(p->primary) {
109380ee5cbfSDavid du Colombier 			*tp = p->Tentry;
10949a747e4fSDavid du Colombier 			wrtentry(disk, tp, p->type, 0, s, p->end*sec2cyl);
109580ee5cbfSDavid du Colombier 			tp++;
109680ee5cbfSDavid du Colombier 			i++;
109780ee5cbfSDavid du Colombier 		} else {
10989a747e4fSDavid du Colombier 			ni = wrextend(edit, i, p->start*sec2cyl, p->start*sec2cyl, &endlba);
109980ee5cbfSDavid du Colombier 			memset(tp, 0, sizeof *tp);
11009a747e4fSDavid du Colombier 			if(endlba >= 1024*sec2cyl)
11019a747e4fSDavid du Colombier 				t = TypeEXTHUGE;
11029a747e4fSDavid du Colombier 			else
11039a747e4fSDavid du Colombier 				t = TypeEXTENDED;
11049a747e4fSDavid du Colombier 			wrtentry(disk, tp, t, 0, s, endlba);
110580ee5cbfSDavid du Colombier 			tp++;
110680ee5cbfSDavid du Colombier 			i = ni;
110780ee5cbfSDavid du Colombier 		}
110880ee5cbfSDavid du Colombier 	}
110980ee5cbfSDavid du Colombier 	for(; tp<ep; tp++)
111080ee5cbfSDavid du Colombier 		memset(tp, 0, sizeof(*tp));
111180ee5cbfSDavid du Colombier 
111280ee5cbfSDavid du Colombier 	if(i != edit->npart)
111380ee5cbfSDavid du Colombier 		sysfatal("cannot happen #1");
111480ee5cbfSDavid du Colombier 
1115*9e732705SDavid du Colombier 	if(diskwrite(disk, &table, Tablesz, mbroffset, Toffset) < 0)
111680ee5cbfSDavid du Colombier 		recover(edit);
111780ee5cbfSDavid du Colombier 
111880ee5cbfSDavid du Colombier 	/* bring parts up to date */
111980ee5cbfSDavid du Colombier 	freenamelist();
112080ee5cbfSDavid du Colombier 	for(i=0; i<edit->npart; i++)
112180ee5cbfSDavid du Colombier 		plan9print((Dospart*)edit->part[i], -1);
112280ee5cbfSDavid du Colombier 
112380ee5cbfSDavid du Colombier 	if(ctldiff(edit, disk->ctlfd) < 0)
112480ee5cbfSDavid du Colombier 		fprint(2, "?warning: partitions could not be updated in devsd\n");
112580ee5cbfSDavid du Colombier }
1126