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 179a747e4fSDavid du Colombier static void rdpart(Edit*, ulong, ulong); 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 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 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 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 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 1957dd7cddfSDavid du Colombier enum { 1967dd7cddfSDavid du Colombier Active = 0x80, /* partition is active */ 1977dd7cddfSDavid du Colombier Primary = 0x01, /* internal flag */ 1987dd7cddfSDavid du Colombier 1997dd7cddfSDavid du Colombier TypeBB = 0xFF, 2007dd7cddfSDavid du Colombier 2017dd7cddfSDavid du Colombier TypeEMPTY = 0x00, 2027dd7cddfSDavid du Colombier TypeFAT12 = 0x01, 2037dd7cddfSDavid du Colombier TypeXENIX = 0x02, /* root */ 2047dd7cddfSDavid du Colombier TypeXENIXUSR = 0x03, /* usr */ 2057dd7cddfSDavid du Colombier TypeFAT16 = 0x04, 2067dd7cddfSDavid du Colombier TypeEXTENDED = 0x05, 2077dd7cddfSDavid du Colombier TypeFATHUGE = 0x06, 2087dd7cddfSDavid du Colombier TypeHPFS = 0x07, 2097dd7cddfSDavid du Colombier TypeAIXBOOT = 0x08, 2107dd7cddfSDavid du Colombier TypeAIXDATA = 0x09, 2117dd7cddfSDavid du Colombier TypeOS2BOOT = 0x0A, /* OS/2 Boot Manager */ 2127dd7cddfSDavid du Colombier TypeFAT32 = 0x0B, /* FAT 32 */ 2137dd7cddfSDavid du Colombier TypeFAT32LBA = 0x0C, /* FAT 32 needing LBA support */ 2147dd7cddfSDavid du Colombier TypeEXTHUGE = 0x0F, /* FAT 32 extended partition */ 2157dd7cddfSDavid du Colombier TypeUNFORMATTED = 0x16, /* unformatted primary partition (OS/2 FDISK)? */ 2167dd7cddfSDavid du Colombier TypeHPFS2 = 0x17, 2176b6b9ac8SDavid du Colombier TypeIBMRecovery = 0x1C, /* really hidden fat */ 2187dd7cddfSDavid du Colombier TypeCPM0 = 0x52, 2197dd7cddfSDavid du Colombier TypeDMDDO = 0x54, /* Disk Manager Dynamic Disk Overlay */ 2207dd7cddfSDavid du Colombier TypeGB = 0x56, /* ???? */ 2217dd7cddfSDavid du Colombier TypeSPEEDSTOR = 0x61, 2227dd7cddfSDavid du Colombier TypeSYSV386 = 0x63, /* also HURD? */ 2237dd7cddfSDavid du Colombier TypeNETWARE = 0x64, 2247dd7cddfSDavid du Colombier TypePCIX = 0x75, 2257dd7cddfSDavid du Colombier TypeMINIX13 = 0x80, /* Minix v1.3 and below */ 2267dd7cddfSDavid du Colombier TypeMINIX = 0x81, /* Minix v1.5+ */ 2277dd7cddfSDavid du Colombier TypeLINUXSWAP = 0x82, 2287dd7cddfSDavid du Colombier TypeLINUX = 0x83, 2299a747e4fSDavid du Colombier TypeLINUXEXT = 0x85, 2307dd7cddfSDavid du Colombier TypeAMOEBA = 0x93, 2317dd7cddfSDavid du Colombier TypeAMOEBABB = 0x94, 2327dd7cddfSDavid du Colombier TypeBSD386 = 0xA5, 2337dd7cddfSDavid du Colombier TypeBSDI = 0xB7, 2347dd7cddfSDavid du Colombier TypeBSDISWAP = 0xB8, 23580ee5cbfSDavid du Colombier TypeOTHER = 0xDA, 2367dd7cddfSDavid du Colombier TypeCPM = 0xDB, 237*65fa3f8bSDavid du Colombier TypeDellRecovery = 0xDE, 2387dd7cddfSDavid du Colombier TypeSPEEDSTOR12 = 0xE1, 2397dd7cddfSDavid du Colombier TypeSPEEDSTOR16 = 0xE4, 2407dd7cddfSDavid du Colombier TypeLANSTEP = 0xFE, 2417dd7cddfSDavid du Colombier 2427dd7cddfSDavid du Colombier Type9 = 0x39, 2437dd7cddfSDavid du Colombier 2447dd7cddfSDavid du Colombier Toffset = 446, /* offset of partition table in sector */ 2457dd7cddfSDavid du Colombier Magic0 = 0x55, 2467dd7cddfSDavid du Colombier Magic1 = 0xAA, 2477dd7cddfSDavid du Colombier }; 2487dd7cddfSDavid du Colombier 2497dd7cddfSDavid du Colombier struct Table { 2507dd7cddfSDavid du Colombier Tentry entry[NTentry]; 2517dd7cddfSDavid du Colombier uchar magic[2]; 2527dd7cddfSDavid du Colombier }; 2537dd7cddfSDavid du Colombier 2547dd7cddfSDavid du Colombier struct Type { 2557dd7cddfSDavid du Colombier char *desc; 2567dd7cddfSDavid du Colombier char *name; 2577dd7cddfSDavid du Colombier }; 2587dd7cddfSDavid du Colombier 25980ee5cbfSDavid du Colombier struct Dospart { 26080ee5cbfSDavid du Colombier Part; 2617dd7cddfSDavid du Colombier Tentry; 2627dd7cddfSDavid du Colombier 2637dd7cddfSDavid du Colombier u32int lba; 2647dd7cddfSDavid du Colombier u32int size; 26580ee5cbfSDavid du Colombier int primary; 2667dd7cddfSDavid du Colombier }; 2677dd7cddfSDavid du Colombier 26880ee5cbfSDavid du Colombier struct Recover { 26980ee5cbfSDavid du Colombier Table table; 27080ee5cbfSDavid du Colombier ulong lba; 2717dd7cddfSDavid du Colombier }; 2727dd7cddfSDavid du Colombier 2737dd7cddfSDavid du Colombier static Type types[256] = { 2747dd7cddfSDavid du Colombier [TypeEMPTY] { "EMPTY", "" }, 2757dd7cddfSDavid du Colombier [TypeFAT12] { "FAT12", "dos" }, 2767dd7cddfSDavid du Colombier [TypeFAT16] { "FAT16", "dos" }, 2777dd7cddfSDavid du Colombier [TypeFAT32] { "FAT32", "dos" }, 2787dd7cddfSDavid du Colombier [TypeFAT32LBA] { "FAT32LBA", "dos" }, 2797dd7cddfSDavid du Colombier [TypeEXTHUGE] { "EXTHUGE", "" }, 2806b6b9ac8SDavid du Colombier [TypeIBMRecovery] { "IBMRECOVERY", "ibm" }, 2817dd7cddfSDavid du Colombier [TypeEXTENDED] { "EXTENDED", "" }, 2827dd7cddfSDavid du Colombier [TypeFATHUGE] { "FATHUGE", "dos" }, 2837dd7cddfSDavid du Colombier [TypeBB] { "BB", "bb" }, 2847dd7cddfSDavid du Colombier 2857dd7cddfSDavid du Colombier [TypeXENIX] { "XENIX", "xenix" }, 2867dd7cddfSDavid du Colombier [TypeXENIXUSR] { "XENIX USR", "xenixusr" }, 2877dd7cddfSDavid du Colombier [TypeHPFS] { "HPFS", "ntfs" }, 2887dd7cddfSDavid du Colombier [TypeAIXBOOT] { "AIXBOOT", "aixboot" }, 2897dd7cddfSDavid du Colombier [TypeAIXDATA] { "AIXDATA", "aixdata" }, 2907dd7cddfSDavid du Colombier [TypeOS2BOOT] { "OS/2BOOT", "os2boot" }, 2917dd7cddfSDavid du Colombier [TypeUNFORMATTED] { "UNFORMATTED", "" }, 2927dd7cddfSDavid du Colombier [TypeHPFS2] { "HPFS2", "hpfs2" }, 2937dd7cddfSDavid du Colombier [TypeCPM0] { "CPM0", "cpm0" }, 2947dd7cddfSDavid du Colombier [TypeDMDDO] { "DMDDO", "dmdd0" }, 2957dd7cddfSDavid du Colombier [TypeGB] { "GB", "gb" }, 2967dd7cddfSDavid du Colombier [TypeSPEEDSTOR] { "SPEEDSTOR", "speedstor" }, 2977dd7cddfSDavid du Colombier [TypeSYSV386] { "SYSV386", "sysv386" }, 2987dd7cddfSDavid du Colombier [TypeNETWARE] { "NETWARE", "netware" }, 2997dd7cddfSDavid du Colombier [TypePCIX] { "PCIX", "pcix" }, 3007dd7cddfSDavid du Colombier [TypeMINIX13] { "MINIXV1.3", "minix13" }, 3017dd7cddfSDavid du Colombier [TypeMINIX] { "MINIXV1.5", "minix15" }, 3027dd7cddfSDavid du Colombier [TypeLINUXSWAP] { "LINUXSWAP", "linuxswap" }, 3037dd7cddfSDavid du Colombier [TypeLINUX] { "LINUX", "linux" }, 3049a747e4fSDavid du Colombier [TypeLINUXEXT] { "LINUXEXTENDED", "" }, 3057dd7cddfSDavid du Colombier [TypeAMOEBA] { "AMOEBA", "amoeba" }, 3067dd7cddfSDavid du Colombier [TypeAMOEBABB] { "AMOEBABB", "amoebaboot" }, 3077dd7cddfSDavid du Colombier [TypeBSD386] { "BSD386", "bsd386" }, 3087dd7cddfSDavid du Colombier [TypeBSDI] { "BSDI", "bsdi" }, 3097dd7cddfSDavid du Colombier [TypeBSDISWAP] { "BSDISWAP", "bsdiswap" }, 31080ee5cbfSDavid du Colombier [TypeOTHER] { "OTHER", "other" }, 3117dd7cddfSDavid du Colombier [TypeCPM] { "CPM", "cpm" }, 312*65fa3f8bSDavid du Colombier [TypeDellRecovery] { "DELLRECOVERY", "dell" }, 3137dd7cddfSDavid du Colombier [TypeSPEEDSTOR12] { "SPEEDSTOR12", "speedstor" }, 3147dd7cddfSDavid du Colombier [TypeSPEEDSTOR16] { "SPEEDSTOR16", "speedstor" }, 3157dd7cddfSDavid du Colombier [TypeLANSTEP] { "LANSTEP", "lanstep" }, 3167dd7cddfSDavid du Colombier 3177dd7cddfSDavid du Colombier [Type9] { "PLAN9", "plan9" }, 3187dd7cddfSDavid du Colombier }; 3197dd7cddfSDavid du Colombier 32080ee5cbfSDavid du Colombier static Dospart part[Mpart]; 32180ee5cbfSDavid du Colombier static int npart; 32280ee5cbfSDavid du Colombier 3237dd7cddfSDavid du Colombier static char* 32480ee5cbfSDavid du Colombier typestr0(int type) 3257dd7cddfSDavid du Colombier { 3267dd7cddfSDavid du Colombier static char buf[100]; 3277dd7cddfSDavid du Colombier 3287dd7cddfSDavid du Colombier sprint(buf, "type %d", type); 3297dd7cddfSDavid du Colombier if(type < 0 || type >= 256) 3307dd7cddfSDavid du Colombier return buf; 3317dd7cddfSDavid du Colombier if(types[type].desc == nil) 3327dd7cddfSDavid du Colombier return buf; 3337dd7cddfSDavid du Colombier return types[type].desc; 3347dd7cddfSDavid du Colombier } 3357dd7cddfSDavid du Colombier 3367dd7cddfSDavid du Colombier static u32int 3377dd7cddfSDavid du Colombier getle32(void* v) 3387dd7cddfSDavid du Colombier { 3397dd7cddfSDavid du Colombier uchar *p; 3407dd7cddfSDavid du Colombier 3417dd7cddfSDavid du Colombier p = v; 3427dd7cddfSDavid du Colombier return (p[3]<<24)|(p[2]<<16)|(p[1]<<8)|p[0]; 3437dd7cddfSDavid du Colombier } 3447dd7cddfSDavid du Colombier 3457dd7cddfSDavid du Colombier static void 3467dd7cddfSDavid du Colombier putle32(void* v, u32int i) 3477dd7cddfSDavid du Colombier { 3487dd7cddfSDavid du Colombier uchar *p; 3497dd7cddfSDavid du Colombier 3507dd7cddfSDavid du Colombier p = v; 3517dd7cddfSDavid du Colombier p[0] = i; 3527dd7cddfSDavid du Colombier p[1] = i>>8; 3537dd7cddfSDavid du Colombier p[2] = i>>16; 3547dd7cddfSDavid du Colombier p[3] = i>>24; 3557dd7cddfSDavid du Colombier } 3567dd7cddfSDavid du Colombier 35780ee5cbfSDavid du Colombier static void 35880ee5cbfSDavid du Colombier diskread(Disk *disk, void *data, int ndata, u32int sec, u32int off) 3597dd7cddfSDavid du Colombier { 3609a747e4fSDavid du Colombier if(seek(disk->fd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off) 36180ee5cbfSDavid du Colombier sysfatal("diskread seek %lud.%lud: %r", (ulong)sec, (ulong)off); 36280ee5cbfSDavid du Colombier if(readn(disk->fd, data, ndata) != ndata) 36380ee5cbfSDavid du Colombier sysfatal("diskread %lud at %lud.%lud: %r", (ulong)ndata, (ulong)sec, (ulong)off); 36480ee5cbfSDavid du Colombier } 3657dd7cddfSDavid du Colombier 36680ee5cbfSDavid du Colombier static int 36780ee5cbfSDavid du Colombier diskwrite(Disk *disk, void *data, int ndata, u32int sec, u32int off) 36880ee5cbfSDavid du Colombier { 36980ee5cbfSDavid du Colombier written = 1; 3709a747e4fSDavid du Colombier if(seek(disk->wfd, (vlong)sec*disk->secsize+off, 0) != (vlong)sec*disk->secsize+off) 37180ee5cbfSDavid du Colombier goto Error; 37280ee5cbfSDavid du Colombier if(write(disk->wfd, data, ndata) != ndata) 37380ee5cbfSDavid du Colombier goto Error; 37480ee5cbfSDavid du Colombier return 0; 3757dd7cddfSDavid du Colombier 37680ee5cbfSDavid du Colombier Error: 37780ee5cbfSDavid du Colombier fprint(2, "write %d bytes at %lud.%lud failed: %r\n", ndata, (ulong)sec, (ulong)off); 37880ee5cbfSDavid du Colombier return -1; 3797dd7cddfSDavid du Colombier } 3807dd7cddfSDavid du Colombier 3817dd7cddfSDavid du Colombier static Dospart* 38280ee5cbfSDavid du Colombier mkpart(char *name, int primary, u32int lba, u32int size, Tentry *t) 3837dd7cddfSDavid du Colombier { 38480ee5cbfSDavid du Colombier static int n; 3857dd7cddfSDavid du Colombier Dospart *p; 3867dd7cddfSDavid du Colombier 38780ee5cbfSDavid du Colombier p = emalloc(sizeof(*p)); 38880ee5cbfSDavid du Colombier if(name) 3899a747e4fSDavid du Colombier p->name = estrdup(name); 3909a747e4fSDavid du Colombier else{ 3919a747e4fSDavid du Colombier p->name = emalloc(20); 39280ee5cbfSDavid du Colombier sprint(p->name, "%c%d", primary ? 'p' : 's', ++n); 3939a747e4fSDavid du Colombier } 39480ee5cbfSDavid du Colombier 39580ee5cbfSDavid du Colombier if(t) 39680ee5cbfSDavid du Colombier p->Tentry = *t; 39780ee5cbfSDavid du Colombier else 39880ee5cbfSDavid du Colombier memset(&p->Tentry, 0, sizeof(Tentry)); 39980ee5cbfSDavid du Colombier 4007dd7cddfSDavid du Colombier p->changed = 0; 40180ee5cbfSDavid du Colombier p->start = lba/sec2cyl; 40280ee5cbfSDavid du Colombier p->end = (lba+size)/sec2cyl; 40380ee5cbfSDavid du Colombier p->ctlstart = lba; 40480ee5cbfSDavid du Colombier p->ctlend = lba+size; 40580ee5cbfSDavid du Colombier p->lba = lba; 40680ee5cbfSDavid du Colombier p->size = size; 40780ee5cbfSDavid du Colombier p->primary = primary; 4087dd7cddfSDavid du Colombier return p; 4097dd7cddfSDavid du Colombier } 4107dd7cddfSDavid du Colombier 41180ee5cbfSDavid du Colombier /* 41280ee5cbfSDavid du Colombier * Recovery takes care of remembering what the various tables 41380ee5cbfSDavid du Colombier * looked like when we started, attempting to restore them when 41480ee5cbfSDavid du Colombier * we are finished. 41580ee5cbfSDavid du Colombier */ 41680ee5cbfSDavid du Colombier static Recover *rtab; 41780ee5cbfSDavid du Colombier static int nrtab; 4187dd7cddfSDavid du Colombier 41980ee5cbfSDavid du Colombier static void 42080ee5cbfSDavid du Colombier addrecover(Table t, ulong lba) 42180ee5cbfSDavid du Colombier { 42280ee5cbfSDavid du Colombier if((nrtab%8) == 0) { 42380ee5cbfSDavid du Colombier rtab = realloc(rtab, (nrtab+8)*sizeof(rtab[0])); 42480ee5cbfSDavid du Colombier if(rtab == nil) 42580ee5cbfSDavid du Colombier sysfatal("out of memory"); 4267dd7cddfSDavid du Colombier } 42780ee5cbfSDavid du Colombier rtab[nrtab] = (Recover){t, lba}; 42880ee5cbfSDavid du Colombier nrtab++; 42980ee5cbfSDavid du Colombier } 43080ee5cbfSDavid du Colombier 43180ee5cbfSDavid du Colombier static void 43280ee5cbfSDavid du Colombier recover(Edit *edit) 43380ee5cbfSDavid du Colombier { 43480ee5cbfSDavid du Colombier int err, i, ctlfd; 43580ee5cbfSDavid du Colombier vlong offset; 43680ee5cbfSDavid du Colombier 43780ee5cbfSDavid du Colombier err = 0; 43880ee5cbfSDavid du Colombier for(i=0; i<nrtab; i++) 43980ee5cbfSDavid du Colombier if(diskwrite(edit->disk, &rtab[i].table, sizeof(Table), rtab[i].lba, Toffset) < 0) 44080ee5cbfSDavid du Colombier err = 1; 44180ee5cbfSDavid du Colombier if(err) { 44280ee5cbfSDavid du Colombier fprint(2, "warning: some writes failed during restoration of old partition tables\n"); 44380ee5cbfSDavid du Colombier exits("inconsistent"); 44480ee5cbfSDavid du Colombier } else { 44580ee5cbfSDavid du Colombier fprint(2, "restored old partition tables\n"); 44680ee5cbfSDavid du Colombier } 44780ee5cbfSDavid du Colombier 44880ee5cbfSDavid du Colombier ctlfd = edit->disk->ctlfd; 44980ee5cbfSDavid du Colombier offset = edit->disk->offset; 45080ee5cbfSDavid du Colombier if(ctlfd >= 0){ 45180ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) 4526b6b9ac8SDavid du Colombier if(edit->part[i]->ctlname && fprint(ctlfd, "delpart %s", edit->part[i]->ctlname)<0) 45380ee5cbfSDavid du Colombier fprint(2, "delpart failed: %s: %r", edit->part[i]->ctlname); 45480ee5cbfSDavid du Colombier for(i=0; i<edit->nctlpart; i++) 4556b6b9ac8SDavid du Colombier if(edit->part[i]->name && fprint(ctlfd, "delpart %s", edit->ctlpart[i]->name)<0) 45680ee5cbfSDavid du Colombier fprint(2, "delpart failed: %s: %r", edit->ctlpart[i]->name); 45780ee5cbfSDavid du Colombier for(i=0; i<edit->nctlpart; i++){ 45880ee5cbfSDavid du Colombier if(fprint(ctlfd, "part %s %lld %lld", edit->ctlpart[i]->name, 45980ee5cbfSDavid du Colombier edit->ctlpart[i]->start+offset, edit->ctlpart[i]->end+offset) < 0){ 46080ee5cbfSDavid du Colombier fprint(2, "restored disk partition table but not kernel; reboot\n"); 46180ee5cbfSDavid du Colombier exits("inconsistent"); 46280ee5cbfSDavid du Colombier } 46380ee5cbfSDavid du Colombier } 46480ee5cbfSDavid du Colombier } 46580ee5cbfSDavid du Colombier exits("restored"); 46680ee5cbfSDavid du Colombier 46780ee5cbfSDavid du Colombier } 46880ee5cbfSDavid du Colombier 46980ee5cbfSDavid du Colombier /* 47080ee5cbfSDavid du Colombier * Read the partition table (including extended partition tables) 47180ee5cbfSDavid du Colombier * from the disk into the part array. 47280ee5cbfSDavid du Colombier */ 47380ee5cbfSDavid du Colombier static void 4749a747e4fSDavid du Colombier rdpart(Edit *edit, ulong lba, ulong xbase) 47580ee5cbfSDavid du Colombier { 47680ee5cbfSDavid du Colombier char *err; 47780ee5cbfSDavid du Colombier Table table; 47880ee5cbfSDavid du Colombier Tentry *tp, *ep; 47980ee5cbfSDavid du Colombier Dospart *p; 48080ee5cbfSDavid du Colombier 4819a747e4fSDavid du Colombier if(xbase == 0) 4829a747e4fSDavid du Colombier xbase = lba; 4839a747e4fSDavid du Colombier 48480ee5cbfSDavid du Colombier diskread(edit->disk, &table, sizeof table, mbroffset+lba, Toffset); 48580ee5cbfSDavid du Colombier addrecover(table, mbroffset+lba); 4867dd7cddfSDavid du Colombier 4877dd7cddfSDavid du Colombier if(table.magic[0] != Magic0 || table.magic[1] != Magic1) { 48880ee5cbfSDavid du Colombier assert(lba != 0); 4897dd7cddfSDavid du Colombier return; 4907dd7cddfSDavid du Colombier } 4917dd7cddfSDavid du Colombier 49280ee5cbfSDavid du Colombier for(tp=table.entry, ep=tp+NTentry; tp<ep && npart < Mpart; tp++) { 49380ee5cbfSDavid du Colombier switch(tp->type) { 4947dd7cddfSDavid du Colombier case TypeEMPTY: 4957dd7cddfSDavid du Colombier break; 4967dd7cddfSDavid du Colombier case TypeEXTENDED: 4977dd7cddfSDavid du Colombier case TypeEXTHUGE: 4989a747e4fSDavid du Colombier case TypeLINUXEXT: 4999a747e4fSDavid du Colombier rdpart(edit, xbase+getle32(tp->xlba), xbase); 5007dd7cddfSDavid du Colombier break; 5017dd7cddfSDavid du Colombier default: 50280ee5cbfSDavid du Colombier p = mkpart(nil, lba==0, lba+getle32(tp->xlba), getle32(tp->xsize), tp); 5037dd7cddfSDavid du Colombier if(err = addpart(edit, p)) 50480ee5cbfSDavid du Colombier fprint(2, "adding partition: %s\n", err); 50580ee5cbfSDavid du Colombier break; 50680ee5cbfSDavid du Colombier } 5077dd7cddfSDavid du Colombier } 5087dd7cddfSDavid du Colombier } 5097dd7cddfSDavid du Colombier 5107dd7cddfSDavid du Colombier static void 5117dd7cddfSDavid du Colombier blankpart(Edit *edit) 5127dd7cddfSDavid du Colombier { 5137dd7cddfSDavid du Colombier edit->changed = 1; 5147dd7cddfSDavid du Colombier } 5157dd7cddfSDavid du Colombier 5167dd7cddfSDavid du Colombier static void 5177dd7cddfSDavid du Colombier findmbr(Edit *edit) 5187dd7cddfSDavid du Colombier { 5197dd7cddfSDavid du Colombier Table table; 5207dd7cddfSDavid du Colombier Tentry *tp; 5217dd7cddfSDavid du Colombier 52280ee5cbfSDavid du Colombier diskread(edit->disk, &table, sizeof(Table), 0, Toffset); 5237dd7cddfSDavid du Colombier if(table.magic[0] != Magic0 || table.magic[1] != Magic1) 5247dd7cddfSDavid du Colombier sysfatal("did not find master boot record"); 5257dd7cddfSDavid du Colombier 5267dd7cddfSDavid du Colombier for(tp = table.entry; tp < &table.entry[NTentry]; tp++) 5277dd7cddfSDavid du Colombier if(tp->type == TypeDMDDO) 52880ee5cbfSDavid du Colombier mbroffset = edit->disk->s; 5297dd7cddfSDavid du Colombier } 5307dd7cddfSDavid du Colombier 53180ee5cbfSDavid du Colombier static int 53280ee5cbfSDavid du Colombier haveroom(Edit *edit, int primary, vlong start) 5337dd7cddfSDavid du Colombier { 5349a747e4fSDavid du Colombier int i, lastsec, n; 5359a747e4fSDavid du Colombier Dospart *p, *q; 5369a747e4fSDavid du Colombier ulong pend, qstart; 53780ee5cbfSDavid du Colombier 53880ee5cbfSDavid du Colombier if(primary) { 53980ee5cbfSDavid du Colombier /* 54080ee5cbfSDavid du Colombier * must be open primary slot. 54180ee5cbfSDavid du Colombier * primary slots are taken by primary partitions 54280ee5cbfSDavid du Colombier * and runs of secondary partitions. 54380ee5cbfSDavid du Colombier */ 54480ee5cbfSDavid du Colombier n = 0; 54580ee5cbfSDavid du Colombier lastsec = 0; 54680ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) { 54780ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 54880ee5cbfSDavid du Colombier if(p->primary) 54980ee5cbfSDavid du Colombier n++, lastsec=0; 5509a747e4fSDavid du Colombier else if(!lastsec) 55180ee5cbfSDavid du Colombier n++, lastsec=1; 5527dd7cddfSDavid du Colombier } 55380ee5cbfSDavid du Colombier return n<4; 5547dd7cddfSDavid du Colombier } 5557dd7cddfSDavid du Colombier 55680ee5cbfSDavid du Colombier /* 55780ee5cbfSDavid du Colombier * secondary partitions can be inserted between two primary 55880ee5cbfSDavid du Colombier * partitions only if there is an empty primary slot. 55980ee5cbfSDavid du Colombier * otherwise, we can put a new secondary partition next 56080ee5cbfSDavid du Colombier * to a secondary partition no problem. 56180ee5cbfSDavid du Colombier */ 56280ee5cbfSDavid du Colombier n = 0; 5636b6b9ac8SDavid du Colombier for(i=0; i<edit->npart; i++){ 56480ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 56580ee5cbfSDavid du Colombier if(p->primary) 5669a747e4fSDavid du Colombier n++; 5679a747e4fSDavid du Colombier pend = p->end; 5689a747e4fSDavid du Colombier if(i+1<edit->npart){ 5699a747e4fSDavid du Colombier q = (Dospart*)edit->part[i+1]; 5709a747e4fSDavid du Colombier qstart = q->start; 5719a747e4fSDavid du Colombier }else{ 5729a747e4fSDavid du Colombier qstart = edit->end; 5739a747e4fSDavid du Colombier q = nil; 5747dd7cddfSDavid du Colombier } 5759a747e4fSDavid du Colombier if(start < pend || start >= qstart) 5769a747e4fSDavid du Colombier continue; 5779a747e4fSDavid du Colombier /* we go between these two */ 5789a747e4fSDavid du Colombier if(p->primary==0 || (q && q->primary==0)) 5799a747e4fSDavid du Colombier return 1; 5807dd7cddfSDavid du Colombier } 58180ee5cbfSDavid du Colombier /* not next to a secondary, need a new primary */ 58280ee5cbfSDavid du Colombier return n<4; 5837dd7cddfSDavid du Colombier } 5847dd7cddfSDavid du Colombier 5857dd7cddfSDavid du Colombier static void 5867dd7cddfSDavid du Colombier autopart(Edit *edit) 5877dd7cddfSDavid du Colombier { 58880ee5cbfSDavid du Colombier char *err; 58980ee5cbfSDavid du Colombier int active, i; 59080ee5cbfSDavid du Colombier vlong bigstart, bigsize, start; 59180ee5cbfSDavid du Colombier Dospart *p; 5927dd7cddfSDavid du Colombier 59380ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) 59480ee5cbfSDavid du Colombier if(((Dospart*)edit->part[i])->type == Type9) 5957dd7cddfSDavid du Colombier return; 5967dd7cddfSDavid du Colombier 59780ee5cbfSDavid du Colombier /* look for the biggest gap in which we can put a primary partition */ 59880ee5cbfSDavid du Colombier start = 0; 5997dd7cddfSDavid du Colombier bigsize = 0; 6007dd7cddfSDavid du Colombier SET(bigstart); 6017dd7cddfSDavid du Colombier for(i=0; i<edit->npart; i++) { 60280ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 60380ee5cbfSDavid du Colombier if(p->start > start && p->start - start > bigsize && haveroom(edit, 1, start)) { 6047dd7cddfSDavid du Colombier bigsize = p->start - start; 6057dd7cddfSDavid du Colombier bigstart = start; 6067dd7cddfSDavid du Colombier } 6077dd7cddfSDavid du Colombier start = p->end; 6087dd7cddfSDavid du Colombier } 6097dd7cddfSDavid du Colombier 61080ee5cbfSDavid du Colombier if(edit->end - start > bigsize && haveroom(edit, 1, start)) { 61180ee5cbfSDavid du Colombier bigsize = edit->end - start; 6127dd7cddfSDavid du Colombier bigstart = start; 6137dd7cddfSDavid du Colombier } 61480ee5cbfSDavid du Colombier if(bigsize < 1) { 61580ee5cbfSDavid du Colombier fprint(2, "couldn't find space or partition slot for plan 9 partition\n"); 6167dd7cddfSDavid du Colombier return; 6177dd7cddfSDavid du Colombier } 6187dd7cddfSDavid du Colombier 61980ee5cbfSDavid du Colombier /* set new partition active only if no others are */ 6207dd7cddfSDavid du Colombier active = Active; 62180ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) 62280ee5cbfSDavid du Colombier if(((Dospart*)edit->part[i])->primary && (((Dospart*)edit->part[i])->active & Active)) 6237dd7cddfSDavid du Colombier active = 0; 6247dd7cddfSDavid du Colombier 62580ee5cbfSDavid du Colombier /* add new plan 9 partition */ 62680ee5cbfSDavid du Colombier bigsize *= sec2cyl; 62780ee5cbfSDavid du Colombier bigstart *= sec2cyl; 62880ee5cbfSDavid du Colombier if(bigstart == 0) { 62980ee5cbfSDavid du Colombier bigstart += edit->disk->s; 63080ee5cbfSDavid du Colombier bigsize -= edit->disk->s; 6317dd7cddfSDavid du Colombier } 63280ee5cbfSDavid du Colombier p = mkpart(nil, 1, bigstart, bigsize, nil); 63380ee5cbfSDavid du Colombier p->active = active; 63480ee5cbfSDavid du Colombier p->changed = 1; 63580ee5cbfSDavid du Colombier p->type = Type9; 63680ee5cbfSDavid du Colombier edit->changed = 1; 63780ee5cbfSDavid du Colombier if(err = addpart(edit, p)) { 63880ee5cbfSDavid du Colombier fprint(2, "error adding plan9 partition: %s\n", err); 6397dd7cddfSDavid du Colombier return; 6407dd7cddfSDavid du Colombier } 6417dd7cddfSDavid du Colombier } 6427dd7cddfSDavid du Colombier 6437dd7cddfSDavid du Colombier typedef struct Name Name; 6447dd7cddfSDavid du Colombier struct Name { 6459a747e4fSDavid du Colombier char *name; 6467dd7cddfSDavid du Colombier Name *link; 6477dd7cddfSDavid du Colombier }; 6487dd7cddfSDavid du Colombier Name *namelist; 6497dd7cddfSDavid du Colombier static void 65080ee5cbfSDavid du Colombier plan9print(Dospart *part, int fd) 6517dd7cddfSDavid du Colombier { 6527dd7cddfSDavid du Colombier int i, ok; 6539a747e4fSDavid du Colombier char *name, *vname; 6547dd7cddfSDavid du Colombier Name *n; 65580ee5cbfSDavid du Colombier vlong start, end; 65680ee5cbfSDavid du Colombier char *sep; 65780ee5cbfSDavid du Colombier 65880ee5cbfSDavid du Colombier vname = types[part->type].name; 6599a747e4fSDavid du Colombier if(vname==nil || strcmp(vname, "")==0) { 6609a747e4fSDavid du Colombier part->ctlname = ""; 66180ee5cbfSDavid du Colombier return; 66280ee5cbfSDavid du Colombier } 66380ee5cbfSDavid du Colombier 66480ee5cbfSDavid du Colombier start = mbroffset+part->lba; 66580ee5cbfSDavid du Colombier end = start+part->size; 66680ee5cbfSDavid du Colombier 66780ee5cbfSDavid du Colombier /* avoid names like plan90 */ 66880ee5cbfSDavid du Colombier i = strlen(vname) - 1; 66980ee5cbfSDavid du Colombier if(vname[i] >= '0' && vname[i] <= '9') 67080ee5cbfSDavid du Colombier sep = "."; 67180ee5cbfSDavid du Colombier else 67280ee5cbfSDavid du Colombier sep = ""; 6737dd7cddfSDavid du Colombier 6747dd7cddfSDavid du Colombier i = 0; 6759a747e4fSDavid du Colombier name = emalloc(strlen(vname)+10); 6769a747e4fSDavid du Colombier 67780ee5cbfSDavid du Colombier sprint(name, "%s", vname); 6787dd7cddfSDavid du Colombier do { 6797dd7cddfSDavid du Colombier ok = 1; 6807dd7cddfSDavid du Colombier for(n=namelist; n; n=n->link) { 6817dd7cddfSDavid du Colombier if(strcmp(name, n->name) == 0) { 6827dd7cddfSDavid du Colombier i++; 68380ee5cbfSDavid du Colombier sprint(name, "%s%s%d", vname, sep, i); 6847dd7cddfSDavid du Colombier ok = 0; 6857dd7cddfSDavid du Colombier } 6867dd7cddfSDavid du Colombier } 6877dd7cddfSDavid du Colombier } while(ok == 0); 6887dd7cddfSDavid du Colombier 6899a747e4fSDavid du Colombier n = emalloc(sizeof(*n)); 6909a747e4fSDavid du Colombier n->name = name; 6917dd7cddfSDavid du Colombier n->link = namelist; 6927dd7cddfSDavid du Colombier namelist = n; 6939a747e4fSDavid du Colombier part->ctlname = name; 6947dd7cddfSDavid du Colombier 6957dd7cddfSDavid du Colombier if(fd >= 0) 6967dd7cddfSDavid du Colombier print("part %s %lld %lld\n", name, start, end); 6977dd7cddfSDavid du Colombier } 6987dd7cddfSDavid du Colombier 6997dd7cddfSDavid du Colombier static void 7007dd7cddfSDavid du Colombier freenamelist(void) 7017dd7cddfSDavid du Colombier { 7027dd7cddfSDavid du Colombier Name *n, *next; 7037dd7cddfSDavid du Colombier 7047dd7cddfSDavid du Colombier for(n=namelist; n; n=next) { 7057dd7cddfSDavid du Colombier next = n->link; 7067dd7cddfSDavid du Colombier free(n); 7077dd7cddfSDavid du Colombier } 7087dd7cddfSDavid du Colombier namelist = nil; 7097dd7cddfSDavid du Colombier } 7107dd7cddfSDavid du Colombier 7117dd7cddfSDavid du Colombier static void 7127dd7cddfSDavid du Colombier cmdprintctl(Edit *edit, int ctlfd) 7137dd7cddfSDavid du Colombier { 7147dd7cddfSDavid du Colombier int i; 7157dd7cddfSDavid du Colombier 7167dd7cddfSDavid du Colombier freenamelist(); 7177dd7cddfSDavid du Colombier for(i=0; i<edit->npart; i++) 71880ee5cbfSDavid du Colombier plan9print((Dospart*)edit->part[i], -1); 7197dd7cddfSDavid du Colombier ctldiff(edit, ctlfd); 7207dd7cddfSDavid du Colombier } 7217dd7cddfSDavid du Colombier 7227dd7cddfSDavid du Colombier static char* 7237dd7cddfSDavid du Colombier cmdokname(Edit*, char *name) 7247dd7cddfSDavid du Colombier { 72580ee5cbfSDavid du Colombier char *q; 72680ee5cbfSDavid du Colombier 72780ee5cbfSDavid du Colombier if(name[0] != 'p' && name[0] != 's') 72880ee5cbfSDavid du Colombier return "name must be pN or sN"; 72980ee5cbfSDavid du Colombier 73080ee5cbfSDavid du Colombier strtol(name+1, &q, 10); 73180ee5cbfSDavid du Colombier if(*q != '\0') 73280ee5cbfSDavid du Colombier return "name must be pN or sN"; 73380ee5cbfSDavid du Colombier 7347dd7cddfSDavid du Colombier return nil; 7357dd7cddfSDavid du Colombier } 7367dd7cddfSDavid du Colombier 7377dd7cddfSDavid du Colombier #define GB (1024*1024*1024) 7387dd7cddfSDavid du Colombier #define MB (1024*1024) 7397dd7cddfSDavid du Colombier #define KB (1024) 7407dd7cddfSDavid du Colombier 7417dd7cddfSDavid du Colombier static void 7427dd7cddfSDavid du Colombier cmdsum(Edit *edit, Part *vp, vlong a, vlong b) 7437dd7cddfSDavid du Colombier { 7447dd7cddfSDavid du Colombier char *name, *ty; 7457dd7cddfSDavid du Colombier char buf[3]; 74680ee5cbfSDavid du Colombier char *suf; 7477dd7cddfSDavid du Colombier Dospart *p; 74880ee5cbfSDavid du Colombier vlong sz, div; 7497dd7cddfSDavid du Colombier 7507dd7cddfSDavid du Colombier p = (Dospart*)vp; 7517dd7cddfSDavid du Colombier 7527dd7cddfSDavid du Colombier buf[0] = p && p->changed ? '\'' : ' '; 7537dd7cddfSDavid du Colombier buf[1] = p && (p->active & Active) ? '*' : ' '; 7547dd7cddfSDavid du Colombier buf[2] = '\0'; 7557dd7cddfSDavid du Colombier 7567dd7cddfSDavid du Colombier name = p ? p->name : "empty"; 75780ee5cbfSDavid du Colombier ty = p ? typestr0(p->type) : ""; 7587dd7cddfSDavid du Colombier 75980ee5cbfSDavid du Colombier sz = (b-a)*edit->disk->secsize*sec2cyl; 76080ee5cbfSDavid du Colombier if(sz >= 1*GB){ 76180ee5cbfSDavid du Colombier suf = "GB"; 76280ee5cbfSDavid du Colombier div = GB; 76380ee5cbfSDavid du Colombier }else if(sz >= 1*MB){ 76480ee5cbfSDavid du Colombier suf = "MB"; 76580ee5cbfSDavid du Colombier div = MB; 76680ee5cbfSDavid du Colombier }else if(sz >= 1*KB){ 76780ee5cbfSDavid du Colombier suf = "KB"; 76880ee5cbfSDavid du Colombier div = KB; 76980ee5cbfSDavid du Colombier }else{ 77080ee5cbfSDavid du Colombier suf = "B "; 77180ee5cbfSDavid du Colombier div = 1; 77280ee5cbfSDavid du Colombier } 77380ee5cbfSDavid du Colombier 77480ee5cbfSDavid du Colombier if(div == 1) 77580ee5cbfSDavid du Colombier print("%s %-12s %*lld %-*lld (%lld cylinders, %lld %s) %s\n", buf, name, 77680ee5cbfSDavid du Colombier edit->disk->width, a, edit->disk->width, b, b-a, sz, suf, ty); 77780ee5cbfSDavid du Colombier else 77880ee5cbfSDavid du Colombier print("%s %-12s %*lld %-*lld (%lld cylinders, %lld.%.2d %s) %s\n", buf, name, 77980ee5cbfSDavid du Colombier edit->disk->width, a, edit->disk->width, b, b-a, 78080ee5cbfSDavid du Colombier sz/div, (int)(((sz%div)*100)/div), suf, ty); 7817dd7cddfSDavid du Colombier } 7827dd7cddfSDavid du Colombier 7837dd7cddfSDavid du Colombier static char* 7847dd7cddfSDavid du Colombier cmdadd(Edit *edit, char *name, vlong start, vlong end) 7857dd7cddfSDavid du Colombier { 78680ee5cbfSDavid du Colombier Dospart *p; 7877dd7cddfSDavid du Colombier 78880ee5cbfSDavid du Colombier if(!haveroom(edit, name[0]=='p', start)) 78980ee5cbfSDavid du Colombier return "no room for partition"; 7909a747e4fSDavid du Colombier start *= sec2cyl; 7919a747e4fSDavid du Colombier end *= sec2cyl; 7926b6b9ac8SDavid du Colombier if(start == 0 || name[0] != 'p') 7936b6b9ac8SDavid du Colombier start += edit->disk->s; 7949a747e4fSDavid du Colombier p = mkpart(name, name[0]=='p', start, end-start, nil); 79580ee5cbfSDavid du Colombier p->changed = 1; 79680ee5cbfSDavid du Colombier return addpart(edit, p); 7977dd7cddfSDavid du Colombier } 7987dd7cddfSDavid du Colombier 7997dd7cddfSDavid du Colombier static char* 8007dd7cddfSDavid du Colombier cmddel(Edit *edit, Part *p) 8017dd7cddfSDavid du Colombier { 80280ee5cbfSDavid du Colombier return delpart(edit, p); 8037dd7cddfSDavid du Colombier } 8047dd7cddfSDavid du Colombier 8057dd7cddfSDavid du Colombier static char* 8067dd7cddfSDavid du Colombier cmdwrite(Edit *edit) 8077dd7cddfSDavid du Colombier { 8087dd7cddfSDavid du Colombier wrpart(edit); 8097dd7cddfSDavid du Colombier return nil; 8107dd7cddfSDavid du Colombier } 8117dd7cddfSDavid du Colombier 8127dd7cddfSDavid du Colombier static char *help = 8137dd7cddfSDavid du Colombier "A name - set partition active\n" 8147dd7cddfSDavid du Colombier "P - print table in ctl format\n" 8156b6b9ac8SDavid du Colombier "R - restore disk back to initial configuration and exit\n" 8167dd7cddfSDavid du Colombier "e - show empty dos partitions\n" 8177dd7cddfSDavid du Colombier "t name [type] - set partition type\n"; 8187dd7cddfSDavid du Colombier 8197dd7cddfSDavid du Colombier static char* 8207dd7cddfSDavid du Colombier cmdhelp(Edit*) 8217dd7cddfSDavid du Colombier { 8227dd7cddfSDavid du Colombier print("%s\n", help); 8237dd7cddfSDavid du Colombier return nil; 8247dd7cddfSDavid du Colombier } 8257dd7cddfSDavid du Colombier 8267dd7cddfSDavid du Colombier static char* 8277dd7cddfSDavid du Colombier cmdactive(Edit *edit, int nf, char **f) 8287dd7cddfSDavid du Colombier { 8297dd7cddfSDavid du Colombier int i; 83080ee5cbfSDavid du Colombier Dospart *p, *ip; 8317dd7cddfSDavid du Colombier 8327dd7cddfSDavid du Colombier if(nf != 2) 8337dd7cddfSDavid du Colombier return "args"; 8347dd7cddfSDavid du Colombier 8359a747e4fSDavid du Colombier if(f[1][0] != 'p') 8369a747e4fSDavid du Colombier return "cannot set secondary partition active"; 8379a747e4fSDavid du Colombier 83880ee5cbfSDavid du Colombier if((p = (Dospart*)findpart(edit, f[1])) == nil) 83980ee5cbfSDavid du Colombier return "unknown partition"; 8407dd7cddfSDavid du Colombier 84180ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) { 84280ee5cbfSDavid du Colombier ip = (Dospart*)edit->part[i]; 84380ee5cbfSDavid du Colombier if(ip->active & Active) { 84480ee5cbfSDavid du Colombier ip->active &= ~Active; 84580ee5cbfSDavid du Colombier ip->changed = 1; 8467dd7cddfSDavid du Colombier edit->changed = 1; 8477dd7cddfSDavid du Colombier } 8487dd7cddfSDavid du Colombier } 84980ee5cbfSDavid du Colombier 8507dd7cddfSDavid du Colombier if((p->active & Active) == 0) { 8517dd7cddfSDavid du Colombier p->active |= Active; 8527dd7cddfSDavid du Colombier p->changed = 1; 8537dd7cddfSDavid du Colombier edit->changed = 1; 8547dd7cddfSDavid du Colombier } 8557dd7cddfSDavid du Colombier 8567dd7cddfSDavid du Colombier return nil; 8577dd7cddfSDavid du Colombier } 8587dd7cddfSDavid du Colombier 8597dd7cddfSDavid du Colombier static char* 8607dd7cddfSDavid du Colombier strupr(char *s) 8617dd7cddfSDavid du Colombier { 8627dd7cddfSDavid du Colombier char *p; 8637dd7cddfSDavid du Colombier 8647dd7cddfSDavid du Colombier for(p=s; *p; p++) 8657dd7cddfSDavid du Colombier *p = toupper(*p); 8667dd7cddfSDavid du Colombier return s; 8677dd7cddfSDavid du Colombier } 8687dd7cddfSDavid du Colombier 8697dd7cddfSDavid du Colombier static void 8707dd7cddfSDavid du Colombier dumplist(void) 8717dd7cddfSDavid du Colombier { 8727dd7cddfSDavid du Colombier int i, n; 8737dd7cddfSDavid du Colombier 8747dd7cddfSDavid du Colombier n = 0; 8757dd7cddfSDavid du Colombier for(i=0; i<256; i++) { 8767dd7cddfSDavid du Colombier if(types[i].desc) { 8777dd7cddfSDavid du Colombier print("%-16s", types[i].desc); 8787dd7cddfSDavid du Colombier if(n++%4 == 3) 8797dd7cddfSDavid du Colombier print("\n"); 8807dd7cddfSDavid du Colombier } 8817dd7cddfSDavid du Colombier } 8827dd7cddfSDavid du Colombier if(n%4) 8837dd7cddfSDavid du Colombier print("\n"); 8847dd7cddfSDavid du Colombier } 8857dd7cddfSDavid du Colombier 8867dd7cddfSDavid du Colombier static char* 8877dd7cddfSDavid du Colombier cmdtype(Edit *edit, int nf, char **f) 8887dd7cddfSDavid du Colombier { 8897dd7cddfSDavid du Colombier char *q; 8907dd7cddfSDavid du Colombier Dospart *p; 8917dd7cddfSDavid du Colombier int i; 8927dd7cddfSDavid du Colombier 8937dd7cddfSDavid du Colombier if(nf < 2) 8947dd7cddfSDavid du Colombier return "args"; 8957dd7cddfSDavid du Colombier 8967dd7cddfSDavid du Colombier if((p = (Dospart*)findpart(edit, f[1])) == nil) 8977dd7cddfSDavid du Colombier return "unknown partition"; 8987dd7cddfSDavid du Colombier 8997dd7cddfSDavid du Colombier if(nf == 2) { 9007dd7cddfSDavid du Colombier for(;;) { 9017dd7cddfSDavid du Colombier fprint(2, "new partition type [? for list]: "); 9027dd7cddfSDavid du Colombier q = getline(edit); 9037dd7cddfSDavid du Colombier if(q[0] == '?') 9047dd7cddfSDavid du Colombier dumplist(); 9057dd7cddfSDavid du Colombier else 9067dd7cddfSDavid du Colombier break; 9077dd7cddfSDavid du Colombier } 9087dd7cddfSDavid du Colombier } else 9097dd7cddfSDavid du Colombier q = f[2]; 9107dd7cddfSDavid du Colombier 9117dd7cddfSDavid du Colombier strupr(q); 9127dd7cddfSDavid du Colombier for(i=0; i<256; i++) 9137dd7cddfSDavid du Colombier if(types[i].desc && strcmp(types[i].desc, q) == 0) 9147dd7cddfSDavid du Colombier break; 9157dd7cddfSDavid du Colombier if(i < 256 && p->type != i) { 9167dd7cddfSDavid du Colombier p->type = i; 9177dd7cddfSDavid du Colombier p->changed = 1; 9187dd7cddfSDavid du Colombier edit->changed = 1; 9197dd7cddfSDavid du Colombier } 9207dd7cddfSDavid du Colombier return nil; 9217dd7cddfSDavid du Colombier } 9227dd7cddfSDavid du Colombier 9237dd7cddfSDavid du Colombier static char* 9247dd7cddfSDavid du Colombier cmdext(Edit *edit, int nf, char **f) 9257dd7cddfSDavid du Colombier { 9267dd7cddfSDavid du Colombier switch(f[0][0]) { 9277dd7cddfSDavid du Colombier case 'A': 9287dd7cddfSDavid du Colombier return cmdactive(edit, nf, f); 9297dd7cddfSDavid du Colombier case 't': 9307dd7cddfSDavid du Colombier return cmdtype(edit, nf, f); 93180ee5cbfSDavid du Colombier case 'R': 93280ee5cbfSDavid du Colombier recover(edit); 93380ee5cbfSDavid du Colombier return nil; 9347dd7cddfSDavid du Colombier default: 9357dd7cddfSDavid du Colombier return "unknown command"; 9367dd7cddfSDavid du Colombier } 9377dd7cddfSDavid du Colombier } 9387dd7cddfSDavid du Colombier 93980ee5cbfSDavid du Colombier static int 9409a747e4fSDavid du Colombier Dfmt(Fmt *f) 94180ee5cbfSDavid du Colombier { 94280ee5cbfSDavid du Colombier char buf[60]; 94380ee5cbfSDavid du Colombier uchar *p; 94480ee5cbfSDavid du Colombier int c, h, s; 94580ee5cbfSDavid du Colombier 9469a747e4fSDavid du Colombier p = va_arg(f->args, uchar*); 94780ee5cbfSDavid du Colombier h = p[0]; 94880ee5cbfSDavid du Colombier c = p[2]; 94980ee5cbfSDavid du Colombier c |= (p[1]&0xC0)<<2; 95080ee5cbfSDavid du Colombier s = (p[1] & 0x3F); 95180ee5cbfSDavid du Colombier 95280ee5cbfSDavid du Colombier sprint(buf, "%d/%d/%d", c, h, s); 9539a747e4fSDavid du Colombier return fmtstrcpy(f, buf); 95480ee5cbfSDavid du Colombier } 95580ee5cbfSDavid du Colombier 95680ee5cbfSDavid du Colombier static void 95780ee5cbfSDavid du Colombier writechs(Disk *disk, uchar *p, vlong lba) 95880ee5cbfSDavid du Colombier { 95980ee5cbfSDavid du Colombier int c, h, s; 96080ee5cbfSDavid du Colombier 96180ee5cbfSDavid du Colombier s = lba % disk->s; 96280ee5cbfSDavid du Colombier h = (lba / disk->s) % disk->h; 96380ee5cbfSDavid du Colombier c = lba / (disk->s * disk->h); 96480ee5cbfSDavid du Colombier 96580ee5cbfSDavid du Colombier if(c >= 1024) { 96680ee5cbfSDavid du Colombier c = 1023; 96780ee5cbfSDavid du Colombier h = disk->h - 1; 96880ee5cbfSDavid du Colombier s = disk->s - 1; 96980ee5cbfSDavid du Colombier } 97080ee5cbfSDavid du Colombier 97180ee5cbfSDavid du Colombier p[0] = h; 97280ee5cbfSDavid du Colombier p[1] = ((s+1) & 0x3F) | ((c>>2) & 0xC0); 97380ee5cbfSDavid du Colombier p[2] = c; 97480ee5cbfSDavid du Colombier } 97580ee5cbfSDavid du Colombier 97680ee5cbfSDavid du Colombier static void 9779a747e4fSDavid du Colombier wrtentry(Disk *disk, Tentry *tp, int type, u32int xbase, u32int lba, u32int end) 97880ee5cbfSDavid du Colombier { 97980ee5cbfSDavid du Colombier tp->type = type; 9809a747e4fSDavid du Colombier writechs(disk, &tp->starth, lba); 9819a747e4fSDavid du Colombier writechs(disk, &tp->endh, end-1); 9829a747e4fSDavid du Colombier putle32(tp->xlba, lba-xbase); 9839a747e4fSDavid du Colombier putle32(tp->xsize, end-lba); 98480ee5cbfSDavid du Colombier } 98580ee5cbfSDavid du Colombier 98680ee5cbfSDavid du Colombier static int 9879a747e4fSDavid du Colombier wrextend(Edit *edit, int i, vlong xbase, vlong startlba, vlong *endlba) 98880ee5cbfSDavid du Colombier { 98980ee5cbfSDavid du Colombier int ni; 99080ee5cbfSDavid du Colombier Table table; 99180ee5cbfSDavid du Colombier Tentry *tp, *ep; 99280ee5cbfSDavid du Colombier Dospart *p; 99380ee5cbfSDavid du Colombier Disk *disk; 99480ee5cbfSDavid du Colombier 9959a747e4fSDavid du Colombier if(i == edit->npart){ 9969a747e4fSDavid du Colombier *endlba = edit->disk->secs; 9979a747e4fSDavid du Colombier Finish: 9989a747e4fSDavid du Colombier if(startlba < *endlba){ 9999a747e4fSDavid du Colombier disk = edit->disk; 10009a747e4fSDavid du Colombier diskread(disk, &table, sizeof table, mbroffset+startlba, Toffset); 10019a747e4fSDavid du Colombier tp = table.entry; 10029a747e4fSDavid du Colombier ep = tp+NTentry; 10039a747e4fSDavid du Colombier for(; tp<ep; tp++) 10049a747e4fSDavid du Colombier memset(tp, 0, sizeof *tp); 10059a747e4fSDavid du Colombier table.magic[0] = Magic0; 10069a747e4fSDavid du Colombier table.magic[1] = Magic1; 10079a747e4fSDavid du Colombier 10089a747e4fSDavid du Colombier if(diskwrite(edit->disk, &table, sizeof table, mbroffset+startlba, Toffset) < 0) 10099a747e4fSDavid du Colombier recover(edit); 10109a747e4fSDavid du Colombier } 101180ee5cbfSDavid du Colombier return i; 10129a747e4fSDavid du Colombier } 101380ee5cbfSDavid du Colombier 101480ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 10159a747e4fSDavid du Colombier if(p->primary){ 10169a747e4fSDavid du Colombier *endlba = (vlong)p->start*sec2cyl; 10179a747e4fSDavid du Colombier goto Finish; 10189a747e4fSDavid du Colombier } 101980ee5cbfSDavid du Colombier 102080ee5cbfSDavid du Colombier disk = edit->disk; 10219a747e4fSDavid du Colombier diskread(disk, &table, sizeof table, mbroffset+startlba, Toffset); 102280ee5cbfSDavid du Colombier tp = table.entry; 102380ee5cbfSDavid du Colombier ep = tp+NTentry; 102480ee5cbfSDavid du Colombier 10259a747e4fSDavid du Colombier ni = wrextend(edit, i+1, xbase, p->end*sec2cyl, endlba); 102680ee5cbfSDavid du Colombier 102780ee5cbfSDavid du Colombier *tp = p->Tentry; 10289a747e4fSDavid du Colombier wrtentry(disk, tp, p->type, startlba, startlba+disk->s, p->end*sec2cyl); 102980ee5cbfSDavid du Colombier tp++; 103080ee5cbfSDavid du Colombier 10319a747e4fSDavid du Colombier if(p->end*sec2cyl != *endlba){ 103280ee5cbfSDavid du Colombier memset(tp, 0, sizeof *tp); 10339a747e4fSDavid du Colombier wrtentry(disk, tp, TypeEXTENDED, xbase, p->end*sec2cyl, *endlba); 103480ee5cbfSDavid du Colombier tp++; 103580ee5cbfSDavid du Colombier } 103680ee5cbfSDavid du Colombier 103780ee5cbfSDavid du Colombier for(; tp<ep; tp++) 103880ee5cbfSDavid du Colombier memset(tp, 0, sizeof *tp); 103980ee5cbfSDavid du Colombier 104080ee5cbfSDavid du Colombier table.magic[0] = Magic0; 104180ee5cbfSDavid du Colombier table.magic[1] = Magic1; 104280ee5cbfSDavid du Colombier 10439a747e4fSDavid du Colombier if(diskwrite(edit->disk, &table, sizeof table, mbroffset+startlba, Toffset) < 0) 104480ee5cbfSDavid du Colombier recover(edit); 104580ee5cbfSDavid du Colombier return ni; 104680ee5cbfSDavid du Colombier } 104780ee5cbfSDavid du Colombier 104880ee5cbfSDavid du Colombier static void 104980ee5cbfSDavid du Colombier wrpart(Edit *edit) 105080ee5cbfSDavid du Colombier { 10519a747e4fSDavid du Colombier int i, ni, t; 105280ee5cbfSDavid du Colombier Table table; 105380ee5cbfSDavid du Colombier Tentry *tp, *ep; 105480ee5cbfSDavid du Colombier Disk *disk; 105580ee5cbfSDavid du Colombier vlong s, endlba; 105680ee5cbfSDavid du Colombier Dospart *p; 105780ee5cbfSDavid du Colombier 105880ee5cbfSDavid du Colombier disk = edit->disk; 105980ee5cbfSDavid du Colombier 106080ee5cbfSDavid du Colombier diskread(disk, &table, sizeof table, mbroffset, Toffset); 106180ee5cbfSDavid du Colombier 106280ee5cbfSDavid du Colombier tp = table.entry; 106380ee5cbfSDavid du Colombier ep = tp+NTentry; 106480ee5cbfSDavid du Colombier for(i=0; i<edit->npart && tp<ep; ) { 106580ee5cbfSDavid du Colombier p = (Dospart*)edit->part[i]; 106680ee5cbfSDavid du Colombier if(p->start == 0) 106780ee5cbfSDavid du Colombier s = disk->s; 106880ee5cbfSDavid du Colombier else 106980ee5cbfSDavid du Colombier s = p->start*sec2cyl; 107080ee5cbfSDavid du Colombier if(p->primary) { 107180ee5cbfSDavid du Colombier *tp = p->Tentry; 10729a747e4fSDavid du Colombier wrtentry(disk, tp, p->type, 0, s, p->end*sec2cyl); 107380ee5cbfSDavid du Colombier tp++; 107480ee5cbfSDavid du Colombier i++; 107580ee5cbfSDavid du Colombier } else { 10769a747e4fSDavid du Colombier ni = wrextend(edit, i, p->start*sec2cyl, p->start*sec2cyl, &endlba); 107780ee5cbfSDavid du Colombier memset(tp, 0, sizeof *tp); 10789a747e4fSDavid du Colombier if(endlba >= 1024*sec2cyl) 10799a747e4fSDavid du Colombier t = TypeEXTHUGE; 10809a747e4fSDavid du Colombier else 10819a747e4fSDavid du Colombier t = TypeEXTENDED; 10829a747e4fSDavid du Colombier wrtentry(disk, tp, t, 0, s, endlba); 108380ee5cbfSDavid du Colombier tp++; 108480ee5cbfSDavid du Colombier i = ni; 108580ee5cbfSDavid du Colombier } 108680ee5cbfSDavid du Colombier } 108780ee5cbfSDavid du Colombier for(; tp<ep; tp++) 108880ee5cbfSDavid du Colombier memset(tp, 0, sizeof(*tp)); 108980ee5cbfSDavid du Colombier 109080ee5cbfSDavid du Colombier if(i != edit->npart) 109180ee5cbfSDavid du Colombier sysfatal("cannot happen #1"); 109280ee5cbfSDavid du Colombier 109380ee5cbfSDavid du Colombier if(diskwrite(disk, &table, sizeof table, mbroffset, Toffset) < 0) 109480ee5cbfSDavid du Colombier recover(edit); 109580ee5cbfSDavid du Colombier 109680ee5cbfSDavid du Colombier /* bring parts up to date */ 109780ee5cbfSDavid du Colombier freenamelist(); 109880ee5cbfSDavid du Colombier for(i=0; i<edit->npart; i++) 109980ee5cbfSDavid du Colombier plan9print((Dospart*)edit->part[i], -1); 110080ee5cbfSDavid du Colombier 110180ee5cbfSDavid du Colombier if(ctldiff(edit, disk->ctlfd) < 0) 110280ee5cbfSDavid du Colombier fprint(2, "?warning: partitions could not be updated in devsd\n"); 110380ee5cbfSDavid du Colombier } 1104