tizen 2.4 release
[kernel/u-boot-tm1.git] / nand_fdl / fdl-2 / src / newfs_msdos.c
1 #include <linux/time.h>
2 #include <linux/ctype.h>
3
4
5
6 #define MAXU16    0xffff        /* maximum unsigned 16-bit quantity */
7 #define BPN       4             /* bits per nibble */
8 #define NPB       2             /* nibbles per byte */
9
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 :  \
30                                     MINCLS32)
31
32 #define maxcls(fat)  ((fat) == 12 ? MAXCLS12 :  \
33                       (fat) == 16 ? MAXCLS16 :  \
34                                     MAXCLS32)
35
36 #define mk1(p, x)                               \
37     (p) = (unsigned char)(x)
38
39 #define mk2(p, x)                               \
40     (p)[0] = (unsigned char)(x),                        \
41     (p)[1] = (unsigned char)((x) >> 010)
42
43 #define mk4(p, x)                               \
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)
48
49 struct timeval {
50         long            tv_sec;         /* seconds */
51         long            tv_usec;        /* microseconds */
52 };
53
54 struct bs {
55     unsigned char jmp[3];               /* bootstrap entry point */
56     unsigned char oem[8];               /* OEM name and version */
57 };
58
59 struct bsbpb {
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 */
72 };
73
74 struct bsxbpb {
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 */
82 };
83
84 struct bsx {
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 */
91 };
92
93 struct de {
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 */
101 };
102
103 struct bpb {
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 */
120 };
121
122 #define BPBGAP 0, 0, 0, 0, 0, 0
123
124 static struct {
125     const char *name;
126     struct bpb bpb;
127 } const stdfmt[] = {
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}}
138 };
139
140 static const unsigned char bootcode[] = {
141     0xfa,                       /* cli              */
142     0x31, 0xc0,                 /* xor     ax,ax    */
143     0x8e, 0xd0,                 /* mov     ss,ax    */
144     0xbc, 0x00, 0x7c,           /* mov     sp,7c00h */
145     0xfb,                       /* sti              */
146     0x8e, 0xd8,                 /* mov     ds,ax    */
147     0xe8, 0x00, 0x00,           /* call    $ + 3    */
148     0x5e,                       /* pop     si       */
149     0x83, 0xc6, 0x19,           /* add     si,+19h  */
150     0xbb, 0x07, 0x00,           /* mov     bx,0007h */
151     0xfc,                       /* cld              */
152     0xac,                       /* lodsb            */
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      */
161     0x0d, 0x0a,
162     'N', 'o', 'n', '-', 's', 'y', 's', 't',
163     'e', 'm', ' ', 'd', 'i', 's', 'k',
164     0x0d, 0x0a,
165     'P', 'r', 'e', 's', 's', ' ', 'a', 'n',
166     'y', ' ', 'k', 'e', 'y', ' ', 't', 'o',
167     ' ', 'r', 'e', 'b', 'o', 'o', 't',
168     0x0d, 0x0a,
169     0
170 };
171
172
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);
177
178
179 /*
180  * Construct a FAT12, FAT16, or FAT32 file system.
181  */
182 unsigned int newfs_msdos_main(unsigned char *newfs_SDBUF, unsigned long part_size)
183 {
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;
188     int opt_N = 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; 
194     struct bpb bpb;
195     struct tm *tm;
196     struct bs *bs;
197     struct bsbpb *bsbpb;
198     struct bsxbpb *bsxbpb;
199     struct bsx *bsx;
200     struct de *de;
201     unsigned char *img;
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;
204     int  fd = 0;
205     long opt_ofs = 0;
206
207     memset(&bpb, 0, sizeof(bpb));
208     if (opt_h)
209         bpb.hds = opt_h;
210     if (opt_u)
211         bpb.spt = opt_u;
212     if (opt_S)
213         bpb.bps = opt_S;
214     if (opt_s)
215         bpb.bsec = opt_s;
216     if (oflag)
217         bpb.hid = opt_o;
218     if (!(opt_f || (opt_h && opt_u && opt_S && opt_s && oflag))) {
219         //long delta;
220         getdiskinfo(part_size, &bpb);
221         bpb.spc = 8;
222         #if 0
223         if (opt_s) {
224             bpb.bsec = opt_s;
225         }
226         bpb.bsec -= (opt_ofs / bpb.bps);
227         delta = bpb.bsec % bpb.spt;
228         if (delta != 0) {
229             bpb.bsec -= delta;
230         }
231         if (bpb.spc == 0) {     /* set defaults */
232             if (bpb.bsec <= 6000)       /* about 3MB -> 512 bytes */
233                 bpb.spc = 1;
234             else if (bpb.bsec <= (1<<17)) /* 64M -> 4k */
235                 bpb.spc = 8;
236             else if (bpb.bsec <= (1<<19)) /* 256M -> 8k */
237                 bpb.spc = 16;
238             else if (bpb.bsec <= (1<<21)) /* 1G -> 16k */
239                 bpb.spc = 32;
240             else
241                 bpb.spc = 64;           /* otherwise 32k */
242         }
243         #endif
244     }
245
246     if (opt_f && fat == 32)
247         bpb.rde = 0;
248     bss = 1;
249
250     if (!bpb.nft)
251         bpb.nft = 2;
252     if (!fat) {
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) *
256             bpb.nft +
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)))
261             fat = 12;
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)) +
266                  (MAXCLS16 + 1) *
267                  (bpb.spc ? bpb.spc : howmany(8192, bpb.bps)))
268             fat = 16;
269         else
270             fat = 32;
271     }
272     x = bss;
273     if (fat == 32) {
274         if (!bpb.infs) {
275             bpb.infs = x;
276         }
277         if (bpb.infs != MAXU16 && x <= bpb.infs)
278             x = bpb.infs + 1;
279         if (!bpb.bkbs) {
280             bpb.bkbs = x;
281         }
282         if (bpb.bkbs != MAXU16 && x <= bpb.bkbs)
283             x = bpb.bkbs + 1;
284     }
285         
286     if (!bpb.res)
287         bpb.res = fat == 32 ? MAX(x, MAX(16384 / bpb.bps, 4)) : x;
288     if (fat != 32 && !bpb.rde)
289         bpb.rde = DEFRDE;
290     rds = howmany(bpb.rde, bpb.bps / sizeof(struct de));
291     if (!bpb.spc)
292         for (bpb.spc = howmany(fat == 16 ? DEFBLK16 : DEFBLK, bpb.bps);
293              bpb.spc < MAXSPC &&
294              bpb.res +
295              howmany((RESFTE + maxcls(fat)) * (fat / BPN),
296                      bpb.bps * NPB) * bpb.nft +
297              rds +
298              (unsigned long long)(maxcls(fat) + 1) * bpb.spc <= bpb.bsec;
299              bpb.spc <<= 1);
300     x1 = bpb.res + rds;
301     x = bpb.bspf ? bpb.bspf : 1;
302     x1 += x * bpb.nft;
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),
306                  bpb.bps * NPB);
307     if (!bpb.bspf) {
308         bpb.bspf = x2;
309         x1 += (bpb.bspf - 1) * bpb.nft;
310     }
311     cls = (bpb.bsec - x1) / bpb.spc;
312     x = (unsigned long long)bpb.bspf * bpb.bps * NPB / (fat / BPN) - RESFTE;
313     if (cls > x)
314         cls = x;
315     if (cls > maxcls(fat)) {
316         cls = maxcls(fat);
317         bpb.bsec = x1 + (cls + 1) * bpb.spc - 1;
318     }
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);
323     if (!bpb.mid)
324         bpb.mid = !bpb.hid ? 0xf0 : 0xf8;
325     if (fat == 32)
326         bpb.rdcl = RESFTE;
327     if (bpb.hid + bpb.bsec <= MAXU16) {
328         bpb.sec = bpb.bsec;
329         bpb.bsec = 0;
330     }
331     if (fat != 32) {
332         bpb.spf = bpb.bspf;
333         bpb.bspf = 0;
334     }
335     print_bpb(&bpb);
336     if (!opt_N) {       
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++) {
340             x = lsn;
341             if (opt_B &&
342                 fat == 32 && bpb.bkbs != MAXU16 &&
343                 bss <= bpb.bkbs && x >= bpb.bkbs) {
344                 x -= bpb.bkbs;
345             }
346             memset(img, 0, bpb.bps);
347             if (!lsn ||
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);
364                 if (fat == 32) {
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);
373                 }
374                 bsx = (struct bsx *)(img + x1);
375                 mk1(bsx->sig, 0x29);
376                 if (Iflag)
377                     x = opt_I;
378                 mk4(bsx->volid, 0);
379                 sprintf(buf, "FAT%u", fat);
380                 setstr(bsx->type, buf, sizeof(bsx->type));
381                 if (!opt_B) {
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",
388                            sizeof(bs->oem));
389                     memcpy(img + x1, bootcode, sizeof(bootcode));
390                     mk2(img + MINBPS - 2, DOSMAGIC);
391                 }
392             } else if (fat == 32 && bpb.infs != MAXU16 &&
393                        (lsn == bpb.infs ||
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 &&
402                        !((lsn - bpb.res) %
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;
409                 mk1(de->attr, 050);
410                 mk2(de->time, 0);
411                 mk2(de->date, 0);
412             }
413             memcpy(fname + fname_off, img, bpb.bps);
414             fname_off = fname_off + bpb.bps;
415             sectorCount = sectorCount + bpb.bps;
416         }
417         free(img);
418         }
419
420         return sectorCount;
421 }
422
423
424
425 /*
426  * Get disk slice, partition, and geometry information.
427  */
428
429 static void getdiskinfo(unsigned long count, struct bpb *bpb)
430 {
431     bpb->bps = 512;
432     bpb->spt = 16;
433     bpb->hds = 4;
434     bpb->bsec = count / 512 ;
435 }
436
437
438 /*
439  * Print out BPB values.
440  */
441 static void print_bpb(struct bpb *bpb)
442 {
443     printf("bps = %u spc = %u res = %u nft = %u", bpb->bps, bpb->spc, bpb->res,
444            bpb->nft);
445     if (bpb->rde)
446         printf(" rde = %u", bpb->rde);
447     if (bpb->sec)
448         printf(" sec=%u", bpb->sec);
449         printf(" mid=%#x", bpb->mid);
450     if (bpb->spf)
451         printf(" spf=%u", bpb->spf);
452     printf(" spt = %u hds=%u hid=%u", bpb->spt, bpb->hds, bpb->hid);
453     if (bpb->bsec)
454         printf(" bsec=%u", bpb->bsec);
455     if (!bpb->spf) {
456         printf(" bspf=%u rdcl=%u", bpb->bspf, bpb->rdcl);
457         printf(" infs=");
458         printf(bpb->infs == MAXU16 ? "%#x" : "%u", bpb->infs);
459         printf(" bkbs=");
460         printf(bpb->bkbs == MAXU16 ? "%#x" : "%u", bpb->bkbs);
461     }
462     printf("\n");
463 }
464
465 /*
466  * Copy string, padding with spaces.
467  */
468 static void setstr(unsigned char *dest, const char *src, size_t len)
469 {
470     while (len--)
471         *dest++ = *src ? *src++ : ' ';
472 }
473