1: /* 2: * Add an MSDOS filesystem to a low level formatted diskette. 3: * 4: * Emmet P. Gray US Army, HQ III Corps & Fort Hood 5: * ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV 6: * fthood!egray@uxc.cso.uiuc.edu Directorate of Engineering & Housing 7: * Environmental Management Office 8: * Fort Hood, TX 76544-5057 9: */ 10: 11: #include <stdio.h> 12: #include <ctype.h> 13: #include "msdos.h" 14: #include "patchlevel.h" 15: 16: int fd, dir_dirty, dir_entries; 17: long dir_chain[MAX_DIR_SECS]; 18: unsigned char *dir_buf; 19: 20: main(argc, argv) 21: int argc; 22: char *argv[]; 23: { 24: extern int optind; 25: extern char *optarg; 26: extern struct device devices[]; 27: struct bootsector boot; 28: int i, c, oops, tracks, heads, sectors, fat_len, dir_len, clus_size; 29: int tot_sectors, num_clus, fat_guess; 30: long time(), now, lseek(); 31: char drive, *name, *expand(); 32: char *strncpy(), *memset(), *memcpy(); 33: unsigned char media, label[12], buf[MSECTOR_SIZE]; 34: struct device *dev; 35: struct directory *dir, *mk_entry(); 36: void exit(), perror(); 37: 38: oops = 0; 39: tracks = 0; 40: heads = 0; 41: sectors = 0; 42: label[0] = '\0'; 43: /* get command line options */ 44: while ((c = getopt(argc, argv, "t:h:s:l:")) != EOF) { 45: switch (c) { 46: case 't': 47: tracks = atoi(optarg); 48: break; 49: case 'h': 50: heads = atoi(optarg); 51: break; 52: case 's': 53: sectors = atoi(optarg); 54: break; 55: case 'l': 56: sprintf((char *) label, "%-11.11s", optarg); 57: break; 58: default: 59: oops = 1; 60: break; 61: } 62: } 63: 64: if (oops || (argc - optind) != 1) { 65: fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE); 66: fprintf(stderr, "Usage: %s [-t tracks] [-h heads] [-s sectors] [-l label] device\n", argv[0]); 67: exit(1); 68: } 69: 70: drive = argv[argc -1][0]; 71: if (islower(drive)) 72: drive = toupper(drive); 73: 74: /* check out the drive letter */ 75: dev = devices; 76: while (dev->drive) { 77: if (dev->drive == drive) 78: break; 79: dev++; 80: } 81: if (!dev->drive) { 82: fprintf(stderr, "Drive '%c:' not supported\n", drive); 83: exit(1); 84: } 85: if (dev->tracks == 0) { 86: fprintf(stderr, "Non-removable media is not supported\n"); 87: exit(1); 88: } 89: /* find the right one */ 90: if (!dev->gioctl) { 91: while (dev->drive == drive) { 92: if ((!tracks || dev->tracks == tracks) && (!heads || dev->heads == heads) && (!sectors || dev->sectors == sectors)) 93: break; 94: dev++; 95: } 96: } 97: if (dev->drive != drive) { 98: fprintf(stderr, "%s: Paramaters not supported\n", argv[0]); 99: exit(1); 100: } 101: /* open the device */ 102: name = expand(dev->name); 103: if ((fd = open(name, 2 | dev->mode)) < 0) { 104: perror("init: open"); 105: exit(1); 106: } 107: /* fill in the blanks */ 108: if (!tracks) 109: tracks = dev->tracks; 110: if (!heads) 111: heads = dev->heads; 112: if (!sectors) 113: sectors = dev->sectors; 114: 115: /* set parameters, if needed */ 116: if (dev->gioctl) { 117: if ((*(dev->gioctl)) (fd, tracks, heads, sectors)) 118: exit(1); 119: } 120: /* do a "test" read */ 121: if (read(fd, (char *) buf, MSECTOR_SIZE) != MSECTOR_SIZE) { 122: fprintf(stderr, "%s: Error reading from '%s', wrong parameters?\n", argv[0], name); 123: exit(1); 124: } 125: /* get the parameters */ 126: tot_sectors = tracks * heads * sectors; 127: switch (tot_sectors) { 128: case 320: /* 40t * 1h * 8s = 160k */ 129: media = 0xfe; 130: clus_size = 1; 131: dir_len = 4; 132: fat_len = 1; 133: break; 134: case 360: /* 40t * 1h * 9s = 180k */ 135: media = 0xfc; 136: clus_size = 1; 137: dir_len = 4; 138: fat_len = 2; 139: break; 140: case 640: /* 40t * 2h * 8s = 320k */ 141: media = 0xff; 142: clus_size = 2; 143: dir_len = 7; 144: fat_len = 1; 145: break; 146: case 720: /* 40t * 2h * 9s = 360k */ 147: media = 0xfd; 148: clus_size = 2; 149: dir_len = 7; 150: fat_len = 2; 151: break; 152: case 1440: /* 80t * 2h * 9s = 720k */ 153: media = 0xf9; 154: clus_size = 2; 155: dir_len = 7; 156: fat_len = 3; 157: break; 158: case 2400: /* 80t * 2h * 15s = 1.2m */ 159: media = 0xf9; 160: clus_size = 1; 161: dir_len = 14; 162: fat_len = 7; 163: break; 164: case 2880: /* 80t * 2h * 18s = 1.44m */ 165: media = 0xf0; 166: clus_size = 1; 167: dir_len = 14; 168: fat_len = 9; 169: break; 170: default: /* a non-standard format */ 171: media = 0xf0; 172: if (heads == 1) 173: clus_size = 1; 174: else 175: clus_size = (tot_sectors > 2000) ? 1 : 2; 176: if (heads == 1) 177: dir_len = 4; 178: else 179: dir_len = (tot_sectors > 2000) ? 14 : 7; 180: /* 181: * Estimate the fat length, then figure it out. The 182: * 341 is the number of 12 bit fat entries in a sector. 183: */ 184: fat_guess = ((tot_sectors / clus_size) / 341.0) + 0.95; 185: num_clus = (tot_sectors -dir_len - (2 * fat_guess) -1) / clus_size; 186: fat_len = (num_clus / 341.0) + 1; 187: break; 188: } 189: /* the boot sector */ 190: memset((char *) &boot, '\0', MSECTOR_SIZE); 191: boot.jump[0] = 0xeb; 192: boot.jump[1] = 0x44; 193: boot.jump[2] = 0x90; 194: strncpy((char *) boot.banner, "Mtools ", 8); 195: boot.secsiz[0] = 512 % 0x100; 196: boot.secsiz[1] = 512 / 0x100; 197: boot.clsiz = (unsigned char) clus_size; 198: boot.nrsvsect[0] = 1; 199: boot.nrsvsect[1] = 0; 200: boot.nfat = 2; 201: boot.dirents[0] = (dir_len * 16) % 0x100; 202: boot.dirents[1] = (dir_len * 16) / 0x100; 203: boot.psect[0] = tot_sectors % 0x100; 204: boot.psect[1] = tot_sectors / 0x100; 205: boot.descr = media; 206: boot.fatlen[0] = fat_len % 0x100; 207: boot.fatlen[1] = fat_len / 0x100; 208: boot.nsect[0] = sectors % 0x100; 209: boot.nsect[1] = sectors / 0x100; 210: boot.nheads[0] = heads % 0x100; 211: boot.nheads[1] = heads / 0x100; 212: 213: /* write the boot */ 214: lseek(fd, 0L, 0); 215: write(fd, (char *) &boot, MSECTOR_SIZE); 216: /* first fat */ 217: memset((char *) buf, '\0', MSECTOR_SIZE); 218: buf[0] = media; 219: buf[1] = 0xff; 220: buf[2] = 0xff; 221: write(fd, (char *) buf, MSECTOR_SIZE); 222: memset((char *) buf, '\0', MSECTOR_SIZE); 223: for (i = 1; i < fat_len; i++) 224: write(fd, (char *) buf, MSECTOR_SIZE); 225: /* second fat */ 226: buf[0] = media; 227: buf[1] = 0xff; 228: buf[2] = 0xff; 229: write(fd, (char *) buf, MSECTOR_SIZE); 230: memset((char *) buf, '\0', MSECTOR_SIZE); 231: for (i = 1; i < fat_len; i++) 232: write(fd, (char *) buf, MSECTOR_SIZE); 233: /* the root directory */ 234: if (label[0] != '\0') { 235: time(&now); 236: dir = mk_entry(label, 0x08, 0, 0L, now); 237: memcpy((char *) buf, (char *) dir, MDIR_SIZE); 238: } 239: write(fd, (char *) buf, MSECTOR_SIZE); 240: memset((char *) buf, '\0', MSECTOR_SIZE); 241: for (i = 1; i < dir_len; i++) 242: write(fd, (char *) buf, MSECTOR_SIZE); 243: close(fd); 244: exit(0); 245: } 246: 247: /* hooks for the missing parts */ 248: void disk_write() {}