--- mformat.c.orig 2013-01-08 23:14:21.000000000 +0100 +++ mformat.c 2018-08-11 12:43:23.357909111 +0200 @@ -541,11 +541,23 @@ static void calc_cluster_size(struct Fs_ FAT_SIZE(16, Fs->sector_size, max_clusters); break; case 32: - Fs->cluster_size = 8; - /* According to - * http://support.microsoft.com/support/kb/articles/q154/9/97.asp - * Micro$oft does not support FAT32 with less than 4K + /* + FAT32 cluster sizes for disks with 512 block size + according to Microsoft specification fatgen103.doc: + + 32.5 MB - 260 MB cluster_size = 1 + 260 MB - 8 GB cluster_size = 8 + 8 GB - 16 GB cluster_size = 16 + 16 GB - 32 GB cluster_size = 32 + 32 GB - 2 TB cluster_size = 64 + + Below calculation is generalized and does not depend + on 512 block size. */ + Fs->cluster_size = tot_sectors > 32*1024*1024*2 ? 64 : + tot_sectors > 16*1024*1024*2 ? 32 : + tot_sectors > 8*1024*1024*2 ? 16 : + tot_sectors > 260*1024*2 ? 8 : 1; return; default: fprintf(stderr,"Bad fat size\n"); @@ -564,13 +576,13 @@ static void calc_cluster_size(struct Fs_ /* double the cluster size until we can fill up the disk with * the maximal number of sectors of this size */ while(Fs->cluster_size * max_clusters + max_fat_size < rem_sect) { + Fs->cluster_size <<= 1; if(Fs->cluster_size > 64) { /* bigger than 64. Should fit */ fprintf(stderr, "Internal error while calculating cluster size\n"); exit(1); } - Fs->cluster_size <<= 1; } } @@ -680,15 +692,15 @@ static void calc_fs_parameters_32(unsign boot->boot.descr = 0xf8; else boot->boot.descr = 0xf0; - if(!Fs->cluster_size) - /* According to - * http://www.microsoft.com/kb/articles/q154/9/97.htm, - * Micro$oft does not support FAT32 with less than 4K - */ - Fs->cluster_size = 8; Fs->dir_len = 0; + calc_cluster_size(Fs, tot_sectors, 32); Fs->num_clus = tot_sectors / Fs->cluster_size; + /* Maximal number of clusters on FAT32 is 268435446 */ + if (Fs->num_clus > 268435446) { + fprintf(stderr, "Too many clusters\n"); + exit(1); + } set_fat32(Fs); calc_fat_size(Fs, tot_sectors); set_word(boot->boot.fatlen, 0); @@ -1189,6 +1201,11 @@ void mformat(int argc, char **argv, int if(tot_sectors == 0) { unsigned long sect_per_track = used_dev.heads*used_dev.sectors; tot_sectors = used_dev.tracks*sect_per_track - used_dev.hidden%sect_per_track; + /* Number of sectors must fit into 32bit value */ + if (tot_sectors > 0xFFFFFFFF) { + fprintf(stderr, "Too many sectors\n"); + exit(1); + } } /* create the image file if needed */