1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46#include "libbb.h"
47
48#include <linux/hdreg.h>
49#include <linux/fd.h>
50#include <sys/mount.h>
51#if !defined(BLKSSZGET)
52# define BLKSSZGET _IO(0x12, 104)
53#endif
54
55
56#define SECTOR_SIZE 512
57
58#define SECTORS_PER_BLOCK (BLOCK_SIZE / SECTOR_SIZE)
59
60
61#define EOF_FAT32 0x0FFFFFF8
62#define BAD_FAT32 0x0FFFFFF7
63#define MAX_CLUST_32 0x0FFFFFF0
64
65#define ATTR_VOLUME 8
66
67#define NUM_FATS 2
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92enum {
93
94 info_sector_number = 1,
95
96
97 backup_boot_sector = 3,
98 reserved_sect = 6,
99};
100
101
102#define TEST_BUFFER_BLOCKS 16
103
104struct msdos_dir_entry {
105 char name[11];
106 uint8_t attr;
107 uint8_t lcase;
108 uint8_t ctime_cs;
109 uint16_t ctime;
110 uint16_t cdate;
111 uint16_t adate;
112 uint16_t starthi;
113 uint16_t time;
114 uint16_t date;
115 uint16_t start;
116 uint32_t size;
117} PACKED;
118
119
120
121
122
123
124
125
126
127struct msdos_volume_info {
128 uint8_t drive_number;
129 uint8_t reserved;
130 uint8_t ext_boot_sign;
131 uint32_t volume_id32;
132 char volume_label[11];
133 char fs_type[8];
134} PACKED;
135
136struct msdos_boot_sector {
137
138 char boot_jump_and_sys_id[3+8];
139
140 uint16_t bytes_per_sect;
141 uint8_t sect_per_clust;
142 uint16_t reserved_sect;
143 uint8_t fats;
144 uint16_t dir_entries;
145 uint16_t volume_size_sect;
146 uint8_t media_byte;
147 uint16_t sect_per_fat;
148 uint16_t sect_per_track;
149 uint16_t heads;
150 uint32_t hidden;
151 uint32_t fat32_volume_size_sect;
152 uint32_t fat32_sect_per_fat;
153 uint16_t fat32_flags;
154 uint8_t fat32_version[2];
155 uint32_t fat32_root_cluster;
156 uint16_t fat32_info_sector;
157 uint16_t fat32_backup_boot;
158 uint32_t reserved2[3];
159 struct msdos_volume_info vi;
160 char boot_code[0x200 - 0x5a - 2];
161#define BOOT_SIGN 0xAA55
162 uint16_t boot_sign;
163} PACKED;
164
165#define FAT_FSINFO_SIG1 0x41615252
166#define FAT_FSINFO_SIG2 0x61417272
167struct fat32_fsinfo {
168 uint32_t signature1;
169 uint32_t reserved1[128 - 8];
170 uint32_t signature2;
171 uint32_t free_clusters;
172 uint32_t next_cluster;
173 uint32_t reserved2[3];
174 uint16_t reserved3;
175 uint16_t boot_sign;
176} PACKED;
177
178struct bug_check {
179 char BUG1[sizeof(struct msdos_dir_entry ) == 0x20 ? 1 : -1];
180 char BUG2[sizeof(struct msdos_volume_info) == 0x1a ? 1 : -1];
181 char BUG3[sizeof(struct msdos_boot_sector) == 0x200 ? 1 : -1];
182 char BUG4[sizeof(struct fat32_fsinfo ) == 0x200 ? 1 : -1];
183};
184
185static const char boot_code[] ALIGN1 =
186 "\x0e"
187 "\x1f"
188 "\xbe\x77\x7c"
189 "\xac"
190 "\x22\xc0"
191 "\x74\x0b"
192 "\x56"
193 "\xb4\x0e"
194 "\xbb\x07\x00"
195 "\xcd\x10"
196 "\x5e"
197 "\xeb\xf0"
198 "\x32\xe4"
199 "\xcd\x16"
200 "\xcd\x19"
201 "\xeb\xfe"
202
203 "This is not a bootable disk\r\n";
204
205
206#define MARK_CLUSTER(cluster, value) \
207 ((uint32_t *)fat)[cluster] = SWAP_LE32(value)
208
209
210
211
212
213
214
215
216
217
218
219
220int mkfs_vfat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
221int mkfs_vfat_main(int argc UNUSED_PARAM, char **argv)
222{
223 struct stat st;
224 const char *volume_label = "";
225 char *buf;
226 char *device_name;
227 uoff_t volume_size_bytes;
228 uoff_t volume_size_sect;
229 uint32_t total_clust;
230 uint32_t volume_id;
231 int dev;
232 unsigned bytes_per_sect;
233 unsigned sect_per_fat;
234 unsigned opts;
235 uint16_t sect_per_track;
236 uint8_t media_byte;
237 uint8_t sect_per_clust;
238 uint8_t heads;
239 enum {
240 OPT_A = 1 << 0,
241 OPT_b = 1 << 1,
242 OPT_c = 1 << 2,
243 OPT_C = 1 << 3,
244 OPT_f = 1 << 4,
245 OPT_F = 1 << 5,
246 OPT_h = 1 << 6,
247 OPT_I = 1 << 7,
248 OPT_i = 1 << 8,
249 OPT_l = 1 << 9,
250 OPT_m = 1 << 10,
251 OPT_n = 1 << 11,
252 OPT_r = 1 << 12,
253 OPT_R = 1 << 13,
254 OPT_s = 1 << 14,
255 OPT_S = 1 << 15,
256 OPT_v = 1 << 16,
257 };
258
259 opts = getopt32(argv, "^"
260 "Ab:cCf:F:h:Ii:l:m:n:r:R:s:S:v"
261 "\0" "-1",
262 NULL, NULL, NULL, NULL, NULL,
263 NULL, NULL, &volume_label, NULL, NULL, NULL, NULL);
264 argv += optind;
265
266
267 device_name = argv[0];
268
269 volume_id = time(NULL);
270
271 dev = xopen(device_name, O_RDWR);
272 xfstat(dev, &st, device_name);
273
274
275
276
277 bytes_per_sect = SECTOR_SIZE;
278 if (!S_ISBLK(st.st_mode)) {
279 if (!S_ISREG(st.st_mode)) {
280 if (!argv[1])
281 bb_error_msg_and_die("image size must be specified");
282 }
283
284 opts &= ~OPT_c;
285 } else {
286 int min_bytes_per_sect;
287#if 0
288 unsigned device_num;
289
290 device_num = st.st_rdev & 0xff3f;
291
292 if (!(opts & OPT_I) && (
293 device_num == 0x0300 ||
294 (device_num & 0xff0f) == 0x0800 ||
295 device_num == 0x0d00 ||
296 device_num == 0x1600 )
297 )
298 bb_error_msg_and_die("will not try to make filesystem on full-disk device (use -I if wanted)");
299
300 if (find_mount_point(device_name, 0))
301 bb_error_msg_and_die("can't format mounted filesystem");
302#endif
303
304
305 xioctl(dev, BLKSSZGET, &min_bytes_per_sect);
306 if (min_bytes_per_sect > SECTOR_SIZE) {
307 bytes_per_sect = min_bytes_per_sect;
308 bb_error_msg("for this device sector size is %u", min_bytes_per_sect);
309 }
310 }
311 volume_size_bytes = get_volume_size_in_bytes(dev, argv[1], 1024, 1);
312 volume_size_sect = volume_size_bytes / bytes_per_sect;
313
314
315
316
317 media_byte = 0xf8;
318 heads = 255;
319 sect_per_track = 63;
320 sect_per_clust = 1;
321 {
322 struct hd_geometry geometry;
323
324 struct floppy_struct param;
325
326
327 if (ioctl(dev, HDIO_GETGEO, &geometry) == 0
328 && geometry.sectors
329 && geometry.heads
330 ) {
331
332 sect_per_track = geometry.sectors;
333 heads = geometry.heads;
334
335 set_cluster_size:
336
337
338
339
340
341
342
343 sect_per_clust = 1;
344 if (volume_size_bytes >= 260*1024*1024) {
345 sect_per_clust = 8;
346
347
348
349 if (sizeof(off_t) > 4) {
350 unsigned t = (volume_size_bytes >> 31 >> 1);
351 if (t >= 8/4)
352 sect_per_clust = 16;
353 if (t >= 16/4)
354 sect_per_clust = 32;
355 }
356 }
357 } else {
358
359 int not_floppy = ioctl(dev, FDGETPRM, ¶m);
360 if (not_floppy == 0) {
361
362 sect_per_track = param.sect;
363 heads = param.head;
364 volume_size_sect = param.size;
365 volume_size_bytes = param.size * SECTOR_SIZE;
366 }
367
368 switch (volume_size_sect) {
369 case 2*360:
370 media_byte = 0xfd;
371 break;
372 case 2*720:
373 case 2*1200:
374 media_byte = 0xf9;
375 break;
376 default:
377 if (not_floppy)
378 goto set_cluster_size;
379 case 2*1440:
380 case 2*2880:
381 media_byte = 0xf0;
382 break;
383 }
384
385
386
387
388 heads = 2;
389 sect_per_track = (unsigned)volume_size_sect / 160;
390 if (sect_per_track < 9)
391 sect_per_track = 9;
392 }
393 }
394
395
396
397
398
399
400
401 if ((off_t)(volume_size_sect - reserved_sect) < 4)
402 bb_error_msg_and_die("the image is too small for FAT32");
403 sect_per_fat = 1;
404 while (1) {
405 while (1) {
406 int spf_adj;
407 uoff_t tcl = (volume_size_sect - reserved_sect - NUM_FATS * sect_per_fat) / sect_per_clust;
408
409
410
411
412
413 if (tcl > 0x80ffffff)
414 goto next;
415 total_clust = tcl;
416
417
418
419
420
421
422 spf_adj = ((total_clust+2) + (bytes_per_sect/4)-1) / (bytes_per_sect/4) - sect_per_fat;
423#if 0
424 bb_error_msg("sect_per_clust:%u sect_per_fat:%u total_clust:%u",
425 sect_per_clust, sect_per_fat, (int)tcl);
426 bb_error_msg("adjust to sect_per_fat:%d", spf_adj);
427#endif
428 if (spf_adj <= 0) {
429
430
431 if (total_clust <= MAX_CLUST_32)
432 goto found_total_clust;
433
434 goto next;
435 }
436
437
438 sect_per_fat += ((unsigned)spf_adj / 2) | 1;
439 }
440 next:
441 if (sect_per_clust == 128)
442 bb_error_msg_and_die("can't make FAT32 with >128 sectors/cluster");
443 sect_per_clust *= 2;
444 sect_per_fat = (sect_per_fat / 2) | 1;
445 }
446 found_total_clust:
447
448
449
450
451 if (opts & OPT_v) {
452 fprintf(stderr,
453 "Device '%s':\n"
454 "heads:%u, sectors/track:%u, bytes/sector:%u\n"
455 "media descriptor:%02x\n"
456 "total sectors:%"OFF_FMT"u, clusters:%u, sectors/cluster:%u\n"
457 "FATs:2, sectors/FAT:%u\n"
458 "volumeID:%08x, label:'%s'\n",
459 device_name,
460 heads, sect_per_track, bytes_per_sect,
461 (int)media_byte,
462 volume_size_sect, (int)total_clust, (int)sect_per_clust,
463 sect_per_fat,
464 (int)volume_id, volume_label
465 );
466 }
467
468
469
470
471 {
472
473 unsigned bufsize = reserved_sect;
474
475 bufsize |= 2;
476 bufsize |= sect_per_clust;
477 buf = xzalloc(bufsize * bytes_per_sect);
478 }
479
480 {
481 struct msdos_boot_sector *boot_blk = (void*)buf;
482 struct fat32_fsinfo *info = (void*)(buf + bytes_per_sect);
483
484 strcpy(boot_blk->boot_jump_and_sys_id, "\xeb\x58\x90" "mkdosfs");
485 STORE_LE(boot_blk->bytes_per_sect, bytes_per_sect);
486 STORE_LE(boot_blk->sect_per_clust, sect_per_clust);
487
488 STORE_LE(boot_blk->reserved_sect, (uint16_t)reserved_sect);
489 STORE_LE(boot_blk->fats, 2);
490
491 if (volume_size_sect <= 0xffff)
492 STORE_LE(boot_blk->volume_size_sect, volume_size_sect);
493 STORE_LE(boot_blk->media_byte, media_byte);
494
495
496
497
498
499 STORE_LE(boot_blk->sect_per_track, sect_per_track);
500 STORE_LE(boot_blk->heads, heads);
501
502 STORE_LE(boot_blk->fat32_volume_size_sect, volume_size_sect);
503 STORE_LE(boot_blk->fat32_sect_per_fat, sect_per_fat);
504
505
506 STORE_LE(boot_blk->fat32_root_cluster, 2);
507 STORE_LE(boot_blk->fat32_info_sector, info_sector_number);
508 STORE_LE(boot_blk->fat32_backup_boot, backup_boot_sector);
509
510 STORE_LE(boot_blk->vi.ext_boot_sign, 0x29);
511 STORE_LE(boot_blk->vi.volume_id32, volume_id);
512 memcpy(boot_blk->vi.fs_type, "FAT32 ", sizeof(boot_blk->vi.fs_type));
513 strncpy(boot_blk->vi.volume_label, volume_label, sizeof(boot_blk->vi.volume_label));
514 memcpy(boot_blk->boot_code, boot_code, sizeof(boot_code));
515 STORE_LE(boot_blk->boot_sign, BOOT_SIGN);
516
517 STORE_LE(info->signature1, FAT_FSINFO_SIG1);
518 STORE_LE(info->signature2, FAT_FSINFO_SIG2);
519
520 STORE_LE(info->free_clusters, (total_clust - 1));
521 STORE_LE(info->next_cluster, 2);
522 STORE_LE(info->boot_sign, BOOT_SIGN);
523
524
525 xwrite(dev, buf, bytes_per_sect * backup_boot_sector);
526
527 xwrite(dev, buf, bytes_per_sect * (reserved_sect - backup_boot_sector));
528 }
529
530 {
531 unsigned i,j;
532 unsigned char *fat = (void*)buf;
533
534 memset(buf, 0, bytes_per_sect * 2);
535
536 MARK_CLUSTER(0, 0x0fffff00 | media_byte);
537 MARK_CLUSTER(1, 0xffffffff);
538
539 MARK_CLUSTER(2, EOF_FAT32);
540 for (i = 0; i < NUM_FATS; i++) {
541 xwrite(dev, buf, bytes_per_sect);
542 for (j = 1; j < sect_per_fat; j++)
543 xwrite(dev, buf + bytes_per_sect, bytes_per_sect);
544 }
545 }
546
547
548
549 memset(buf, 0, sect_per_clust * bytes_per_sect);
550 if (volume_label[0]) {
551
552 struct msdos_dir_entry *de;
553#if 0
554 struct tm tm_time;
555 uint16_t t, d;
556#endif
557 de = (void*)buf;
558 strncpy(de->name, volume_label, sizeof(de->name));
559 STORE_LE(de->attr, ATTR_VOLUME);
560#if 0
561 localtime_r(&create_time, &tm_time);
562 t = (tm_time.tm_sec >> 1) + (tm_time.tm_min << 5) + (tm_time.tm_hour << 11);
563 d = tm_time.tm_mday + ((tm_time.tm_mon+1) << 5) + ((tm_time.tm_year-80) << 9);
564 STORE_LE(de->time, t);
565 STORE_LE(de->date, d);
566
567 de->ctime = de->time;
568 de->cdate = de->date;
569 de->adate = de->date;
570#endif
571 }
572 xwrite(dev, buf, sect_per_clust * bytes_per_sect);
573
574#if 0
575 if (opts & OPT_c) {
576 uoff_t volume_size_blocks;
577 unsigned start_data_sector;
578 unsigned start_data_block;
579 unsigned badblocks = 0;
580 int try, got;
581 off_t currently_testing;
582 char *blkbuf = xmalloc(BLOCK_SIZE * TEST_BUFFER_BLOCKS);
583
584 volume_size_blocks = (volume_size_bytes >> BLOCK_SIZE_BITS);
585
586 start_data_sector = (reserved_sect + NUM_FATS * sect_per_fat) * (bytes_per_sect / SECTOR_SIZE);
587 start_data_block = (start_data_sector + SECTORS_PER_BLOCK - 1) / SECTORS_PER_BLOCK;
588
589 bb_error_msg("searching for bad blocks");
590 currently_testing = 0;
591 try = TEST_BUFFER_BLOCKS;
592 while (currently_testing < volume_size_blocks) {
593 if (currently_testing + try > volume_size_blocks)
594 try = volume_size_blocks - currently_testing;
595
596
597
598 xlseek(dev, currently_testing * BLOCK_SIZE, SEEK_SET);
599
600 got = read(dev, blkbuf, try * BLOCK_SIZE);
601 if (got < 0)
602 got = 0;
603 if (got & (BLOCK_SIZE - 1))
604 bb_error_msg("unexpected values in do_check: probably bugs");
605 got /= BLOCK_SIZE;
606 currently_testing += got;
607 if (got == try) {
608 try = TEST_BUFFER_BLOCKS;
609 continue;
610 }
611 try = 1;
612 if (currently_testing < start_data_block)
613 bb_error_msg_and_die("bad blocks before data-area: cannot make fs");
614
615
616 for (i = 0; i < SECTORS_PER_BLOCK; i++) {
617 int cluster = (currently_testing * SECTORS_PER_BLOCK + i - start_data_sector) / (int) (sect_per_clust) / (bytes_per_sect / SECTOR_SIZE);
618 if (cluster < 0)
619 bb_error_msg_and_die("invalid cluster number in mark_sector: probably bug!");
620 MARK_CLUSTER(cluster, BAD_FAT32);
621 }
622 badblocks++;
623 currently_testing++;
624 }
625 free(blkbuf);
626 if (badblocks)
627 bb_error_msg("%d bad block(s)", badblocks);
628 }
629#endif
630
631
632 if (ENABLE_FEATURE_CLEAN_UP) {
633 free(buf);
634 close(dev);
635 }
636
637 return 0;
638}
639