1 /* ----------------------------------------------------------------------- *
3 * Copyright 2004 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
)