1 /* ----------------------------------------------------------------------- *
3 * Copyright 2004-2008 H. Peter Anvin - All Rights Reserved
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 * Boston MA 02111-1307, USA; either version 2 of the License, or
9 * (at your option) any later version; incorporated herein by reference.
11 * ----------------------------------------------------------------------- */
16 * Open a FAT filesystem and compute some initial values; return NULL
21 #include "libfatint.h"
24 struct libfat_filesystem
*
25 libfat_open(int (*readfunc
) (intptr_t, void *, size_t, libfat_sector_t
),
28 struct libfat_filesystem
*fs
= NULL
;
29 struct fat_bootsect
*bs
;
31 uint32_t sectors
, fatsize
, minfatsize
, rootdirsize
;
34 fs
= malloc(sizeof(struct libfat_filesystem
));
40 fs
->readptr
= readptr
;
42 bs
= libfat_get_sector(fs
, 0);
46 if (read16(&bs
->bsBytesPerSec
) != LIBFAT_SECTOR_SIZE
)
49 for (i
= 0; i
<= 8; i
++) {
50 if ((uint8_t) (1 << i
) == read8(&bs
->bsSecPerClust
))
55 fs
->clustsize
= 1 << i
; /* Treat 0 as 2^8 = 64K */
58 sectors
= read16(&bs
->bsSectors
);
60 sectors
= read32(&bs
->bsHugeSectors
);
64 fs
->fat
= read16(&bs
->bsResSectors
);
65 fatsize
= read16(&bs
->bsFATsecs
);
67 fatsize
= read32(&bs
->u
.fat32
.bpb_fatsz32
);
69 fs
->rootdir
= fs
->fat
+ fatsize
* read8(&bs
->bsFATs
);
71 rootdirsize
= ((read16(&bs
->bsRootDirEnts
) << 5) + LIBFAT_SECTOR_MASK
)
72 >> LIBFAT_SECTOR_SHIFT
;
73 fs
->data
= fs
->rootdir
+ rootdirsize
;
76 if (fs
->data
>= fs
->end
)
79 /* Figure out how many clusters */
80 nclusters
= (fs
->end
- fs
->data
) >> fs
->clustshift
;
81 fs
->endcluster
= nclusters
+ 2;
83 if (nclusters
<= 0xff4) {
85 minfatsize
= fs
->endcluster
+ (fs
->endcluster
>> 1);
86 } else if (nclusters
<= 0xfff4) {
88 minfatsize
= fs
->endcluster
<< 1;
89 } else if (nclusters
<= 0xffffff4) {
91 minfatsize
= fs
->endcluster
<< 2;
93 goto barf
; /* Impossibly many clusters */
95 minfatsize
= (minfatsize
+ LIBFAT_SECTOR_SIZE
- 1) >> LIBFAT_SECTOR_SHIFT
;
97 if (minfatsize
> fatsize
)
98 goto barf
; /* The FATs don't fit */
100 if (fs
->fat_type
== FAT28
)
101 fs
->rootcluster
= read32(&bs
->u
.fat32
.bpb_rootclus
);
105 return fs
; /* All good */
113 void libfat_close(struct libfat_filesystem
*fs
)