1 /* Copyright 1986-1992 Emmet P. Gray.
2 * Copyright 1994,1996-2009 Alain Knaff.
3 * This file is part of mtools.
5 * Mtools is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * Mtools is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
21 #define DONT_NEED_WAIT
23 #include "sysincludes.h"
30 #include "floppyd_io.h"
31 #include "nameclash.h"
39 #include "partition.h"
40 #include "file_name.h"
43 #define abs(x) ((x)>0?(x):-(x))
47 #include "linux/hdreg.h"
49 #define _LINUX_STRING_H_
52 #undef _LINUX_STRING_H_
57 static int init_geometry_boot(union bootsector *boot, struct device *dev,
58 int sectors0, int rate_0, int rate_any,
59 unsigned long *tot_sectors, int keepBoot)
68 set_word(boot->boot.nsect, dev->sectors);
69 set_word(boot->boot.nheads, dev->heads);
72 assert(*tot_sectors != 0);
75 if (*tot_sectors < 0x10000){
76 set_word(boot->boot.psect, *tot_sectors);
77 set_dword(boot->boot.bigsect, 0);
79 set_word(boot->boot.psect, 0);
80 set_dword(boot->boot.bigsect, *tot_sectors);
83 if (dev->use_2m & 0x7f){
85 strncpy(boot->boot.banner, "2M-STV04", 8);
86 boot->boot.ext.old.res_2m = 0;
87 boot->boot.ext.old.fmt_2mf = 6;
88 if ( dev->sectors % ( ((1 << dev->ssize) + 3) >> 2 ))
89 boot->boot.ext.old.wt = 1;
91 boot->boot.ext.old.wt = 0;
92 boot->boot.ext.old.rate_0= rate_0;
93 boot->boot.ext.old.rate_any= rate_any;
94 if (boot->boot.ext.old.rate_any== 2 )
95 boot->boot.ext.old.rate_any= 1;
99 set_word(boot->boot.ext.old.Infp0, i);
100 boot->bytes[i++] = sectors0;
101 boot->bytes[i++] = 108;
102 for(j=1; j<= sectors0; j++)
103 boot->bytes[i++] = j;
105 set_word(boot->boot.ext.old.InfpX, i);
107 boot->bytes[i++] = 64;
108 boot->bytes[i++] = 3;
110 sector2 = dev->sectors;
114 while ( sector2 < (1 << size2) >> 2 )
116 boot->bytes[i++] = 128 + j;
117 boot->bytes[i++] = j++;
118 boot->bytes[i++] = size2;
119 sector2 -= (1 << size2) >> 2;
121 boot->bytes[nb_renum] = ( i - nb_renum - 1 ) / 3;
123 set_word(boot->boot.ext.old.InfTm, i);
125 sector2 = dev->sectors;
128 while ( sector2 < 1 << ( size2 - 2) )
130 boot->bytes[i++] = size2;
131 sector2 -= 1 << (size2 - 2 );
134 set_word(boot->boot.ext.old.BootP,i);
138 for (sum=0, j=64; j<i; j++)
139 sum += boot->bytes[j];/* checksum */
140 boot->boot.ext.old.CheckSum=-sum;
144 boot->boot.jump[0] = 0xeb;
145 boot->boot.jump[1] = 0;
146 boot->boot.jump[2] = 0x90;
147 strncpy(boot->boot.banner, mformat_banner, 8);
148 /* It looks like some versions of DOS are
149 * rather picky about this, and assume default
150 * parameters without this, ignoring any
151 * indication about cluster size et al. */
158 static int comp_fat_bits(Fs_t *Fs, int estimate,
159 unsigned long tot_sectors, int fat32)
163 needed_fat_bits = 12;
165 #define MAX_DISK_SIZE(bits,clusters) \
166 TOTAL_DISK_SIZE((bits), Fs->sector_size, (clusters), \
167 Fs->num_fat, MAX_BYTES_PER_CLUSTER/Fs->sector_size)
169 if(tot_sectors > MAX_DISK_SIZE(12, FAT12-1))
170 needed_fat_bits = 16;
171 if(fat32 || tot_sectors > MAX_DISK_SIZE(16, FAT16-1))
172 needed_fat_bits = 32;
176 if(abs(estimate) && abs(estimate) < needed_fat_bits) {
179 "Contradiction between FAT size on command line and FAT size in conf file\n");
183 "Device too big for a %d bit FAT\n",
189 unsigned int min_fat16_size;
191 if(needed_fat_bits > 12)
192 return needed_fat_bits;
193 min_fat16_size = DISK_SIZE(16, Fs->sector_size, FAT12,
195 if(tot_sectors < min_fat16_size)
197 else if(tot_sectors >= 2* min_fat16_size)
198 return 16; /* heuristics */
206 * According to Microsoft "Hardware White Paper", "Microsoft
207 * Extensible Formware Initiative", "FAT32 File System Specification",
208 * Version 1.03, December 6, 2000:
209 * If (CountofClusters < 4085) {
211 * } else if (CountofClusters < 65525) {
217 * This document can be found at the following URL
218 * http://www.microsoft.com/hwdev/download/hardware/fatgen103.pdf
219 * The relevant passus is on page 15.
221 * Actually, experimentations with Windows NT 4 show that the
222 * cutoff is 4087 rather than 4085... This is Microsoft after all.
223 * Not sure what the other Microsoft OS'es do though...
225 static void calc_fat_bits2(Fs_t *Fs, unsigned long tot_sectors, int fat_bits,
226 int may_change_cluster_size,
227 int may_change_root_size)
229 unsigned long rem_sect;
232 * the "remaining sectors" after directory and boot
233 * hasve been accounted for.
235 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
236 switch(abs(fat_bits)) {
239 #define MY_DISK_SIZE(bits,clusters) \
240 DISK_SIZE( (bits), Fs->sector_size, (clusters), \
241 Fs->num_fat, Fs->cluster_size)
243 if(rem_sect >= MY_DISK_SIZE(16, FAT12+2))
244 /* big enough for FAT16
245 * We take a margin of 2, because NT4
246 * misbehaves, and starts considering a disk
247 * as FAT16 only if it is larger than 4086
248 * sectors, rather than 4084 as it should
251 else if(rem_sect <= MY_DISK_SIZE(12, FAT12-1))
252 /* small enough for FAT12 */
255 /* "between two chairs",
256 * augment cluster size, and
258 if(may_change_cluster_size &&
259 Fs->cluster_size * Fs->sector_size * 2
260 <= MAX_BYTES_PER_CLUSTER)
261 Fs->cluster_size <<= 1;
262 else if(may_change_root_size) {
264 rem_sect - MY_DISK_SIZE(12, FAT12-1);
283 static __inline__ void format_root(Fs_t *Fs, char *label, union bootsector *boot)
288 struct ClashHandling_t ch;
291 init_clash_handling(&ch);
292 ch.name_converter = label_name;
293 ch.ignore_entry = -2;
295 buf = safe_malloc(Fs->sector_size);
296 RootDir = OpenRoot((Stream_t *)Fs);
298 fprintf(stderr,"Could not open root directory\n");
302 memset(buf, '\0', Fs->sector_size);
304 if(Fs->fat_bits == 32) {
305 /* on a FAT32 system, we only write one sector,
306 * as the directory can be extended at will...*/
307 dirlen = Fs->cluster_size;
308 fatAllocate(Fs, Fs->rootCluster, Fs->end_fat);
310 dirlen = Fs->dir_len;
311 for (i = 0; i < dirlen; i++)
312 WRITES(RootDir, buf, sectorsToBytes((Stream_t*)Fs, i),
317 mwrite_one(RootDir,label, 0, labelit, NULL,&ch);
320 if(Fs->fat_bits == 32)
321 set_word(boot->boot.dirents, 0);
323 set_word(boot->boot.dirents, Fs->dir_len * (Fs->sector_size / 32));
328 static void xdf_calc_fat_size(Fs_t *Fs, unsigned long tot_sectors,
331 unsigned int rem_sect;
333 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start - 2 * Fs->fat_len;
336 /* an XDF disk, we know the fat_size and have to find
337 * out the rest. We start with a cluster size of 1 and
338 * keep doubling until everything fits into the
339 * FAT. This will occur eventually, as our FAT has a
340 * minimal size of 1 */
341 for(Fs->cluster_size = 1; 1 ; Fs->cluster_size <<= 1) {
342 Fs->num_clus = rem_sect / Fs->cluster_size;
343 if(abs(fat_bits) == 16 || Fs->num_clus >= FAT12)
347 if (Fs->fat_len >= NEEDED_FAT_SIZE(Fs))
351 fprintf(stderr,"Internal error while calculating Xdf fat size\n");
356 static void calc_fat_size(Fs_t *Fs, unsigned long tot_sectors)
358 unsigned long rem_sect;
359 unsigned long real_rem_sect;
360 unsigned long numerator;
361 unsigned long denominator;
364 int printGrowMsg=1; /* Should we print "growing FAT" messages ?*/
367 fprintf(stderr, "Fat start=%d\n", Fs->fat_start);
368 fprintf(stderr, "tot_sectors=%lu\n", tot_sectors);
369 fprintf(stderr, "dir_len=%d\n", Fs->dir_len);
371 real_rem_sect = rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
373 /* Cheat a little bit to address the _really_ common case of
374 odd number of remaining sectors while both nfat and cluster size
376 if(rem_sect %2 == 1 &&
377 Fs->num_fat %2 == 0 &&
378 Fs->cluster_size %2 == 0)
382 fprintf(stderr, "Rem sect=%lu\n", rem_sect);
385 if(Fs->fat_bits == 0) {
386 fprintf(stderr, "Weird, fat bits = 0\n");
391 /* See fat_size_calculation.tex or
392 (http://ftp.gnu.org/software/mtools/manual/fat_size_calculation.pdf)
393 for an explantation about why the stuff below works...
396 fat_nybbles = Fs->fat_bits / 4;
397 numerator = rem_sect+2*Fs->cluster_size;
399 Fs->cluster_size * Fs->sector_size * 2 +
400 Fs->num_fat * fat_nybbles;
403 numerator *= fat_nybbles;
405 /* Avoid numerical overflows, divide the denominator
406 * rather than multiplying the numerator */
407 denominator = denominator / fat_nybbles;
410 fprintf(stderr, "Numerator=%lu denominator=%lu\n",
411 numerator, denominator);
414 Fs->fat_len = (numerator-1)/denominator+1;
415 Fs->num_clus = (rem_sect-(Fs->fat_len*Fs->num_fat))/Fs->cluster_size;
417 /* Apply upper bounds for FAT bits */
418 if(Fs->fat_bits == 16 && Fs->num_clus >= FAT16)
419 Fs->num_clus = FAT16-1;
420 if(Fs->fat_bits == 12 && Fs->num_clus >= FAT12)
421 Fs->num_clus = FAT12-1;
423 /* A safety, if above math is correct, this should not be happen...*/
424 if(Fs->num_clus > (Fs->fat_len * Fs->sector_size * 2 /
427 "Fat size miscalculation, shrinking num_clus from %d ",
429 Fs->num_clus = (Fs->fat_len * Fs->sector_size * 2 /
431 fprintf(stderr, " to %d\n", Fs->num_clus);
434 fprintf(stderr, "Num_clus=%d fat_len=%d nybbles=%d\n",
435 Fs->num_clus, Fs->fat_len, fat_nybbles);
438 if ( Fs->num_clus < FAT16 && Fs->fat_bits > 16 ){
439 fprintf(stderr,"Too few clusters for this fat size."
440 " Please choose a 16-bit fat in your /etc/mtools.conf"
441 " or .mtoolsrc file\n");
445 /* As the number of clusters is specified nowhere in the boot sector,
446 * it will be calculated by removing everything else from total number
447 * of sectors. This means that if we reduced the number of clusters
448 * above, we will have to grow the FAT in order to take up any excess
451 assert(rem_sect >= Fs->num_clus * Fs->cluster_size +
452 Fs->fat_len * Fs->num_fat);
455 Fs->num_clus * Fs->cluster_size -
456 Fs->fat_len * Fs->num_fat;
457 if(slack >= Fs->cluster_size) {
458 /* This can happen under two circumstances:
459 1. We had to reduce num_clus because we reached maximum
460 number of cluster for FAT12 or FAT16
463 fprintf(stderr, "Slack=%d\n", slack);
464 fprintf(stderr, "Growing fat size from %d",
468 (slack - Fs->cluster_size) / Fs->num_fat + 1;
471 " to %d in order to take up excess cluster area\n",
474 Fs->num_clus = (rem_sect-(Fs->fat_len*Fs->num_fat))/
480 /* Fat must be big enough for all clusters */
481 assert( ((Fs->num_clus+2) * fat_nybbles) <=
482 (Fs->fat_len*Fs->sector_size*2));
484 /* num_clus must be big enough to cover rest of disk, or else further
485 * users of the filesystem will assume a bigger num_clus, which might
486 * be too big for fat_len */
487 assert(Fs->num_clus ==
488 (real_rem_sect - Fs->num_fat * Fs->fat_len) / Fs->cluster_size);
493 static unsigned char bootprog[]=
494 {0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
495 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
496 0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
497 0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
500 static __inline__ void inst_boot_prg(union bootsector *boot, int offset)
502 memcpy((char *) boot->boot.jump + offset,
503 (char *) bootprog, sizeof(bootprog) /sizeof(bootprog[0]));
504 if(offset - 2 < 0x80) {
506 boot->boot.jump[0] = 0xeb;
507 boot->boot.jump[1] = offset -2;
508 boot->boot.jump[2] = 0x90;
510 /* long jump, if offset is too large */
511 boot->boot.jump[0] = 0xe9;
512 boot->boot.jump[1] = offset -3;
513 boot->boot.jump[2] = 0x00;
515 set_word(boot->boot.jump + offset + 20, offset + 24);
518 static void calc_cluster_size(struct Fs_t *Fs, unsigned long tot_sectors,
522 unsigned int max_clusters; /* maximal possible number of sectors for
523 * this FAT entry length (12/16/32) */
524 unsigned int max_fat_size; /* maximal size of the FAT for this FAT
525 * entry length (12/16/32) */
526 unsigned int rem_sect; /* remaining sectors after we accounted for
527 * the root directory and boot sector(s) */
529 switch(abs(fat_bits)) {
531 max_clusters = FAT12-1;
532 max_fat_size = Fs->num_fat *
533 FAT_SIZE(12, Fs->sector_size, max_clusters);
536 case 0: /* still hesititating between 12 and 16 */
537 max_clusters = FAT16-1;
538 max_fat_size = Fs->num_fat *
539 FAT_SIZE(16, Fs->sector_size, max_clusters);
542 Fs->cluster_size = 8;
544 * http://support.microsoft.com/support/kb/articles/q154/9/97.asp
545 * Micro$oft does not support FAT32 with less than 4K
549 fprintf(stderr,"Bad fat size\n");
553 if(tot_sectors <= Fs->fat_start + Fs->num_fat + Fs->dir_len) {
554 /* we need at least enough sectors to fit boot, fat and root
556 fprintf(stderr, "Not enough sectors\n");
560 rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
562 /* double the cluster size until we can fill up the disk with
563 * the maximal number of sectors of this size */
564 while(Fs->cluster_size * max_clusters + max_fat_size < rem_sect) {
565 if(Fs->cluster_size > 64) {
566 /* bigger than 64. Should fit */
568 "Internal error while calculating cluster size\n");
571 Fs->cluster_size <<= 1;
576 struct OldDos_t old_dos[]={
577 { 40, 9, 1, 4, 1, 2, 0xfc },
578 { 40, 9, 2, 7, 2, 2, 0xfd },
579 { 40, 8, 1, 4, 1, 1, 0xfe },
580 { 40, 8, 2, 7, 2, 1, 0xff },
581 { 80, 9, 2, 7, 2, 3, 0xf9 },
582 { 80, 15, 2,14, 1, 7, 0xf9 },
583 { 80, 18, 2,14, 1, 9, 0xf0 },
584 { 80, 36, 2,15, 2, 9, 0xf0 },
585 { 1, 8, 1, 1, 1, 1, 0xf0 },
588 static int old_dos_size_to_geom(size_t size, int *cyls, int *heads, int *sects)
592 for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
593 if (old_dos[i].sectors *
595 old_dos[i].heads == size) {
596 *cyls = old_dos[i].tracks;
597 *heads = old_dos[i].heads;
598 *sects = old_dos[i].sectors;
606 static void calc_fs_parameters(struct device *dev, unsigned long tot_sectors,
607 struct Fs_t *Fs, union bootsector *boot)
611 for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
612 if (dev->sectors == old_dos[i].sectors &&
613 dev->tracks == old_dos[i].tracks &&
614 dev->heads == old_dos[i].heads &&
615 (dev->fat_bits == 0 || abs(dev->fat_bits) == 12) &&
616 (Fs->dir_len == 0 || Fs->dir_len == old_dos[i].dir_len) &&
617 (Fs->cluster_size == 0 ||
618 Fs->cluster_size == old_dos[i].cluster_size)) {
619 boot->boot.descr = old_dos[i].media;
620 Fs->cluster_size = old_dos[i].cluster_size;
621 Fs->dir_len = old_dos[i].dir_len;
622 Fs->fat_len = old_dos[i].fat_len;
627 if (i == sizeof(old_dos) / sizeof(old_dos[0]) ){
628 int may_change_cluster_size = (Fs->cluster_size == 0);
629 int may_change_root_size = (Fs->dir_len == 0);
631 /* a non-standard format */
632 if(DWORD(nhs) || tot_sectors % (dev->sectors * dev->heads))
633 boot->boot.descr = 0xf8;
635 boot->boot.descr = 0xf0;
638 if(!Fs->cluster_size) {
640 Fs->cluster_size = 1;
642 Fs->cluster_size = (tot_sectors > 2000 ) ? 1:2;
643 if (dev->use_2m & 0x7f)
644 Fs->cluster_size = 1;
652 Fs->dir_len = (tot_sectors > 2000) ? 32 : 7;
655 calc_cluster_size(Fs, tot_sectors, dev->fat_bits);
657 xdf_calc_fat_size(Fs, tot_sectors, dev->fat_bits);
659 calc_fat_bits2(Fs, tot_sectors, dev->fat_bits,
660 may_change_cluster_size,
661 may_change_root_size);
662 calc_fat_size(Fs, tot_sectors);
666 set_word(boot->boot.fatlen, Fs->fat_len);
671 static void calc_fs_parameters_32(unsigned long tot_sectors,
672 struct Fs_t *Fs, union bootsector *boot)
675 boot->boot.descr = 0xf8;
677 boot->boot.descr = 0xf0;
678 if(!Fs->cluster_size)
680 * http://www.microsoft.com/kb/articles/q154/9/97.htm,
681 * Micro$oft does not support FAT32 with less than 4K
683 Fs->cluster_size = 8;
686 Fs->num_clus = tot_sectors / Fs->cluster_size;
688 calc_fat_size(Fs, tot_sectors);
689 set_word(boot->boot.fatlen, 0);
690 set_dword(boot->boot.ext.fat32.bigFat, Fs->fat_len);
696 static void usage(int ret)
699 "Mtools version %s, dated %s\n", mversion, mdate);
701 "Usage: %s [-V] [-t tracks] [-h heads] [-n sectors] "
702 "[-v label] [-1] [-4] [-8] [-f size] "
704 "[-k] [-B bootsector] [-r root_dir_len] [-L fat_len] "
705 "[-F] [-I fsVersion] [-C] [-c cluster_size] "
706 "[-H hidden_sectors] "
710 "[-S hardsectorsize] [-M softsectorsize] [-3] "
711 "[-2 track0sectors] [-0 rate0] [-A rateany] [-a]"
712 "device\n", progname);
717 static int get_block_geom(int fd, struct MT_STAT *buf, struct device *dev,
719 struct hd_geometry geom;
721 int heads=dev->heads;
722 int sectors=dev->sectors;
725 if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
726 sprintf(errmsg, "Could not get geometry of device (%s)",
731 if (ioctl(fd, BLKGETSIZE, &size) < 0) {
732 sprintf(errmsg, "Could not get size of device (%s)",
740 sectors = geom.sectors;
742 sect_per_track = heads * sectors;
745 hidden = geom.start % sect_per_track;
746 if(hidden && hidden != sectors) {
748 "Hidden (%d) does not match sectors (%d)\n",
752 dev->hidden = hidden;
755 dev->sectors = sectors;
757 dev->tracks = (size + dev->hidden % sect_per_track) / sect_per_track;
762 void mformat(int argc, char **argv, int dummy)
764 int r; /* generic return value */
768 int sectors0=18; /* number of sectors on track 0 */
770 int rate_0, rate_any;
772 int argssize=0; /* sector size */
775 struct label_blk_t *labelBlock;
781 struct xdf_info info;
783 union bootsector boot;
787 struct device used_dev;
788 int argtracks, argheads, argsectors;
789 unsigned long tot_sectors=0;
792 char drive, name[EXPAND_BUF];
794 char label[VBUFSIZE];
796 dos_name_t shortlabel;
800 unsigned long serial;
807 int Atari = 0; /* should we add an Atari-style serial number ? */
825 if(getenv("MTOOLS_DIR_LEN")) {
826 Fs.dir_len = atoi(getenv("MTOOLS_DIR_LEN"));
832 if(getenv("MTOOLS_NFATS")) {
833 Fs.num_fat = atoi(getenv("MTOOLS_NFATS"));
838 rate_0 = mtools_rate_0;
839 rate_any = mtools_rate_any;
841 /* get command line options */
842 if(helpFlag(argc, argv))
844 while ((c = getopt(argc,argv,
846 "kK:B:r:L:I:FCc:Xh:s:T:l:N:H:M:S:2:30:Aad:m:"))!= EOF) {
849 set_cmd_line_image(optarg, 0);
852 /* standard DOS flags */
865 r=old_dos_size_to_geom(atoi(optarg),
866 &argtracks, &argheads,
870 "Bad size %s\n", optarg);
875 argtracks = atoi(optarg);
879 tot_sectors = atoi(optarg);
882 case 'n': /*non-standard*/
884 argsectors = atoi(optarg);
887 case 'l': /* non-standard */
889 strncpy(label, optarg, VBUFSIZE-1);
890 label[VBUFSIZE-1] = '\0';
893 /* flags supported by Dos but not mtools */
897 /*case 's': leave this for compatibility */
899 "Flag %c not supported by mtools\n",c);
904 /* flags added by mtools */
911 argssize = atoi(optarg) | 0x80;
914 if(argssize >= 0x87) {
915 fprintf(stderr, "argssize must be less than 6\n");
928 sectors0 = atoi(optarg);
934 case '0': /* rate on track 0 */
935 rate_0 = atoi(optarg);
937 case 'A': /* rate on other tracks */
938 rate_any = atoi(optarg);
942 msize = atoi(optarg);
947 fprintf(stderr, "Only sector sizes of 512, 1024, 2048 or 4096 bytes are allowed\n");
953 serial = strtoul(optarg,0,16);
956 case 'a': /* Atari style serial number */
961 create = O_CREAT | O_TRUNC;
970 fsVersion = strtoul(optarg,0,0);
974 Fs.cluster_size = atoi(optarg);
978 Fs.dir_len = strtoul(optarg,0,0);
981 Fs.fat_len = strtoul(optarg,0,0);
992 backupBoot = atoi(optarg);
993 if(backupBoot < 2 || backupBoot >= 32) {
994 fprintf(stderr, "Backupboot must be comprised between 2 and 32\n");
999 argheads = atoi(optarg);
1002 Fs.num_fat = atoi(optarg);
1005 mediaDesc = strtoul(optarg,0,0);
1012 if (argc - optind != 1 ||
1013 !argv[optind][0] || argv[optind][1] != ':')
1016 if(argtracks && tot_sectors) {
1017 fprintf(stderr, "Only one of -t or -T may be specified\n");
1022 if(create && format_xdf) {
1023 fprintf(stderr,"Create and XDF can't be used together\n");
1028 drive = toupper(argv[argc -1][0]);
1030 /* check out a drive whose letter and parameters match */
1031 sprintf(errmsg, "Drive '%c:' not supported", drive);
1034 for(dev=devices;dev->drive;dev++) {
1037 if (dev->drive != drive)
1041 SET_INT(used_dev.tracks, argtracks);
1042 SET_INT(used_dev.heads, argheads);
1043 SET_INT(used_dev.sectors, argsectors);
1044 SET_INT(used_dev.use_2m, arguse_2m);
1045 SET_INT(used_dev.ssize, argssize);
1047 used_dev.hidden = hs;
1049 expand(dev->name, name);
1050 #ifdef USING_NEW_VOLD
1051 strcpy(name, getVoldName(dev, name));
1059 Fs.Direct = FloppydOpen(&used_dev, dev, name,
1061 errmsg, 0, 1, &maxSize);
1064 Fs.Direct = SimpleFileOpen(&used_dev, dev, name,
1071 used_dev.misc_flags |= USE_XDF_FLAG;
1072 Fs.Direct = XdfOpen(&used_dev, name, O_RDWR,
1074 if(Fs.Direct && !Fs.fat_len)
1075 Fs.fat_len = info.FatSize;
1076 if(Fs.Direct && !Fs.dir_len)
1077 Fs.dir_len = info.RootDirSize;
1085 if ((!used_dev.tracks || !used_dev.heads || !used_dev.sectors) &&
1087 int fd= get_fd(Fs.Direct);
1088 struct MT_STAT stbuf;
1090 if (MT_FSTAT(fd, &stbuf) < 0) {
1091 sprintf(errmsg, "Could not stat file (%s)", strerror(errno));
1095 if (S_ISBLK(stbuf.st_mode) &&
1096 get_block_geom(fd, &stbuf, &used_dev, errmsg) < 0)
1101 /* no way to find out geometry */
1102 if ((!used_dev.tracks && !tot_sectors) ||
1103 !used_dev.heads || !used_dev.sectors){
1106 "(You must tell the complete geometry "
1107 "of the disk, \neither in /etc/mtools.conf or "
1108 "on the command line) ");
1113 /* set parameters, if needed */
1114 if(SET_GEOM(Fs.Direct, &used_dev, 0xf0, boot)){
1115 sprintf(errmsg,"Can't set disk parameters: %s",
1120 Fs.sector_size = 512;
1121 if( !(used_dev.use_2m & 0x7f)) {
1122 Fs.sector_size = 128 << (used_dev.ssize & 0x7f);
1125 SET_INT(Fs.sector_size, msize);
1128 for(j = 0; j < 31; j++) {
1129 if (Fs.sector_size == (unsigned int) (1 << j)) {
1134 Fs.sectorMask = Fs.sector_size - 1;
1137 if(!used_dev.blocksize || used_dev.blocksize < Fs.sector_size)
1138 blocksize = Fs.sector_size;
1140 blocksize = used_dev.blocksize;
1142 if(blocksize > MAX_SECTOR)
1143 blocksize = MAX_SECTOR;
1145 /* do a "test" read */
1147 READS(Fs.Direct, &boot.characters, 0, Fs.sector_size) !=
1148 (signed int) Fs.sector_size) {
1150 "Error reading from '%s', wrong parameters?",
1158 /* print error msg if needed */
1159 if ( dev->drive == 0 ){
1161 fprintf(stderr,"%s: %s\n", argv[0],errmsg);
1165 /* calculate the total number of sectors */
1166 if(tot_sectors == 0) {
1167 unsigned long sect_per_track = used_dev.heads*used_dev.sectors;
1168 tot_sectors = used_dev.tracks*sect_per_track - used_dev.hidden%sect_per_track;
1171 /* create the image file if needed */
1173 WRITES(Fs.Direct, &boot.characters,
1174 sectorsToBytes((Stream_t*)&Fs, tot_sectors-1),
1178 /* the boot sector */
1182 fd = open(bootSector, O_RDONLY | O_BINARY | O_LARGEFILE);
1184 perror("open boot sector");
1187 if(read(fd, &boot.bytes, blocksize) < blocksize) {
1188 perror("short read on boot sector");
1194 if(!keepBoot && !(used_dev.use_2m & 0x7f)) {
1195 memset(boot.characters, '\0', Fs.sector_size);
1196 if(Fs.sector_size == 512 && !used_dev.partition) {
1197 /* install fake partition table pointing to itself */
1198 struct partition *partTable=(struct partition *)
1199 (&boot.bytes[0x1ae]);
1200 setBeginEnd(&partTable[1], 0,
1201 used_dev.heads * used_dev.sectors * used_dev.tracks,
1202 used_dev.heads, used_dev.sectors, 1, 0);
1205 set_dword(boot.boot.nhs, used_dev.hidden);
1207 Fs.Next = buf_init(Fs.Direct,
1208 blocksize * used_dev.heads * used_dev.sectors,
1209 blocksize * used_dev.heads * used_dev.sectors,
1213 boot.boot.nfat = Fs.num_fat;
1215 set_word(&boot.bytes[510], 0xaa55);
1217 /* Initialize the remaining parameters */
1218 set_word(boot.boot.nsect, used_dev.sectors);
1219 set_word(boot.boot.nheads, used_dev.heads);
1221 used_dev.fat_bits = comp_fat_bits(&Fs,used_dev.fat_bits, tot_sectors, fat32);
1223 if(used_dev.fat_bits == 32) {
1225 Fs.writeAllFats = 1;
1227 calc_fs_parameters_32(tot_sectors, &Fs, &boot);
1229 Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
1231 /* extension flags: mirror fats, and use #0 as primary */
1232 set_word(boot.boot.ext.fat32.extFlags,0);
1234 /* fs version. What should go here? */
1235 set_word(boot.boot.ext.fat32.fsVersion,fsVersion);
1237 /* root directory */
1238 set_dword(boot.boot.ext.fat32.rootCluster, Fs.rootCluster = 2);
1241 set_word(boot.boot.ext.fat32.infoSector, Fs.infoSectorLoc = 1);
1242 Fs.infoSectorLoc = 1;
1244 /* no backup boot sector */
1245 set_word(boot.boot.ext.fat32.backupBoot, backupBoot);
1247 labelBlock = & boot.boot.ext.fat32.labelBlock;
1249 Fs.infoSectorLoc = 0;
1251 calc_fs_parameters(&used_dev, tot_sectors, &Fs, &boot);
1252 Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
1253 Fs.clus_start = Fs.dir_start + Fs.dir_len;
1254 labelBlock = & boot.boot.ext.old.labelBlock;
1258 /* Set the codepage */
1259 Fs.cp = cp_open(used_dev.codepage);
1264 /* only zero out physdrive if we don't have a template
1266 labelBlock->physdrive = 0x00;
1267 labelBlock->reserved = 0;
1268 labelBlock->dos4 = 0x29;
1270 if (!serial_set || Atari)
1271 srandom((long)time (0));
1274 set_dword(labelBlock->serial, serial);
1275 label_name(GET_DOSCONVERT((Stream_t *)&Fs),
1276 label[0] ? label : "NO NAME ", 0, &mangled, &shortlabel);
1277 strncpy(labelBlock->label, shortlabel.base, 11);
1278 sprintf(labelBlock->fat_type, "FAT%2.2d ", Fs.fat_bits);
1279 labelBlock->fat_type[7] = ' ';
1281 set_word(boot.boot.secsiz, Fs.sector_size);
1282 boot.boot.clsiz = (unsigned char) Fs.cluster_size;
1283 set_word(boot.boot.nrsvsect, Fs.fat_start);
1285 bootOffset = init_geometry_boot(&boot, &used_dev, sectors0,
1287 &tot_sectors, keepBoot);
1289 bootOffset = ((unsigned char *) labelBlock) - boot.bytes +
1290 sizeof(struct label_blk_t);
1293 boot.boot.banner[4] = 0;
1294 boot.boot.banner[5] = random();
1295 boot.boot.banner[6] = random();
1296 boot.boot.banner[7] = random();
1300 inst_boot_prg(&boot, bootOffset);
1301 /* Mimic 3.8 behavior, else 2m disk do not work (???)
1302 * luferbu@fluidsignal.com (Luis Bustamante), Fri, 14 Jun 2002
1304 if(used_dev.use_2m & 0x7f) {
1305 boot.boot.jump[0] = 0xeb;
1306 boot.boot.jump[1] = 0x80;
1307 boot.boot.jump[2] = 0x90;
1309 if(used_dev.use_2m & 0x7f)
1312 boot.boot.descr=mediaDesc;
1313 Fs.lastFatSectorNr = 0;
1314 Fs.lastFatSectorData = 0;
1315 zero_fat(&Fs, boot.boot.descr);
1316 Fs.freeSpace = Fs.num_clus;
1322 i < (info.BadSectors+Fs.cluster_size-1)/Fs.cluster_size;
1324 fatEncode(&Fs, i+2, 0xfff7);
1327 format_root(&Fs, label, &boot);
1328 WRITES((Stream_t *)&Fs, boot.characters,
1329 (mt_off_t) 0, Fs.sector_size);
1331 if(used_dev.fat_bits == 32) {
1332 WRITES((Stream_t *)&Fs, boot.characters,
1333 (mt_off_t) backupBoot * Fs.sector_size, Fs.sector_size);
1336 if(Fs.fat_bits == 32 && WORD_S(ext.fat32.backupBoot) != MAX16) {
1337 WRITES((Stream_t *)&Fs, boot.characters,
1338 sectorsToBytes((Stream_t*)&Fs,
1339 WORD_S(ext.fat32.backupBoot)),
1342 FLUSH((Stream_t *)&Fs); /* flushes Fs.
1343 * This triggers the writing of the FAT */
1345 Fs.Class->freeFunc((Stream_t *)&Fs);
1347 if(format_xdf && isatty(0) && !getenv("MTOOLS_USE_XDF"))
1350 "Remember to set the \"MTOOLS_USE_XDF\" environmental\n"
1351 "variable before accessing this disk\n\n"
1352 "Bourne shell syntax (sh, ash, bash, ksh, zsh etc):\n"
1353 " export MTOOLS_USE_XDF=1\n\n"
1354 "C shell syntax (csh and tcsh):\n"
1355 " setenv MTOOLS_USE_XDF 1\n" );