1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 3bd389b36SDavid du Colombier 4bd389b36SDavid du Colombier /* 5bd389b36SDavid du Colombier * floppy types (all MFM encoding) 6bd389b36SDavid du Colombier */ 7bd389b36SDavid du Colombier typedef struct Type Type; 8bd389b36SDavid du Colombier struct Type 9bd389b36SDavid du Colombier { 10bd389b36SDavid du Colombier char *name; 11bd389b36SDavid du Colombier int bytes; /* bytes/sector */ 12bd389b36SDavid du Colombier int sectors; /* sectors/track */ 13bd389b36SDavid du Colombier int heads; /* number of heads */ 14bd389b36SDavid du Colombier int tracks; /* tracks/disk */ 15bd389b36SDavid du Colombier int media; /* media descriptor byte */ 16bd389b36SDavid du Colombier int cluster; /* default cluster size */ 17bd389b36SDavid du Colombier }; 18bd389b36SDavid du Colombier Type floppytype[] = 19bd389b36SDavid du Colombier { 20bd389b36SDavid du Colombier { "3½HD", 512, 18, 2, 80, 0xf0, 1, }, 21bd389b36SDavid du Colombier { "3½DD", 512, 9, 2, 80, 0xf9, 2, }, 22bd389b36SDavid du Colombier { "5¼HD", 512, 15, 2, 80, 0xf9, 1, }, 23bd389b36SDavid du Colombier { "5¼DD", 512, 9, 2, 40, 0xfd, 2, }, 24bd389b36SDavid du Colombier }; 25bd389b36SDavid du Colombier #define NTYPES (sizeof(floppytype)/sizeof(Type)) 26bd389b36SDavid du Colombier 27bd389b36SDavid du Colombier typedef struct Dosboot Dosboot; 28bd389b36SDavid du Colombier struct Dosboot{ 29bd389b36SDavid du Colombier uchar magic[3]; /* really an xx86 JMP instruction */ 30bd389b36SDavid du Colombier uchar version[8]; 31bd389b36SDavid du Colombier uchar sectsize[2]; 32bd389b36SDavid du Colombier uchar clustsize; 33bd389b36SDavid du Colombier uchar nresrv[2]; 34bd389b36SDavid du Colombier uchar nfats; 35bd389b36SDavid du Colombier uchar rootsize[2]; 36bd389b36SDavid du Colombier uchar volsize[2]; 37bd389b36SDavid du Colombier uchar mediadesc; 38bd389b36SDavid du Colombier uchar fatsize[2]; 39bd389b36SDavid du Colombier uchar trksize[2]; 40bd389b36SDavid du Colombier uchar nheads[2]; 41bd389b36SDavid du Colombier uchar nhidden[4]; 42bd389b36SDavid du Colombier uchar bigvolsize[4]; 43bd389b36SDavid du Colombier uchar driveno; 44bd389b36SDavid du Colombier uchar reserved0; 45bd389b36SDavid du Colombier uchar bootsig; 46bd389b36SDavid du Colombier uchar volid[4]; 47bd389b36SDavid du Colombier uchar label[11]; 48*219b2ee8SDavid du Colombier uchar type[8]; 49bd389b36SDavid du Colombier }; 50bd389b36SDavid du Colombier #define PUTSHORT(p, v) { (p)[1] = (v)>>8; (p)[0] = (v); } 51bd389b36SDavid du Colombier #define PUTLONG(p, v) { PUTSHORT((p), (v)); PUTSHORT((p)+2, (v)>>16); } 52bd389b36SDavid du Colombier 53bd389b36SDavid du Colombier typedef struct Dosdir Dosdir; 54bd389b36SDavid du Colombier struct Dosdir 55bd389b36SDavid du Colombier { 56bd389b36SDavid du Colombier uchar name[8]; 57bd389b36SDavid du Colombier uchar ext[3]; 58bd389b36SDavid du Colombier uchar attr; 59bd389b36SDavid du Colombier uchar reserved[10]; 60bd389b36SDavid du Colombier uchar time[2]; 61bd389b36SDavid du Colombier uchar date[2]; 62bd389b36SDavid du Colombier uchar start[2]; 63bd389b36SDavid du Colombier uchar length[4]; 64bd389b36SDavid du Colombier }; 65bd389b36SDavid du Colombier 66bd389b36SDavid du Colombier #define DRONLY 0x01 67bd389b36SDavid du Colombier #define DHIDDEN 0x02 68bd389b36SDavid du Colombier #define DSYSTEM 0x04 69bd389b36SDavid du Colombier #define DVLABEL 0x08 70bd389b36SDavid du Colombier #define DDIR 0x10 71bd389b36SDavid du Colombier #define DARCH 0x20 72bd389b36SDavid du Colombier 73bd389b36SDavid du Colombier /* 74*219b2ee8SDavid du Colombier * the boot program for the boot sector. 75bd389b36SDavid du Colombier */ 76bd389b36SDavid du Colombier uchar bootprog[512] = 77bd389b36SDavid du Colombier { 78*219b2ee8SDavid du Colombier [0x000] 0xEB, 0x3C, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 79bd389b36SDavid du Colombier 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 80*219b2ee8SDavid du Colombier [0x03E] 0xFA, 0xFC, 0x8C, 0xC8, 0x8E, 0xD8, 0x8E, 0xD0, 81*219b2ee8SDavid du Colombier 0xBC, 0x00, 0x7C, 0xBE, 0x77, 0x7C, 0xE8, 0x19, 82*219b2ee8SDavid du Colombier 0x00, 0x33, 0xC0, 0xCD, 0x16, 0xBB, 0x40, 0x00, 83*219b2ee8SDavid du Colombier 0x8E, 0xC3, 0xBB, 0x72, 0x00, 0xB8, 0x34, 0x12, 84*219b2ee8SDavid du Colombier 0x26, 0x89, 0x07, 0xEA, 0x00, 0x00, 0xFF, 0xFF, 85*219b2ee8SDavid du Colombier 0xEB, 0xD6, 0xAC, 0x0A, 0xC0, 0x74, 0x09, 0xB4, 86*219b2ee8SDavid du Colombier 0x0E, 0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xF2, 87*219b2ee8SDavid du Colombier 0xC3, 'N', 'o', 't', ' ', 'a', ' ', 'b', 88*219b2ee8SDavid du Colombier 'o', 'o', 't', 'a', 'b', 'l', 'e', ' ', 89*219b2ee8SDavid du Colombier 'd', 'i', 's', 'c', ' ', 'o', 'r', ' ', 90*219b2ee8SDavid du Colombier 'd', 'i', 's', 'c', ' ', 'e', 'r', 'r', 91*219b2ee8SDavid du Colombier 'o', 'r', '\r', '\n', 'P', 'r', 'e', 's', 92*219b2ee8SDavid du Colombier 's', ' ', 'a', 'l', 'm', 'o', 's', 't', 93*219b2ee8SDavid du Colombier ' ', 'a', 'n', 'y', ' ', 'k', 'e', 'y', 94*219b2ee8SDavid du Colombier ' ', 't', 'o', ' ', 'r', 'e', 'b', 'o', 95*219b2ee8SDavid du Colombier 'o', 't', '.', '.', '.', 0x00, 0x00, 0x00, 96*219b2ee8SDavid du Colombier [0x1F0] 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 97*219b2ee8SDavid du Colombier 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA, 98bd389b36SDavid du Colombier }; 99bd389b36SDavid du Colombier 100bd389b36SDavid du Colombier char *dev; 101bd389b36SDavid du Colombier int clustersize; 102bd389b36SDavid du Colombier uchar *fat; /* the fat */ 103bd389b36SDavid du Colombier int fatbits; 104bd389b36SDavid du Colombier int fatsecs; 105bd389b36SDavid du Colombier int fatlast; /* last cluster allocated */ 106bd389b36SDavid du Colombier int clusters; 107bd389b36SDavid du Colombier int fatsecs; 108bd389b36SDavid du Colombier int volsecs; 109bd389b36SDavid du Colombier uchar *root; /* first block of root */ 110bd389b36SDavid du Colombier int rootsecs; 111bd389b36SDavid du Colombier int rootfiles; 112bd389b36SDavid du Colombier int rootnext; 113bd389b36SDavid du Colombier Type *t; 114*219b2ee8SDavid du Colombier int fflag; 115*219b2ee8SDavid du Colombier char file[64]; /* output file name */ 116*219b2ee8SDavid du Colombier char *bootfile; 117*219b2ee8SDavid du Colombier char *type; 118bd389b36SDavid du Colombier 119bd389b36SDavid du Colombier enum 120bd389b36SDavid du Colombier { 121bd389b36SDavid du Colombier Sof = 1, /* start of file */ 122bd389b36SDavid du Colombier Eof = 2, /* end of file */ 123bd389b36SDavid du Colombier }; 124bd389b36SDavid du Colombier 125bd389b36SDavid du Colombier 126*219b2ee8SDavid du Colombier void dosfs(int, char*, int, char*[]); 127bd389b36SDavid du Colombier ulong clustalloc(int); 128*219b2ee8SDavid du Colombier void addrname(uchar*, Dir*, ulong); 129bd389b36SDavid du Colombier 130bd389b36SDavid du Colombier void 131bd389b36SDavid du Colombier usage(void) 132bd389b36SDavid du Colombier { 133*219b2ee8SDavid du Colombier fprint(2, "usage: format [-b bfile] [-c csize] [-df] [-l label] [-t type] file [args ...]\n"); 134bd389b36SDavid du Colombier exits("usage"); 135bd389b36SDavid du Colombier } 136bd389b36SDavid du Colombier 137bd389b36SDavid du Colombier void 138bd389b36SDavid du Colombier fatal(char *fmt, ...) 139bd389b36SDavid du Colombier { 140bd389b36SDavid du Colombier int n; 141bd389b36SDavid du Colombier char err[128]; 142bd389b36SDavid du Colombier 143bd389b36SDavid du Colombier n = doprint(err, err+sizeof(err), fmt, &fmt+1) - err; 144bd389b36SDavid du Colombier err[n] = 0; 145bd389b36SDavid du Colombier fprint(2, "format: %s\n", err); 146*219b2ee8SDavid du Colombier if(fflag && file[0]) 147*219b2ee8SDavid du Colombier remove(file); 148bd389b36SDavid du Colombier exits(err); 149bd389b36SDavid du Colombier } 150bd389b36SDavid du Colombier 151bd389b36SDavid du Colombier void 152bd389b36SDavid du Colombier main(int argc, char **argv) 153bd389b36SDavid du Colombier { 154*219b2ee8SDavid du Colombier int n, dos; 155bd389b36SDavid du Colombier int cfd; 156bd389b36SDavid du Colombier char buf[512]; 157bd389b36SDavid du Colombier char label[11]; 158bd389b36SDavid du Colombier char *a; 159bd389b36SDavid du Colombier 160bd389b36SDavid du Colombier dos = 0; 161*219b2ee8SDavid du Colombier type = 0; 162bd389b36SDavid du Colombier clustersize = 0; 163*219b2ee8SDavid du Colombier memmove(label, "CYLINDRICAL", sizeof(label)); 164bd389b36SDavid du Colombier ARGBEGIN { 165*219b2ee8SDavid du Colombier case 'b': 166*219b2ee8SDavid du Colombier bootfile = ARGF(); 167*219b2ee8SDavid du Colombier break; 168bd389b36SDavid du Colombier case 'd': 169bd389b36SDavid du Colombier dos = 1; 170bd389b36SDavid du Colombier break; 171bd389b36SDavid du Colombier case 'c': 172bd389b36SDavid du Colombier clustersize = atoi(ARGF()); 173bd389b36SDavid du Colombier break; 174*219b2ee8SDavid du Colombier case 'f': 175*219b2ee8SDavid du Colombier fflag = 1; 176*219b2ee8SDavid du Colombier break; 177bd389b36SDavid du Colombier case 'l': 178bd389b36SDavid du Colombier a = ARGF(); 179bd389b36SDavid du Colombier n = strlen(a); 180bd389b36SDavid du Colombier if(n > sizeof(label)) 181bd389b36SDavid du Colombier n = sizeof(label); 182bd389b36SDavid du Colombier memmove(label, a, n); 183*219b2ee8SDavid du Colombier while(n < sizeof(label)) 184*219b2ee8SDavid du Colombier label[n++] = ' '; 185bd389b36SDavid du Colombier break; 186*219b2ee8SDavid du Colombier case 't': 187*219b2ee8SDavid du Colombier type = ARGF(); 188bd389b36SDavid du Colombier break; 189bd389b36SDavid du Colombier default: 190bd389b36SDavid du Colombier usage(); 191bd389b36SDavid du Colombier } ARGEND 192bd389b36SDavid du Colombier 193bd389b36SDavid du Colombier if(argc < 1) 194bd389b36SDavid du Colombier usage(); 195*219b2ee8SDavid du Colombier 196*219b2ee8SDavid du Colombier dev = argv[0]; 197*219b2ee8SDavid du Colombier cfd = -1; 198*219b2ee8SDavid du Colombier if(fflag == 0){ 199bd389b36SDavid du Colombier n = strlen(argv[0]); 200bd389b36SDavid du Colombier if(n > 4 && strcmp(argv[0]+n-4, "disk") == 0) 201bd389b36SDavid du Colombier *(argv[0]+n-4) = 0; 202*219b2ee8SDavid du Colombier else if(n > 3 && strcmp(argv[0]+n-3, "ctl") == 0) 203bd389b36SDavid du Colombier *(argv[0]+n-3) = 0; 204bd389b36SDavid du Colombier 205bd389b36SDavid du Colombier sprint(buf, "%sctl", dev); 206bd389b36SDavid du Colombier cfd = open(buf, ORDWR); 207bd389b36SDavid du Colombier if(cfd < 0) 208bd389b36SDavid du Colombier fatal("opening %s: %r", buf); 209bd389b36SDavid du Colombier print("Formatting floppy %s\n", dev); 210*219b2ee8SDavid du Colombier if(type) 211*219b2ee8SDavid du Colombier sprint(buf, "format %s", type); 212bd389b36SDavid du Colombier else 213bd389b36SDavid du Colombier strcpy(buf, "format"); 214bd389b36SDavid du Colombier if(write(cfd, buf, strlen(buf)) < 0) 215bd389b36SDavid du Colombier fatal("formatting tracks: %r"); 216bd389b36SDavid du Colombier } 217bd389b36SDavid du Colombier 218bd389b36SDavid du Colombier if(dos) 219*219b2ee8SDavid du Colombier dosfs(cfd, label, argc-1, argv+1); 220*219b2ee8SDavid du Colombier if(cfd >= 0) 221bd389b36SDavid du Colombier close(cfd); 222bd389b36SDavid du Colombier exits(0); 223bd389b36SDavid du Colombier } 224bd389b36SDavid du Colombier 225bd389b36SDavid du Colombier void 226*219b2ee8SDavid du Colombier dosfs(int cfd, char *label, int argc, char *argv[]) 227bd389b36SDavid du Colombier { 228bd389b36SDavid du Colombier char r[16]; 229bd389b36SDavid du Colombier Dosboot *b; 230bd389b36SDavid du Colombier uchar *buf; 231bd389b36SDavid du Colombier Dir d; 232*219b2ee8SDavid du Colombier int n, fd, sysfd; 233*219b2ee8SDavid du Colombier ulong length, x; 234*219b2ee8SDavid du Colombier uchar *p; 235bd389b36SDavid du Colombier 236*219b2ee8SDavid du Colombier print("Initialising MS-DOS file system\n"); 237bd389b36SDavid du Colombier 238*219b2ee8SDavid du Colombier if(fflag){ 239*219b2ee8SDavid du Colombier sprint(file, "%s", dev); 240*219b2ee8SDavid du Colombier if((fd = create(dev, ORDWR, 0666)) < 0) 241*219b2ee8SDavid du Colombier fatal("create %s: %r", file); 242*219b2ee8SDavid du Colombier t = floppytype; 243*219b2ee8SDavid du Colombier if(type){ 244*219b2ee8SDavid du Colombier for(t = floppytype; t < &floppytype[NTYPES]; t++) 245*219b2ee8SDavid du Colombier if(strcmp(type, t->name) == 0) 246*219b2ee8SDavid du Colombier break; 247*219b2ee8SDavid du Colombier if(t == &floppytype[NTYPES]) 248*219b2ee8SDavid du Colombier fatal("unknown floppy type %s", type); 249*219b2ee8SDavid du Colombier } 250*219b2ee8SDavid du Colombier length = t->bytes*t->sectors*t->heads*t->tracks; 251*219b2ee8SDavid du Colombier } 252*219b2ee8SDavid du Colombier else{ 253bd389b36SDavid du Colombier sprint(file, "%sdisk", dev); 254bd389b36SDavid du Colombier fd = open(file, ORDWR); 255bd389b36SDavid du Colombier if(fd < 0) 256*219b2ee8SDavid du Colombier fatal("open %s: %r", file); 257bd389b36SDavid du Colombier if(dirfstat(fd, &d) < 0) 258*219b2ee8SDavid du Colombier fatal("stat %s: %r", file); 259*219b2ee8SDavid du Colombier length = d.length; 260bd389b36SDavid du Colombier 261bd389b36SDavid du Colombier t = 0; 262bd389b36SDavid du Colombier seek(cfd, 0, 0); 263bd389b36SDavid du Colombier n = read(cfd, file, sizeof(file)-1); 264bd389b36SDavid du Colombier if(n < 0) 265bd389b36SDavid du Colombier fatal("reading floppy type"); 266bd389b36SDavid du Colombier else { 267bd389b36SDavid du Colombier file[n] = 0; 268bd389b36SDavid du Colombier for(t = floppytype; t < &floppytype[NTYPES]; t++) 269bd389b36SDavid du Colombier if(strcmp(file, t->name) == 0) 270bd389b36SDavid du Colombier break; 271bd389b36SDavid du Colombier if(t == &floppytype[NTYPES]) 272bd389b36SDavid du Colombier fatal("unknown floppy type %s", file); 273bd389b36SDavid du Colombier } 274*219b2ee8SDavid du Colombier } 275bd389b36SDavid du Colombier print("floppy type %s, %d tracks, %d heads, %d sectors/track, %d bytes/sec\n", 276bd389b36SDavid du Colombier t->name, t->tracks, t->heads, t->sectors, t->bytes); 277bd389b36SDavid du Colombier 278bd389b36SDavid du Colombier if(clustersize == 0) 279bd389b36SDavid du Colombier clustersize = t->cluster; 280*219b2ee8SDavid du Colombier clusters = length/(t->bytes*clustersize); 281bd389b36SDavid du Colombier if(clusters < 4087) 282bd389b36SDavid du Colombier fatbits = 12; 283bd389b36SDavid du Colombier else 284bd389b36SDavid du Colombier fatbits = 16; 285*219b2ee8SDavid du Colombier volsecs = length/t->bytes; 286bd389b36SDavid du Colombier fatsecs = (fatbits*clusters + 8*t->bytes - 1)/(8*t->bytes); 287bd389b36SDavid du Colombier rootsecs = volsecs/200; 288*219b2ee8SDavid du Colombier rootfiles = rootsecs * (t->bytes/sizeof(Dosdir)); 289bd389b36SDavid du Colombier buf = malloc(t->bytes); 290bd389b36SDavid du Colombier if(buf == 0) 291bd389b36SDavid du Colombier fatal("out of memory"); 292bd389b36SDavid du Colombier 293bd389b36SDavid du Colombier /* 294bd389b36SDavid du Colombier * write bootstrap & parameter block 295bd389b36SDavid du Colombier */ 296*219b2ee8SDavid du Colombier if(bootfile){ 297*219b2ee8SDavid du Colombier if((sysfd = open(bootfile, OREAD)) < 0) 298*219b2ee8SDavid du Colombier fatal("open %s: %r", bootfile); 299*219b2ee8SDavid du Colombier if(read(sysfd, buf, t->bytes) < 0) 300*219b2ee8SDavid du Colombier fatal("read %s: %r", bootfile); 301*219b2ee8SDavid du Colombier close(sysfd); 302*219b2ee8SDavid du Colombier } 303*219b2ee8SDavid du Colombier else 304bd389b36SDavid du Colombier memmove(buf, bootprog, sizeof(bootprog)); 305bd389b36SDavid du Colombier b = (Dosboot*)buf; 306*219b2ee8SDavid du Colombier b->magic[0] = 0xEB; 307*219b2ee8SDavid du Colombier b->magic[1] = 0x3C; 308*219b2ee8SDavid du Colombier b->magic[2] = 0x90; 309*219b2ee8SDavid du Colombier memmove(b->version, "Plan9.00", sizeof(b->version)); 310bd389b36SDavid du Colombier PUTSHORT(b->sectsize, t->bytes); 311bd389b36SDavid du Colombier b->clustsize = clustersize; 312bd389b36SDavid du Colombier PUTSHORT(b->nresrv, 1); 313bd389b36SDavid du Colombier b->nfats = 2; 314bd389b36SDavid du Colombier PUTSHORT(b->rootsize, rootfiles); 315bd389b36SDavid du Colombier if(volsecs < (1<<16)){ 316bd389b36SDavid du Colombier PUTSHORT(b->volsize, volsecs); 317bd389b36SDavid du Colombier } 318bd389b36SDavid du Colombier PUTLONG(b->bigvolsize, volsecs); 319bd389b36SDavid du Colombier b->mediadesc = t->media; 320bd389b36SDavid du Colombier PUTSHORT(b->fatsize, fatsecs); 321bd389b36SDavid du Colombier PUTSHORT(b->trksize, t->sectors); 322bd389b36SDavid du Colombier PUTSHORT(b->nheads, t->heads); 323bd389b36SDavid du Colombier PUTLONG(b->nhidden, 0); 324bd389b36SDavid du Colombier b->driveno = 0; 325bd389b36SDavid du Colombier b->bootsig = 0x29; 326bd389b36SDavid du Colombier x = time(0); 327bd389b36SDavid du Colombier PUTLONG(b->volid, x); 328bd389b36SDavid du Colombier memmove(b->label, label, sizeof(b->label)); 329bd389b36SDavid du Colombier sprint(r, "FAT%d ", fatbits); 330*219b2ee8SDavid du Colombier memmove(b->type, r, sizeof(b->type)); 331*219b2ee8SDavid du Colombier buf[t->bytes-2] = 0x55; 332*219b2ee8SDavid du Colombier buf[t->bytes-1] = 0xAA; 333*219b2ee8SDavid du Colombier if(seek(fd, 0, 0) < 0) 334*219b2ee8SDavid du Colombier fatal("seek to boot sector: %r\n"); 335bd389b36SDavid du Colombier if(write(fd, buf, t->bytes) != t->bytes) 336bd389b36SDavid du Colombier fatal("writing boot sector: %r"); 337bd389b36SDavid du Colombier free(buf); 338bd389b36SDavid du Colombier 339bd389b36SDavid du Colombier /* 340bd389b36SDavid du Colombier * allocate an in memory fat 341bd389b36SDavid du Colombier */ 342bd389b36SDavid du Colombier fat = malloc(fatsecs*t->bytes); 343bd389b36SDavid du Colombier if(fat == 0) 344bd389b36SDavid du Colombier fatal("out of memory"); 345*219b2ee8SDavid du Colombier memset(fat, 0, fatsecs*t->bytes); 346bd389b36SDavid du Colombier fat[0] = t->media; 347bd389b36SDavid du Colombier fat[1] = 0xff; 348bd389b36SDavid du Colombier fat[2] = 0xff; 349bd389b36SDavid du Colombier if(fatbits == 16) 350bd389b36SDavid du Colombier fat[3] = 0xff; 351bd389b36SDavid du Colombier fatlast = 1; 352bd389b36SDavid du Colombier seek(fd, 2*fatsecs*t->bytes, 1); /* 2 fats */ 353bd389b36SDavid du Colombier 354bd389b36SDavid du Colombier /* 355bd389b36SDavid du Colombier * allocate an in memory root 356bd389b36SDavid du Colombier */ 357bd389b36SDavid du Colombier root = malloc(rootsecs*t->bytes); 358bd389b36SDavid du Colombier if(root == 0) 359bd389b36SDavid du Colombier fatal("out of memory"); 360*219b2ee8SDavid du Colombier memset(root, 0, rootsecs*t->bytes); 361*219b2ee8SDavid du Colombier seek(fd, rootsecs*t->bytes, 1); /* rootsecs */ 362bd389b36SDavid du Colombier 363bd389b36SDavid du Colombier /* 364*219b2ee8SDavid du Colombier * Now positioned at the Files Area. 365*219b2ee8SDavid du Colombier * If we have any arguments, process 366*219b2ee8SDavid du Colombier * them and write out. 367bd389b36SDavid du Colombier */ 368*219b2ee8SDavid du Colombier for(p = root; argc > 0; argc--, argv++, p += sizeof(Dosdir)){ 369*219b2ee8SDavid du Colombier if(p >= (root+(rootsecs*t->bytes))) 370*219b2ee8SDavid du Colombier fatal("too many files in root"); 371*219b2ee8SDavid du Colombier /* 372*219b2ee8SDavid du Colombier * Open the file and get its length. 373*219b2ee8SDavid du Colombier */ 374*219b2ee8SDavid du Colombier if((sysfd = open(*argv, OREAD)) < 0) 375*219b2ee8SDavid du Colombier fatal("open %s: %r", *argv); 376*219b2ee8SDavid du Colombier if(dirfstat(sysfd, &d) < 0) 377*219b2ee8SDavid du Colombier fatal("stat %s: %r", *argv); 378*219b2ee8SDavid du Colombier print("Adding file %s, length %ld\n", *argv, d.length); 379*219b2ee8SDavid du Colombier 380*219b2ee8SDavid du Colombier length = d.length; 381*219b2ee8SDavid du Colombier if(length){ 382*219b2ee8SDavid du Colombier /* 383*219b2ee8SDavid du Colombier * Allocate a buffer to read the entire file into. 384*219b2ee8SDavid du Colombier * This must be rounded up to a cluster boundary. 385*219b2ee8SDavid du Colombier * 386*219b2ee8SDavid du Colombier * Read the file and write it out to the Files Area. 387*219b2ee8SDavid du Colombier */ 388*219b2ee8SDavid du Colombier length += t->bytes*clustersize - 1; 389*219b2ee8SDavid du Colombier length /= t->bytes*clustersize; 390*219b2ee8SDavid du Colombier length *= t->bytes*clustersize; 391*219b2ee8SDavid du Colombier if((buf = malloc(length)) == 0) 392*219b2ee8SDavid du Colombier fatal("out of memory"); 393*219b2ee8SDavid du Colombier 394*219b2ee8SDavid du Colombier if(read(sysfd, buf, d.length) < 0) 395*219b2ee8SDavid du Colombier fatal("read %s: %r", *argv); 396*219b2ee8SDavid du Colombier memset(buf+d.length, 0, length-d.length); 397*219b2ee8SDavid du Colombier if(write(fd, buf, length) < 0) 398*219b2ee8SDavid du Colombier fatal("write %s: %r", *argv); 399*219b2ee8SDavid du Colombier free(buf); 400*219b2ee8SDavid du Colombier 401*219b2ee8SDavid du Colombier close(sysfd); 402*219b2ee8SDavid du Colombier 403*219b2ee8SDavid du Colombier /* 404*219b2ee8SDavid du Colombier * Allocate the FAT clusters. 405*219b2ee8SDavid du Colombier * We're assuming here that where we 406*219b2ee8SDavid du Colombier * wrote the file is in sync with 407*219b2ee8SDavid du Colombier * the cluster allocation. 408*219b2ee8SDavid du Colombier * Save the starting cluster. 409*219b2ee8SDavid du Colombier */ 410*219b2ee8SDavid du Colombier length /= t->bytes*clustersize; 411*219b2ee8SDavid du Colombier x = clustalloc(Sof); 412*219b2ee8SDavid du Colombier for(n = 0; n < length-1; n++) 413*219b2ee8SDavid du Colombier clustalloc(0); 414*219b2ee8SDavid du Colombier clustalloc(Eof); 415*219b2ee8SDavid du Colombier } 416*219b2ee8SDavid du Colombier else 417*219b2ee8SDavid du Colombier x = 0; 418*219b2ee8SDavid du Colombier 419*219b2ee8SDavid du Colombier /* 420*219b2ee8SDavid du Colombier * Add the filename to the root. 421*219b2ee8SDavid du Colombier */ 422*219b2ee8SDavid du Colombier addrname(p, &d, x); 423*219b2ee8SDavid du Colombier } 424bd389b36SDavid du Colombier 425bd389b36SDavid du Colombier /* 426bd389b36SDavid du Colombier * write the fats and root 427bd389b36SDavid du Colombier */ 428bd389b36SDavid du Colombier seek(fd, t->bytes, 0); 429bd389b36SDavid du Colombier if(write(fd, fat, fatsecs*t->bytes) < 0) 430bd389b36SDavid du Colombier fatal("writing fat #1: %r"); 431bd389b36SDavid du Colombier if(write(fd, fat, fatsecs*t->bytes) < 0) 432bd389b36SDavid du Colombier fatal("writing fat #2: %r"); 433bd389b36SDavid du Colombier if(write(fd, root, rootsecs*t->bytes) < 0) 434bd389b36SDavid du Colombier fatal("writing root: %r"); 435*219b2ee8SDavid du Colombier 436*219b2ee8SDavid du Colombier if(fflag){ 437*219b2ee8SDavid du Colombier seek(fd, t->bytes*t->sectors*t->heads*t->tracks-1, 0); 438*219b2ee8SDavid du Colombier write(fd, "9", 1); 439*219b2ee8SDavid du Colombier } 440bd389b36SDavid du Colombier } 441bd389b36SDavid du Colombier 442bd389b36SDavid du Colombier /* 443bd389b36SDavid du Colombier * allocate a cluster 444bd389b36SDavid du Colombier */ 445bd389b36SDavid du Colombier ulong 446bd389b36SDavid du Colombier clustalloc(int flag) 447bd389b36SDavid du Colombier { 448bd389b36SDavid du Colombier ulong o, x; 449bd389b36SDavid du Colombier 450bd389b36SDavid du Colombier if(flag != Sof){ 451bd389b36SDavid du Colombier x = (flag == Eof) ? 0xffff : (fatlast+1); 452bd389b36SDavid du Colombier if(fatbits == 12){ 453bd389b36SDavid du Colombier x &= 0xfff; 454bd389b36SDavid du Colombier o = (3*fatlast)/2; 455bd389b36SDavid du Colombier if(fatlast & 1){ 456bd389b36SDavid du Colombier fat[o] = (fat[o]&0x0f) | (x<<4); 457*219b2ee8SDavid du Colombier fat[o+1] = (x>>4); 458bd389b36SDavid du Colombier } else { 459bd389b36SDavid du Colombier fat[o] = x; 460*219b2ee8SDavid du Colombier fat[o+1] = (fat[o+1]&0xf0) | ((x>>8) & 0x0F); 461bd389b36SDavid du Colombier } 462bd389b36SDavid du Colombier } else { 463bd389b36SDavid du Colombier o = 2*fatlast; 464bd389b36SDavid du Colombier fat[o] = x; 465bd389b36SDavid du Colombier fat[o+1] = x>>8; 466bd389b36SDavid du Colombier } 467bd389b36SDavid du Colombier } 468bd389b36SDavid du Colombier 469bd389b36SDavid du Colombier if(flag == Eof) 470bd389b36SDavid du Colombier return 0; 471bd389b36SDavid du Colombier else 472bd389b36SDavid du Colombier return ++fatlast; 473bd389b36SDavid du Colombier } 474bd389b36SDavid du Colombier 475bd389b36SDavid du Colombier void 476*219b2ee8SDavid du Colombier putname(char *p, Dosdir *d) 477bd389b36SDavid du Colombier { 478*219b2ee8SDavid du Colombier int i; 479bd389b36SDavid du Colombier 480*219b2ee8SDavid du Colombier memset(d->name, ' ', sizeof d->name+sizeof d->ext); 481*219b2ee8SDavid du Colombier for(i = 0; i< sizeof(d->name); i++){ 482*219b2ee8SDavid du Colombier if(*p == 0 || *p == '.') 483bd389b36SDavid du Colombier break; 484*219b2ee8SDavid du Colombier d->name[i] = toupper(*p++); 485bd389b36SDavid du Colombier } 486*219b2ee8SDavid du Colombier p = strrchr(p, '.'); 487*219b2ee8SDavid du Colombier if(p){ 488*219b2ee8SDavid du Colombier for(i = 0; i < sizeof d->ext; i++){ 489*219b2ee8SDavid du Colombier if(*++p == 0) 490*219b2ee8SDavid du Colombier break; 491*219b2ee8SDavid du Colombier d->ext[i] = toupper(*p); 492*219b2ee8SDavid du Colombier } 493*219b2ee8SDavid du Colombier } 494*219b2ee8SDavid du Colombier } 495bd389b36SDavid du Colombier 496*219b2ee8SDavid du Colombier void 497*219b2ee8SDavid du Colombier puttime(Dosdir *d) 498*219b2ee8SDavid du Colombier { 499*219b2ee8SDavid du Colombier Tm *t = localtime(time(0)); 500*219b2ee8SDavid du Colombier ushort x; 501*219b2ee8SDavid du Colombier 502*219b2ee8SDavid du Colombier x = (t->hour<<11) | (t->min<<5) | (t->sec>>1); 503*219b2ee8SDavid du Colombier d->time[0] = x; 504*219b2ee8SDavid du Colombier d->time[1] = x>>8; 505*219b2ee8SDavid du Colombier x = ((t->year-80)<<9) | ((t->mon+1)<<5) | t->mday; 506*219b2ee8SDavid du Colombier d->date[0] = x; 507*219b2ee8SDavid du Colombier d->date[1] = x>>8; 508*219b2ee8SDavid du Colombier } 509*219b2ee8SDavid du Colombier 510*219b2ee8SDavid du Colombier void 511*219b2ee8SDavid du Colombier addrname(uchar *entry, Dir *dir, ulong start) 512*219b2ee8SDavid du Colombier { 513*219b2ee8SDavid du Colombier Dosdir *d; 514*219b2ee8SDavid du Colombier 515*219b2ee8SDavid du Colombier d = (Dosdir*)entry; 516*219b2ee8SDavid du Colombier putname(dir->name, d); 517*219b2ee8SDavid du Colombier d->attr = DRONLY; 518*219b2ee8SDavid du Colombier puttime(d); 519*219b2ee8SDavid du Colombier d->start[0] = start; 520*219b2ee8SDavid du Colombier d->start[1] = start>>8; 521*219b2ee8SDavid du Colombier d->length[0] = dir->length; 522*219b2ee8SDavid du Colombier d->length[1] = dir->length>>8; 523*219b2ee8SDavid du Colombier d->length[2] = dir->length>>16; 524*219b2ee8SDavid du Colombier d->length[3] = dir->length>>24; 525bd389b36SDavid du Colombier } 526