1 #include <linux/time.h>
2 #include <linux/ctype.h>
6 #define MAXU16 0xffff /* maximum unsigned 16-bit quantity */
7 #define BPN 4 /* bits per nibble */
8 #define NPB 2 /* nibbles per byte */
10 #define DOSMAGIC 0xaa55 /* DOS magic number */
11 #define MINBPS 512 /* minimum bytes per sector */
12 #define MAXSPC 128 /* maximum sectors per cluster */
13 #define MAXNFT 16 /* maximum number of FATs */
14 #define DEFBLK 4096 /* default block size */
15 #define DEFBLK16 2048 /* default block size FAT16 */
16 #define DEFRDE 512 /* default root directory entries */
17 #define RESFTE 2 /* reserved FAT entries */
18 #define MINCLS12 1 /* minimum FAT12 clusters */
19 #define MINCLS16 0x1000 /* minimum FAT16 clusters */
20 #define MINCLS32 2 /* minimum FAT32 clusters */
21 #define MAXCLS12 0xfed /* maximum FAT12 clusters */
22 #define MAXCLS16 0xfff5 /* maximum FAT16 clusters */
23 #define MAXCLS32 0xffffff5 /* maximum FAT32 clusters */
24 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
25 #define powerof2(x) ((((x) - 1) & (x)) == 0)
26 #define howmany(x, y) (((x) + ((y) - 1)) / (y))
27 #define MAX(x, y) ((x) > (y) ? (x) : (y))
28 #define mincls(fat) ((fat) == 12 ? MINCLS12 : \
29 (fat) == 16 ? MINCLS16 : \
32 #define maxcls(fat) ((fat) == 12 ? MAXCLS12 : \
33 (fat) == 16 ? MAXCLS16 : \
37 (p) = (unsigned char)(x)
40 (p)[0] = (unsigned char)(x), \
41 (p)[1] = (unsigned char)((x) >> 010)
44 (p)[0] = (unsigned char)(x), \
45 (p)[1] = (unsigned char)((x) >> 010), \
46 (p)[2] = (unsigned char)((x) >> 020), \
47 (p)[3] = (unsigned char)((x) >> 030)
50 long tv_sec; /* seconds */
51 long tv_usec; /* microseconds */
55 unsigned char jmp[3]; /* bootstrap entry point */
56 unsigned char oem[8]; /* OEM name and version */
60 unsigned char bps[2]; /* bytes per sector */
61 unsigned char spc; /* sectors per cluster */
62 unsigned char res[2]; /* reserved sectors */
63 unsigned char nft; /* number of FATs */
64 unsigned char rde[2]; /* root directory entries */
65 unsigned char sec[2]; /* total sectors */
66 unsigned char mid; /* media descriptor */
67 unsigned char spf[2]; /* sectors per FAT */
68 unsigned char spt[2]; /* sectors per track */
69 unsigned char hds[2]; /* drive heads */
70 unsigned char hid[4]; /* hidden sectors */
71 unsigned char bsec[4]; /* big total sectors */
75 unsigned char bspf[4]; /* big sectors per FAT */
76 unsigned char xflg[2]; /* FAT control flags */
77 unsigned char vers[2]; /* file system version */
78 unsigned char rdcl[4]; /* root directory start cluster */
79 unsigned char infs[2]; /* file system info sector */
80 unsigned char bkbs[2]; /* backup boot sector */
81 unsigned char rsvd[12]; /* reserved */
85 unsigned char drv; /* drive number */
86 unsigned char rsvd; /* reserved */
87 unsigned char sig; /* extended boot signature */
88 unsigned char volid[4]; /* volume ID number */
89 unsigned char label[11]; /* volume label */
90 unsigned char type[8]; /* file system type */
94 unsigned char namext[11]; /* name and extension */
95 unsigned char attr; /* attributes */
96 unsigned char rsvd[10]; /* reserved */
97 unsigned char time[2]; /* creation time */
98 unsigned char date[2]; /* creation date */
99 unsigned char clus[2]; /* starting cluster */
100 unsigned char size[4]; /* size */
104 unsigned int bps; /* bytes per sector */
105 unsigned int spc; /* sectors per cluster */
106 unsigned int res; /* reserved sectors */
107 unsigned int nft; /* number of FATs */
108 unsigned int rde; /* root directory entries */
109 unsigned int sec; /* total sectors */
110 unsigned int mid; /* media descriptor */
111 unsigned int spf; /* sectors per FAT */
112 unsigned int spt; /* sectors per track */
113 unsigned int hds; /* drive heads */
114 unsigned int hid; /* hidden sectors */
115 unsigned int bsec; /* big total sectors */
116 unsigned int bspf; /* big sectors per FAT */
117 unsigned int rdcl; /* root directory start cluster */
118 unsigned int infs; /* file system info sector */
119 unsigned int bkbs; /* backup boot sector */
122 #define BPBGAP 0, 0, 0, 0, 0, 0
128 {"160", {512, 1, 1, 2, 64, 320, 0xfe, 1, 8, 1, BPBGAP}},
129 {"180", {512, 1, 1, 2, 64, 360, 0xfc, 2, 9, 1, BPBGAP}},
130 {"320", {512, 2, 1, 2, 112, 640, 0xff, 1, 8, 2, BPBGAP}},
131 {"360", {512, 2, 1, 2, 112, 720, 0xfd, 2, 9, 2, BPBGAP}},
132 {"640", {512, 2, 1, 2, 112, 1280, 0xfb, 2, 8, 2, BPBGAP}},
133 {"720", {512, 2, 1, 2, 112, 1440, 0xf9, 3, 9, 2, BPBGAP}},
134 {"1200", {512, 1, 1, 2, 224, 2400, 0xf9, 7, 15, 2, BPBGAP}},
135 {"1232", {1024,1, 1, 2, 192, 1232, 0xfe, 2, 8, 2, BPBGAP}},
136 {"1440", {512, 1, 1, 2, 224, 2880, 0xf0, 9, 18, 2, BPBGAP}},
137 {"2880", {512, 2, 1, 2, 240, 5760, 0xf0, 9, 36, 2, BPBGAP}}
140 static const unsigned char bootcode[] = {
142 0x31, 0xc0, /* xor ax,ax */
143 0x8e, 0xd0, /* mov ss,ax */
144 0xbc, 0x00, 0x7c, /* mov sp,7c00h */
146 0x8e, 0xd8, /* mov ds,ax */
147 0xe8, 0x00, 0x00, /* call $ + 3 */
149 0x83, 0xc6, 0x19, /* add si,+19h */
150 0xbb, 0x07, 0x00, /* mov bx,0007h */
153 0x84, 0xc0, /* test al,al */
154 0x74, 0x06, /* jz $ + 8 */
155 0xb4, 0x0e, /* mov ah,0eh */
156 0xcd, 0x10, /* int 10h */
157 0xeb, 0xf5, /* jmp $ - 9 */
158 0x30, 0xe4, /* xor ah,ah */
159 0xcd, 0x16, /* int 16h */
160 0xcd, 0x19, /* int 19h */
162 'N', 'o', 'n', '-', 's', 'y', 's', 't',
163 'e', 'm', ' ', 'd', 'i', 's', 'k',
165 'P', 'r', 'e', 's', 's', ' ', 'a', 'n',
166 'y', ' ', 'k', 'e', 'y', ' ', 't', 'o',
167 ' ', 'r', 'e', 'b', 'o', 'o', 't',
173 static void getdiskinfo(unsigned long count, struct bpb *);
174 static void print_bpb(struct bpb *);
175 static void setstr(unsigned char *dest, const char *src, size_t len);
176 unsigned int newfs_msdos_main(unsigned char *newfs_SDBUF, unsigned long part_size);
180 * Construct a FAT12, FAT16, or FAT32 file system.
182 unsigned int newfs_msdos_main(unsigned char *newfs_SDBUF, unsigned long part_size)
184 const char *opt_B =0, *opt_L =0, *opt_O=0, *opt_f =0;
185 unsigned int opt_I = 0, opt_S = 0, opt_a = 0, opt_b = 0, opt_c = 0;
186 unsigned int opt_e = 0, opt_h = 0, opt_i = 0, opt_k = 0, opt_m = 0, opt_n = 0;
187 unsigned int opt_o = 0, opt_r = 0, opt_s = 0, opt_u = 0;
189 int Iflag = 0, mflag = 0, oflag = 0;
190 int MAXPATHLEN = 4096;
191 unsigned sectorCount = 0;
192 char buf[MAXPATHLEN];
193 unsigned int fname_off = 0;
198 struct bsxbpb *bsxbpb;
202 unsigned char *fname = newfs_SDBUF;
203 unsigned int fat = 32, bss = 0, rds = 0, cls, dir = 0, lsn = 0, x = 0, x1 = 0, x2 = 0;
207 memset(&bpb, 0, sizeof(bpb));
218 if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) {
220 getdiskinfo(part_size, &bpb);
226 bpb.bsec -= (opt_ofs / bpb.bps);
227 delta = bpb.bsec % bpb.spt;
231 if (bpb.spc == 0) { /* set defaults */
232 if (bpb.bsec <= 6000) /* about 3MB -> 512 bytes */
234 else if (bpb.bsec <= (1<<17)) /* 64M -> 4k */
236 else if (bpb.bsec <= (1<<19)) /* 256M -> 8k */
238 else if (bpb.bsec <= (1<<21)) /* 1G -> 16k */
241 bpb.spc = 64; /* otherwise 32k */
246 if (opt_f && fat == 32)
253 if (bpb.bsec < (bpb.res ? bpb.res : bss) +
254 howmany((RESFTE + (bpb.spc ? MINCLS16 : MAXCLS12 + 1)) *
255 ((bpb.spc ? 16 : 12) / BPN), bpb.bps * NPB) *
257 howmany(bpb.rde ? bpb.rde : DEFRDE,
258 bpb.bps / sizeof(struct de)) +
259 (bpb.spc ? MINCLS16 : MAXCLS12 + 1) *
260 (bpb.spc ? bpb.spc : howmany(DEFBLK, bpb.bps)))
262 else if (bpb.rde || bpb.bsec <
263 (bpb.res ? bpb.res : bss) +
264 howmany((RESFTE + MAXCLS16) * 2, bpb.bps) * bpb.nft +
265 howmany(DEFRDE, bpb.bps / sizeof(struct de)) +
267 (bpb.spc ? bpb.spc : howmany(8192, bpb.bps)))
277 if (bpb.infs != MAXU16 && x <= bpb.infs)
282 if (bpb.bkbs != MAXU16 && x <= bpb.bkbs)
287 bpb.res = fat == 32 ? MAX(x, MAX(16384 / bpb.bps, 4)) : x;
288 if (fat != 32 && !bpb.rde)
290 rds = howmany(bpb.rde, bpb.bps / sizeof(struct de));
292 for (bpb.spc = howmany(fat == 16 ? DEFBLK16 : DEFBLK, bpb.bps);
295 howmany((RESFTE + maxcls(fat)) * (fat / BPN),
296 bpb.bps * NPB) * bpb.nft +
298 (unsigned long long)(maxcls(fat) + 1) * bpb.spc <= bpb.bsec;
301 x = bpb.bspf ? bpb.bspf : 1;
303 x = (unsigned long long)(bpb.bsec - x1) * bpb.bps * NPB /
304 (bpb.spc * bpb.bps * NPB + fat / BPN * bpb.nft);
305 x2 = howmany((RESFTE + MIN(x, maxcls(fat))) * (fat / BPN),
309 x1 += (bpb.bspf - 1) * bpb.nft;
311 cls = (bpb.bsec - x1) / bpb.spc;
312 x = (unsigned long long)bpb.bspf * bpb.bps * NPB / (fat / BPN) - RESFTE;
315 if (cls > maxcls(fat)) {
317 bpb.bsec = x1 + (cls + 1) * bpb.spc - 1;
319 printf("%u sector%s in %u FAT%u cluster%s "
320 "(%u bytes/cluster)\n", cls * bpb.spc,
321 cls * bpb.spc == 1 ? "" : "s", cls, fat,
322 cls == 1 ? "" : "s", bpb.bps * bpb.spc);
324 bpb.mid = !bpb.hid ? 0xf0 : 0xf8;
327 if (bpb.hid + bpb.bsec <= MAXU16) {
337 img = malloc(bpb.bps);
338 dir = bpb.res + (bpb.spf ? bpb.spf : bpb.bspf) * bpb.nft;
339 for (lsn = 0; lsn < dir + (fat == 32 ? bpb.spc : rds); lsn++) {
342 fat == 32 && bpb.bkbs != MAXU16 &&
343 bss <= bpb.bkbs && x >= bpb.bkbs) {
346 memset(img, 0, bpb.bps);
348 (fat == 32 && bpb.bkbs != MAXU16 && lsn == bpb.bkbs)) {
349 x1 = sizeof(struct bs);
350 bsbpb = (struct bsbpb *)(img + x1);
351 mk2(bsbpb->bps, bpb.bps);
352 mk1(bsbpb->spc, bpb.spc);
353 mk2(bsbpb->res, bpb.res);
354 mk1(bsbpb->nft, bpb.nft);
355 mk2(bsbpb->rde, bpb.rde);
356 mk2(bsbpb->sec, bpb.sec);
357 mk1(bsbpb->mid, bpb.mid);
358 mk2(bsbpb->spf, bpb.spf);
359 mk2(bsbpb->spt, bpb.spt);
360 mk2(bsbpb->hds, bpb.hds);
361 mk4(bsbpb->hid, bpb.hid);
362 mk4(bsbpb->bsec, bpb.bsec);
363 x1 += sizeof(struct bsbpb);
365 bsxbpb = (struct bsxbpb *)(img + x1);
366 mk4(bsxbpb->bspf, bpb.bspf);
367 mk2(bsxbpb->xflg, 0);
368 mk2(bsxbpb->vers, 0);
369 mk4(bsxbpb->rdcl, bpb.rdcl);
370 mk2(bsxbpb->infs, bpb.infs);
371 mk2(bsxbpb->bkbs, bpb.bkbs);
372 x1 += sizeof(struct bsxbpb);
374 bsx = (struct bsx *)(img + x1);
379 sprintf(buf, "FAT%u", fat);
380 setstr(bsx->type, buf, sizeof(bsx->type));
382 x1 += sizeof(struct bsx);
383 bs = (struct bs *)img;
384 mk1(bs->jmp[0], 0xeb);
385 mk1(bs->jmp[1], x1 - 2);
386 mk1(bs->jmp[2], 0x90);
387 setstr(bs->oem, opt_O ? opt_O : "BSD 4.4",
389 memcpy(img + x1, bootcode, sizeof(bootcode));
390 mk2(img + MINBPS - 2, DOSMAGIC);
392 } else if (fat == 32 && bpb.infs != MAXU16 &&
394 (bpb.bkbs != MAXU16 &&
395 lsn == bpb.bkbs + bpb.infs))) {
396 mk4(img, 0x41615252);
397 mk4(img + MINBPS - 28, 0x61417272);
398 mk4(img + MINBPS - 24, 0xffffffff);
399 mk4(img + MINBPS - 20, bpb.rdcl);
400 mk2(img + MINBPS - 2, DOSMAGIC);
401 } else if (lsn >= bpb.res && lsn < dir &&
403 (bpb.spf ? bpb.spf : bpb.bspf))) {
404 mk1(img[0], bpb.mid);
405 for (x = 1; x < fat * (fat == 32 ? 3 : 2) / 8; x++)
406 mk1(img[x], fat == 32 && x % 4 == 3 ? 0x0f : 0xff);
407 } else if (lsn == dir && opt_L) {
408 de = (struct de *)img;
413 memcpy(fname + fname_off, img, bpb.bps);
414 fname_off = fname_off + bpb.bps;
415 sectorCount = sectorCount + bpb.bps;
426 * Get disk slice, partition, and geometry information.
429 static void getdiskinfo(unsigned long count, struct bpb *bpb)
434 bpb->bsec = count / 512 ;
439 * Print out BPB values.
441 static void print_bpb(struct bpb *bpb)
443 printf("bps = %u spc = %u res = %u nft = %u", bpb->bps, bpb->spc, bpb->res,
446 printf(" rde = %u", bpb->rde);
448 printf(" sec=%u", bpb->sec);
449 printf(" mid=%#x", bpb->mid);
451 printf(" spf=%u", bpb->spf);
452 printf(" spt = %u hds=%u hid=%u", bpb->spt, bpb->hds, bpb->hid);
454 printf(" bsec=%u", bpb->bsec);
456 printf(" bspf=%u rdcl=%u", bpb->bspf, bpb->rdcl);
458 printf(bpb->infs == MAXU16 ? "%#x" : "%u", bpb->infs);
460 printf(bpb->bkbs == MAXU16 ? "%#x" : "%u", bpb->bkbs);
466 * Copy string, padding with spaces.
468 static void setstr(unsigned char *dest, const char *src, size_t len)
471 *dest++ = *src ? *src++ : ' ';