1 | // Fat32 formatter version 1.05
|
---|
2 | // (c) Tom Thornhill 2007,2008,2009
|
---|
3 | // This software is covered by the GPL.
|
---|
4 | // By using this tool, you agree to absolve Ridgecrop of an liabilities for lost data.
|
---|
5 | // Please backup any data you value before using this tool.
|
---|
6 |
|
---|
7 | #include <stdio.h>
|
---|
8 | #include <stdlib.h>
|
---|
9 | #include <string.h>
|
---|
10 | #include <signal.h>
|
---|
11 | #include <math.h>
|
---|
12 |
|
---|
13 | #include "fat32c.h"
|
---|
14 |
|
---|
15 | /*
|
---|
16 | 28.2 CALCULATING THE VOLUME SERIAL NUMBER
|
---|
17 |
|
---|
18 | For example, say a disk was formatted on 26 Dec 95 at 9:55 PM and 41.94
|
---|
19 | seconds. DOS takes the date and time just before it writes it to the
|
---|
20 | disk.
|
---|
21 |
|
---|
22 | Low order word is calculated: Volume Serial Number is:
|
---|
23 | Month & Day 12/26 0c1ah
|
---|
24 | Sec & Hundrenths 41:94 295eh 3578:1d02
|
---|
25 | -----
|
---|
26 | 3578h
|
---|
27 |
|
---|
28 | High order word is calculated:
|
---|
29 | Hours & Minutes 21:55 1537h
|
---|
30 | Year 1995 07cbh
|
---|
31 | -----
|
---|
32 | 1d02h
|
---|
33 | */
|
---|
34 |
|
---|
35 |
|
---|
36 | /*
|
---|
37 | This is the Microsoft calculation from FATGEN
|
---|
38 |
|
---|
39 | DWORD RootDirSectors = 0;
|
---|
40 | DWORD TmpVal1, TmpVal2, FATSz;
|
---|
41 |
|
---|
42 | TmpVal1 = DskSize - ( ReservedSecCnt + RootDirSectors);
|
---|
43 | TmpVal2 = (256 * SecPerClus) + NumFATs;
|
---|
44 | TmpVal2 = TmpVal2 / 2;
|
---|
45 | FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
|
---|
46 |
|
---|
47 | return( FatSz );
|
---|
48 | */
|
---|
49 |
|
---|
50 | // disk file open handle
|
---|
51 | HANDLE hDev = 0;
|
---|
52 | extern char msg;
|
---|
53 |
|
---|
54 | DWORD get_fat_size_sectors ( DWORD DskSize, DWORD ReservedSecCnt, DWORD SecPerClus, DWORD NumFATs, DWORD BytesPerSect )
|
---|
55 | {
|
---|
56 | ULONGLONG Numerator, Denominator;
|
---|
57 | ULONGLONG FatElementSize = 4;
|
---|
58 | ULONGLONG FatSz;
|
---|
59 |
|
---|
60 | // This is based on
|
---|
61 | // http://hjem.get2net.dk/rune_moeller_barnkob/filesystems/fat.html
|
---|
62 | // I've made the obvious changes for FAT32
|
---|
63 | Numerator = FatElementSize * ( DskSize - ReservedSecCnt );
|
---|
64 | Denominator = ( SecPerClus * BytesPerSect ) + ( FatElementSize * NumFATs );
|
---|
65 | FatSz = Numerator / Denominator;
|
---|
66 | // round up
|
---|
67 | FatSz += 1;
|
---|
68 |
|
---|
69 | return( (DWORD) FatSz );
|
---|
70 | }
|
---|
71 |
|
---|
72 |
|
---|
73 | BYTE get_spc ( DWORD ClusterSizeKB, DWORD BytesPerSect )
|
---|
74 | {
|
---|
75 | DWORD spc = ( ClusterSizeKB * 1024 ) / BytesPerSect;
|
---|
76 | return( (BYTE) spc );
|
---|
77 | }
|
---|
78 |
|
---|
79 | BYTE get_sectors_per_cluster ( LONGLONG DiskSizeBytes, DWORD BytesPerSect )
|
---|
80 | {
|
---|
81 | BYTE ret = 0x01; // 1 sector per cluster
|
---|
82 | LONGLONG DiskSizeMB = DiskSizeBytes / ( 1024*1024 );
|
---|
83 |
|
---|
84 | // 512 MB to 8,191 MB 4 KB
|
---|
85 | if ( DiskSizeMB > 512 )
|
---|
86 | ret = get_spc( 4, BytesPerSect ); // ret = 0x8;
|
---|
87 |
|
---|
88 | // 8,192 MB to 16,383 MB 8 KB
|
---|
89 | if ( DiskSizeMB > 8192 )
|
---|
90 | ret = get_spc( 8, BytesPerSect ); // ret = 0x10;
|
---|
91 |
|
---|
92 | // 16,384 MB to 32,767 MB 16 KB
|
---|
93 | if ( DiskSizeMB > 16384 )
|
---|
94 | ret = get_spc( 16, BytesPerSect ); // ret = 0x20;
|
---|
95 |
|
---|
96 | // Larger than 32,768 MB 32 KB
|
---|
97 | if ( DiskSizeMB > 32768 )
|
---|
98 | ret = get_spc( 32, BytesPerSect ); // ret = 0x40;
|
---|
99 |
|
---|
100 | return( ret );
|
---|
101 |
|
---|
102 | }
|
---|
103 |
|
---|
104 | void zero_sectors ( HANDLE hDevice, DWORD Sector, DWORD BytesPerSect, DWORD NumSects) //, DISK_GEOMETRY* pdgDrive )
|
---|
105 | {
|
---|
106 | BYTE *pZeroSect;
|
---|
107 | DWORD BurstSize;
|
---|
108 | DWORD WriteSize;
|
---|
109 | BOOL ret;
|
---|
110 | DWORD dwWritten;
|
---|
111 | //LARGE_INTEGER Start, End, Ticks, Frequency;
|
---|
112 | ULONGLONG Start, End, Ticks, Frequency;
|
---|
113 | double fTime;
|
---|
114 | double fBytesTotal;
|
---|
115 | ULONGLONG qBytesTotal, qBytesWritten;
|
---|
116 | float fPercentWritten, fPrevPercentWritten = 0;
|
---|
117 | //char Str[12];
|
---|
118 |
|
---|
119 | //BurstSize = pdgDrive->SectorsPerTrack * pdgDrive->TracksPerCylinder;
|
---|
120 | BurstSize = 64; // 32K
|
---|
121 | //BurstSize = 128; // 64K
|
---|
122 | //BurstSize = 8; // 4k
|
---|
123 | //BurstSize = 1; // one sector
|
---|
124 |
|
---|
125 | //printf("zero_sectors: \nhDevice=0x%lx, Sector=%lu, \nBytesPerSect=%lu, NumSects=%lu\n",
|
---|
126 | // hDevice, Sector, BytesPerSect, NumSects);
|
---|
127 |
|
---|
128 | mem_alloc((void **)&pZeroSect, BytesPerSect * BurstSize);
|
---|
129 |
|
---|
130 | seek_to_sect( hDevice, Sector, BytesPerSect );
|
---|
131 |
|
---|
132 | query_freq( &Frequency );
|
---|
133 | query_time( &Start );
|
---|
134 |
|
---|
135 | qBytesTotal = NumSects * BytesPerSect;
|
---|
136 | qBytesWritten = 0;
|
---|
137 | fPercentWritten = 0;
|
---|
138 |
|
---|
139 | //printf("Percent written: ");
|
---|
140 |
|
---|
141 | while ( NumSects )
|
---|
142 | {
|
---|
143 | if ( NumSects > BurstSize )
|
---|
144 | WriteSize = BurstSize;
|
---|
145 | else
|
---|
146 | WriteSize = NumSects;
|
---|
147 |
|
---|
148 | //ret = WriteFile ( hDevice, pZeroSect, WriteSize*BytesPerSect, &dwWritten, NULL );
|
---|
149 | ret = write_file ( hDevice, pZeroSect, WriteSize * BytesPerSect, &dwWritten );
|
---|
150 |
|
---|
151 | if ( !ret )
|
---|
152 | die ( "Failed to write", ret );
|
---|
153 |
|
---|
154 | qBytesWritten += dwWritten;
|
---|
155 |
|
---|
156 | fPercentWritten = ( 100 * qBytesWritten ) / qBytesTotal;
|
---|
157 | //sprintf(Str, "%.2f%%...", fPercentWritten);
|
---|
158 |
|
---|
159 | if ( fPercentWritten - fPrevPercentWritten >= 1 )
|
---|
160 | {
|
---|
161 | // update progress indicator if it has grown by >= 5%
|
---|
162 | fPrevPercentWritten = fPercentWritten;
|
---|
163 | // percent written indication
|
---|
164 | show_progress(fPercentWritten);
|
---|
165 | }
|
---|
166 |
|
---|
167 | NumSects -= WriteSize;
|
---|
168 | }
|
---|
169 |
|
---|
170 | query_time( &End );
|
---|
171 |
|
---|
172 | //Ticks.QuadPart = End.QuadPart - Start.QuadPart;
|
---|
173 | //fTime = (double) ( Ticks.QuadPart ) / Frequency.QuadPart;
|
---|
174 |
|
---|
175 | Ticks = End - Start;
|
---|
176 | fTime = (double) ( Ticks ) / Frequency;
|
---|
177 |
|
---|
178 | mem_free(pZeroSect, BytesPerSect * BurstSize);
|
---|
179 |
|
---|
180 | fBytesTotal = (double) qBytesTotal;
|
---|
181 | show_message ( "\nWrote %I64d bytes in %.2f seconds, %.2f Megabytes/sec\n", 0, 3,
|
---|
182 | qBytesTotal, fTime, fBytesTotal/(fTime*1024.0*1024.0) );
|
---|
183 | }
|
---|
184 |
|
---|
185 | int format_volume (char *path, format_params *params)
|
---|
186 | {
|
---|
187 | // First open the device
|
---|
188 | char *p;
|
---|
189 | DWORD i;
|
---|
190 | HANDLE hDevice;
|
---|
191 | UCHAR PartitionType = 0x0c;
|
---|
192 |
|
---|
193 | int cbRet;
|
---|
194 | BOOL bRet;
|
---|
195 | BYTE szString[12];
|
---|
196 |
|
---|
197 | // extended BPB
|
---|
198 | struct extbpb dp = {0, 0, 32, 2, 0, 0, 0xf8, 0, 0, 0, 0, 0, {0}};
|
---|
199 |
|
---|
200 | // Recommended values
|
---|
201 | //DWORD ReservedSectCount = 32; !!! create cmd line parameter !!!
|
---|
202 | //DWORD NumFATs = 2;
|
---|
203 | DWORD BackupBootSect = 6;
|
---|
204 | DWORD VolumeId=0; // calculated before format
|
---|
205 |
|
---|
206 | // // Calculated later
|
---|
207 | //DWORD FatSize=0;
|
---|
208 | //DWORD BytesPerSect=0;
|
---|
209 | //DWORD SectorsPerCluster=0;
|
---|
210 | //DWORD TotalSectors=0;
|
---|
211 | DWORD SystemAreaSize=0;
|
---|
212 | DWORD UserAreaSize=0;
|
---|
213 | ULONGLONG qTotalSectors=0;
|
---|
214 |
|
---|
215 | // structures to be written to the disk
|
---|
216 | FAT_BOOTSECTOR32 *pFAT32BootSect;
|
---|
217 | FAT_FSINFO *pFAT32FsInfo;
|
---|
218 |
|
---|
219 | DWORD *pFirstSectOfFat;
|
---|
220 |
|
---|
221 | // Debug temp vars
|
---|
222 | ULONGLONG FatNeeded, ClusterCount;
|
---|
223 | char c;
|
---|
224 |
|
---|
225 | static char volId[12] = {0};
|
---|
226 | char *vol = volId;
|
---|
227 |
|
---|
228 | if (params->reserved_sectors)
|
---|
229 | dp.ReservedSectCount = params->reserved_sectors;
|
---|
230 |
|
---|
231 | VolumeId = get_vol_id( );
|
---|
232 |
|
---|
233 | strncpy(vol, params->volume_label, 11);
|
---|
234 | check_vol_label(path, (char **)&vol);
|
---|
235 |
|
---|
236 | // Open drive
|
---|
237 | open_drive (path, &hDevice);
|
---|
238 | get_drive_params(hDevice, &dp);
|
---|
239 | lock_drive(hDevice);
|
---|
240 | begin_format(hDevice);
|
---|
241 | sectorio(hDevice);
|
---|
242 |
|
---|
243 | // Checks on Disk Size
|
---|
244 | // qTotalSectors = dp.PartitionLength / dp.BytesPerSect;
|
---|
245 | qTotalSectors = dp.TotalSectors;
|
---|
246 | // low end limit - 65536 sectors
|
---|
247 | if ( qTotalSectors < 65536 )
|
---|
248 | {
|
---|
249 | // I suspect that most FAT32 implementations would mount this volume just fine, but the
|
---|
250 | // spec says that we shouldn't do this, so we won't
|
---|
251 | die ( "This drive is too small for FAT32 - there must be at least 64K clusters\n", -1);
|
---|
252 | }
|
---|
253 |
|
---|
254 | if ( qTotalSectors >= 0xffffffff )
|
---|
255 | {
|
---|
256 | // This is a more fundamental limitation on FAT32 - the total sector count in the root dir
|
---|
257 | // ís 32bit. With a bit of creativity, FAT32 could be extended to handle at least 2^28 clusters
|
---|
258 | // There would need to be an extra field in the FSInfo sector, and the old sector count could
|
---|
259 | // be set to 0xffffffff. This is non standard though, the Windows FAT driver FASTFAT.SYS won't
|
---|
260 | // understand this. Perhaps a future version of FAT32 and FASTFAT will handle this.
|
---|
261 | die ( "This drive is too big for FAT32 - max 2TB supported\n", -1);
|
---|
262 | }
|
---|
263 |
|
---|
264 | mem_alloc ( (void **)&pFAT32BootSect, dp.BytesPerSect );
|
---|
265 | mem_alloc ( (void **)&pFAT32FsInfo, dp.BytesPerSect );
|
---|
266 | mem_alloc ( (void **)&pFirstSectOfFat, dp.BytesPerSect );
|
---|
267 |
|
---|
268 | if ( !pFAT32BootSect || !pFAT32FsInfo || !pFirstSectOfFat )
|
---|
269 | die ( "Failed to allocate memory", -2 );
|
---|
270 |
|
---|
271 | // fill out the boot sector and fs info
|
---|
272 | pFAT32BootSect->sJmpBoot[0]=0xEB;
|
---|
273 | pFAT32BootSect->sJmpBoot[1]=0x5A;
|
---|
274 | pFAT32BootSect->sJmpBoot[2]=0x90;
|
---|
275 | strcpy( pFAT32BootSect->sOEMName, "MSWIN4.1" );
|
---|
276 | pFAT32BootSect->wBytsPerSec = (WORD) dp.BytesPerSect;
|
---|
277 |
|
---|
278 | if ( params->sectors_per_cluster )
|
---|
279 | dp.SectorsPerCluster = params->sectors_per_cluster;
|
---|
280 | else
|
---|
281 | dp.SectorsPerCluster = get_sectors_per_cluster( ((LONGLONG)dp.TotalSectors) * dp.BytesPerSect, dp.BytesPerSect );
|
---|
282 |
|
---|
283 | pFAT32BootSect->bSecPerClus = (BYTE) dp.SectorsPerCluster ;
|
---|
284 | pFAT32BootSect->wRsvdSecCnt = (WORD) dp.ReservedSectCount;
|
---|
285 | pFAT32BootSect->bNumFATs = (BYTE) dp.NumFATs;
|
---|
286 | pFAT32BootSect->wRootEntCnt = 0;
|
---|
287 | pFAT32BootSect->wTotSec16 = 0;
|
---|
288 | pFAT32BootSect->bMedia = 0xF8;
|
---|
289 | pFAT32BootSect->wFATSz16 = 0;
|
---|
290 | pFAT32BootSect->wSecPerTrk = (WORD) dp.SectorsPerTrack;
|
---|
291 | pFAT32BootSect->wNumHeads = (WORD) dp.TracksPerCylinder;
|
---|
292 | pFAT32BootSect->dHiddSec = (DWORD) dp.HiddenSectors;
|
---|
293 | //dp.TotalSectors = (DWORD) (dp.PartitionLength / dp.BytesPerSect);
|
---|
294 | pFAT32BootSect->dTotSec32 = dp.TotalSectors;
|
---|
295 |
|
---|
296 | dp.FatSize = get_fat_size_sectors ( pFAT32BootSect->dTotSec32, pFAT32BootSect->wRsvdSecCnt, pFAT32BootSect->bSecPerClus, pFAT32BootSect->bNumFATs, dp.BytesPerSect );
|
---|
297 |
|
---|
298 | pFAT32BootSect->dFATSz32 = dp.FatSize;
|
---|
299 | pFAT32BootSect->wExtFlags = 0;
|
---|
300 | pFAT32BootSect->wFSVer = 0;
|
---|
301 | pFAT32BootSect->dRootClus = 2;
|
---|
302 | pFAT32BootSect->wFSInfo = 1;
|
---|
303 | pFAT32BootSect->wBkBootSec = (WORD) BackupBootSect;
|
---|
304 | pFAT32BootSect->bDrvNum = 0x80;
|
---|
305 | pFAT32BootSect->Reserved1 = 0;
|
---|
306 | pFAT32BootSect->bBootSig = 0x29;
|
---|
307 |
|
---|
308 | // Specify volume label
|
---|
309 | if (!*vol)
|
---|
310 | vol = get_vol_label(path, vol);
|
---|
311 |
|
---|
312 | vol = strupr(vol);
|
---|
313 |
|
---|
314 | pFAT32BootSect->dBS_VolID = VolumeId;
|
---|
315 | strncpy ( pFAT32BootSect->sVolLab, vol, 11 );
|
---|
316 | strncpy ( pFAT32BootSect->sBS_FilSysType, "FAT32 ", 8 );
|
---|
317 | ((BYTE*)pFAT32BootSect)[510] = 0x55;
|
---|
318 | ((BYTE*)pFAT32BootSect)[511] = 0xaa;
|
---|
319 |
|
---|
320 | /* FATGEN103.DOC says "NOTE: Many FAT documents mistakenly say that this 0xAA55 signature occupies the "last 2 bytes of
|
---|
321 | the boot sector". This statement is correct if - and only if - BPB_BytsPerSec is 512. If BPB_BytsPerSec is greater than
|
---|
322 | 512, the offsets of these signature bytes do not change (although it is perfectly OK for the last two bytes at the end
|
---|
323 | of the boot sector to also contain this signature)."
|
---|
324 |
|
---|
325 | Windows seems to only check the bytes at offsets 510 and 511. Other OSs might check the ones at the end of the sector,
|
---|
326 | so we'll put them there too.
|
---|
327 | */
|
---|
328 | if ( dp.BytesPerSect != 512 )
|
---|
329 | {
|
---|
330 | ((BYTE*)pFAT32BootSect)[dp.BytesPerSect-2] = 0x55;
|
---|
331 | ((BYTE*)pFAT32BootSect)[dp.BytesPerSect-1] = 0xaa;
|
---|
332 | }
|
---|
333 |
|
---|
334 | // FSInfo sect
|
---|
335 | pFAT32FsInfo->dLeadSig = 0x41615252;
|
---|
336 | pFAT32FsInfo->dStrucSig = 0x61417272;
|
---|
337 | pFAT32FsInfo->dFree_Count = (DWORD) -1;
|
---|
338 | pFAT32FsInfo->dNxt_Free = (DWORD) -1;
|
---|
339 | pFAT32FsInfo->dTrailSig = 0xaa550000;
|
---|
340 |
|
---|
341 | // First FAT Sector
|
---|
342 | pFirstSectOfFat[0] = 0x0ffffff8; // Reserved cluster 1 media id in low byte
|
---|
343 | pFirstSectOfFat[1] = 0x0fffffff; // Reserved cluster 2 EOC
|
---|
344 | pFirstSectOfFat[2] = 0x0fffffff; // end of cluster chain for root dir
|
---|
345 |
|
---|
346 | // Write boot sector, fats
|
---|
347 | // Sector 0 Boot Sector
|
---|
348 | // Sector 1 FSInfo
|
---|
349 | // Sector 2 More boot code - we write zeros here
|
---|
350 | // Sector 3 unused
|
---|
351 | // Sector 4 unused
|
---|
352 | // Sector 5 unused
|
---|
353 | // Sector 6 Backup boot sector
|
---|
354 | // Sector 7 Backup FSInfo sector
|
---|
355 | // Sector 8 Backup 'more boot code'
|
---|
356 | // zero'd sectors upto ReservedSectCount
|
---|
357 | // FAT1 ReservedSectCount to ReservedSectCount + FatSize
|
---|
358 | // ...
|
---|
359 | // FATn ReservedSectCount to ReservedSectCount + FatSize
|
---|
360 | // RootDir - allocated to cluster2
|
---|
361 |
|
---|
362 | UserAreaSize = dp.TotalSectors - dp.ReservedSectCount - (dp.NumFATs*dp.FatSize);
|
---|
363 | ClusterCount = UserAreaSize / dp.SectorsPerCluster;
|
---|
364 |
|
---|
365 | // Sanity check for a cluster count of >2^28, since the upper 4 bits of the cluster values in
|
---|
366 | // the FAT are reserved.
|
---|
367 | if ( ClusterCount > 0x0FFFFFFF )
|
---|
368 | {
|
---|
369 | die ( "This drive has more than 2^28 clusters, \n"
|
---|
370 | "try to specify a larger cluster size or use \n"
|
---|
371 | "the default (i.e. don't use -cXX)\n", -3 );
|
---|
372 | }
|
---|
373 |
|
---|
374 | // Sanity check - < 64K clusters means that the volume will be misdetected as FAT16
|
---|
375 | if ( ClusterCount < 65536 )
|
---|
376 | {
|
---|
377 | die ( "FAT32 must have at least 65536 clusters, \n"
|
---|
378 | "try to specify a smaller cluster size or \n"
|
---|
379 | "use the default (i.e. don't use -cXX)\n", -4 );
|
---|
380 | }
|
---|
381 |
|
---|
382 | // Sanity check, make sure the fat is big enough
|
---|
383 | // Convert the cluster count into a Fat sector count, and check the fat size value we calculated
|
---|
384 | // earlier is OK.
|
---|
385 | FatNeeded = ClusterCount * 4;
|
---|
386 | FatNeeded += (dp.BytesPerSect-1);
|
---|
387 | FatNeeded /= dp.BytesPerSect;
|
---|
388 |
|
---|
389 | //printf("dp.BytesPerSect=%lu\n", dp.BytesPerSect);
|
---|
390 | //printf("ClusterCount=%llu, FatNeeded=%llu, FatSize=%lu\n", ClusterCount, FatNeeded, dp.FatSize);
|
---|
391 | if ( FatNeeded > dp.FatSize )
|
---|
392 | {
|
---|
393 | die ( "This drive is too big for this version \n"
|
---|
394 | "of fat32format, check for an upgrade\n", -5 );
|
---|
395 | }
|
---|
396 |
|
---|
397 | // Now we're commited - print some info first
|
---|
398 | show_message ( "Size: %g MB %u sectors\n", 0, 0, (double) ((dp.TotalSectors / (1024*1024)) * dp.BytesPerSect), dp.TotalSectors );
|
---|
399 | show_message ( "%d Bytes Per Sector, Cluster size %d bytes\n", 0, 0, dp.BytesPerSect, dp.SectorsPerCluster * dp.BytesPerSect );
|
---|
400 |
|
---|
401 | //show_message ( "Volume Serial No. is %x:%x", 1243, 1, TYPE_LONG, VolumeId );
|
---|
402 | sprintf(szString, "%4.4X-%4.4X", HIUSHORT(VolumeId), LOUSHORT(VolumeId));
|
---|
403 | show_message ( "The Volume Serial Number is %s.", 1243, 1, TYPE_STRING, szString);
|
---|
404 | show_message ( "Volume label is %s", 1375, 1, TYPE_STRING, vol );
|
---|
405 |
|
---|
406 | show_message ( "%d Reserved Sectors, %d Sectors per FAT, %d fats\n", 0, 0, dp.ReservedSectCount, dp.FatSize, dp.NumFATs );
|
---|
407 |
|
---|
408 | show_message ( "%d Total clusters\n", 0, 0, ClusterCount );
|
---|
409 |
|
---|
410 | // fix up the FSInfo sector
|
---|
411 | pFAT32FsInfo->dFree_Count = (UserAreaSize/dp.SectorsPerCluster)-1;
|
---|
412 | pFAT32FsInfo->dNxt_Free = 3; // clusters 0-1 resered, we used cluster 2 for the root dir
|
---|
413 |
|
---|
414 | show_message ( "%d Free Clusters\n", 0, 0, pFAT32FsInfo->dFree_Count );
|
---|
415 | // Work out the Cluster count
|
---|
416 |
|
---|
417 | show_message( "Formatting drive %s\n", 534, 0, path );
|
---|
418 |
|
---|
419 | // Once zero_sectors has run, any data on the drive is basically lost....
|
---|
420 |
|
---|
421 | // First zero out ReservedSect + FatSize * NumFats + SectorsPerCluster
|
---|
422 | SystemAreaSize = (dp.ReservedSectCount+(dp.NumFATs*dp.FatSize) + dp.SectorsPerCluster);
|
---|
423 | zero_sectors( hDevice, 0, dp.BytesPerSect, SystemAreaSize); // &dgDrive);
|
---|
424 |
|
---|
425 | show_message ( "Clearing out %d sectors for \nReserved sectors, fats and root cluster...\n", 0, 0, SystemAreaSize );
|
---|
426 | show_message ( "Initialising reserved sectors and FATs...\n", 0, 0 );
|
---|
427 | // Now we should write the boot sector and fsinfo twice, once at 0 and once at the backup boot sect position
|
---|
428 | for ( i=0; i<2; i++ )
|
---|
429 | {
|
---|
430 | int SectorStart = (i==0) ? 0 : BackupBootSect;
|
---|
431 | write_sect ( hDevice, SectorStart, dp.BytesPerSect, pFAT32BootSect, 1 );
|
---|
432 | write_sect ( hDevice, SectorStart+1, dp.BytesPerSect, pFAT32FsInfo, 1 );
|
---|
433 | }
|
---|
434 | // Write the first fat sector in the right places
|
---|
435 | for ( i=0; i<dp.NumFATs; i++ )
|
---|
436 | {
|
---|
437 | int SectorStart = dp.ReservedSectCount + (i * dp.FatSize );
|
---|
438 | write_sect ( hDevice, SectorStart, dp.BytesPerSect, pFirstSectOfFat, 1 );
|
---|
439 | }
|
---|
440 |
|
---|
441 | // The filesystem recogniser in Windows XP doesn't use the partition type - in can be
|
---|
442 | // set to pretty much anything other Os's like Dos (still useful for Norton Ghost!) and Windows ME might,
|
---|
443 | // so we could fix it here
|
---|
444 | // On the other hand, I'm not sure that exposing big partitions to Windows ME/98 is a very good idea
|
---|
445 | // There are a couple of issues here -
|
---|
446 | // 1) WinME/98 doesn't know about 48bit LBA, so IDE drives bigger than 137GB will cause it
|
---|
447 | // problems. Rather than refuse to mount them, it uses 28bit LBA which wraps
|
---|
448 | // around, so writing to files above the 137GB boundary will erase the FAT and root dirs.
|
---|
449 | // 2) Win98 and WinME have 16 bit scandisk tools, which you need to disable, assuming you
|
---|
450 | // can get third party support for 48bit LBA, or use a USB external case, most of which
|
---|
451 | // will let you use a 48bit LBA drive.
|
---|
452 | // see http://www.48bitlba.com/win98.htm for instructions
|
---|
453 |
|
---|
454 | set_part_type (hDevice, &dp, 0xc);
|
---|
455 | remount_media ( hDevice );
|
---|
456 | unlock_drive ( hDevice );
|
---|
457 | close_drive ( hDevice );
|
---|
458 | fflush(stdout);
|
---|
459 |
|
---|
460 | set_vol_label (path, vol);
|
---|
461 |
|
---|
462 | // free memory
|
---|
463 | mem_free ( (void *)pFirstSectOfFat, dp.BytesPerSect );
|
---|
464 | mem_free ( (void *)pFAT32FsInfo, dp.BytesPerSect );
|
---|
465 | mem_free ( (void *)pFAT32BootSect, dp.BytesPerSect );
|
---|
466 |
|
---|
467 | return( TRUE );
|
---|
468 | }
|
---|
469 |
|
---|
470 | void usage( char *s )
|
---|
471 | {
|
---|
472 | printf ( "\nFat32format, ver. 1.07, \n"
|
---|
473 | "see http://www.ridgecrop.demon.co.uk/fat32format.htm\n"
|
---|
474 | "Modified and ported to OS/2 by osFree project \n"
|
---|
475 | "(http://osfree.org) for ufat32.dll.\n"
|
---|
476 | "This software is covered by the GPL.\n"
|
---|
477 | "Use with care - Ridgecrop are not liable\n"
|
---|
478 | "for data lost using this tool.\n\n"
|
---|
479 | "Usage:[c:\\] %s <d>: [options]\n\n"
|
---|
480 | "/C:<N> with different cluster sizes:\n"
|
---|
481 | " N: sectors per cluster:\n"
|
---|
482 | " 1 ( max size 137GB ) \n"
|
---|
483 | " 2 ( max size 274GB )\n"
|
---|
484 | " 4 ( max size 549GB )\n"
|
---|
485 | " 8 ( max size 1TB. )\n"
|
---|
486 | " ... \n"
|
---|
487 | " 128 - use 128 sectors per cluster (64K clusters)\n"
|
---|
488 | "/V:<volume label>\n"
|
---|
489 | "/R:<reserved sectors>\n"
|
---|
490 | "/? this help message\n\n", s );
|
---|
491 |
|
---|
492 | exit(1);
|
---|
493 | }
|
---|
494 |
|
---|
495 | void sig_handler (int sig);
|
---|
496 |
|
---|
497 | int setup_signals (void)
|
---|
498 | {
|
---|
499 | if (SIG_ERR == signal(SIGABRT, sig_handler)) {
|
---|
500 | perror("Could not set SIGABRT");
|
---|
501 | return EXIT_FAILURE;
|
---|
502 | }
|
---|
503 |
|
---|
504 | if (SIG_ERR == signal(SIGBREAK, sig_handler)) {
|
---|
505 | perror("Could not set SIGBREAK");
|
---|
506 | return EXIT_FAILURE;
|
---|
507 | }
|
---|
508 |
|
---|
509 | if (SIG_ERR == signal(SIGINT, sig_handler)) {
|
---|
510 | perror("Could not set SIGINT");
|
---|
511 | return EXIT_FAILURE;
|
---|
512 | }
|
---|
513 |
|
---|
514 | if (SIG_ERR == signal(SIGFPE, sig_handler)) {
|
---|
515 | perror("Could not set SIGFPE");
|
---|
516 | return EXIT_FAILURE;
|
---|
517 | }
|
---|
518 | if (SIG_ERR == signal(SIGSEGV, sig_handler)) {
|
---|
519 | perror("Could not set SIGSEGV");
|
---|
520 | return EXIT_FAILURE;
|
---|
521 | }
|
---|
522 | if (SIG_ERR == signal(SIGILL, sig_handler)) {
|
---|
523 | perror("Could not set SIGILL");
|
---|
524 | return EXIT_FAILURE;
|
---|
525 | }
|
---|
526 |
|
---|
527 | return 0;
|
---|
528 | }
|
---|
529 |
|
---|
530 | int format(int argc, char *argv[], char *envp[])
|
---|
531 | {
|
---|
532 | format_params p;
|
---|
533 | char cVolume;
|
---|
534 | int i=1;
|
---|
535 | char path[] = "Z:";
|
---|
536 | char *s, *t;
|
---|
537 | char key[12], val[12];
|
---|
538 |
|
---|
539 | // set up signal handlers
|
---|
540 | if (setup_signals())
|
---|
541 | {
|
---|
542 | printf("Error setting the signal handler!\n");
|
---|
543 | quit (1);
|
---|
544 | }
|
---|
545 |
|
---|
546 | memset( &p, 0, sizeof(p) );
|
---|
547 |
|
---|
548 | if ( argc < 2 )
|
---|
549 | {
|
---|
550 | usage( argv[0] );
|
---|
551 | }
|
---|
552 |
|
---|
553 | cVolume = argv[1][0];
|
---|
554 |
|
---|
555 | if (!isalpha(cVolume) || argv[1][1] != ':')
|
---|
556 | usage( argv[0] );
|
---|
557 |
|
---|
558 | #if 0
|
---|
559 | if ( cVolume != 'f' )
|
---|
560 | die( "Debug - only F: can be formatted\n", -9 );
|
---|
561 | #endif
|
---|
562 |
|
---|
563 | path[0] = cVolume;
|
---|
564 | path[1] = ':';
|
---|
565 | path[2] = '\0';
|
---|
566 |
|
---|
567 | for ( i = 2; i < argc; i++ )
|
---|
568 | {
|
---|
569 | if ( !((strlen(argv[i])>=2) && ((argv[i][0] == '-')||(argv[i][0] == '/'))) )
|
---|
570 | usage( argv[0] );
|
---|
571 |
|
---|
572 | memset(key, 0, 12);
|
---|
573 | memset(val, 0, 12);
|
---|
574 |
|
---|
575 | if ( strlen(argv[i]) > 3 )
|
---|
576 | {
|
---|
577 | // move to ':'
|
---|
578 | s = argv[i] + 1;
|
---|
579 | t = strchr(s, ':');
|
---|
580 |
|
---|
581 | if (t >= s)
|
---|
582 | {
|
---|
583 | strncpy(key, s, t - s); key[t - s] = '\0';
|
---|
584 | strncpy(val, t + 1, strlen(t + 1)); val[strlen(t + 1)] = '\0';
|
---|
585 | }
|
---|
586 | else
|
---|
587 | {
|
---|
588 | strncpy(key, s, 12);
|
---|
589 | val[0] = '\0';
|
---|
590 | }
|
---|
591 | }
|
---|
592 |
|
---|
593 | // skip /fs:... parameter
|
---|
594 | if (!stricmp(key, "FS"))
|
---|
595 | continue;
|
---|
596 |
|
---|
597 | switch ( toupper(argv[i][1]) )
|
---|
598 | {
|
---|
599 | case 'C':
|
---|
600 | p.sectors_per_cluster = atol(val);
|
---|
601 | if ( (p.sectors_per_cluster != 1) && // 512 bytes, 0.5k
|
---|
602 | (p.sectors_per_cluster != 2) && // 1K
|
---|
603 | (p.sectors_per_cluster != 4) && // 2K
|
---|
604 | (p.sectors_per_cluster != 8) && // 4K
|
---|
605 | (p.sectors_per_cluster != 16) && // 8K
|
---|
606 | (p.sectors_per_cluster != 32) && // 16K
|
---|
607 | (p.sectors_per_cluster != 64) && // 32K
|
---|
608 | (p.sectors_per_cluster != 128) // 64K ( Microsoft say don't use 64K or bigger);
|
---|
609 | )
|
---|
610 | {
|
---|
611 | printf ( "Ignoring bad cluster size %d\n", p.sectors_per_cluster );
|
---|
612 | p.sectors_per_cluster = 0;
|
---|
613 | usage( argv[0] );
|
---|
614 | }
|
---|
615 | continue;
|
---|
616 | case 'R':
|
---|
617 | p.reserved_sectors = atol(val);
|
---|
618 | if (! p.reserved_sectors)
|
---|
619 | {
|
---|
620 | printf( "Ignoring bad reserved sectors %d\n", p.reserved_sectors );
|
---|
621 | p.reserved_sectors = 32;
|
---|
622 | usage( argv[0] );
|
---|
623 | }
|
---|
624 | continue;
|
---|
625 | case 'H':
|
---|
626 | case '?':
|
---|
627 | usage( argv[0] );
|
---|
628 | case 'V':
|
---|
629 | memcpy(p.volume_label, val, 12);
|
---|
630 | continue;
|
---|
631 | case 'P':
|
---|
632 | msg = TRUE;
|
---|
633 | continue;
|
---|
634 | default:
|
---|
635 | // printf ( "Ignoring bad flag '-%c'\n", argv[i][1] );
|
---|
636 | usage( argv[0] );
|
---|
637 | }
|
---|
638 | //i++;
|
---|
639 | }
|
---|
640 |
|
---|
641 | if ( format_volume( path, &p ) )
|
---|
642 | show_message( "Done.", 1294, 0 );
|
---|
643 |
|
---|
644 | return 0;
|
---|
645 | }
|
---|
646 |
|
---|
647 | #ifndef __DLL__
|
---|
648 | int main(int argc, char *argv[])
|
---|
649 | {
|
---|
650 | return format(argc, argv, NULL);
|
---|
651 | }
|
---|
652 | #endif
|
---|
653 |
|
---|
654 | void cleanup ( void )
|
---|
655 | {
|
---|
656 | if (hDev == 0)
|
---|
657 | return;
|
---|
658 |
|
---|
659 | remount_media ( hDev );
|
---|
660 | unlock_drive ( hDev );
|
---|
661 | close_drive ( hDev);
|
---|
662 | hDev = 0;
|
---|
663 | }
|
---|
664 |
|
---|
665 | void quit (int rc)
|
---|
666 | {
|
---|
667 | cleanup ();
|
---|
668 | exit (rc);
|
---|
669 | }
|
---|
670 |
|
---|
671 | void show_sig_string(int s)
|
---|
672 | {
|
---|
673 | char *str = "";
|
---|
674 | switch (s)
|
---|
675 | {
|
---|
676 | case SIGABRT:
|
---|
677 | str="SIGABRT";
|
---|
678 | break;
|
---|
679 | case SIGBREAK:
|
---|
680 | str="SIGBREAK";
|
---|
681 | break;
|
---|
682 | case SIGINT:
|
---|
683 | str="SIGINT";
|
---|
684 | break;
|
---|
685 | case SIGFPE:
|
---|
686 | str="SIGFPE";
|
---|
687 | break;
|
---|
688 | case SIGSEGV:
|
---|
689 | str="SIGSEGV";
|
---|
690 | break;
|
---|
691 | case SIGILL:
|
---|
692 | str="SIGILL";
|
---|
693 | break;
|
---|
694 | default:
|
---|
695 | ;
|
---|
696 | }
|
---|
697 | printf("Signal: %d = %s\n", s, str);
|
---|
698 | }
|
---|
699 |
|
---|
700 | void sig_handler (int sig)
|
---|
701 | {
|
---|
702 | show_sig_string(sig);
|
---|
703 | cleanup();
|
---|
704 | }
|
---|