[9] | 1 | /*
|
---|
| 2 | * mformat.c
|
---|
| 3 | */
|
---|
| 4 |
|
---|
| 5 | #define DONT_NEED_WAIT
|
---|
| 6 |
|
---|
| 7 | #include "sysincludes.h"
|
---|
| 8 | #include "msdos.h"
|
---|
| 9 | #include "mtools.h"
|
---|
| 10 | #include "mainloop.h"
|
---|
| 11 | #include "fsP.h"
|
---|
| 12 | #include "file.h"
|
---|
| 13 | #include "plain_io.h"
|
---|
| 14 | #include "floppyd_io.h"
|
---|
| 15 | #include "nameclash.h"
|
---|
| 16 | #include "buffer.h"
|
---|
| 17 | #ifdef USE_XDF
|
---|
| 18 | #include "xdf_io.h"
|
---|
| 19 | #endif
|
---|
| 20 | #include "partition.h"
|
---|
| 21 |
|
---|
| 22 | #ifndef abs
|
---|
| 23 | #define abs(x) ((x)>0?(x):-(x))
|
---|
| 24 | #endif
|
---|
| 25 |
|
---|
| 26 | #ifdef OS_linux
|
---|
| 27 | #include "linux/hdreg.h"
|
---|
| 28 |
|
---|
| 29 | #define _LINUX_STRING_H_
|
---|
| 30 | #define kdev_t int
|
---|
| 31 | #include "linux/fs.h"
|
---|
| 32 | #undef _LINUX_STRING_H_
|
---|
| 33 |
|
---|
| 34 | #endif
|
---|
| 35 |
|
---|
| 36 |
|
---|
| 37 | extern int errno;
|
---|
| 38 |
|
---|
| 39 | static int init_geometry_boot(struct bootsector *boot, struct device *dev,
|
---|
| 40 | int sectors0, int rate_0, int rate_any,
|
---|
| 41 | int *tot_sectors, int keepBoot)
|
---|
| 42 | {
|
---|
| 43 | int i;
|
---|
| 44 | int nb_renum;
|
---|
| 45 | int sector2;
|
---|
| 46 | int size2;
|
---|
| 47 | int j;
|
---|
| 48 | int sum;
|
---|
| 49 |
|
---|
| 50 | set_word(boot->nsect, dev->sectors);
|
---|
| 51 | set_word(boot->nheads, dev->heads);
|
---|
| 52 |
|
---|
| 53 | *tot_sectors = dev->heads * dev->sectors * dev->tracks - DWORD(nhs);
|
---|
| 54 |
|
---|
| 55 | if (*tot_sectors < 0x10000){
|
---|
| 56 | set_word(boot->psect, *tot_sectors);
|
---|
| 57 | set_dword(boot->bigsect, 0);
|
---|
| 58 | } else {
|
---|
| 59 | set_word(boot->psect, 0);
|
---|
| 60 | set_dword(boot->bigsect, *tot_sectors);
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | if (dev->use_2m & 0x7f){
|
---|
| 64 | int bootOffset;
|
---|
| 65 | strncpy(boot->banner, "2M-STV04", 8);
|
---|
| 66 | boot->ext.old.res_2m = 0;
|
---|
| 67 | boot->ext.old.fmt_2mf = 6;
|
---|
| 68 | if ( dev->sectors % ( ((1 << dev->ssize) + 3) >> 2 ))
|
---|
| 69 | boot->ext.old.wt = 1;
|
---|
| 70 | else
|
---|
| 71 | boot->ext.old.wt = 0;
|
---|
| 72 | boot->ext.old.rate_0= rate_0;
|
---|
| 73 | boot->ext.old.rate_any= rate_any;
|
---|
| 74 | if (boot->ext.old.rate_any== 2 )
|
---|
| 75 | boot->ext.old.rate_any= 1;
|
---|
| 76 | i=76;
|
---|
| 77 |
|
---|
| 78 | /* Infp0 */
|
---|
| 79 | set_word(boot->ext.old.Infp0, i);
|
---|
| 80 | boot->jump[i++] = sectors0;
|
---|
| 81 | boot->jump[i++] = 108;
|
---|
| 82 | for(j=1; j<= sectors0; j++)
|
---|
| 83 | boot->jump[i++] = j;
|
---|
| 84 |
|
---|
| 85 | set_word(boot->ext.old.InfpX, i);
|
---|
| 86 |
|
---|
| 87 | boot->jump[i++] = 64;
|
---|
| 88 | boot->jump[i++] = 3;
|
---|
| 89 | nb_renum = i++;
|
---|
| 90 | sector2 = dev->sectors;
|
---|
| 91 | size2 = dev->ssize;
|
---|
| 92 | j=1;
|
---|
| 93 | while( sector2 ){
|
---|
| 94 | while ( sector2 < (1 << size2) >> 2 )
|
---|
| 95 | size2--;
|
---|
| 96 | boot->jump[i++] = 128 + j;
|
---|
| 97 | boot->jump[i++] = j++;
|
---|
| 98 | boot->jump[i++] = size2;
|
---|
| 99 | sector2 -= (1 << size2) >> 2;
|
---|
| 100 | }
|
---|
| 101 | boot->jump[nb_renum] = ( i - nb_renum - 1 ) / 3;
|
---|
| 102 |
|
---|
| 103 | set_word(boot->ext.old.InfTm, i);
|
---|
| 104 |
|
---|
| 105 | sector2 = dev->sectors;
|
---|
| 106 | size2= dev->ssize;
|
---|
| 107 | while(sector2){
|
---|
| 108 | while ( sector2 < 1 << ( size2 - 2) )
|
---|
| 109 | size2--;
|
---|
| 110 | boot->jump[i++] = size2;
|
---|
| 111 | sector2 -= 1 << (size2 - 2 );
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | set_word(boot->ext.old.BootP,i);
|
---|
| 115 | bootOffset = i;
|
---|
| 116 |
|
---|
| 117 | /* checksum */
|
---|
| 118 | for (sum=0, j=64; j<i; j++)
|
---|
| 119 | sum += boot->jump[j];/* checksum */
|
---|
| 120 | boot->ext.old.CheckSum=-sum;
|
---|
| 121 | return bootOffset;
|
---|
| 122 | } else {
|
---|
| 123 | if(!keepBoot) {
|
---|
| 124 | boot->jump[0] = 0xeb;
|
---|
| 125 | boot->jump[1] = 0;
|
---|
| 126 | boot->jump[2] = 0x90;
|
---|
| 127 | strncpy(boot->banner, "MTOOL397", 8);
|
---|
| 128 | /* It looks like some versions of DOS are
|
---|
| 129 | * rather picky about this, and assume default
|
---|
| 130 | * parameters without this, ignoring any
|
---|
| 131 | * indication about cluster size et al. */
|
---|
| 132 | }
|
---|
| 133 | return 0;
|
---|
| 134 | }
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 |
|
---|
| 138 | static int comp_fat_bits(Fs_t *Fs, int estimate,
|
---|
| 139 | unsigned int tot_sectors, int fat32)
|
---|
| 140 | {
|
---|
| 141 | int needed_fat_bits;
|
---|
| 142 |
|
---|
| 143 | needed_fat_bits = 12;
|
---|
| 144 |
|
---|
| 145 | #define MAX_DISK_SIZE(bits,clusters) \
|
---|
| 146 | TOTAL_DISK_SIZE((bits), Fs->sector_size, (clusters), \
|
---|
| 147 | Fs->num_fat, MAX_SECT_PER_CLUSTER)
|
---|
| 148 |
|
---|
| 149 | if(tot_sectors > MAX_DISK_SIZE(12, FAT12))
|
---|
| 150 | needed_fat_bits = 16;
|
---|
| 151 | if(fat32 || tot_sectors > MAX_DISK_SIZE(16, FAT16))
|
---|
| 152 | needed_fat_bits = 32;
|
---|
| 153 |
|
---|
| 154 | #undef MAX_DISK_SIZE
|
---|
| 155 |
|
---|
| 156 | if(abs(estimate) && abs(estimate) < needed_fat_bits) {
|
---|
| 157 | if(fat32) {
|
---|
| 158 | fprintf(stderr,
|
---|
| 159 | "Contradiction between FAT size on command line and FAT size in conf file\n");
|
---|
| 160 | exit(1);
|
---|
| 161 | }
|
---|
| 162 | fprintf(stderr,
|
---|
| 163 | "Device too big for a %d bit FAT\n",
|
---|
| 164 | estimate);
|
---|
| 165 | exit(1);
|
---|
| 166 | }
|
---|
| 167 |
|
---|
| 168 | if(needed_fat_bits == 32 && !fat32 && abs(estimate) !=32){
|
---|
| 169 | fprintf(stderr,"Warning: Using 32 bit FAT. Drive will only be accessibly by Win95 OEM / Win98\n");
|
---|
| 170 | }
|
---|
| 171 |
|
---|
| 172 | if(!estimate) {
|
---|
| 173 | int min_fat16_size;
|
---|
| 174 |
|
---|
| 175 | if(needed_fat_bits > 12)
|
---|
| 176 | return needed_fat_bits;
|
---|
| 177 | min_fat16_size = DISK_SIZE(16, Fs->sector_size, FAT12+1,
|
---|
| 178 | Fs->num_fat, 1);
|
---|
| 179 | if(tot_sectors < min_fat16_size)
|
---|
| 180 | return 12;
|
---|
| 181 | else if(tot_sectors >= 2* min_fat16_size)
|
---|
| 182 | return 16; /* heuristics */
|
---|
| 183 | }
|
---|
| 184 |
|
---|
| 185 | return estimate;
|
---|
| 186 | }
|
---|
| 187 |
|
---|
| 188 | static void calc_fat_bits2(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
|
---|
| 189 | {
|
---|
| 190 | unsigned int rem_sect;
|
---|
| 191 |
|
---|
| 192 | /*
|
---|
| 193 | * the "remaining sectors" after directory and boot
|
---|
| 194 | * hasve been accounted for.
|
---|
| 195 | */
|
---|
| 196 | rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
|
---|
| 197 | switch(abs(fat_bits)) {
|
---|
| 198 | case 0:
|
---|
| 199 |
|
---|
| 200 | #define MY_DISK_SIZE(bits,clusters) \
|
---|
| 201 | DISK_SIZE( (bits), Fs->sector_size, (clusters), \
|
---|
| 202 | Fs->num_fat, Fs->cluster_size)
|
---|
| 203 |
|
---|
| 204 | if(rem_sect >= MY_DISK_SIZE(16, FAT12 + 1))
|
---|
| 205 | /* big enough for FAT16 */
|
---|
| 206 | set_fat16(Fs);
|
---|
| 207 | else if(rem_sect <= MY_DISK_SIZE(12, FAT12))
|
---|
| 208 | /* small enough for FAT12 */
|
---|
| 209 | set_fat12(Fs);
|
---|
| 210 | else {
|
---|
| 211 | /* "between two chairs",
|
---|
| 212 | * augment cluster size, and
|
---|
| 213 | * settle it */
|
---|
| 214 | if(Fs->cluster_size < MAX_SECT_PER_CLUSTER)
|
---|
| 215 | Fs->cluster_size <<= 1;
|
---|
| 216 | set_fat12(Fs);
|
---|
| 217 | }
|
---|
| 218 | break;
|
---|
| 219 | #undef MY_DISK_SIZE
|
---|
| 220 |
|
---|
| 221 | case 12:
|
---|
| 222 | set_fat12(Fs);
|
---|
| 223 | break;
|
---|
| 224 | case 16:
|
---|
| 225 | set_fat16(Fs);
|
---|
| 226 | break;
|
---|
| 227 | case 32:
|
---|
| 228 | set_fat32(Fs);
|
---|
| 229 | break;
|
---|
| 230 | }
|
---|
| 231 | }
|
---|
| 232 |
|
---|
| 233 | static inline void format_root(Fs_t *Fs, char *label, struct bootsector *boot)
|
---|
| 234 | {
|
---|
| 235 | Stream_t *RootDir;
|
---|
| 236 | char *buf;
|
---|
| 237 | int i;
|
---|
| 238 | struct ClashHandling_t ch;
|
---|
| 239 | int dirlen;
|
---|
| 240 |
|
---|
| 241 | init_clash_handling(&ch);
|
---|
| 242 | ch.name_converter = label_name;
|
---|
| 243 | ch.ignore_entry = -2;
|
---|
| 244 |
|
---|
| 245 | buf = safe_malloc(Fs->sector_size);
|
---|
| 246 | RootDir = OpenRoot((Stream_t *)Fs);
|
---|
| 247 | if(!RootDir){
|
---|
| 248 | fprintf(stderr,"Could not open root directory\n");
|
---|
| 249 | exit(1);
|
---|
| 250 | }
|
---|
| 251 |
|
---|
| 252 | memset(buf, '\0', Fs->sector_size);
|
---|
| 253 |
|
---|
| 254 | if(Fs->fat_bits == 32) {
|
---|
| 255 | /* on a FAT32 system, we only write one sector,
|
---|
| 256 | * as the directory can be extended at will...*/
|
---|
| 257 | dirlen = 1;
|
---|
| 258 | fatAllocate(Fs, Fs->rootCluster, Fs->end_fat);
|
---|
| 259 | } else
|
---|
| 260 | dirlen = Fs->dir_len;
|
---|
| 261 | for (i = 0; i < dirlen; i++)
|
---|
| 262 | WRITES(RootDir, buf, sectorsToBytes((Stream_t*)Fs, i),
|
---|
| 263 | Fs->sector_size);
|
---|
| 264 |
|
---|
| 265 | ch.ignore_entry = 1;
|
---|
| 266 | if(label[0])
|
---|
| 267 | mwrite_one(RootDir,label, 0, labelit, NULL,&ch);
|
---|
| 268 |
|
---|
| 269 | FREE(&RootDir);
|
---|
| 270 | if(Fs->fat_bits == 32)
|
---|
| 271 | set_word(boot->dirents, 0);
|
---|
| 272 | else
|
---|
| 273 | set_word(boot->dirents, Fs->dir_len * (Fs->sector_size / 32));
|
---|
| 274 | free(buf);
|
---|
| 275 | }
|
---|
| 276 |
|
---|
| 277 |
|
---|
| 278 | static void xdf_calc_fat_size(Fs_t *Fs, unsigned int tot_sectors, int fat_bits)
|
---|
| 279 | {
|
---|
| 280 | unsigned int rem_sect;
|
---|
| 281 |
|
---|
| 282 | rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start - 2 * Fs->fat_len;
|
---|
| 283 |
|
---|
| 284 | if(Fs->fat_len) {
|
---|
| 285 | /* an XDF disk, we know the fat_size and have to find
|
---|
| 286 | * out the rest. We start with a cluster size of 1 and
|
---|
| 287 | * keep doubling until everything fits into the
|
---|
| 288 | * FAT. This will occur eventually, as our FAT has a
|
---|
| 289 | * minimal size of 1 */
|
---|
| 290 | for(Fs->cluster_size = 1; 1 ; Fs->cluster_size <<= 1) {
|
---|
| 291 | Fs->num_clus = rem_sect / Fs->cluster_size;
|
---|
| 292 | if(abs(fat_bits) == 16 || Fs->num_clus > FAT12)
|
---|
| 293 | set_fat16(Fs);
|
---|
| 294 | else
|
---|
| 295 | set_fat12(Fs);
|
---|
| 296 | if (Fs->fat_len >= NEEDED_FAT_SIZE(Fs))
|
---|
| 297 | return;
|
---|
| 298 | }
|
---|
| 299 | }
|
---|
| 300 | fprintf(stderr,"Internal error while calculating Xdf fat size\n");
|
---|
| 301 | exit(1);
|
---|
| 302 | }
|
---|
| 303 |
|
---|
| 304 |
|
---|
| 305 | static void calc_fat_size(Fs_t *Fs, unsigned int tot_sectors)
|
---|
| 306 | {
|
---|
| 307 | unsigned int rem_sect;
|
---|
| 308 | int tries;
|
---|
| 309 | int occupied;
|
---|
| 310 |
|
---|
| 311 | tries=0;
|
---|
| 312 | /* rough estimate of fat size */
|
---|
| 313 | Fs->fat_len = 1;
|
---|
| 314 | rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
|
---|
| 315 | while(1){
|
---|
| 316 | Fs->num_clus = (rem_sect - 2 * Fs->fat_len ) /Fs->cluster_size;
|
---|
| 317 | Fs->fat_len = NEEDED_FAT_SIZE(Fs);
|
---|
| 318 | occupied = 2 * Fs->fat_len + Fs->cluster_size * Fs->num_clus;
|
---|
| 319 |
|
---|
| 320 | /* if we have used up more than we have,
|
---|
| 321 | * we'll have to reloop */
|
---|
| 322 |
|
---|
| 323 | if ( occupied > rem_sect )
|
---|
| 324 | continue;
|
---|
| 325 |
|
---|
| 326 |
|
---|
| 327 | /* if we have exactly used up all
|
---|
| 328 | * sectors, fine */
|
---|
| 329 | if ( rem_sect - occupied < Fs->cluster_size )
|
---|
| 330 | break;
|
---|
| 331 |
|
---|
| 332 | /* if we have not used up all our
|
---|
| 333 | * sectors, try again. After the second
|
---|
| 334 | * try, decrease the amount of available
|
---|
| 335 | * space. This is to deal with the case of
|
---|
| 336 | * 344 or 345, ..., 1705, ... available
|
---|
| 337 | * sectors. */
|
---|
| 338 |
|
---|
| 339 | switch(tries++){
|
---|
| 340 | default:
|
---|
| 341 | /* this should never happen */
|
---|
| 342 | fprintf(stderr,
|
---|
| 343 | "Internal error in cluster/fat repartition"
|
---|
| 344 | " calculation.\n");
|
---|
| 345 | exit(1);
|
---|
| 346 | case 2:
|
---|
| 347 | /* FALLTHROUGH */
|
---|
| 348 | case 1:
|
---|
| 349 | rem_sect-= Fs->cluster_size;
|
---|
| 350 | Fs->dir_len += Fs->cluster_size;
|
---|
| 351 | case 0:
|
---|
| 352 | continue;
|
---|
| 353 | }
|
---|
| 354 | }
|
---|
| 355 |
|
---|
| 356 | if ( Fs->num_clus > FAT12 && Fs->fat_bits == 12 ){
|
---|
| 357 | fprintf(stderr,"Too many clusters for this fat size."
|
---|
| 358 | " Please choose a 16-bit fat in your /etc/mtools"
|
---|
| 359 | " or .mtoolsrc file\n");
|
---|
| 360 | exit(1);
|
---|
| 361 | }
|
---|
| 362 | if ( Fs->num_clus <= FAT12 && Fs->fat_bits > 12 ){
|
---|
| 363 | fprintf(stderr,"Too few clusters for this fat size."
|
---|
| 364 | " Please choose a 12-bit fat in your /etc/mtools"
|
---|
| 365 | " or .mtoolsrc file\n");
|
---|
| 366 | exit(1);
|
---|
| 367 | }
|
---|
| 368 | }
|
---|
| 369 |
|
---|
| 370 |
|
---|
| 371 | static unsigned char bootprog[]=
|
---|
| 372 | {0xfa, 0x31, 0xc0, 0x8e, 0xd8, 0x8e, 0xc0, 0xfc, 0xb9, 0x00, 0x01,
|
---|
| 373 | 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x80, 0xf3, 0xa5, 0xea, 0x00, 0x00,
|
---|
| 374 | 0x00, 0x08, 0xb8, 0x01, 0x02, 0xbb, 0x00, 0x7c, 0xba, 0x80, 0x00,
|
---|
| 375 | 0xb9, 0x01, 0x00, 0xcd, 0x13, 0x72, 0x05, 0xea, 0x00, 0x7c, 0x00,
|
---|
| 376 | 0x00, 0xcd, 0x19};
|
---|
| 377 |
|
---|
| 378 | static inline void inst_boot_prg(struct bootsector *boot, int offset)
|
---|
| 379 | {
|
---|
| 380 | memcpy((char *) boot->jump + offset,
|
---|
| 381 | (char *) bootprog, sizeof(bootprog) /sizeof(bootprog[0]));
|
---|
| 382 | boot->jump[0] = 0xeb;
|
---|
| 383 | boot->jump[1] = offset - 1;
|
---|
| 384 | boot->jump[2] = 0x90;
|
---|
| 385 | set_word(boot->jump + offset + 20, offset + 24);
|
---|
| 386 | }
|
---|
| 387 |
|
---|
| 388 | static void calc_cluster_size(struct Fs_t *Fs, unsigned int tot_sectors,
|
---|
| 389 | int fat_bits)
|
---|
| 390 |
|
---|
| 391 | {
|
---|
| 392 | unsigned int max_clusters; /* maximal possible number of sectors for
|
---|
| 393 | * this FAT entry length (12/16/32) */
|
---|
| 394 | unsigned int max_fat_size; /* maximal size of the FAT for this FAT
|
---|
| 395 | * entry length (12/16/32) */
|
---|
| 396 | unsigned int rem_sect; /* remaining sectors after we accounted for
|
---|
| 397 | * the root directory and boot sector(s) */
|
---|
| 398 |
|
---|
| 399 | switch(abs(fat_bits)) {
|
---|
| 400 | case 12:
|
---|
| 401 | max_clusters = FAT12;
|
---|
| 402 | max_fat_size = Fs->num_fat *
|
---|
| 403 | FAT_SIZE(12, Fs->sector_size, max_clusters);
|
---|
| 404 | break;
|
---|
| 405 | case 16:
|
---|
| 406 | case 0: /* still hesititating between 12 and 16 */
|
---|
| 407 | max_clusters = FAT16;
|
---|
| 408 | max_fat_size = Fs->num_fat *
|
---|
| 409 | FAT_SIZE(16, Fs->sector_size, max_clusters);
|
---|
| 410 | break;
|
---|
| 411 | case 32:
|
---|
| 412 | Fs->cluster_size = 8;
|
---|
| 413 | /* According to
|
---|
| 414 | * http://www.microsoft.com/kb/articles/q154/9/97.htm,
|
---|
| 415 | * Micro$oft does not support FAT32 with less than 4K
|
---|
| 416 | */
|
---|
| 417 | return;
|
---|
| 418 | default:
|
---|
| 419 | fprintf(stderr,"Bad fat size\n");
|
---|
| 420 | exit(1);
|
---|
| 421 | }
|
---|
| 422 |
|
---|
| 423 | rem_sect = tot_sectors - Fs->dir_len - Fs->fat_start;
|
---|
| 424 |
|
---|
| 425 | /* double the cluster size until we can fill up the disk with
|
---|
| 426 | * the maximal number of sectors of this size */
|
---|
| 427 | while(Fs->cluster_size * max_clusters + max_fat_size < rem_sect) {
|
---|
| 428 | if(Fs->cluster_size > 64) {
|
---|
| 429 | /* bigger than 64. Should fit */
|
---|
| 430 | fprintf(stderr,
|
---|
| 431 | "Internal error while calculating cluster size\n");
|
---|
| 432 | exit(1);
|
---|
| 433 | }
|
---|
| 434 | Fs->cluster_size <<= 1;
|
---|
| 435 | }
|
---|
| 436 | }
|
---|
| 437 |
|
---|
| 438 |
|
---|
| 439 | struct OldDos_t old_dos[]={
|
---|
| 440 | { 40, 9, 1, 4, 1, 2, 0xfc },
|
---|
| 441 | { 40, 9, 2, 7, 2, 2, 0xfd },
|
---|
| 442 | { 40, 8, 1, 4, 1, 1, 0xfe },
|
---|
| 443 | { 40, 8, 2, 7, 2, 1, 0xff },
|
---|
| 444 | { 80, 9, 2, 7, 2, 3, 0xf9 },
|
---|
| 445 | { 80, 15, 2,14, 1, 7, 0xf9 },
|
---|
| 446 | { 80, 18, 2,14, 1, 9, 0xf0 },
|
---|
| 447 | { 80, 36, 2,15, 2, 9, 0xf0 },
|
---|
| 448 | { 1, 8, 1, 1, 1, 1, 0xf0 },
|
---|
| 449 | };
|
---|
| 450 |
|
---|
| 451 | static int old_dos_size_to_geom(int size, int *cyls, int *heads, int *sects)
|
---|
| 452 | {
|
---|
| 453 | int i;
|
---|
| 454 | size = size * 2;
|
---|
| 455 | for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
|
---|
| 456 | if (old_dos[i].sectors *
|
---|
| 457 | old_dos[i].tracks *
|
---|
| 458 | old_dos[i].heads == size) {
|
---|
| 459 | *cyls = old_dos[i].tracks;
|
---|
| 460 | *heads = old_dos[i].heads;
|
---|
| 461 | *sects = old_dos[i].sectors;
|
---|
| 462 | return 0;
|
---|
| 463 | }
|
---|
| 464 | }
|
---|
| 465 | return 1;
|
---|
| 466 | }
|
---|
| 467 |
|
---|
| 468 |
|
---|
| 469 | static void calc_fs_parameters(struct device *dev, unsigned int tot_sectors,
|
---|
| 470 | struct Fs_t *Fs, struct bootsector *boot)
|
---|
| 471 | {
|
---|
| 472 | int i;
|
---|
| 473 |
|
---|
| 474 | for(i=0; i < sizeof(old_dos) / sizeof(old_dos[0]); i++){
|
---|
| 475 | if (dev->sectors == old_dos[i].sectors &&
|
---|
| 476 | dev->tracks == old_dos[i].tracks &&
|
---|
| 477 | dev->heads == old_dos[i].heads &&
|
---|
| 478 | (dev->fat_bits == 0 || abs(dev->fat_bits) == 12)){
|
---|
| 479 | boot->descr = old_dos[i].media;
|
---|
| 480 | Fs->cluster_size = old_dos[i].cluster_size;
|
---|
| 481 | Fs->dir_len = old_dos[i].dir_len;
|
---|
| 482 | Fs->fat_len = old_dos[i].fat_len;
|
---|
| 483 | Fs->fat_bits = 12;
|
---|
| 484 | break;
|
---|
| 485 | }
|
---|
| 486 | }
|
---|
| 487 | if (i == sizeof(old_dos) / sizeof(old_dos[0]) ){
|
---|
| 488 | /* a non-standard format */
|
---|
| 489 | if(DWORD(nhs))
|
---|
| 490 | boot->descr = 0xf8;
|
---|
| 491 | else
|
---|
| 492 | boot->descr = 0xf0;
|
---|
| 493 |
|
---|
| 494 |
|
---|
| 495 | if(!Fs->cluster_size) {
|
---|
| 496 | if (dev->heads == 1)
|
---|
| 497 | Fs->cluster_size = 1;
|
---|
| 498 | else {
|
---|
| 499 | Fs->cluster_size = (tot_sectors > 2000 ) ? 1:2;
|
---|
| 500 | if (dev->use_2m & 0x7f)
|
---|
| 501 | Fs->cluster_size = 1;
|
---|
| 502 | }
|
---|
| 503 | }
|
---|
| 504 |
|
---|
| 505 | if(!Fs->dir_len) {
|
---|
| 506 | if (dev->heads == 1)
|
---|
| 507 | Fs->dir_len = 4;
|
---|
| 508 | else
|
---|
| 509 | Fs->dir_len = (tot_sectors > 2000) ? 11 : 7;
|
---|
| 510 | }
|
---|
| 511 |
|
---|
| 512 | calc_cluster_size(Fs, tot_sectors, dev->fat_bits);
|
---|
| 513 | if(Fs->fat_len)
|
---|
| 514 | xdf_calc_fat_size(Fs, tot_sectors, dev->fat_bits);
|
---|
| 515 | else {
|
---|
| 516 | calc_fat_bits2(Fs, tot_sectors, dev->fat_bits);
|
---|
| 517 | calc_fat_size(Fs, tot_sectors);
|
---|
| 518 | }
|
---|
| 519 | }
|
---|
| 520 |
|
---|
| 521 | set_word(boot->fatlen, Fs->fat_len);
|
---|
| 522 | }
|
---|
| 523 |
|
---|
| 524 |
|
---|
| 525 |
|
---|
| 526 | static void calc_fs_parameters_32(unsigned int tot_sectors,
|
---|
| 527 | struct Fs_t *Fs, struct bootsector *boot)
|
---|
| 528 | {
|
---|
| 529 | if(DWORD(nhs))
|
---|
| 530 | boot->descr = 0xf8;
|
---|
| 531 | else
|
---|
| 532 | boot->descr = 0xf0;
|
---|
| 533 | if(!Fs->cluster_size)
|
---|
| 534 | /* According to
|
---|
| 535 | * http://www.microsoft.com/kb/articles/q154/9/97.htm,
|
---|
| 536 | * Micro$oft does not support FAT32 with less than 4K
|
---|
| 537 | */
|
---|
| 538 | Fs->cluster_size = 8;
|
---|
| 539 |
|
---|
| 540 | Fs->dir_len = 0;
|
---|
| 541 | Fs->num_clus = tot_sectors / Fs->cluster_size;
|
---|
| 542 | set_fat32(Fs);
|
---|
| 543 | calc_fat_size(Fs, tot_sectors);
|
---|
| 544 | set_word(boot->fatlen, 0);
|
---|
| 545 | set_dword(boot->ext.fat32.bigFat, Fs->fat_len);
|
---|
| 546 | }
|
---|
| 547 |
|
---|
| 548 |
|
---|
| 549 |
|
---|
| 550 |
|
---|
| 551 | static void usage(void)
|
---|
| 552 | {
|
---|
| 553 | fprintf(stderr,
|
---|
| 554 | "Mtools version %s, dated %s\n", mversion, mdate);
|
---|
| 555 | fprintf(stderr,
|
---|
| 556 | "Usage: %s [-t tracks] [-h heads] [-n sectors] "
|
---|
| 557 | "[-v label] [-1] [-4] [-8] [-f size] "
|
---|
| 558 | "[-N serialnumber] "
|
---|
| 559 | "[-k] [-B bootsector] [-r root_dir_len] [-L fat_len] "
|
---|
| 560 | "[-F] [-I fsVersion] [-C] [-c cluster_size] "
|
---|
| 561 | "[-H hidden_sectors] "
|
---|
| 562 | #ifdef USE_XDF
|
---|
| 563 | "[-X] "
|
---|
| 564 | #endif
|
---|
| 565 | "[-S hardsectorsize] [-M softsectorsize] [-3] "
|
---|
| 566 | "[-2 track0sectors] [-0 rate0] [-A rateany] [-a]"
|
---|
| 567 | "device\n", progname);
|
---|
| 568 | exit(1);
|
---|
| 569 | }
|
---|
| 570 |
|
---|
| 571 | void mformat(int argc, char **argv, int dummy)
|
---|
| 572 | {
|
---|
| 573 | int r; /* generic return value */
|
---|
| 574 | Fs_t Fs;
|
---|
| 575 | int hs, hs_set;
|
---|
| 576 | int arguse_2m = 0;
|
---|
| 577 | int sectors0=18; /* number of sectors on track 0 */
|
---|
| 578 | int create = 0;
|
---|
| 579 | int rate_0, rate_any;
|
---|
| 580 | int mangled;
|
---|
| 581 | int argssize=0; /* sector size */
|
---|
| 582 | int msize=0;
|
---|
| 583 | int fat32 = 0;
|
---|
| 584 | struct label_blk_t *labelBlock;
|
---|
| 585 | int bootOffset;
|
---|
| 586 |
|
---|
| 587 | #ifdef USE_XDF
|
---|
| 588 | int i;
|
---|
| 589 | int format_xdf = 0;
|
---|
| 590 | struct xdf_info info;
|
---|
| 591 | #endif
|
---|
| 592 | struct bootsector *boot;
|
---|
| 593 | char *bootSector=0;
|
---|
| 594 | int c;
|
---|
| 595 | int keepBoot = 0;
|
---|
| 596 | struct device used_dev;
|
---|
| 597 | int argtracks, argheads, argsectors;
|
---|
| 598 | int tot_sectors;
|
---|
| 599 | int blocksize;
|
---|
| 600 |
|
---|
| 601 | char *drive, name[EXPAND_BUF];
|
---|
| 602 |
|
---|
| 603 | char label[VBUFSIZE], buf[MAX_SECTOR], shortlabel[13];
|
---|
| 604 | struct device *dev;
|
---|
| 605 | char errmsg[200];
|
---|
| 606 |
|
---|
| 607 | unsigned long serial;
|
---|
| 608 | int serial_set;
|
---|
| 609 | int fsVersion;
|
---|
| 610 |
|
---|
| 611 | mt_off_t maxSize;
|
---|
| 612 |
|
---|
| 613 | int Atari = 0; /* should we add an Atari-style serial number ? */
|
---|
| 614 | #ifdef OS_Minix
|
---|
| 615 | char *devname;
|
---|
| 616 | struct device onedevice[2];
|
---|
| 617 | struct stat stbuf;
|
---|
| 618 | #endif
|
---|
| 619 |
|
---|
| 620 | hs = hs_set = 0;
|
---|
| 621 | argtracks = 0;
|
---|
| 622 | argheads = 0;
|
---|
| 623 | argsectors = 0;
|
---|
| 624 | arguse_2m = 0;
|
---|
| 625 | argssize = 0x2;
|
---|
| 626 | label[0] = '\0';
|
---|
| 627 | serial_set = 0;
|
---|
| 628 | serial = 0;
|
---|
| 629 | fsVersion = 0;
|
---|
| 630 |
|
---|
| 631 | Fs.cluster_size = 0;
|
---|
| 632 | Fs.refs = 1;
|
---|
| 633 | Fs.dir_len = 0;
|
---|
| 634 | Fs.fat_len = 0;
|
---|
| 635 | Fs.Class = &FsClass;
|
---|
| 636 | rate_0 = mtools_rate_0;
|
---|
| 637 | rate_any = mtools_rate_any;
|
---|
| 638 |
|
---|
| 639 | /* get command line options */
|
---|
| 640 | while ((c = getopt(argc,argv,
|
---|
| 641 | "148f:t:n:v:qub"
|
---|
| 642 | "kB:r:L:IFCc:Xh:s:l:N:H:M:S:230:Aa"))!= EOF) {
|
---|
| 643 | switch (c) {
|
---|
| 644 | /* standard DOS flags */
|
---|
| 645 | case '1':
|
---|
| 646 | argheads = 1;
|
---|
| 647 | break;
|
---|
| 648 | case '4':
|
---|
| 649 | argsectors = 9;
|
---|
| 650 | argtracks = 40;
|
---|
| 651 | break;
|
---|
| 652 | case '8':
|
---|
| 653 | argsectors = 8;
|
---|
| 654 | argtracks = 40;
|
---|
| 655 | break;
|
---|
| 656 | case 'f':
|
---|
| 657 | r=old_dos_size_to_geom(atoi(optarg),
|
---|
| 658 | &argtracks, &argheads,
|
---|
| 659 | &argsectors);
|
---|
| 660 | if(r) {
|
---|
| 661 | fprintf(stderr,
|
---|
| 662 | "Bad size %s\n", optarg);
|
---|
| 663 | exit(1);
|
---|
| 664 | }
|
---|
| 665 | break;
|
---|
| 666 | case 't':
|
---|
| 667 | argtracks = atoi(optarg);
|
---|
| 668 | break;
|
---|
| 669 |
|
---|
| 670 | case 'n': /*non-standard*/
|
---|
| 671 | case 's':
|
---|
| 672 | argsectors = atoi(optarg);
|
---|
| 673 | break;
|
---|
| 674 |
|
---|
| 675 | case 'l': /* non-standard */
|
---|
| 676 | case 'v':
|
---|
| 677 | strncpy(label, optarg, VBUFSIZE-1);
|
---|
| 678 | label[VBUFSIZE-1] = '\0';
|
---|
| 679 | break;
|
---|
| 680 |
|
---|
| 681 | /* flags supported by Dos but not mtools */
|
---|
| 682 | case 'q':
|
---|
| 683 | case 'u':
|
---|
| 684 | case 'b':
|
---|
| 685 | /*case 's': leave this for compatibility */
|
---|
| 686 | fprintf(stderr,
|
---|
| 687 | "Flag %c not supported by mtools\n",c);
|
---|
| 688 | exit(1);
|
---|
| 689 |
|
---|
| 690 |
|
---|
| 691 |
|
---|
| 692 | /* flags added by mtools */
|
---|
| 693 | case 'F':
|
---|
| 694 | fat32 = 1;
|
---|
| 695 | break;
|
---|
| 696 |
|
---|
| 697 |
|
---|
| 698 | case 'S':
|
---|
| 699 | argssize = atoi(optarg) | 0x80;
|
---|
| 700 | if(argssize < 0x81)
|
---|
| 701 | usage();
|
---|
| 702 | break;
|
---|
| 703 |
|
---|
| 704 | #ifdef USE_XDF
|
---|
| 705 | case 'X':
|
---|
| 706 | format_xdf = 1;
|
---|
| 707 | break;
|
---|
| 708 | #endif
|
---|
| 709 |
|
---|
| 710 | case '2':
|
---|
| 711 | arguse_2m = 0xff;
|
---|
| 712 | sectors0 = atoi(optarg);
|
---|
| 713 | break;
|
---|
| 714 | case '3':
|
---|
| 715 | arguse_2m = 0x80;
|
---|
| 716 | break;
|
---|
| 717 |
|
---|
| 718 | case '0': /* rate on track 0 */
|
---|
| 719 | rate_0 = atoi(optarg);
|
---|
| 720 | break;
|
---|
| 721 | case 'A': /* rate on other tracks */
|
---|
| 722 | rate_any = atoi(optarg);
|
---|
| 723 | break;
|
---|
| 724 |
|
---|
| 725 | case 'M':
|
---|
| 726 | msize = atoi(optarg);
|
---|
| 727 | if (msize % 256 || msize > 8192 )
|
---|
| 728 | usage();
|
---|
| 729 | break;
|
---|
| 730 |
|
---|
| 731 | case 'N':
|
---|
| 732 | serial = strtoul(optarg,0,16);
|
---|
| 733 | serial_set = 1;
|
---|
| 734 | break;
|
---|
| 735 | case 'a': /* Atari style serial number */
|
---|
| 736 | Atari = 1;
|
---|
| 737 | break;
|
---|
| 738 |
|
---|
| 739 | case 'C':
|
---|
| 740 | create = O_CREAT;
|
---|
| 741 | break;
|
---|
| 742 |
|
---|
| 743 | case 'H':
|
---|
| 744 | hs = atoi(optarg);
|
---|
| 745 | hs_set = 1;
|
---|
| 746 | break;
|
---|
| 747 |
|
---|
| 748 | case 'I':
|
---|
| 749 | fsVersion = strtoul(optarg,0,0);
|
---|
| 750 | break;
|
---|
| 751 |
|
---|
| 752 | case 'c':
|
---|
| 753 | Fs.cluster_size = atoi(optarg);
|
---|
| 754 | break;
|
---|
| 755 |
|
---|
| 756 | case 'r':
|
---|
| 757 | Fs.dir_len = strtoul(optarg,0,0);
|
---|
| 758 | break;
|
---|
| 759 | case 'L':
|
---|
| 760 | Fs.fat_len = strtoul(optarg,0,0);
|
---|
| 761 | break;
|
---|
| 762 |
|
---|
| 763 |
|
---|
| 764 | case 'B':
|
---|
| 765 | bootSector = optarg;
|
---|
| 766 | break;
|
---|
| 767 | case 'k':
|
---|
| 768 | keepBoot = 1;
|
---|
| 769 | break;
|
---|
| 770 | case 'h':
|
---|
| 771 | argheads = atoi(optarg);
|
---|
| 772 | break;
|
---|
| 773 |
|
---|
| 774 | default:
|
---|
| 775 | usage();
|
---|
| 776 | }
|
---|
| 777 | }
|
---|
| 778 |
|
---|
| 779 | if (argc - optind != 1 ||
|
---|
| 780 | skip_drive(argv[optind]) == argv[optind])
|
---|
| 781 | usage();
|
---|
| 782 |
|
---|
| 783 | #ifdef USE_XDF
|
---|
| 784 | if(create && format_xdf) {
|
---|
| 785 | fprintf(stderr,"Create and XDF can't be used together\n");
|
---|
| 786 | exit(1);
|
---|
| 787 | }
|
---|
| 788 | #endif
|
---|
| 789 |
|
---|
| 790 | drive = get_drive(argv[argc -1], NULL);
|
---|
| 791 |
|
---|
| 792 | #ifdef OS_Minix
|
---|
| 793 | devname = safe_malloc((9 + strlen(drive)) * sizeof(devname[0]));
|
---|
| 794 | strcpy(devname, "/dev/dosX");
|
---|
| 795 | if (isupper(drive[0]) && drive[1] == 0) {
|
---|
| 796 | /* single letter device name, use /dev/dos$drive */
|
---|
| 797 | devname[8]= drive[0];
|
---|
| 798 | } else
|
---|
| 799 | if (strchr(drive, '/') == NULL) {
|
---|
| 800 | /* a simple name, use /dev/$drive */
|
---|
| 801 | strcpy(devname+5, drive);
|
---|
| 802 | } else {
|
---|
| 803 | /* a pathname, use as is. */
|
---|
| 804 | strcpy(devname, drive);
|
---|
| 805 | }
|
---|
| 806 | if (stat(devname, &stbuf) != -1) {
|
---|
| 807 | memset(onedevice, 0, sizeof(onedevice));
|
---|
| 808 | onedevice[0].name = devname;
|
---|
| 809 | onedevice[0].drive = drive;
|
---|
| 810 | onedevice[1].name = NULL;
|
---|
| 811 | onedevice[1].drive = NULL;
|
---|
| 812 | dev = onedevice;
|
---|
| 813 | } else {
|
---|
| 814 | dev = devices;
|
---|
| 815 | }
|
---|
| 816 | #else
|
---|
| 817 | dev = devices;
|
---|
| 818 | #endif
|
---|
| 819 |
|
---|
| 820 | /* check out a drive whose letter and parameters match */
|
---|
| 821 | sprintf(errmsg, "Drive '%s:' not supported", drive);
|
---|
| 822 | Fs.Direct = NULL;
|
---|
| 823 | blocksize = 0;
|
---|
| 824 | for(;dev->drive;dev++) {
|
---|
| 825 | FREE(&(Fs.Direct));
|
---|
| 826 | /* drive name */
|
---|
| 827 | if (strcmp(dev->drive, drive) != 0)
|
---|
| 828 | continue;
|
---|
| 829 | used_dev = *dev;
|
---|
| 830 |
|
---|
| 831 | SET_INT(used_dev.tracks, argtracks);
|
---|
| 832 | SET_INT(used_dev.heads, argheads);
|
---|
| 833 | SET_INT(used_dev.sectors, argsectors);
|
---|
| 834 | SET_INT(used_dev.use_2m, arguse_2m);
|
---|
| 835 | SET_INT(used_dev.ssize, argssize);
|
---|
| 836 | if(hs_set)
|
---|
| 837 | used_dev.hidden = hs;
|
---|
| 838 |
|
---|
| 839 | expand(dev->name, name);
|
---|
| 840 | #ifdef USING_NEW_VOLD
|
---|
| 841 | strcpy(name, getVoldName(dev, name));
|
---|
| 842 | #endif
|
---|
| 843 |
|
---|
| 844 | #ifdef USE_XDF
|
---|
| 845 | if(!format_xdf) {
|
---|
| 846 | #endif
|
---|
| 847 | Fs.Direct = 0;
|
---|
| 848 | #ifdef USE_FLOPPYD
|
---|
| 849 | Fs.Direct = FloppydOpen(&used_dev, dev, name, O_RDWR | create,
|
---|
| 850 | errmsg, 0, 1);
|
---|
| 851 | if(Fs.Direct) {
|
---|
| 852 | maxSize = max_off_t_31;
|
---|
| 853 | }
|
---|
| 854 | #endif
|
---|
| 855 | if(!Fs.Direct) {
|
---|
| 856 | Fs.Direct = SimpleFileOpen(&used_dev, dev, name,
|
---|
| 857 | O_RDWR | create,
|
---|
| 858 | errmsg, 0, 1, &maxSize);
|
---|
| 859 | }
|
---|
| 860 | #ifdef USE_XDF
|
---|
| 861 | } else {
|
---|
| 862 | used_dev.misc_flags |= USE_XDF_FLAG;
|
---|
| 863 | Fs.Direct = XdfOpen(&used_dev, name, O_RDWR,
|
---|
| 864 | errmsg, &info);
|
---|
| 865 | if(Fs.Direct && !Fs.fat_len)
|
---|
| 866 | Fs.fat_len = info.FatSize;
|
---|
| 867 | if(Fs.Direct && !Fs.dir_len)
|
---|
| 868 | Fs.dir_len = info.RootDirSize;
|
---|
| 869 | }
|
---|
| 870 | #endif
|
---|
| 871 |
|
---|
| 872 | if (!Fs.Direct)
|
---|
| 873 | continue;
|
---|
| 874 |
|
---|
| 875 | #ifdef OS_linux
|
---|
| 876 | if ((!used_dev.tracks || !used_dev.heads || !used_dev.sectors) &&
|
---|
| 877 | (!IS_SCSI(dev))) {
|
---|
| 878 | int fd= get_fd(Fs.Direct);
|
---|
| 879 | struct stat buf;
|
---|
| 880 |
|
---|
| 881 | if (fstat(fd, &buf) < 0) {
|
---|
| 882 | sprintf(errmsg, "Could not stat file (%s)", strerror(errno));
|
---|
| 883 | continue;
|
---|
| 884 | }
|
---|
| 885 |
|
---|
| 886 | if (S_ISBLK(buf.st_mode)) {
|
---|
| 887 | struct hd_geometry geom;
|
---|
| 888 | long size;
|
---|
| 889 | int sect_per_track;
|
---|
| 890 |
|
---|
| 891 | if (ioctl(fd, HDIO_GETGEO, &geom) < 0) {
|
---|
| 892 | sprintf(errmsg, "Could not get geometry of device (%s)",
|
---|
| 893 | strerror(errno));
|
---|
| 894 | continue;
|
---|
| 895 | }
|
---|
| 896 |
|
---|
| 897 | if (ioctl(fd, BLKGETSIZE, &size) < 0) {
|
---|
| 898 | sprintf(errmsg, "Could not get size of device (%s)",
|
---|
| 899 | strerror(errno));
|
---|
| 900 | continue;
|
---|
| 901 | }
|
---|
| 902 |
|
---|
| 903 | sect_per_track = geom.heads * geom.sectors;
|
---|
| 904 | used_dev.heads = geom.heads;
|
---|
| 905 | used_dev.sectors = geom.sectors;
|
---|
| 906 | used_dev.hidden = geom.start % sect_per_track;
|
---|
| 907 | used_dev.tracks = (size + used_dev.hidden) / sect_per_track;
|
---|
| 908 | }
|
---|
| 909 | }
|
---|
| 910 | #endif
|
---|
| 911 |
|
---|
| 912 | /* no way to find out geometry */
|
---|
| 913 | if (!used_dev.tracks || !used_dev.heads || !used_dev.sectors){
|
---|
| 914 | sprintf(errmsg,
|
---|
| 915 | "Unknown geometry "
|
---|
| 916 | "(You must tell the complete geometry "
|
---|
| 917 | "of the disk, \neither in /etc/mtools.conf or "
|
---|
| 918 | "on the command line) ");
|
---|
| 919 | continue;
|
---|
| 920 | }
|
---|
| 921 |
|
---|
| 922 | #if 0
|
---|
| 923 | /* set parameters, if needed */
|
---|
| 924 | if(SET_GEOM(Fs.Direct, &used_dev, 0xf0, boot)){
|
---|
| 925 | sprintf(errmsg,"Can't set disk parameters: %s",
|
---|
| 926 | strerror(errno));
|
---|
| 927 | continue;
|
---|
| 928 | }
|
---|
| 929 | #endif
|
---|
| 930 | Fs.sector_size = 512;
|
---|
| 931 | if( !(used_dev.use_2m & 0x7f)) {
|
---|
| 932 | Fs.sector_size = 128 << (used_dev.ssize & 0x7f);
|
---|
| 933 | }
|
---|
| 934 |
|
---|
| 935 | SET_INT(Fs.sector_size, msize);
|
---|
| 936 | {
|
---|
| 937 | int i;
|
---|
| 938 | for(i = 0; i < 31; i++) {
|
---|
| 939 | if (Fs.sector_size == 1 << i) {
|
---|
| 940 | Fs.sectorShift = i;
|
---|
| 941 | break;
|
---|
| 942 | }
|
---|
| 943 | }
|
---|
| 944 | Fs.sectorMask = Fs.sector_size - 1;
|
---|
| 945 | }
|
---|
| 946 |
|
---|
| 947 | if(!used_dev.blocksize || used_dev.blocksize < Fs.sector_size)
|
---|
| 948 | blocksize = Fs.sector_size;
|
---|
| 949 | else
|
---|
| 950 | blocksize = used_dev.blocksize;
|
---|
| 951 |
|
---|
| 952 | if(blocksize > MAX_SECTOR)
|
---|
| 953 | blocksize = MAX_SECTOR;
|
---|
| 954 |
|
---|
| 955 | /* do a "test" read */
|
---|
| 956 | if (!create &&
|
---|
| 957 | READS(Fs.Direct, (char *) buf, 0, Fs.sector_size) !=
|
---|
| 958 | Fs.sector_size) {
|
---|
| 959 | sprintf(errmsg,
|
---|
| 960 | "Error reading from '%s', wrong parameters?",
|
---|
| 961 | name);
|
---|
| 962 | continue;
|
---|
| 963 | }
|
---|
| 964 | break;
|
---|
| 965 | }
|
---|
| 966 |
|
---|
| 967 |
|
---|
| 968 | /* print error msg if needed */
|
---|
| 969 | if ( dev->drive == 0 ){
|
---|
| 970 | FREE(&Fs.Direct);
|
---|
| 971 | fprintf(stderr,"%s: %s\n", argv[0],errmsg);
|
---|
| 972 | exit(1);
|
---|
| 973 | }
|
---|
| 974 |
|
---|
| 975 | /* the boot sector */
|
---|
| 976 | boot = (struct bootsector *) buf;
|
---|
| 977 | if(bootSector) {
|
---|
| 978 | int fd;
|
---|
| 979 |
|
---|
| 980 | fd = open(bootSector, O_RDONLY);
|
---|
| 981 | if(fd < 0) {
|
---|
| 982 | perror("open boot sector");
|
---|
| 983 | exit(1);
|
---|
| 984 | }
|
---|
| 985 | read(fd, buf, blocksize);
|
---|
| 986 | keepBoot = 1;
|
---|
| 987 | }
|
---|
| 988 | if(!keepBoot) {
|
---|
| 989 | memset((char *)boot, '\0', Fs.sector_size);
|
---|
| 990 | if(Fs.sector_size == 512 && !used_dev.partition) {
|
---|
| 991 | /* install fake partition table pointing to itself */
|
---|
| 992 | struct partition *partTable=(struct partition *)
|
---|
| 993 | (((char*) boot) + 0x1ae);
|
---|
| 994 | setBeginEnd(&partTable[1], 0,
|
---|
| 995 | used_dev.heads * used_dev.sectors * used_dev.tracks,
|
---|
| 996 | used_dev.heads, used_dev.sectors, 1, 0);
|
---|
| 997 | }
|
---|
| 998 | }
|
---|
| 999 | set_dword(boot->nhs, used_dev.hidden);
|
---|
| 1000 |
|
---|
| 1001 | Fs.Next = buf_init(Fs.Direct,
|
---|
| 1002 | blocksize * used_dev.heads * used_dev.sectors,
|
---|
| 1003 | blocksize * used_dev.heads * used_dev.sectors,
|
---|
| 1004 | blocksize);
|
---|
| 1005 | Fs.Buffer = 0;
|
---|
| 1006 |
|
---|
| 1007 | boot->nfat = Fs.num_fat = 2;
|
---|
| 1008 | if(!keepBoot)
|
---|
| 1009 | set_word(boot->jump + 510, 0xaa55);
|
---|
| 1010 |
|
---|
| 1011 | /* get the parameters */
|
---|
| 1012 | tot_sectors = used_dev.tracks * used_dev.heads * used_dev.sectors -
|
---|
| 1013 | DWORD(nhs);
|
---|
| 1014 |
|
---|
| 1015 | set_word(boot->nsect, dev->sectors);
|
---|
| 1016 | set_word(boot->nheads, dev->heads);
|
---|
| 1017 |
|
---|
| 1018 | dev->fat_bits = comp_fat_bits(&Fs,dev->fat_bits, tot_sectors, fat32);
|
---|
| 1019 |
|
---|
| 1020 | if(dev->fat_bits == 32) {
|
---|
| 1021 | Fs.primaryFat = 0;
|
---|
| 1022 | Fs.writeAllFats = 1;
|
---|
| 1023 | Fs.fat_start = 32;
|
---|
| 1024 | calc_fs_parameters_32(tot_sectors, &Fs, boot);
|
---|
| 1025 |
|
---|
| 1026 | Fs.clus_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
|
---|
| 1027 |
|
---|
| 1028 | /* extension flags: mirror fats, and use #0 as primary */
|
---|
| 1029 | set_word(boot->ext.fat32.extFlags,0);
|
---|
| 1030 |
|
---|
| 1031 | /* fs version. What should go here? */
|
---|
| 1032 | set_word(boot->ext.fat32.fsVersion,fsVersion);
|
---|
| 1033 |
|
---|
| 1034 | /* root directory */
|
---|
| 1035 | set_dword(boot->ext.fat32.rootCluster, Fs.rootCluster = 2);
|
---|
| 1036 |
|
---|
| 1037 | /* info sector */
|
---|
| 1038 | set_word(boot->ext.fat32.infoSector, Fs.infoSectorLoc = 1);
|
---|
| 1039 | Fs.infoSectorLoc = 1;
|
---|
| 1040 |
|
---|
| 1041 | /* no backup boot sector */
|
---|
| 1042 | set_word(boot->ext.fat32.backupBoot, 6);
|
---|
| 1043 |
|
---|
| 1044 | labelBlock = & boot->ext.fat32.labelBlock;
|
---|
| 1045 | } else {
|
---|
| 1046 | Fs.infoSectorLoc = 0;
|
---|
| 1047 | Fs.fat_start = 1;
|
---|
| 1048 | calc_fs_parameters(&used_dev, tot_sectors, &Fs, boot);
|
---|
| 1049 | Fs.dir_start = Fs.num_fat * Fs.fat_len + Fs.fat_start;
|
---|
| 1050 | Fs.clus_start = Fs.dir_start + Fs.dir_len;
|
---|
| 1051 | labelBlock = & boot->ext.old.labelBlock;
|
---|
| 1052 |
|
---|
| 1053 | }
|
---|
| 1054 |
|
---|
| 1055 | if (!keepBoot)
|
---|
| 1056 | /* only zero out physdrive if we don't have a template
|
---|
| 1057 | * bootsector */
|
---|
| 1058 | labelBlock->physdrive = 0x00;
|
---|
| 1059 | labelBlock->reserved = 0;
|
---|
| 1060 | labelBlock->dos4 = 0x29;
|
---|
| 1061 |
|
---|
| 1062 | if (!serial_set || Atari)
|
---|
| 1063 | srandom((long)time (0));
|
---|
| 1064 | if (!serial_set)
|
---|
| 1065 | serial=random();
|
---|
| 1066 | set_dword(labelBlock->serial, serial);
|
---|
| 1067 | if(!label[0])
|
---|
| 1068 | strncpy(shortlabel, "NO NAME ",11);
|
---|
| 1069 | else
|
---|
| 1070 | label_name(label, 0, &mangled, shortlabel);
|
---|
| 1071 | strncpy(labelBlock->label, shortlabel, 11);
|
---|
| 1072 | sprintf(labelBlock->fat_type, "FAT%2.2d ", Fs.fat_bits);
|
---|
| 1073 | labelBlock->fat_type[7] = ' ';
|
---|
| 1074 |
|
---|
| 1075 | set_word(boot->secsiz, Fs.sector_size);
|
---|
| 1076 | boot->clsiz = (unsigned char) Fs.cluster_size;
|
---|
| 1077 | set_word(boot->nrsvsect, Fs.fat_start);
|
---|
| 1078 |
|
---|
| 1079 | bootOffset = init_geometry_boot(boot, &used_dev, sectors0,
|
---|
| 1080 | rate_0, rate_any,
|
---|
| 1081 | &tot_sectors, keepBoot);
|
---|
| 1082 | if(!bootOffset) {
|
---|
| 1083 | bootOffset = ((char *) labelBlock) - ((char *) boot) +
|
---|
| 1084 | sizeof(struct label_blk_t);
|
---|
| 1085 | }
|
---|
| 1086 | if(Atari) {
|
---|
| 1087 | boot->banner[4] = 0;
|
---|
| 1088 | boot->banner[5] = random();
|
---|
| 1089 | boot->banner[6] = random();
|
---|
| 1090 | boot->banner[7] = random();
|
---|
| 1091 | }
|
---|
| 1092 |
|
---|
| 1093 | if (create) {
|
---|
| 1094 | WRITES(Fs.Direct, (char *) buf,
|
---|
| 1095 | sectorsToBytes((Stream_t*)&Fs, tot_sectors-1),
|
---|
| 1096 | Fs.sector_size);
|
---|
| 1097 | }
|
---|
| 1098 |
|
---|
| 1099 | if(!keepBoot)
|
---|
| 1100 | inst_boot_prg(boot, bootOffset);
|
---|
| 1101 | if(dev->use_2m & 0x7f)
|
---|
| 1102 | Fs.num_fat = 1;
|
---|
| 1103 | Fs.lastFatSectorNr = 0;
|
---|
| 1104 | Fs.lastFatSectorData = 0;
|
---|
| 1105 | zero_fat(&Fs, boot->descr);
|
---|
| 1106 | Fs.freeSpace = Fs.num_clus;
|
---|
| 1107 | Fs.last = 2;
|
---|
| 1108 |
|
---|
| 1109 | #ifdef USE_XDF
|
---|
| 1110 | if(format_xdf)
|
---|
| 1111 | for(i=0;
|
---|
| 1112 | i < (info.BadSectors+Fs.cluster_size-1)/Fs.cluster_size;
|
---|
| 1113 | i++)
|
---|
| 1114 | fatEncode(&Fs, i+2, 0xfff7);
|
---|
| 1115 | #endif
|
---|
| 1116 |
|
---|
| 1117 | format_root(&Fs, label, boot);
|
---|
| 1118 | WRITES((Stream_t *)&Fs, (char *) boot, (mt_off_t) 0, Fs.sector_size);
|
---|
| 1119 | if(Fs.fat_bits == 32 && WORD(ext.fat32.backupBoot) != MAX32) {
|
---|
| 1120 | WRITES((Stream_t *)&Fs, (char *) boot,
|
---|
| 1121 | sectorsToBytes((Stream_t*)&Fs, WORD(ext.fat32.backupBoot)),
|
---|
| 1122 | Fs.sector_size);
|
---|
| 1123 | }
|
---|
| 1124 | FLUSH((Stream_t *)&Fs); /* flushes Fs.
|
---|
| 1125 | * This triggers the writing of the FAT */
|
---|
| 1126 | FREE(&Fs.Next);
|
---|
| 1127 | Fs.Class->freeFunc((Stream_t *)&Fs);
|
---|
| 1128 | #ifdef USE_XDF
|
---|
| 1129 | if(format_xdf && isatty(0) && !getenv("MTOOLS_USE_XDF"))
|
---|
| 1130 | fprintf(stderr,
|
---|
| 1131 | "Note:\n"
|
---|
| 1132 | "Remember to set the \"MTOOLS_USE_XDF\" environmental\n"
|
---|
| 1133 | "variable before accessing this disk\n\n"
|
---|
| 1134 | "Bourne shell syntax (sh, ash, bash, ksh, zsh etc):\n"
|
---|
| 1135 | " export MTOOLS_USE_XDF=1\n\n"
|
---|
| 1136 | "C shell syntax (csh and tcsh):\n"
|
---|
| 1137 | " setenv MTOOLS_USE_XDF 1\n" );
|
---|
| 1138 | #endif
|
---|
| 1139 | exit(0);
|
---|
| 1140 | }
|
---|