1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 37dd7cddfSDavid du Colombier #include <ctype.h> 47dd7cddfSDavid du Colombier #include <disk.h> 5bd389b36SDavid du Colombier 6bd389b36SDavid du Colombier /* 77dd7cddfSDavid du Colombier * disk types (all MFM encoding) 8bd389b36SDavid du Colombier */ 9bd389b36SDavid du Colombier typedef struct Type Type; 10bd389b36SDavid du Colombier struct Type 11bd389b36SDavid du Colombier { 12bd389b36SDavid du Colombier char *name; 13bd389b36SDavid du Colombier int bytes; /* bytes/sector */ 14bd389b36SDavid du Colombier int sectors; /* sectors/track */ 15bd389b36SDavid du Colombier int heads; /* number of heads */ 16bd389b36SDavid du Colombier int tracks; /* tracks/disk */ 17bd389b36SDavid du Colombier int media; /* media descriptor byte */ 18bd389b36SDavid du Colombier int cluster; /* default cluster size */ 19bd389b36SDavid du Colombier }; 20bd389b36SDavid du Colombier Type floppytype[] = 21bd389b36SDavid du Colombier { 22bd389b36SDavid du Colombier { "3½HD", 512, 18, 2, 80, 0xf0, 1, }, 23bd389b36SDavid du Colombier { "3½DD", 512, 9, 2, 80, 0xf9, 2, }, 249a747e4fSDavid du Colombier { "3½QD", 512, 36, 2, 80, 0xf9, 2, }, /* invented */ 25bd389b36SDavid du Colombier { "5¼HD", 512, 15, 2, 80, 0xf9, 1, }, 26bd389b36SDavid du Colombier { "5¼DD", 512, 9, 2, 40, 0xfd, 2, }, 277dd7cddfSDavid du Colombier { "hard", 512, 0, 0, 0, 0xf8, 4, }, 28bd389b36SDavid du Colombier }; 297dd7cddfSDavid du Colombier 30bd389b36SDavid du Colombier #define NTYPES (sizeof(floppytype)/sizeof(Type)) 31bd389b36SDavid du Colombier 32bd389b36SDavid du Colombier typedef struct Dosboot Dosboot; 33bd389b36SDavid du Colombier struct Dosboot{ 347dd7cddfSDavid du Colombier uchar magic[3]; /* really an x86 JMP instruction */ 35bd389b36SDavid du Colombier uchar version[8]; 36bd389b36SDavid du Colombier uchar sectsize[2]; 37bd389b36SDavid du Colombier uchar clustsize; 38bd389b36SDavid du Colombier uchar nresrv[2]; 39bd389b36SDavid du Colombier uchar nfats; 40bd389b36SDavid du Colombier uchar rootsize[2]; 41bd389b36SDavid du Colombier uchar volsize[2]; 42bd389b36SDavid du Colombier uchar mediadesc; 43bd389b36SDavid du Colombier uchar fatsize[2]; 44bd389b36SDavid du Colombier uchar trksize[2]; 45bd389b36SDavid du Colombier uchar nheads[2]; 46bd389b36SDavid du Colombier uchar nhidden[4]; 47bd389b36SDavid du Colombier uchar bigvolsize[4]; 48bd389b36SDavid du Colombier uchar driveno; 49bd389b36SDavid du Colombier uchar reserved0; 50bd389b36SDavid du Colombier uchar bootsig; 51bd389b36SDavid du Colombier uchar volid[4]; 52bd389b36SDavid du Colombier uchar label[11]; 53219b2ee8SDavid du Colombier uchar type[8]; 54bd389b36SDavid du Colombier }; 55bd389b36SDavid du Colombier #define PUTSHORT(p, v) { (p)[1] = (v)>>8; (p)[0] = (v); } 56bd389b36SDavid du Colombier #define PUTLONG(p, v) { PUTSHORT((p), (v)); PUTSHORT((p)+2, (v)>>16); } 577dd7cddfSDavid du Colombier #define GETSHORT(p) (((p)[1]<<8)|(p)[0]) 587dd7cddfSDavid du Colombier #define GETLONG(p) (((ulong)GETSHORT(p+2)<<16)|(ulong)GETSHORT(p)) 59bd389b36SDavid du Colombier 60bd389b36SDavid du Colombier typedef struct Dosdir Dosdir; 61bd389b36SDavid du Colombier struct Dosdir 62bd389b36SDavid du Colombier { 63bd389b36SDavid du Colombier uchar name[8]; 64bd389b36SDavid du Colombier uchar ext[3]; 65bd389b36SDavid du Colombier uchar attr; 66bd389b36SDavid du Colombier uchar reserved[10]; 67bd389b36SDavid du Colombier uchar time[2]; 68bd389b36SDavid du Colombier uchar date[2]; 69bd389b36SDavid du Colombier uchar start[2]; 70bd389b36SDavid du Colombier uchar length[4]; 71bd389b36SDavid du Colombier }; 72bd389b36SDavid du Colombier 73bd389b36SDavid du Colombier #define DRONLY 0x01 74bd389b36SDavid du Colombier #define DHIDDEN 0x02 75bd389b36SDavid du Colombier #define DSYSTEM 0x04 76bd389b36SDavid du Colombier #define DVLABEL 0x08 77bd389b36SDavid du Colombier #define DDIR 0x10 78bd389b36SDavid du Colombier #define DARCH 0x20 79bd389b36SDavid du Colombier 80bd389b36SDavid du Colombier /* 81219b2ee8SDavid du Colombier * the boot program for the boot sector. 82bd389b36SDavid du Colombier */ 837dd7cddfSDavid du Colombier int nbootprog = 188; /* no. of bytes of boot program, including the first 0x3E */ 84bd389b36SDavid du Colombier uchar bootprog[512] = 85bd389b36SDavid du Colombier { 86219b2ee8SDavid du Colombier [0x000] 0xEB, 0x3C, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 87bd389b36SDavid du Colombier 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 88219b2ee8SDavid du Colombier [0x03E] 0xFA, 0xFC, 0x8C, 0xC8, 0x8E, 0xD8, 0x8E, 0xD0, 89219b2ee8SDavid du Colombier 0xBC, 0x00, 0x7C, 0xBE, 0x77, 0x7C, 0xE8, 0x19, 90219b2ee8SDavid du Colombier 0x00, 0x33, 0xC0, 0xCD, 0x16, 0xBB, 0x40, 0x00, 91219b2ee8SDavid du Colombier 0x8E, 0xC3, 0xBB, 0x72, 0x00, 0xB8, 0x34, 0x12, 92219b2ee8SDavid du Colombier 0x26, 0x89, 0x07, 0xEA, 0x00, 0x00, 0xFF, 0xFF, 93219b2ee8SDavid du Colombier 0xEB, 0xD6, 0xAC, 0x0A, 0xC0, 0x74, 0x09, 0xB4, 94219b2ee8SDavid du Colombier 0x0E, 0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xF2, 95219b2ee8SDavid du Colombier 0xC3, 'N', 'o', 't', ' ', 'a', ' ', 'b', 96219b2ee8SDavid du Colombier 'o', 'o', 't', 'a', 'b', 'l', 'e', ' ', 97219b2ee8SDavid du Colombier 'd', 'i', 's', 'c', ' ', 'o', 'r', ' ', 98219b2ee8SDavid du Colombier 'd', 'i', 's', 'c', ' ', 'e', 'r', 'r', 99219b2ee8SDavid du Colombier 'o', 'r', '\r', '\n', 'P', 'r', 'e', 's', 100219b2ee8SDavid du Colombier 's', ' ', 'a', 'l', 'm', 'o', 's', 't', 101219b2ee8SDavid du Colombier ' ', 'a', 'n', 'y', ' ', 'k', 'e', 'y', 102219b2ee8SDavid du Colombier ' ', 't', 'o', ' ', 'r', 'e', 'b', 'o', 103219b2ee8SDavid du Colombier 'o', 't', '.', '.', '.', 0x00, 0x00, 0x00, 104219b2ee8SDavid du Colombier [0x1F0] 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 105219b2ee8SDavid du Colombier 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA, 106bd389b36SDavid du Colombier }; 107bd389b36SDavid du Colombier 108bd389b36SDavid du Colombier char *dev; 109bd389b36SDavid du Colombier int clustersize; 110bd389b36SDavid du Colombier uchar *fat; /* the fat */ 111bd389b36SDavid du Colombier int fatbits; 112bd389b36SDavid du Colombier int fatsecs; 113bd389b36SDavid du Colombier int fatlast; /* last cluster allocated */ 114bd389b36SDavid du Colombier int clusters; 115bd389b36SDavid du Colombier int fatsecs; 1167dd7cddfSDavid du Colombier vlong volsecs; 117bd389b36SDavid du Colombier uchar *root; /* first block of root */ 118bd389b36SDavid du Colombier int rootsecs; 119bd389b36SDavid du Colombier int rootfiles; 120bd389b36SDavid du Colombier int rootnext; 1217dd7cddfSDavid du Colombier int nresrv = 1; 1227dd7cddfSDavid du Colombier int chatty; 1237dd7cddfSDavid du Colombier vlong length; 124bd389b36SDavid du Colombier Type *t; 125219b2ee8SDavid du Colombier int fflag; 1267dd7cddfSDavid du Colombier int hflag; 1277dd7cddfSDavid du Colombier int xflag; 1287dd7cddfSDavid du Colombier char *file; 1297dd7cddfSDavid du Colombier char *pbs; 130219b2ee8SDavid du Colombier char *type; 1317dd7cddfSDavid du Colombier char *bootfile; 132223a736eSDavid du Colombier int dos; 133bd389b36SDavid du Colombier 134bd389b36SDavid du Colombier enum 135bd389b36SDavid du Colombier { 136bd389b36SDavid du Colombier Sof = 1, /* start of file */ 137bd389b36SDavid du Colombier Eof = 2, /* end of file */ 138bd389b36SDavid du Colombier }; 139bd389b36SDavid du Colombier 1407dd7cddfSDavid du Colombier void dosfs(int, int, Disk*, char*, int, char*[], int); 141bd389b36SDavid du Colombier ulong clustalloc(int); 1429a747e4fSDavid du Colombier void addrname(uchar*, Dir*, char*, ulong); 1437dd7cddfSDavid du Colombier void sanitycheck(Disk*); 144bd389b36SDavid du Colombier 145bd389b36SDavid du Colombier void 146bd389b36SDavid du Colombier usage(void) 147bd389b36SDavid du Colombier { 1487dd7cddfSDavid du Colombier fprint(2, "usage: disk/format [-df] [-b bootblock] [-c csize] [-l label] [-r nresrv] [-t type] disk [files ...]\n"); 149bd389b36SDavid du Colombier exits("usage"); 150bd389b36SDavid du Colombier } 151bd389b36SDavid du Colombier 152bd389b36SDavid du Colombier void 153bd389b36SDavid du Colombier fatal(char *fmt, ...) 154bd389b36SDavid du Colombier { 155bd389b36SDavid du Colombier char err[128]; 1567dd7cddfSDavid du Colombier va_list arg; 157bd389b36SDavid du Colombier 1587dd7cddfSDavid du Colombier va_start(arg, fmt); 1599a747e4fSDavid du Colombier vsnprint(err, sizeof(err), fmt, arg); 1607dd7cddfSDavid du Colombier va_end(arg); 161bd389b36SDavid du Colombier fprint(2, "format: %s\n", err); 1627dd7cddfSDavid du Colombier if(fflag && file) 163219b2ee8SDavid du Colombier remove(file); 164bd389b36SDavid du Colombier exits(err); 165bd389b36SDavid du Colombier } 166bd389b36SDavid du Colombier 167bd389b36SDavid du Colombier void 168bd389b36SDavid du Colombier main(int argc, char **argv) 169bd389b36SDavid du Colombier { 170223a736eSDavid du Colombier int n, writepbs; 1717dd7cddfSDavid du Colombier int fd; 172bd389b36SDavid du Colombier char buf[512]; 173bd389b36SDavid du Colombier char label[11]; 174bd389b36SDavid du Colombier char *a; 1757dd7cddfSDavid du Colombier Disk *disk; 176bd389b36SDavid du Colombier 177bd389b36SDavid du Colombier dos = 0; 1787dd7cddfSDavid du Colombier type = nil; 179bd389b36SDavid du Colombier clustersize = 0; 1807dd7cddfSDavid du Colombier writepbs = 0; 181219b2ee8SDavid du Colombier memmove(label, "CYLINDRICAL", sizeof(label)); 182bd389b36SDavid du Colombier ARGBEGIN { 1837dd7cddfSDavid du Colombier case 'c': 1847dd7cddfSDavid du Colombier clustersize = atoi(ARGF()); 185219b2ee8SDavid du Colombier break; 186bd389b36SDavid du Colombier case 'd': 187bd389b36SDavid du Colombier dos = 1; 1887dd7cddfSDavid du Colombier writepbs = 1; 189bd389b36SDavid du Colombier break; 190219b2ee8SDavid du Colombier case 'f': 191219b2ee8SDavid du Colombier fflag = 1; 192219b2ee8SDavid du Colombier break; 193bd389b36SDavid du Colombier case 'l': 194bd389b36SDavid du Colombier a = ARGF(); 195bd389b36SDavid du Colombier n = strlen(a); 196bd389b36SDavid du Colombier if(n > sizeof(label)) 197bd389b36SDavid du Colombier n = sizeof(label); 198bd389b36SDavid du Colombier memmove(label, a, n); 199219b2ee8SDavid du Colombier while(n < sizeof(label)) 200219b2ee8SDavid du Colombier label[n++] = ' '; 201bd389b36SDavid du Colombier break; 2027dd7cddfSDavid du Colombier case 'b': 2037dd7cddfSDavid du Colombier pbs = ARGF(); 2047dd7cddfSDavid du Colombier writepbs = 1; 2057dd7cddfSDavid du Colombier break; 2067dd7cddfSDavid du Colombier case 'r': 2077dd7cddfSDavid du Colombier nresrv = atoi(ARGF()); 2087dd7cddfSDavid du Colombier break; 209219b2ee8SDavid du Colombier case 't': 210219b2ee8SDavid du Colombier type = ARGF(); 211bd389b36SDavid du Colombier break; 2127dd7cddfSDavid du Colombier case 'v': 2137dd7cddfSDavid du Colombier chatty++; 2147dd7cddfSDavid du Colombier break; 2157dd7cddfSDavid du Colombier case 'x': 2167dd7cddfSDavid du Colombier xflag = 1; 2177dd7cddfSDavid du Colombier break; 218bd389b36SDavid du Colombier default: 219bd389b36SDavid du Colombier usage(); 220bd389b36SDavid du Colombier } ARGEND 221bd389b36SDavid du Colombier 222bd389b36SDavid du Colombier if(argc < 1) 223bd389b36SDavid du Colombier usage(); 224219b2ee8SDavid du Colombier 2257dd7cddfSDavid du Colombier disk = opendisk(argv[0], 0, 0); 2267dd7cddfSDavid du Colombier if(disk == nil) { 2277dd7cddfSDavid du Colombier if(fflag) { 2287dd7cddfSDavid du Colombier if((fd = create(argv[0], ORDWR, 0666)) >= 0) { 2297dd7cddfSDavid du Colombier file = argv[0]; 2307dd7cddfSDavid du Colombier close(fd); 2317dd7cddfSDavid du Colombier disk = opendisk(argv[0], 0, 0); 2327dd7cddfSDavid du Colombier } 2337dd7cddfSDavid du Colombier } 2347dd7cddfSDavid du Colombier } 2357dd7cddfSDavid du Colombier if(disk == nil) 2367dd7cddfSDavid du Colombier fatal("opendisk: %r"); 237bd389b36SDavid du Colombier 2387dd7cddfSDavid du Colombier if(disk->type == Tfile) 2397dd7cddfSDavid du Colombier fflag = 1; 2407dd7cddfSDavid du Colombier 2417dd7cddfSDavid du Colombier if(type == nil) { 2427dd7cddfSDavid du Colombier switch(disk->type){ 2437dd7cddfSDavid du Colombier case Tfile: 2447dd7cddfSDavid du Colombier type = "3½HD"; 2457dd7cddfSDavid du Colombier break; 2467dd7cddfSDavid du Colombier case Tfloppy: 2477dd7cddfSDavid du Colombier seek(disk->ctlfd, 0, 0); 2487dd7cddfSDavid du Colombier n = read(disk->ctlfd, buf, 10); 2497dd7cddfSDavid du Colombier if(n <= 0 || n >= 10) 2507dd7cddfSDavid du Colombier fatal("reading floppy type"); 2517dd7cddfSDavid du Colombier buf[n] = 0; 25259cc4ca5SDavid du Colombier type = strdup(buf); 25359cc4ca5SDavid du Colombier if(type == nil) 25459cc4ca5SDavid du Colombier fatal("out of memory"); 2557dd7cddfSDavid du Colombier break; 2567dd7cddfSDavid du Colombier case Tsd: 2577dd7cddfSDavid du Colombier type = "hard"; 2587dd7cddfSDavid du Colombier break; 2597dd7cddfSDavid du Colombier default: 2607dd7cddfSDavid du Colombier type = "unknown"; 2617dd7cddfSDavid du Colombier break; 2627dd7cddfSDavid du Colombier } 263bd389b36SDavid du Colombier } 264bd389b36SDavid du Colombier 2657dd7cddfSDavid du Colombier if(!fflag && disk->type == Tfloppy) 2667dd7cddfSDavid du Colombier if(fprint(disk->ctlfd, "format %s", type) < 0) 2677dd7cddfSDavid du Colombier fatal("formatting floppy as %s: %r", type); 2687dd7cddfSDavid du Colombier 2697dd7cddfSDavid du Colombier if(disk->type != Tfloppy) 2707dd7cddfSDavid du Colombier sanitycheck(disk); 2717dd7cddfSDavid du Colombier 2727dd7cddfSDavid du Colombier /* check that everything will succeed */ 2737dd7cddfSDavid du Colombier dosfs(dos, writepbs, disk, label, argc-1, argv+1, 0); 2747dd7cddfSDavid du Colombier 2757dd7cddfSDavid du Colombier /* commit */ 2767dd7cddfSDavid du Colombier dosfs(dos, writepbs, disk, label, argc-1, argv+1, 1); 2777dd7cddfSDavid du Colombier 2789a747e4fSDavid du Colombier print("used %lld bytes\n", fatlast*clustersize*disk->secsize); 279bd389b36SDavid du Colombier exits(0); 280bd389b36SDavid du Colombier } 281bd389b36SDavid du Colombier 2827dd7cddfSDavid du Colombier /* 2837dd7cddfSDavid du Colombier * Look for a partition table on sector 1, as would be the 2847dd7cddfSDavid du Colombier * case if we were erroneously formatting 9fat without -r 2. 2857dd7cddfSDavid du Colombier * If it's there and nresrv is not big enough, complain and exit. 2867dd7cddfSDavid du Colombier * I've blown away my partition table too many times. 2877dd7cddfSDavid du Colombier */ 288bd389b36SDavid du Colombier void 2897dd7cddfSDavid du Colombier sanitycheck(Disk *disk) 2907dd7cddfSDavid du Colombier { 2917dd7cddfSDavid du Colombier char buf[512]; 2927dd7cddfSDavid du Colombier int bad; 2937dd7cddfSDavid du Colombier 2947dd7cddfSDavid du Colombier if(xflag) 2957dd7cddfSDavid du Colombier return; 2967dd7cddfSDavid du Colombier 2977dd7cddfSDavid du Colombier bad = 0; 298223a736eSDavid du Colombier if(dos && nresrv < 2 && seek(disk->fd, disk->secsize, 0) == disk->secsize 2997dd7cddfSDavid du Colombier && read(disk->fd, buf, sizeof(buf)) >= 5 && strncmp(buf, "part ", 5) == 0) { 3007dd7cddfSDavid du Colombier fprint(2, 3017dd7cddfSDavid du Colombier "there's a plan9 partition on the disk\n" 3027dd7cddfSDavid du Colombier "and you didn't specify -r 2 (or greater).\n" 3037dd7cddfSDavid du Colombier "either specify -r 2 or -x to disable this check.\n"); 3047dd7cddfSDavid du Colombier bad = 1; 3057dd7cddfSDavid du Colombier } 3067dd7cddfSDavid du Colombier 3077dd7cddfSDavid du Colombier if(disk->type == Tsd && disk->offset == 0LL) { 3087dd7cddfSDavid du Colombier fprint(2, 3097dd7cddfSDavid du Colombier "you're attempting to format your disk (/dev/sdXX/data)\n" 3107dd7cddfSDavid du Colombier "rather than a partition like /dev/sdXX/9fat;\n" 3117dd7cddfSDavid du Colombier "this is likely a mistake. specify -x to disable this check.\n"); 3127dd7cddfSDavid du Colombier bad = 1; 3137dd7cddfSDavid du Colombier } 3147dd7cddfSDavid du Colombier 3157dd7cddfSDavid du Colombier if(bad) 3167dd7cddfSDavid du Colombier exits("failed disk sanity check"); 3177dd7cddfSDavid du Colombier } 3187dd7cddfSDavid du Colombier 3197dd7cddfSDavid du Colombier /* 3207dd7cddfSDavid du Colombier * Return the BIOS drive number for the disk. 3217dd7cddfSDavid du Colombier * 0x80 is the first fixed disk, 0x81 the next, etc. 3227dd7cddfSDavid du Colombier * We map sdC0=0x80, sdC1=0x81, sdD0=0x82, sdD1=0x83 3237dd7cddfSDavid du Colombier */ 3247dd7cddfSDavid du Colombier int 3257dd7cddfSDavid du Colombier getdriveno(Disk *disk) 3267dd7cddfSDavid du Colombier { 3279a747e4fSDavid du Colombier char buf[64], *p; 3287dd7cddfSDavid du Colombier 3297dd7cddfSDavid du Colombier if(disk->type != Tsd) 3307dd7cddfSDavid du Colombier return 0x80; /* first hard disk */ 3317dd7cddfSDavid du Colombier 3327dd7cddfSDavid du Colombier if(fd2path(disk->fd, buf, sizeof(buf)) < 0) 3337dd7cddfSDavid du Colombier return 0x80; 3347dd7cddfSDavid du Colombier 3357dd7cddfSDavid du Colombier /* 3367dd7cddfSDavid du Colombier * The name is of the format #SsdC0/foo 3377dd7cddfSDavid du Colombier * or /dev/sdC0/foo. 3387dd7cddfSDavid du Colombier * So that we can just look for /sdC0, turn 3397dd7cddfSDavid du Colombier * #SsdC0/foo into #/sdC0/foo. 3407dd7cddfSDavid du Colombier */ 3417dd7cddfSDavid du Colombier if(buf[0] == '#' && buf[1] == 'S') 3427dd7cddfSDavid du Colombier buf[1] = '/'; 3437dd7cddfSDavid du Colombier 3447dd7cddfSDavid du Colombier for(p=buf; *p; p++) 3457dd7cddfSDavid du Colombier if(p[0] == 's' && p[1] == 'd' && (p[2]=='C' || p[2]=='D') && (p[3]=='0' || p[3]=='1')) 3467dd7cddfSDavid du Colombier return 0x80 + (p[2]-'C')*2 + (p[3]-'0'); 3477dd7cddfSDavid du Colombier 3487dd7cddfSDavid du Colombier return 0x80; 3497dd7cddfSDavid du Colombier } 3507dd7cddfSDavid du Colombier 3513ff48bf5SDavid du Colombier long 3523ff48bf5SDavid du Colombier writen(int fd, void *buf, long n) 3533ff48bf5SDavid du Colombier { 3543ff48bf5SDavid du Colombier /* write 8k at a time, to be nice to the disk subsystem */ 3553ff48bf5SDavid du Colombier 3563ff48bf5SDavid du Colombier long m, tot; 3573ff48bf5SDavid du Colombier 3583ff48bf5SDavid du Colombier for(tot=0; tot<n; tot+=m){ 3593ff48bf5SDavid du Colombier m = n - tot; 3603ff48bf5SDavid du Colombier if(m > 8192) 3613ff48bf5SDavid du Colombier m = 8192; 3623ff48bf5SDavid du Colombier if(write(fd, (uchar*)buf+tot, m) != m) 3633ff48bf5SDavid du Colombier break; 3643ff48bf5SDavid du Colombier } 3653ff48bf5SDavid du Colombier return tot; 3663ff48bf5SDavid du Colombier } 3673ff48bf5SDavid du Colombier 3687dd7cddfSDavid du Colombier void 3697dd7cddfSDavid du Colombier dosfs(int dofat, int dopbs, Disk *disk, char *label, int argc, char *argv[], int commit) 370bd389b36SDavid du Colombier { 371bd389b36SDavid du Colombier char r[16]; 372bd389b36SDavid du Colombier Dosboot *b; 3737dd7cddfSDavid du Colombier uchar *buf, *pbsbuf, *p; 3749a747e4fSDavid du Colombier Dir *d; 3753ff48bf5SDavid du Colombier int i, data, newclusters, npbs, n, sysfd; 3767dd7cddfSDavid du Colombier ulong x; 3777dd7cddfSDavid du Colombier vlong length; 3787dd7cddfSDavid du Colombier vlong secsize; 379bd389b36SDavid du Colombier 3807dd7cddfSDavid du Colombier if(dofat == 0 && dopbs == 0) 3817dd7cddfSDavid du Colombier return; 382bd389b36SDavid du Colombier 383219b2ee8SDavid du Colombier for(t = floppytype; t < &floppytype[NTYPES]; t++) 384219b2ee8SDavid du Colombier if(strcmp(type, t->name) == 0) 385219b2ee8SDavid du Colombier break; 386219b2ee8SDavid du Colombier if(t == &floppytype[NTYPES]) 387219b2ee8SDavid du Colombier fatal("unknown floppy type %s", type); 388bd389b36SDavid du Colombier 3897dd7cddfSDavid du Colombier if(t->sectors == 0 && strcmp(type, "hard") == 0) { 3907dd7cddfSDavid du Colombier t->sectors = disk->s; 3917dd7cddfSDavid du Colombier t->heads = disk->h; 3927dd7cddfSDavid du Colombier t->tracks = disk->c; 393bd389b36SDavid du Colombier } 394bd389b36SDavid du Colombier 3957dd7cddfSDavid du Colombier if(t->sectors == 0 && dofat) 3967dd7cddfSDavid du Colombier fatal("cannot format fat with type %s: geometry unknown\n", type); 3977dd7cddfSDavid du Colombier 3987dd7cddfSDavid du Colombier if(fflag){ 3997dd7cddfSDavid du Colombier disk->size = t->bytes*t->sectors*t->heads*t->tracks; 4007dd7cddfSDavid du Colombier disk->secsize = t->bytes; 4017dd7cddfSDavid du Colombier disk->secs = disk->size / disk->secsize; 4027dd7cddfSDavid du Colombier } 4037dd7cddfSDavid du Colombier 4047dd7cddfSDavid du Colombier secsize = disk->secsize; 4057dd7cddfSDavid du Colombier length = disk->size; 4067dd7cddfSDavid du Colombier 4077dd7cddfSDavid du Colombier buf = malloc(secsize); 408bd389b36SDavid du Colombier if(buf == 0) 409bd389b36SDavid du Colombier fatal("out of memory"); 410bd389b36SDavid du Colombier 411bd389b36SDavid du Colombier /* 4127dd7cddfSDavid du Colombier * Make disk full size if a file. 413bd389b36SDavid du Colombier */ 4149a747e4fSDavid du Colombier if(fflag && disk->type == Tfile){ 4159a747e4fSDavid du Colombier if((d = dirfstat(disk->wfd)) == nil) 4167dd7cddfSDavid du Colombier fatal("fstat disk: %r"); 4179a747e4fSDavid du Colombier if(commit && d->length < disk->size) { 4187dd7cddfSDavid du Colombier if(seek(disk->wfd, disk->size-1, 0) < 0) 4197dd7cddfSDavid du Colombier fatal("seek to 9: %r"); 4207dd7cddfSDavid du Colombier if(write(disk->wfd, "9", 1) < 0) 4217dd7cddfSDavid du Colombier fatal("writing 9: @%lld %r", seek(disk->wfd, 0LL, 1)); 422219b2ee8SDavid du Colombier } 4239a747e4fSDavid du Colombier free(d); 4247dd7cddfSDavid du Colombier } 4257dd7cddfSDavid du Colombier 4267dd7cddfSDavid du Colombier /* 4277dd7cddfSDavid du Colombier * Start with initial sector from disk 4287dd7cddfSDavid du Colombier */ 4297dd7cddfSDavid du Colombier if(seek(disk->fd, 0, 0) < 0) 4307dd7cddfSDavid du Colombier fatal("seek to boot sector: %r\n"); 4317dd7cddfSDavid du Colombier if(commit && read(disk->fd, buf, secsize) != secsize) 4327dd7cddfSDavid du Colombier fatal("reading boot sector: %r"); 4337dd7cddfSDavid du Colombier 4347dd7cddfSDavid du Colombier if(dofat) 4357dd7cddfSDavid du Colombier memset(buf, 0, sizeof(Dosboot)); 4367dd7cddfSDavid du Colombier 4377dd7cddfSDavid du Colombier /* 4387dd7cddfSDavid du Colombier * Jump instruction and OEM name. 4397dd7cddfSDavid du Colombier */ 440bd389b36SDavid du Colombier b = (Dosboot*)buf; 441219b2ee8SDavid du Colombier b->magic[0] = 0xEB; 442219b2ee8SDavid du Colombier b->magic[1] = 0x3C; 443219b2ee8SDavid du Colombier b->magic[2] = 0x90; 444219b2ee8SDavid du Colombier memmove(b->version, "Plan9.00", sizeof(b->version)); 4457dd7cddfSDavid du Colombier 4467dd7cddfSDavid du Colombier /* 4477dd7cddfSDavid du Colombier * Add bootstrapping code; assume it starts 4487dd7cddfSDavid du Colombier * at 0x3E (the destination of the jump we just 4497dd7cddfSDavid du Colombier * wrote to b->magic). 4507dd7cddfSDavid du Colombier */ 4517dd7cddfSDavid du Colombier if(dopbs) { 4527dd7cddfSDavid du Colombier pbsbuf = malloc(secsize); 4537dd7cddfSDavid du Colombier if(pbsbuf == 0) 4547dd7cddfSDavid du Colombier fatal("out of memory"); 4557dd7cddfSDavid du Colombier 4567dd7cddfSDavid du Colombier if(pbs){ 4577dd7cddfSDavid du Colombier if((sysfd = open(pbs, OREAD)) < 0) 4587dd7cddfSDavid du Colombier fatal("open %s: %r", pbs); 4597dd7cddfSDavid du Colombier if((npbs = read(sysfd, pbsbuf, secsize)) < 0) 4607dd7cddfSDavid du Colombier fatal("read %s: %r", pbs); 4617dd7cddfSDavid du Colombier 4627dd7cddfSDavid du Colombier if(npbs > secsize-2) 4637dd7cddfSDavid du Colombier fatal("boot block too large"); 4647dd7cddfSDavid du Colombier 4657dd7cddfSDavid du Colombier close(sysfd); 4667dd7cddfSDavid du Colombier } 4677dd7cddfSDavid du Colombier else { 4687dd7cddfSDavid du Colombier memmove(pbsbuf, bootprog, sizeof(bootprog)); 4697dd7cddfSDavid du Colombier npbs = nbootprog; 4707dd7cddfSDavid du Colombier } 4717dd7cddfSDavid du Colombier if(npbs <= 0x3E) 4727dd7cddfSDavid du Colombier fprint(2, "warning: pbs too small\n"); 4737dd7cddfSDavid du Colombier else 4747dd7cddfSDavid du Colombier memmove(buf+0x3E, pbsbuf+0x3E, npbs-0x3E); 4757dd7cddfSDavid du Colombier 4767dd7cddfSDavid du Colombier free(pbsbuf); 4777dd7cddfSDavid du Colombier } 4787dd7cddfSDavid du Colombier 4797dd7cddfSDavid du Colombier /* 4807dd7cddfSDavid du Colombier * Add FAT BIOS parameter block. 4817dd7cddfSDavid du Colombier */ 4827dd7cddfSDavid du Colombier if(dofat) { 4837dd7cddfSDavid du Colombier if(commit) { 484*f8d0ebfeSDavid du Colombier print("Initializing FAT file system\n"); 4857dd7cddfSDavid du Colombier print("type %s, %d tracks, %d heads, %d sectors/track, %lld bytes/sec\n", 4867dd7cddfSDavid du Colombier t->name, t->tracks, t->heads, t->sectors, secsize); 4877dd7cddfSDavid du Colombier } 4887dd7cddfSDavid du Colombier 4897dd7cddfSDavid du Colombier if(clustersize == 0) 4907dd7cddfSDavid du Colombier clustersize = t->cluster; 4913ff48bf5SDavid du Colombier /* 4923ff48bf5SDavid du Colombier * the number of fat bits depends on how much disk is left 4933ff48bf5SDavid du Colombier * over after you subtract out the space taken up by the fat tables. 4943ff48bf5SDavid du Colombier * try both. what a crock. 4953ff48bf5SDavid du Colombier */ 4967dd7cddfSDavid du Colombier fatbits = 12; 4973ff48bf5SDavid du Colombier Tryagain: 4987dd7cddfSDavid du Colombier volsecs = length/secsize; 4993ff48bf5SDavid du Colombier /* 5003ff48bf5SDavid du Colombier * here's a crock inside a crock. even having fixed fatbits, 5013ff48bf5SDavid du Colombier * the number of fat sectors depends on the number of clusters, 5023ff48bf5SDavid du Colombier * but of course we don't know yet. maybe iterating will get us there. 5033ff48bf5SDavid du Colombier * or maybe it will cycle. 5043ff48bf5SDavid du Colombier */ 5053ff48bf5SDavid du Colombier clusters = 0; 5063ff48bf5SDavid du Colombier for(i=0;; i++){ 5077dd7cddfSDavid du Colombier fatsecs = (fatbits*clusters + 8*secsize - 1)/(8*secsize); 5087dd7cddfSDavid du Colombier rootsecs = volsecs/200; 5097dd7cddfSDavid du Colombier rootfiles = rootsecs * (secsize/sizeof(Dosdir)); 5107dd7cddfSDavid du Colombier if(rootfiles > 512){ 5117dd7cddfSDavid du Colombier rootfiles = 512; 5127dd7cddfSDavid du Colombier rootsecs = rootfiles/(secsize/sizeof(Dosdir)); 5137dd7cddfSDavid du Colombier } 5143ff48bf5SDavid du Colombier data = nresrv + 2*fatsecs + (rootfiles*sizeof(Dosdir) + secsize-1)/secsize; 5153ff48bf5SDavid du Colombier newclusters = 2 + (volsecs - data)/clustersize; 5163ff48bf5SDavid du Colombier if(newclusters == clusters) 5173ff48bf5SDavid du Colombier break; 5183ff48bf5SDavid du Colombier clusters = newclusters; 5193ff48bf5SDavid du Colombier if(i > 10) 5203ff48bf5SDavid du Colombier fatal("can't decide how many clusters to use (%d? %d?)", clusters, newclusters); 5213ff48bf5SDavid du Colombier if(chatty) print("clusters %d\n", clusters); 5223ff48bf5SDavid du Colombier } 5237dd7cddfSDavid du Colombier 5243ff48bf5SDavid du Colombier if(chatty) print("try %d fatbits => %d clusters of %d\n", fatbits, clusters, clustersize); 5253ff48bf5SDavid du Colombier switch(fatbits){ 5263ff48bf5SDavid du Colombier case 12: 5273ff48bf5SDavid du Colombier if(clusters >= 4087){ 5283ff48bf5SDavid du Colombier fatbits = 16; 5293ff48bf5SDavid du Colombier goto Tryagain; 5303ff48bf5SDavid du Colombier } 5313ff48bf5SDavid du Colombier break; 5323ff48bf5SDavid du Colombier case 16: 5333ff48bf5SDavid du Colombier if(clusters >= 65527) 5343ff48bf5SDavid du Colombier fatal("disk too big; implement fat32"); 5353ff48bf5SDavid du Colombier break; 5363ff48bf5SDavid du Colombier } 5377dd7cddfSDavid du Colombier PUTSHORT(b->sectsize, secsize); 538bd389b36SDavid du Colombier b->clustsize = clustersize; 5397dd7cddfSDavid du Colombier PUTSHORT(b->nresrv, nresrv); 540bd389b36SDavid du Colombier b->nfats = 2; 541bd389b36SDavid du Colombier PUTSHORT(b->rootsize, rootfiles); 5427dd7cddfSDavid du Colombier if(volsecs < (1<<16)) 543bd389b36SDavid du Colombier PUTSHORT(b->volsize, volsecs); 544bd389b36SDavid du Colombier b->mediadesc = t->media; 545bd389b36SDavid du Colombier PUTSHORT(b->fatsize, fatsecs); 546bd389b36SDavid du Colombier PUTSHORT(b->trksize, t->sectors); 547bd389b36SDavid du Colombier PUTSHORT(b->nheads, t->heads); 5487dd7cddfSDavid du Colombier PUTLONG(b->nhidden, disk->offset); 5497dd7cddfSDavid du Colombier PUTLONG(b->bigvolsize, volsecs); 5507dd7cddfSDavid du Colombier 5517dd7cddfSDavid du Colombier /* 5527dd7cddfSDavid du Colombier * Extended BIOS Parameter Block. 5537dd7cddfSDavid du Colombier */ 5547dd7cddfSDavid du Colombier if(t->media == 0xF8) 5557dd7cddfSDavid du Colombier b->driveno = getdriveno(disk); 5567dd7cddfSDavid du Colombier else 557bd389b36SDavid du Colombier b->driveno = 0; 5587dd7cddfSDavid du Colombier if(chatty) print("driveno = %ux\n", b->driveno); 5597dd7cddfSDavid du Colombier 560bd389b36SDavid du Colombier b->bootsig = 0x29; 5617dd7cddfSDavid du Colombier x = disk->offset + b->nfats*fatsecs + nresrv; 562bd389b36SDavid du Colombier PUTLONG(b->volid, x); 5637dd7cddfSDavid du Colombier if(chatty) print("volid = %lux %lux\n", x, GETLONG(b->volid)); 564bd389b36SDavid du Colombier memmove(b->label, label, sizeof(b->label)); 565bd389b36SDavid du Colombier sprint(r, "FAT%d ", fatbits); 566219b2ee8SDavid du Colombier memmove(b->type, r, sizeof(b->type)); 5677dd7cddfSDavid du Colombier } 5687dd7cddfSDavid du Colombier 5697dd7cddfSDavid du Colombier buf[secsize-2] = 0x55; 5707dd7cddfSDavid du Colombier buf[secsize-1] = 0xAA; 5717dd7cddfSDavid du Colombier 5727dd7cddfSDavid du Colombier if(commit) { 5737dd7cddfSDavid du Colombier if(seek(disk->wfd, 0, 0) < 0) 574219b2ee8SDavid du Colombier fatal("seek to boot sector: %r\n"); 5757dd7cddfSDavid du Colombier if(write(disk->wfd, buf, secsize) != secsize) 576bd389b36SDavid du Colombier fatal("writing boot sector: %r"); 5777dd7cddfSDavid du Colombier } 5787dd7cddfSDavid du Colombier 579bd389b36SDavid du Colombier free(buf); 580bd389b36SDavid du Colombier 581bd389b36SDavid du Colombier /* 5827dd7cddfSDavid du Colombier * If we were only called to write the PBS, leave now. 5837dd7cddfSDavid du Colombier */ 5847dd7cddfSDavid du Colombier if(dofat == 0) 5857dd7cddfSDavid du Colombier return; 5867dd7cddfSDavid du Colombier 5877dd7cddfSDavid du Colombier /* 588bd389b36SDavid du Colombier * allocate an in memory fat 589bd389b36SDavid du Colombier */ 5907dd7cddfSDavid du Colombier if(seek(disk->wfd, nresrv*secsize, 0) < 0) 5917dd7cddfSDavid du Colombier fatal("seek to fat: %r\n"); 5927dd7cddfSDavid du Colombier if(chatty) print("fat @%lluX\n", seek(disk->wfd, 0, 1)); 5937dd7cddfSDavid du Colombier fat = malloc(fatsecs*secsize); 594bd389b36SDavid du Colombier if(fat == 0) 595bd389b36SDavid du Colombier fatal("out of memory"); 5967dd7cddfSDavid du Colombier memset(fat, 0, fatsecs*secsize); 597bd389b36SDavid du Colombier fat[0] = t->media; 598bd389b36SDavid du Colombier fat[1] = 0xff; 599bd389b36SDavid du Colombier fat[2] = 0xff; 600bd389b36SDavid du Colombier if(fatbits == 16) 601bd389b36SDavid du Colombier fat[3] = 0xff; 602bd389b36SDavid du Colombier fatlast = 1; 6037dd7cddfSDavid du Colombier if(seek(disk->wfd, 2*fatsecs*secsize, 1) < 0) /* 2 fats */ 6047dd7cddfSDavid du Colombier fatal("seek to root: %r"); 6057dd7cddfSDavid du Colombier if(chatty) print("root @%lluX\n", seek(disk->wfd, 0LL, 1)); 606bd389b36SDavid du Colombier 607bd389b36SDavid du Colombier /* 608bd389b36SDavid du Colombier * allocate an in memory root 609bd389b36SDavid du Colombier */ 6107dd7cddfSDavid du Colombier root = malloc(rootsecs*secsize); 611bd389b36SDavid du Colombier if(root == 0) 612bd389b36SDavid du Colombier fatal("out of memory"); 6137dd7cddfSDavid du Colombier memset(root, 0, rootsecs*secsize); 6147dd7cddfSDavid du Colombier if(seek(disk->wfd, rootsecs*secsize, 1) < 0) /* rootsecs */ 6157dd7cddfSDavid du Colombier fatal("seek to files: %r"); 6167dd7cddfSDavid du Colombier if(chatty) print("files @%lluX\n", seek(disk->wfd, 0LL, 1)); 617bd389b36SDavid du Colombier 618bd389b36SDavid du Colombier /* 619219b2ee8SDavid du Colombier * Now positioned at the Files Area. 620219b2ee8SDavid du Colombier * If we have any arguments, process 621219b2ee8SDavid du Colombier * them and write out. 622bd389b36SDavid du Colombier */ 623219b2ee8SDavid du Colombier for(p = root; argc > 0; argc--, argv++, p += sizeof(Dosdir)){ 6247dd7cddfSDavid du Colombier if(p >= (root+(rootsecs*secsize))) 625219b2ee8SDavid du Colombier fatal("too many files in root"); 626219b2ee8SDavid du Colombier /* 627219b2ee8SDavid du Colombier * Open the file and get its length. 628219b2ee8SDavid du Colombier */ 629219b2ee8SDavid du Colombier if((sysfd = open(*argv, OREAD)) < 0) 630219b2ee8SDavid du Colombier fatal("open %s: %r", *argv); 6319a747e4fSDavid du Colombier if((d = dirfstat(sysfd)) == nil) 632219b2ee8SDavid du Colombier fatal("stat %s: %r", *argv); 6339a747e4fSDavid du Colombier if(d->length > 0xFFFFFFFF) 6349a747e4fSDavid du Colombier fatal("file %s too big\n", *argv, d->length); 6357dd7cddfSDavid du Colombier if(commit) 6369a747e4fSDavid du Colombier print("Adding file %s, length %lld\n", *argv, d->length); 637219b2ee8SDavid du Colombier 6389a747e4fSDavid du Colombier length = d->length; 639219b2ee8SDavid du Colombier if(length){ 640219b2ee8SDavid du Colombier /* 641219b2ee8SDavid du Colombier * Allocate a buffer to read the entire file into. 642219b2ee8SDavid du Colombier * This must be rounded up to a cluster boundary. 643219b2ee8SDavid du Colombier * 644219b2ee8SDavid du Colombier * Read the file and write it out to the Files Area. 645219b2ee8SDavid du Colombier */ 6467dd7cddfSDavid du Colombier length += secsize*clustersize - 1; 6477dd7cddfSDavid du Colombier length /= secsize*clustersize; 6487dd7cddfSDavid du Colombier length *= secsize*clustersize; 649219b2ee8SDavid du Colombier if((buf = malloc(length)) == 0) 650219b2ee8SDavid du Colombier fatal("out of memory"); 651219b2ee8SDavid du Colombier 6523ff48bf5SDavid du Colombier if(readn(sysfd, buf, d->length) != d->length) 653219b2ee8SDavid du Colombier fatal("read %s: %r", *argv); 6549a747e4fSDavid du Colombier memset(buf+d->length, 0, length-d->length); 6559a747e4fSDavid du Colombier if(chatty) print("%s @%lluX\n", d->name, seek(disk->wfd, 0LL, 1)); 6563ff48bf5SDavid du Colombier if(commit && writen(disk->wfd, buf, length) != length) 657219b2ee8SDavid du Colombier fatal("write %s: %r", *argv); 658219b2ee8SDavid du Colombier free(buf); 659219b2ee8SDavid du Colombier 660219b2ee8SDavid du Colombier close(sysfd); 661219b2ee8SDavid du Colombier 662219b2ee8SDavid du Colombier /* 663219b2ee8SDavid du Colombier * Allocate the FAT clusters. 664219b2ee8SDavid du Colombier * We're assuming here that where we 665219b2ee8SDavid du Colombier * wrote the file is in sync with 666219b2ee8SDavid du Colombier * the cluster allocation. 667219b2ee8SDavid du Colombier * Save the starting cluster. 668219b2ee8SDavid du Colombier */ 6697dd7cddfSDavid du Colombier length /= secsize*clustersize; 670219b2ee8SDavid du Colombier x = clustalloc(Sof); 671219b2ee8SDavid du Colombier for(n = 0; n < length-1; n++) 672219b2ee8SDavid du Colombier clustalloc(0); 673219b2ee8SDavid du Colombier clustalloc(Eof); 674219b2ee8SDavid du Colombier } 675219b2ee8SDavid du Colombier else 676219b2ee8SDavid du Colombier x = 0; 677219b2ee8SDavid du Colombier 678219b2ee8SDavid du Colombier /* 679219b2ee8SDavid du Colombier * Add the filename to the root. 680219b2ee8SDavid du Colombier */ 6813ff48bf5SDavid du Colombier fprint(2, "add %s at clust %lux\n", d->name, x); 6829a747e4fSDavid du Colombier addrname(p, d, *argv, x); 6839a747e4fSDavid du Colombier free(d); 684219b2ee8SDavid du Colombier } 685bd389b36SDavid du Colombier 686bd389b36SDavid du Colombier /* 687bd389b36SDavid du Colombier * write the fats and root 688bd389b36SDavid du Colombier */ 6897dd7cddfSDavid du Colombier if(commit) { 6907dd7cddfSDavid du Colombier if(seek(disk->wfd, nresrv*secsize, 0) < 0) 6917dd7cddfSDavid du Colombier fatal("seek to fat #1: %r"); 6927dd7cddfSDavid du Colombier if(write(disk->wfd, fat, fatsecs*secsize) < 0) 693bd389b36SDavid du Colombier fatal("writing fat #1: %r"); 6947dd7cddfSDavid du Colombier if(write(disk->wfd, fat, fatsecs*secsize) < 0) 695bd389b36SDavid du Colombier fatal("writing fat #2: %r"); 6967dd7cddfSDavid du Colombier if(write(disk->wfd, root, rootsecs*secsize) < 0) 697bd389b36SDavid du Colombier fatal("writing root: %r"); 698219b2ee8SDavid du Colombier } 6997dd7cddfSDavid du Colombier 7007dd7cddfSDavid du Colombier free(fat); 7017dd7cddfSDavid du Colombier free(root); 702bd389b36SDavid du Colombier } 703bd389b36SDavid du Colombier 704bd389b36SDavid du Colombier /* 705bd389b36SDavid du Colombier * allocate a cluster 706bd389b36SDavid du Colombier */ 707bd389b36SDavid du Colombier ulong 708bd389b36SDavid du Colombier clustalloc(int flag) 709bd389b36SDavid du Colombier { 710bd389b36SDavid du Colombier ulong o, x; 711bd389b36SDavid du Colombier 712bd389b36SDavid du Colombier if(flag != Sof){ 713bd389b36SDavid du Colombier x = (flag == Eof) ? 0xffff : (fatlast+1); 714bd389b36SDavid du Colombier if(fatbits == 12){ 715bd389b36SDavid du Colombier x &= 0xfff; 716bd389b36SDavid du Colombier o = (3*fatlast)/2; 717bd389b36SDavid du Colombier if(fatlast & 1){ 718bd389b36SDavid du Colombier fat[o] = (fat[o]&0x0f) | (x<<4); 719219b2ee8SDavid du Colombier fat[o+1] = (x>>4); 720bd389b36SDavid du Colombier } else { 721bd389b36SDavid du Colombier fat[o] = x; 722219b2ee8SDavid du Colombier fat[o+1] = (fat[o+1]&0xf0) | ((x>>8) & 0x0F); 723bd389b36SDavid du Colombier } 724bd389b36SDavid du Colombier } else { 725bd389b36SDavid du Colombier o = 2*fatlast; 726bd389b36SDavid du Colombier fat[o] = x; 727bd389b36SDavid du Colombier fat[o+1] = x>>8; 728bd389b36SDavid du Colombier } 729bd389b36SDavid du Colombier } 730bd389b36SDavid du Colombier 731bd389b36SDavid du Colombier if(flag == Eof) 732bd389b36SDavid du Colombier return 0; 7339a747e4fSDavid du Colombier else{ 7349a747e4fSDavid du Colombier ++fatlast; 7359a747e4fSDavid du Colombier if(fatlast >= clusters) 7369a747e4fSDavid du Colombier sysfatal("data does not fit on disk (%d %d)", fatlast, clusters); 7379a747e4fSDavid du Colombier return fatlast; 7389a747e4fSDavid du Colombier } 739bd389b36SDavid du Colombier } 740bd389b36SDavid du Colombier 741bd389b36SDavid du Colombier void 742219b2ee8SDavid du Colombier putname(char *p, Dosdir *d) 743bd389b36SDavid du Colombier { 744219b2ee8SDavid du Colombier int i; 745bd389b36SDavid du Colombier 746219b2ee8SDavid du Colombier memset(d->name, ' ', sizeof d->name+sizeof d->ext); 747219b2ee8SDavid du Colombier for(i = 0; i< sizeof(d->name); i++){ 748219b2ee8SDavid du Colombier if(*p == 0 || *p == '.') 749bd389b36SDavid du Colombier break; 750219b2ee8SDavid du Colombier d->name[i] = toupper(*p++); 751bd389b36SDavid du Colombier } 752219b2ee8SDavid du Colombier p = strrchr(p, '.'); 753219b2ee8SDavid du Colombier if(p){ 754219b2ee8SDavid du Colombier for(i = 0; i < sizeof d->ext; i++){ 755219b2ee8SDavid du Colombier if(*++p == 0) 756219b2ee8SDavid du Colombier break; 757219b2ee8SDavid du Colombier d->ext[i] = toupper(*p); 758219b2ee8SDavid du Colombier } 759219b2ee8SDavid du Colombier } 760219b2ee8SDavid du Colombier } 761bd389b36SDavid du Colombier 762219b2ee8SDavid du Colombier void 763219b2ee8SDavid du Colombier puttime(Dosdir *d) 764219b2ee8SDavid du Colombier { 765219b2ee8SDavid du Colombier Tm *t = localtime(time(0)); 766219b2ee8SDavid du Colombier ushort x; 767219b2ee8SDavid du Colombier 768219b2ee8SDavid du Colombier x = (t->hour<<11) | (t->min<<5) | (t->sec>>1); 769219b2ee8SDavid du Colombier d->time[0] = x; 770219b2ee8SDavid du Colombier d->time[1] = x>>8; 771219b2ee8SDavid du Colombier x = ((t->year-80)<<9) | ((t->mon+1)<<5) | t->mday; 772219b2ee8SDavid du Colombier d->date[0] = x; 773219b2ee8SDavid du Colombier d->date[1] = x>>8; 774219b2ee8SDavid du Colombier } 775219b2ee8SDavid du Colombier 776219b2ee8SDavid du Colombier void 7779a747e4fSDavid du Colombier addrname(uchar *entry, Dir *dir, char *name, ulong start) 778219b2ee8SDavid du Colombier { 7799a747e4fSDavid du Colombier char *s; 780219b2ee8SDavid du Colombier Dosdir *d; 781219b2ee8SDavid du Colombier 7829a747e4fSDavid du Colombier s = strrchr(name, '/'); 7839a747e4fSDavid du Colombier if(s) 7849a747e4fSDavid du Colombier s++; 7859a747e4fSDavid du Colombier else 7869a747e4fSDavid du Colombier s = name; 7879a747e4fSDavid du Colombier 788219b2ee8SDavid du Colombier d = (Dosdir*)entry; 7899a747e4fSDavid du Colombier putname(s, d); 7909a747e4fSDavid du Colombier if(strcmp(s, "9load") == 0) 7917dd7cddfSDavid du Colombier d->attr = DSYSTEM; 7927dd7cddfSDavid du Colombier else 7937dd7cddfSDavid du Colombier d->attr = 0; 794219b2ee8SDavid du Colombier puttime(d); 795219b2ee8SDavid du Colombier d->start[0] = start; 796219b2ee8SDavid du Colombier d->start[1] = start>>8; 797219b2ee8SDavid du Colombier d->length[0] = dir->length; 798219b2ee8SDavid du Colombier d->length[1] = dir->length>>8; 799219b2ee8SDavid du Colombier d->length[2] = dir->length>>16; 800219b2ee8SDavid du Colombier d->length[3] = dir->length>>24; 801bd389b36SDavid du Colombier } 802