diff options
-rw-r--r-- | firmware/drivers/fat.c | 529 | ||||
-rw-r--r-- | firmware/drivers/fat.h | 118 |
2 files changed, 290 insertions, 357 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index a4cd77dc89..596166ec11 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -25,8 +25,6 @@ | |||
25 | #include <time.h> | 25 | #include <time.h> |
26 | #include <sys/timeb.h> | 26 | #include <sys/timeb.h> |
27 | 27 | ||
28 | #define BLOCK_SIZE 512 | ||
29 | |||
30 | #include "fat.h" | 28 | #include "fat.h" |
31 | #include "ata.h" | 29 | #include "ata.h" |
32 | 30 | ||
@@ -41,41 +39,100 @@ | |||
41 | #define NUM_RESERVED_SECTORS 1 | 39 | #define NUM_RESERVED_SECTORS 1 |
42 | #define NUM_BLOCKS 10000 | 40 | #define NUM_BLOCKS 10000 |
43 | 41 | ||
44 | struct dsksz2secperclus | 42 | #define FATTYPE_FAT12 0 |
45 | { | 43 | #define FATTYPE_FAT16 1 |
46 | unsigned int disk_size; | 44 | #define FATTYPE_FAT32 2 |
47 | unsigned int sec_per_cluster; | 45 | |
46 | /* BPB offsets; generic */ | ||
47 | #define BS_JMPBOOT 0 | ||
48 | #define BS_OEMNAME 3 | ||
49 | #define BPB_BYTSPERSEC 11 | ||
50 | #define BPB_SECPERCLUS 13 | ||
51 | #define BPB_RSVDSECCNT 14 | ||
52 | #define BPB_NUMFATS 16 | ||
53 | #define BPB_ROOTENTCNT 17 | ||
54 | #define BPB_TOTSEC16 19 | ||
55 | #define BPB_MEDIA 21 | ||
56 | #define BPB_FATSZ16 22 | ||
57 | #define BPB_SECPERTRK 24 | ||
58 | #define BPB_NUMHEADS 26 | ||
59 | #define BPB_HIDDSEC 28 | ||
60 | #define BPB_TOTSEC32 32 | ||
61 | |||
62 | /* fat12/16 */ | ||
63 | #define BS_DRVNUM 36 | ||
64 | #define BS_RESERVED1 37 | ||
65 | #define BS_BOOTSIG 38 | ||
66 | #define BS_VOLID 39 | ||
67 | #define BS_VOLLAB 43 | ||
68 | #define BS_FILSYSTYPE 54 | ||
69 | |||
70 | /* fat32 */ | ||
71 | #define BPB_FATSZ32 36 | ||
72 | #define BPB_EXTFLAGS 40 | ||
73 | #define BPB_FSVER 42 | ||
74 | #define BPB_ROOTCLUS 44 | ||
75 | #define BPB_FSINFO 48 | ||
76 | #define BPB_BKBOOTSEC 50 | ||
77 | #define BS_32_DRVNUM 64 | ||
78 | #define BS_32_BOOTSIG 66 | ||
79 | #define BS_32_VOLID 67 | ||
80 | #define BS_32_VOLLAB 71 | ||
81 | #define BS_32_FILSYSTYPE 82 | ||
82 | |||
83 | #define BPB_LAST_WORD 510 | ||
84 | |||
85 | |||
86 | /* attributes */ | ||
87 | #define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \ | ||
88 | FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID) | ||
89 | #define FAT_ATTR_LONG_NAME_MASK (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \ | ||
90 | FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID | \ | ||
91 | FAT_ATTR_DIRECTORY | FAT_ATTR_ARCHIVE ) | ||
92 | |||
93 | #define FATDIR_NAME 0 | ||
94 | #define FATDIR_ATTR 11 | ||
95 | #define FATDIR_NTRES 12 | ||
96 | #define FATDIR_CRTTIMETENTH 13 | ||
97 | #define FATDIR_CRTTIME 14 | ||
98 | #define FATDIR_CRTDATE 16 | ||
99 | #define FATDIR_LSTACCDATE 18 | ||
100 | #define FATDIR_FSTCLUSHI 20 | ||
101 | #define FATDIR_WRTTIME 22 | ||
102 | #define FATDIR_WRTDATE 24 | ||
103 | #define FATDIR_FSTCLUSLO 26 | ||
104 | #define FATDIR_FILESIZE 28 | ||
105 | |||
106 | struct fsinfo { | ||
107 | int freecount; /* last known free cluster count */ | ||
108 | int nextfree; /* first cluster to start looking for free clusters, | ||
109 | or 0xffffffff for no hint */ | ||
48 | }; | 110 | }; |
49 | 111 | /* fsinfo offsets */ | |
50 | int fat_num_rootdir_sectors(struct bpb *bpb); | 112 | #define FSINFO_FREECOUNT 488 |
51 | int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster); | 113 | #define FSINFO_NEXTFREE 492 |
52 | int fat_get_fatsize(struct bpb* bpb); | 114 | |
53 | int fat_get_totsec(struct bpb* bpb); | 115 | static int first_sector_of_cluster(struct bpb *bpb, unsigned int cluster); |
54 | int fat_get_rootdir_sector(struct bpb *bpb); | 116 | static int get_bpb(struct bpb *bpb); |
55 | int fat_first_data_sector(struct bpb* bpb); | 117 | static int bpb_is_sane(struct bpb *bpb); |
56 | int fat_get_bpb(struct bpb *bpb); | 118 | static int flush_fat(struct bpb *bpb); |
57 | int fat_bpb_is_sane(struct bpb *bpb); | 119 | static void *cache_fat_sector(struct bpb *bpb, int secnum); |
58 | int fat_create_fat(struct bpb* bpb); | 120 | static int update_entry(struct bpb *bpb, int entry, unsigned int val); |
59 | int fat_dbg_read_block(char *name, unsigned char *buf); | 121 | static unsigned int getcurrdostime(unsigned short *dosdate, |
60 | int fat_flush_fat(struct bpb *bpb); | 122 | unsigned short *dostime, |
61 | unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum); | 123 | unsigned char *dostenth); |
62 | int fat_update_entry(struct bpb *bpb, int entry, unsigned int val); | 124 | static int create_dos_name(unsigned char *name, unsigned char *newname); |
63 | unsigned int fat_getcurrdostime(unsigned short *dosdate, | 125 | |
64 | unsigned short *dostime, | 126 | static unsigned char *fat_cache[256]; |
65 | unsigned char *dostenth); | 127 | static int fat_cache_dirty[256]; |
66 | int fat_create_dos_name(unsigned char *name, unsigned char *newname); | ||
67 | int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name); | ||
68 | |||
69 | unsigned char *fat_cache[256]; | ||
70 | int fat_cache_dirty[256]; | ||
71 | char current_directory[256] = "\\"; | ||
72 | struct bpb *global_bpb; | ||
73 | struct disk_info di; | ||
74 | |||
75 | 128 | ||
76 | #ifdef TEST_FAT | 129 | #ifdef TEST_FAT |
77 | 130 | ||
78 | #include "debug.h" | 131 | #include "debug.h" |
132 | #define DEBUG(x) printf(x) | ||
133 | #define DEBUG1(x,y) printf(x,y) | ||
134 | #define DEBUG2(x,y1,y2) printf(x,y1,y2) | ||
135 | #define DEBUG3(x,y1,y2,y3) printf(x,y1,y2,y3) | ||
79 | 136 | ||
80 | int main(int argc, char *argv[]) | 137 | int main(int argc, char *argv[]) |
81 | { | 138 | { |
@@ -84,101 +141,56 @@ int main(int argc, char *argv[]) | |||
84 | memset(fat_cache, 0, sizeof(fat_cache)); | 141 | memset(fat_cache, 0, sizeof(fat_cache)); |
85 | memset(fat_cache_dirty, 0, sizeof(fat_cache_dirty)); | 142 | memset(fat_cache_dirty, 0, sizeof(fat_cache_dirty)); |
86 | 143 | ||
87 | di.num_sectors = NUM_BLOCKS; | ||
88 | di.sec_per_track = 40; | ||
89 | di.num_heads = 250; | ||
90 | di.hidden_sectors = 0; | ||
91 | |||
92 | if(ata_init()) | 144 | if(ata_init()) |
93 | printf("*** Warning! The disk is uninitialized\n"); | 145 | DEBUG("*** Warning! The disk is uninitialized\n"); |
94 | else | 146 | else |
95 | fat_get_bpb(&bpb); | 147 | get_bpb(&bpb); |
96 | 148 | ||
97 | global_bpb = &bpb; | ||
98 | dbg_console(&bpb); | 149 | dbg_console(&bpb); |
99 | return 0; | 150 | return 0; |
100 | } | 151 | } |
152 | #else | ||
153 | #define DEBUG(x); | ||
154 | #define DEBUG1(x,y); | ||
155 | #define DEBUG2(x,y1,y2); | ||
156 | #define DEBUG3(x,y1,y2,y3); | ||
101 | #endif | 157 | #endif |
102 | 158 | ||
103 | int fat_sec2cluster(struct bpb *bpb, unsigned int sec) | 159 | static int sec2cluster(struct bpb *bpb, unsigned int sec) |
104 | { | 160 | { |
105 | int first_sec = fat_first_data_sector(bpb); | 161 | if ( sec < bpb->firstdatasector ) |
106 | |||
107 | if(sec < first_sec) | ||
108 | { | 162 | { |
109 | fprintf(stderr, "fat_sec2cluster() - Bad sector number (%d)\n", sec); | 163 | DEBUG1( "sec2cluster() - Bad sector number (%d)\n", sec); |
110 | return -1; | 164 | return -1; |
111 | } | 165 | } |
112 | 166 | ||
113 | return ((sec - first_sec) / bpb->bpb_secperclus) + 2; | 167 | return ((sec - bpb->firstdatasector) / bpb->bpb_secperclus) + 2; |
114 | } | 168 | } |
115 | 169 | ||
116 | int fat_cluster2sec(struct bpb *bpb, unsigned int cluster) | 170 | static int cluster2sec(struct bpb *bpb, unsigned int cluster) |
117 | { | 171 | { |
118 | int max_cluster = (fat_get_totsec(bpb) - fat_first_data_sector(bpb)) / | 172 | int max_cluster = bpb->totalsectors - |
119 | bpb->bpb_secperclus + 1; | 173 | bpb->firstdatasector / bpb->bpb_secperclus + 1; |
120 | 174 | ||
121 | if(cluster > max_cluster) | 175 | if(cluster > max_cluster) |
122 | { | 176 | { |
123 | fprintf(stderr, "fat_cluster2sec() - Bad cluster number (%d)\n", | 177 | DEBUG1( "cluster2sec() - Bad cluster number (%d)\n", |
124 | cluster); | 178 | cluster); |
125 | return -1; | 179 | return -1; |
126 | } | 180 | } |
127 | 181 | ||
128 | return fat_first_sector_of_cluster(bpb, cluster); | 182 | return first_sector_of_cluster(bpb, cluster); |
129 | } | ||
130 | |||
131 | int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster) | ||
132 | { | ||
133 | return (cluster - 2) * bpb->bpb_secperclus + fat_first_data_sector(bpb); | ||
134 | } | ||
135 | |||
136 | int fat_num_rootdir_sectors(struct bpb *bpb) | ||
137 | { | ||
138 | return ((bpb->bpb_rootentcnt * 32) + (bpb->bpb_bytspersec - 1)) / | ||
139 | bpb->bpb_bytspersec; | ||
140 | } | ||
141 | |||
142 | int fat_get_fatsize(struct bpb* bpb) | ||
143 | { | ||
144 | if(bpb->bpb_fatsz16 != 0) | ||
145 | return bpb->bpb_fatsz16; | ||
146 | else | ||
147 | return bpb->bpb_fatsz32; | ||
148 | } | ||
149 | |||
150 | int fat_get_totsec(struct bpb* bpb) | ||
151 | { | ||
152 | if(bpb->bpb_totsec16 != 0) | ||
153 | return bpb->bpb_totsec16; | ||
154 | else | ||
155 | return bpb->bpb_totsec32; | ||
156 | } | 183 | } |
157 | 184 | ||
158 | int fat_get_rootdir_sector(struct bpb *bpb) | 185 | static int first_sector_of_cluster(struct bpb *bpb, unsigned int cluster) |
159 | { | 186 | { |
160 | return bpb->bpb_rootclus; | 187 | return (cluster - 2) * bpb->bpb_secperclus + bpb->firstdatasector; |
161 | } | 188 | } |
162 | 189 | ||
163 | int fat_first_data_sector(struct bpb* bpb) | 190 | static int get_bpb(struct bpb *bpb) |
164 | { | ||
165 | int fatsz; | ||
166 | int rootdirsectors; | ||
167 | |||
168 | fatsz = fat_get_fatsize(bpb); | ||
169 | |||
170 | rootdirsectors = fat_num_rootdir_sectors(bpb); | ||
171 | |||
172 | return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz + rootdirsectors; | ||
173 | } | ||
174 | |||
175 | int fat_get_bpb(struct bpb *bpb) | ||
176 | { | 191 | { |
177 | unsigned char buf[BLOCK_SIZE]; | 192 | unsigned char buf[BLOCK_SIZE]; |
178 | int err; | 193 | int err; |
179 | int fatsz; | ||
180 | int rootdirsectors; | ||
181 | int totsec; | ||
182 | int datasec; | 194 | int datasec; |
183 | int countofclusters; | 195 | int countofclusters; |
184 | 196 | ||
@@ -186,7 +198,7 @@ int fat_get_bpb(struct bpb *bpb) | |||
186 | err = ata_read_sectors(0,1,buf); | 198 | err = ata_read_sectors(0,1,buf); |
187 | if(err) | 199 | if(err) |
188 | { | 200 | { |
189 | fprintf(stderr, "fat_get_bpb() - Couldn't read BPB (error code %i)\n", | 201 | DEBUG1( "get_bpb() - Couldn't read BPB (error code %i)\n", |
190 | err); | 202 | err); |
191 | return -1; | 203 | return -1; |
192 | } | 204 | } |
@@ -204,158 +216,129 @@ int fat_get_bpb(struct bpb *bpb) | |||
204 | bpb->bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16); | 216 | bpb->bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16); |
205 | bpb->bpb_media = buf[BPB_MEDIA]; | 217 | bpb->bpb_media = buf[BPB_MEDIA]; |
206 | bpb->bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16); | 218 | bpb->bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16); |
219 | bpb->bpb_fatsz32 = BYTES2INT32(buf,BPB_FATSZ32); | ||
207 | bpb->bpb_secpertrk = BYTES2INT16(buf,BPB_SECPERTRK); | 220 | bpb->bpb_secpertrk = BYTES2INT16(buf,BPB_SECPERTRK); |
208 | bpb->bpb_numheads = BYTES2INT16(buf,BPB_NUMHEADS); | 221 | bpb->bpb_numheads = BYTES2INT16(buf,BPB_NUMHEADS); |
209 | bpb->bpb_hiddsec = BYTES2INT32(buf,BPB_HIDDSEC); | 222 | bpb->bpb_hiddsec = BYTES2INT32(buf,BPB_HIDDSEC); |
210 | bpb->bpb_totsec32 = BYTES2INT32(buf,BPB_TOTSEC32); | 223 | bpb->bpb_totsec32 = BYTES2INT32(buf,BPB_TOTSEC32); |
211 | bpb->bs_drvnum = buf[BS_DRVNUM]; | ||
212 | bpb->bs_bootsig = buf[BS_BOOTSIG]; | ||
213 | bpb->bpb_fatsz32 = BYTES2INT32(buf,BPB_FATSZ32); | ||
214 | bpb->last_word = BYTES2INT16(buf,BPB_LAST_WORD); | 224 | bpb->last_word = BYTES2INT16(buf,BPB_LAST_WORD); |
215 | 225 | ||
216 | if(bpb->bs_bootsig == 0x29) | 226 | /* calculate a few commonly used values */ |
217 | { | 227 | if (bpb->bpb_fatsz16 != 0) |
218 | bpb->bs_volid = BYTES2INT32(buf,BS_VOLID); | 228 | bpb->fatsize = bpb->bpb_fatsz16; |
219 | strncpy(bpb->bs_vollab, &buf[BS_VOLLAB], 11); | 229 | else |
220 | strncpy(bpb->bs_filsystype, &buf[BS_FILSYSTYPE], 8); | 230 | bpb->fatsize = bpb->bpb_fatsz32; |
221 | } | ||
222 | |||
223 | /* Determine FAT type */ | ||
224 | fatsz = fat_get_fatsize(bpb); | ||
225 | 231 | ||
226 | if (bpb->bpb_totsec16 != 0) | 232 | if (bpb->bpb_totsec16 != 0) |
227 | totsec = bpb->bpb_totsec16; | 233 | bpb->totalsectors = bpb->bpb_totsec16; |
228 | else | 234 | else |
229 | totsec = bpb->bpb_totsec32; | 235 | bpb->totalsectors = bpb->bpb_totsec32; |
236 | bpb->firstdatasector = bpb->bpb_rsvdseccnt + | ||
237 | bpb->bpb_numfats * bpb->fatsize; | ||
230 | 238 | ||
231 | rootdirsectors = fat_num_rootdir_sectors(bpb); | 239 | /* Determine FAT type */ |
232 | datasec = totsec - (bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz + | 240 | datasec = bpb->totalsectors - bpb->firstdatasector; |
233 | rootdirsectors); | ||
234 | countofclusters = datasec / bpb->bpb_secperclus; | 241 | countofclusters = datasec / bpb->bpb_secperclus; |
235 | 242 | ||
236 | 243 | #ifdef TEST_FAT | |
237 | /* Determining FAT type: | ||
238 | |||
239 | This is the "proper way" to do it: | ||
240 | |||
241 | if (countofclusters < 4085) | ||
242 | fat12 | ||
243 | else | ||
244 | if (countofclusters < 65525) | ||
245 | fat16 | ||
246 | else | ||
247 | fat32 | ||
248 | */ | ||
249 | |||
250 | /* | 244 | /* |
251 | This is the "real world way" to do it | 245 | we are sometimes testing with "illegally small" fat32 images, |
252 | (since not all FAT32 partitions have >65524 clusters) | 246 | so we don't use the proper fat32 test case for test code |
253 | */ | 247 | */ |
254 | if ( bpb->bpb_fatsz16 ) { | 248 | if ( bpb->bpb_fatsz16 ) |
255 | printf("This is not FAT32. Go away!\n"); | 249 | #else |
250 | if ( countofclusters < 65525 ) | ||
251 | #endif | ||
252 | { | ||
253 | DEBUG("This is not FAT32. Go away!\n"); | ||
256 | return -1; | 254 | return -1; |
257 | } | 255 | } |
258 | 256 | ||
259 | if (fat_bpb_is_sane(bpb) < 0) | 257 | bpb->bpb_extflags = BYTES2INT16(buf,BPB_EXTFLAGS); |
258 | bpb->bpb_fsver = BYTES2INT16(buf,BPB_FSVER); | ||
259 | bpb->bpb_rootclus = BYTES2INT32(buf,BPB_ROOTCLUS); | ||
260 | bpb->bpb_fsinfo = BYTES2INT16(buf,BPB_FSINFO); | ||
261 | bpb->bpb_bkbootsec = BYTES2INT16(buf,BPB_BKBOOTSEC); | ||
262 | bpb->bs_drvnum = buf[BS_32_DRVNUM]; | ||
263 | bpb->bs_bootsig = buf[BS_32_BOOTSIG]; | ||
264 | |||
265 | if(bpb->bs_bootsig == 0x29) | ||
260 | { | 266 | { |
261 | fprintf(stderr, "fat_get_bpb() - BPB is not sane\n"); | 267 | bpb->bs_volid = BYTES2INT32(buf,BS_32_VOLID); |
268 | strncpy(bpb->bs_vollab, &buf[BS_32_VOLLAB], 11); | ||
269 | strncpy(bpb->bs_filsystype, &buf[BS_32_FILSYSTYPE], 8); | ||
270 | } | ||
271 | |||
272 | if (bpb_is_sane(bpb) < 0) | ||
273 | { | ||
274 | DEBUG( "get_bpb() - BPB is not sane\n"); | ||
262 | return -1; | 275 | return -1; |
263 | } | 276 | } |
264 | 277 | ||
278 | bpb->rootdirsector = cluster2sec(bpb,bpb->bpb_rootclus); | ||
279 | |||
265 | return 0; | 280 | return 0; |
266 | } | 281 | } |
267 | 282 | ||
268 | int fat_bpb_is_sane(struct bpb *bpb) | 283 | static int bpb_is_sane(struct bpb *bpb) |
269 | { | 284 | { |
270 | if(bpb->bpb_bytspersec != 512) | 285 | if(bpb->bpb_bytspersec != 512) |
271 | { | 286 | { |
272 | fprintf(stderr, | 287 | DEBUG1( "bpb_is_sane() - Warning: sector size is not 512 (%i)\n", |
273 | "fat_bpb_is_sane() - Warning: sector size is not 512 (%i)\n", | ||
274 | bpb->bpb_bytspersec); | 288 | bpb->bpb_bytspersec); |
275 | } | 289 | } |
276 | if(bpb->bpb_secperclus * bpb->bpb_bytspersec > 32768) | 290 | if(bpb->bpb_secperclus * bpb->bpb_bytspersec > 32768) |
277 | { | 291 | { |
278 | fprintf(stderr, | 292 | DEBUG3( "bpb_is_sane() - Warning: cluster size is larger than 32K " |
279 | "fat_bpb_is_sane() - Warning: cluster size is larger than 32K " | ||
280 | "(%i * %i = %i)\n", | 293 | "(%i * %i = %i)\n", |
281 | bpb->bpb_bytspersec, bpb->bpb_secperclus, | 294 | bpb->bpb_bytspersec, bpb->bpb_secperclus, |
282 | bpb->bpb_bytspersec * bpb->bpb_secperclus); | 295 | bpb->bpb_bytspersec * bpb->bpb_secperclus); |
283 | } | 296 | } |
284 | if(bpb->bpb_rsvdseccnt != 1) | 297 | if(bpb->bpb_rsvdseccnt != 1) |
285 | { | 298 | { |
286 | fprintf(stderr, | 299 | DEBUG1( "bpb_is_sane() - Warning: Reserved sectors is not 1 (%i)\n", |
287 | "fat_bpb_is_sane() - Warning: Reserved sectors is not 1 (%i)\n", | ||
288 | bpb->bpb_rsvdseccnt); | 300 | bpb->bpb_rsvdseccnt); |
289 | } | 301 | } |
290 | if(bpb->bpb_numfats != 2) | 302 | if(bpb->bpb_numfats != 2) |
291 | { | 303 | { |
292 | fprintf(stderr, | 304 | DEBUG1( "bpb_is_sane() - Warning: NumFATS is not 2 (%i)\n", |
293 | "fat_bpb_is_sane() - Warning: NumFATS is not 2 (%i)\n", | ||
294 | bpb->bpb_numfats); | 305 | bpb->bpb_numfats); |
295 | } | 306 | } |
296 | if(bpb->bpb_rootentcnt != 512) | 307 | if(bpb->bpb_rootentcnt != 512) |
297 | { | 308 | { |
298 | fprintf(stderr, | 309 | DEBUG1( "bpb_is_sane() - Warning: RootEntCnt is not 512 (%i)\n", |
299 | "fat_bpb_is_sane() - Warning: RootEntCnt is not 512 (%i)\n", | ||
300 | bpb->bpb_rootentcnt); | 310 | bpb->bpb_rootentcnt); |
301 | } | 311 | } |
302 | if(bpb->bpb_totsec16 < 200) | 312 | if(bpb->bpb_totsec16 < 200) |
303 | { | 313 | { |
304 | if(bpb->bpb_totsec16 == 0) | 314 | if(bpb->bpb_totsec16 == 0) |
305 | { | 315 | { |
306 | fprintf(stderr, "fat_bpb_is_sane() - Error: TotSec16 is 0\n"); | 316 | DEBUG( "bpb_is_sane() - Error: TotSec16 is 0\n"); |
307 | return -1; | 317 | return -1; |
308 | } | 318 | } |
309 | else | 319 | else |
310 | { | 320 | { |
311 | fprintf(stderr, | 321 | DEBUG1( "bpb_is_sane() - Warning: TotSec16 " |
312 | "fat_bpb_is_sane() - Warning: TotSec16 " | ||
313 | "is quite small (%i)\n", | 322 | "is quite small (%i)\n", |
314 | bpb->bpb_totsec16); | 323 | bpb->bpb_totsec16); |
315 | } | 324 | } |
316 | } | 325 | } |
317 | if(bpb->bpb_media != 0xf0 && bpb->bpb_media < 0xf8) | 326 | if(bpb->bpb_media != 0xf0 && bpb->bpb_media < 0xf8) |
318 | { | 327 | { |
319 | fprintf(stderr, | 328 | DEBUG1( "bpb_is_sane() - Warning: Non-standard " |
320 | "fat_bpb_is_sane() - Warning: Non-standard " | ||
321 | "media type (0x%02x)\n", | 329 | "media type (0x%02x)\n", |
322 | bpb->bpb_media); | 330 | bpb->bpb_media); |
323 | } | 331 | } |
324 | if(bpb->last_word != 0xaa55) | 332 | if(bpb->last_word != 0xaa55) |
325 | { | 333 | { |
326 | fprintf(stderr, "fat_bpb_is_sane() - Error: Last word is not " | 334 | DEBUG1( "bpb_is_sane() - Error: Last word is not " |
327 | "0xaa55 (0x%04x)\n", bpb->last_word); | 335 | "0xaa55 (0x%04x)\n", bpb->last_word); |
328 | return -1; | 336 | return -1; |
329 | } | 337 | } |
330 | return 0; | 338 | return 0; |
331 | } | 339 | } |
332 | 340 | ||
333 | int fat_dbg_read_block(char *name, unsigned char *buf) | 341 | static void *cache_fat_sector(struct bpb *bpb, int secnum) |
334 | { | ||
335 | FILE *f; | ||
336 | |||
337 | f = fopen(name, "rb"); | ||
338 | if(f) | ||
339 | { | ||
340 | if(fread(buf, 1, 512, f) != 512) | ||
341 | { | ||
342 | fprintf(stderr, "Could not read file \"%s\"\n", name); | ||
343 | fclose(f); | ||
344 | return -1; | ||
345 | } | ||
346 | /* Now write the sector to disk */ | ||
347 | ata_write_sectors(0,1,buf); | ||
348 | fclose(f); | ||
349 | } | ||
350 | else | ||
351 | { | ||
352 | fprintf(stderr, "Could not open file \"%s\"\n", name); | ||
353 | return -1; | ||
354 | } | ||
355 | return 0; | ||
356 | } | ||
357 | |||
358 | unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum) | ||
359 | { | 342 | { |
360 | unsigned char *sec; | 343 | unsigned char *sec; |
361 | 344 | ||
@@ -366,12 +349,12 @@ unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum) | |||
366 | sec = malloc(bpb->bpb_bytspersec); | 349 | sec = malloc(bpb->bpb_bytspersec); |
367 | if(!sec) | 350 | if(!sec) |
368 | { | 351 | { |
369 | fprintf(stderr, "fat_cache_fat_sector() - Out of memory\n"); | 352 | DEBUG( "cache_fat_sector() - Out of memory\n"); |
370 | return NULL; | 353 | return NULL; |
371 | } | 354 | } |
372 | if(ata_read_sectors(secnum + bpb->bpb_rsvdseccnt,1,sec)) | 355 | if(ata_read_sectors(secnum,1,sec)) |
373 | { | 356 | { |
374 | fprintf(stderr, "fat_cache_fat_sector() - Could" | 357 | DEBUG1( "cache_fat_sector() - Could" |
375 | " not read sector %d\n", | 358 | " not read sector %d\n", |
376 | secnum); | 359 | secnum); |
377 | free(sec); | 360 | free(sec); |
@@ -382,66 +365,72 @@ unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum) | |||
382 | return sec; | 365 | return sec; |
383 | } | 366 | } |
384 | 367 | ||
385 | int fat_update_entry(struct bpb *bpb, int entry, unsigned int val) | 368 | static int update_entry(struct bpb *bpb, int entry, unsigned int val) |
386 | { | 369 | { |
387 | unsigned char *sec; | 370 | unsigned long *sec; |
388 | int fatsz; | ||
389 | int fatoffset; | 371 | int fatoffset; |
390 | int thisfatsecnum; | 372 | int thisfatsecnum; |
391 | int thisfatentoffset; | 373 | int thisfatentoffset; |
392 | unsigned int tmp; | ||
393 | 374 | ||
394 | fatsz = fat_get_fatsize(bpb); | ||
395 | fatoffset = entry * 4; | 375 | fatoffset = entry * 4; |
396 | thisfatsecnum = fatoffset / bpb->bpb_bytspersec; | 376 | thisfatsecnum = fatoffset / bpb->bpb_bytspersec + bpb->bpb_rsvdseccnt; |
397 | thisfatentoffset = fatoffset % bpb->bpb_bytspersec; | 377 | thisfatentoffset = fatoffset % bpb->bpb_bytspersec; |
398 | 378 | ||
399 | sec = fat_cache_fat_sector(bpb, thisfatsecnum); | ||
400 | /* Load the sector if it is not cached */ | 379 | /* Load the sector if it is not cached */ |
380 | sec = cache_fat_sector(bpb, thisfatsecnum); | ||
401 | if(!sec) | 381 | if(!sec) |
402 | { | 382 | { |
403 | fprintf(stderr, "fat_update_entry() - Could not cache sector %d\n", | 383 | DEBUG1( "update_entry() - Could not cache sector %d\n", |
404 | thisfatsecnum); | 384 | thisfatsecnum); |
405 | return -1; | 385 | return -1; |
406 | } | 386 | } |
407 | 387 | ||
408 | fat_cache_dirty[thisfatsecnum] = 1; | 388 | fat_cache_dirty[thisfatsecnum] = 1; |
409 | 389 | ||
410 | tmp = *(unsigned short *)(&sec[thisfatentoffset]) & 0xf000000; | 390 | /* don't change top 4 bits */ |
411 | val = tmp | (val & 0x0fffffff); | 391 | sec[thisfatentoffset/sizeof(int)] &= 0xf000000; |
412 | *(unsigned short *)(&sec[thisfatentoffset]) = val; | 392 | sec[thisfatentoffset/sizeof(int)] |= val & 0x0fffffff; |
413 | 393 | ||
414 | return 0; | 394 | return 0; |
415 | } | 395 | } |
416 | 396 | ||
417 | int fat_read_entry(struct bpb *bpb, int entry) | 397 | static int read_entry(struct bpb *bpb, int entry) |
418 | { | 398 | { |
419 | unsigned char *sec; | 399 | unsigned long *sec; |
420 | int fatsz; | ||
421 | int fatoffset; | 400 | int fatoffset; |
422 | int thisfatsecnum; | 401 | int thisfatsecnum; |
423 | int thisfatentoffset; | 402 | int thisfatentoffset; |
424 | int val = -1; | 403 | int val = -1; |
425 | 404 | ||
426 | fatsz = fat_get_fatsize(bpb); | ||
427 | fatoffset = entry * 4; | 405 | fatoffset = entry * 4; |
428 | thisfatsecnum = fatoffset / bpb->bpb_bytspersec; | 406 | thisfatsecnum = fatoffset / bpb->bpb_bytspersec + bpb->bpb_rsvdseccnt; |
429 | thisfatentoffset = fatoffset % bpb->bpb_bytspersec; | 407 | thisfatentoffset = fatoffset % bpb->bpb_bytspersec; |
430 | 408 | ||
431 | sec = fat_cache_fat_sector(bpb, thisfatsecnum); | ||
432 | /* Load the sector if it is not cached */ | 409 | /* Load the sector if it is not cached */ |
410 | sec = cache_fat_sector(bpb, thisfatsecnum); | ||
433 | if(!sec) | 411 | if(!sec) |
434 | { | 412 | { |
435 | fprintf(stderr, "fat_update_entry() - Could not cache sector %d\n", | 413 | DEBUG1( "update_entry() - Could not cache sector %d\n", |
436 | thisfatsecnum); | 414 | thisfatsecnum); |
437 | return -1; | 415 | return -1; |
438 | } | 416 | } |
439 | 417 | ||
440 | val = *(unsigned int *)(&sec[thisfatentoffset]); | 418 | val = sec[thisfatentoffset/sizeof(int)]; |
441 | return val; | 419 | return val; |
442 | } | 420 | } |
443 | 421 | ||
444 | int fat_flush_fat(struct bpb *bpb) | 422 | static int get_next_cluster(struct bpb *bpb, unsigned int cluster) |
423 | { | ||
424 | int next_cluster = read_entry(bpb, cluster); | ||
425 | |||
426 | /* is this last cluster in chain? */ | ||
427 | if ( next_cluster >= 0x0ffffff8 ) | ||
428 | return 0; | ||
429 | else | ||
430 | return next_cluster; | ||
431 | } | ||
432 | |||
433 | static int flush_fat(struct bpb *bpb) | ||
445 | { | 434 | { |
446 | int i; | 435 | int i; |
447 | int err; | 436 | int err; |
@@ -450,25 +439,25 @@ int fat_flush_fat(struct bpb *bpb) | |||
450 | unsigned short d, t; | 439 | unsigned short d, t; |
451 | char m; | 440 | char m; |
452 | 441 | ||
453 | fatsz = fat_get_fatsize(bpb); | 442 | fatsz = bpb->fatsize; |
454 | 443 | ||
455 | for(i = 0;i < 256;i++) | 444 | for(i = 0;i < 256;i++) |
456 | { | 445 | { |
457 | if(fat_cache[i] && fat_cache_dirty[i]) | 446 | if(fat_cache[i] && fat_cache_dirty[i]) |
458 | { | 447 | { |
459 | printf("Flushing FAT sector %d\n", i); | 448 | DEBUG1("Flushing FAT sector %d\n", i); |
460 | sec = fat_cache[i]; | 449 | sec = fat_cache[i]; |
461 | err = ata_write_sectors(i + bpb->bpb_rsvdseccnt,1,sec); | 450 | err = ata_write_sectors(i + bpb->bpb_rsvdseccnt,1,sec); |
462 | if(err) | 451 | if(err) |
463 | { | 452 | { |
464 | fprintf(stderr, "fat_flush_fat() - Couldn't write" | 453 | DEBUG1( "flush_fat() - Couldn't write" |
465 | " sector (%d)\n", i + bpb->bpb_rsvdseccnt); | 454 | " sector (%d)\n", i + bpb->bpb_rsvdseccnt); |
466 | return -1; | 455 | return -1; |
467 | } | 456 | } |
468 | err = ata_write_sectors(i + bpb->bpb_rsvdseccnt + fatsz,1,sec); | 457 | err = ata_write_sectors(i + bpb->bpb_rsvdseccnt + fatsz,1,sec); |
469 | if(err) | 458 | if(err) |
470 | { | 459 | { |
471 | fprintf(stderr, "fat_flush_fat() - Couldn't write" | 460 | DEBUG1( "flush_fat() - Couldn't write" |
472 | " sector (%d)\n", i + bpb->bpb_rsvdseccnt + fatsz); | 461 | " sector (%d)\n", i + bpb->bpb_rsvdseccnt + fatsz); |
473 | return -1; | 462 | return -1; |
474 | } | 463 | } |
@@ -476,11 +465,11 @@ int fat_flush_fat(struct bpb *bpb) | |||
476 | } | 465 | } |
477 | } | 466 | } |
478 | 467 | ||
479 | fat_getcurrdostime(&d, &t, &m); | 468 | getcurrdostime(&d, &t, &m); |
480 | return 0; | 469 | return 0; |
481 | } | 470 | } |
482 | 471 | ||
483 | unsigned int fat_getcurrdostime(unsigned short *dosdate, | 472 | unsigned int getcurrdostime(unsigned short *dosdate, |
484 | unsigned short *dostime, | 473 | unsigned short *dostime, |
485 | unsigned char *dostenth) | 474 | unsigned char *dostenth) |
486 | { | 475 | { |
@@ -502,19 +491,9 @@ unsigned int fat_getcurrdostime(unsigned short *dosdate, | |||
502 | return 0; | 491 | return 0; |
503 | } | 492 | } |
504 | 493 | ||
505 | int fat_get_next_cluster(struct bpb *bpb, unsigned int cluster) | 494 | static int add_dir_entry(struct bpb *bpb, |
506 | { | 495 | unsigned int currdir, |
507 | int next_cluster = fat_read_entry(bpb, cluster); | 496 | struct fat_direntry *de) |
508 | |||
509 | /* is this last cluster in chain? */ | ||
510 | if ( next_cluster >= 0x0ffffff8 ) | ||
511 | return 0; | ||
512 | else | ||
513 | return next_cluster; | ||
514 | } | ||
515 | |||
516 | int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, | ||
517 | struct fat_direntry *de) | ||
518 | { | 497 | { |
519 | unsigned char buf[BLOCK_SIZE]; | 498 | unsigned char buf[BLOCK_SIZE]; |
520 | unsigned char *eptr; | 499 | unsigned char *eptr; |
@@ -529,11 +508,11 @@ int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, | |||
529 | 508 | ||
530 | if(is_rootdir) | 509 | if(is_rootdir) |
531 | { | 510 | { |
532 | sec = fat_get_rootdir_sector(bpb); | 511 | sec = bpb->rootdirsector; |
533 | } | 512 | } |
534 | else | 513 | else |
535 | { | 514 | { |
536 | sec = fat_first_sector_of_cluster(bpb, currdir); | 515 | sec = first_sector_of_cluster(bpb, currdir); |
537 | } | 516 | } |
538 | 517 | ||
539 | sec_cnt = 0; | 518 | sec_cnt = 0; |
@@ -554,7 +533,7 @@ int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, | |||
554 | } | 533 | } |
555 | else | 534 | else |
556 | { | 535 | { |
557 | fprintf(stderr, "fat_add_dir_entry() -" | 536 | DEBUG( "add_dir_entry() -" |
558 | " Root dir is full\n"); | 537 | " Root dir is full\n"); |
559 | return -1; | 538 | return -1; |
560 | } | 539 | } |
@@ -565,9 +544,9 @@ int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, | |||
565 | if(sec_cnt >= bpb->bpb_secperclus) | 544 | if(sec_cnt >= bpb->bpb_secperclus) |
566 | { | 545 | { |
567 | /* We have reached the end of this cluster */ | 546 | /* We have reached the end of this cluster */ |
568 | printf("Moving to the next cluster..."); | 547 | DEBUG("Moving to the next cluster..."); |
569 | currdir = fat_get_next_cluster(bpb, currdir); | 548 | currdir = get_next_cluster(bpb, currdir); |
570 | printf("new cluster is %d\n", currdir); | 549 | DEBUG1("new cluster is %d\n", currdir); |
571 | 550 | ||
572 | if(!currdir) | 551 | if(!currdir) |
573 | { | 552 | { |
@@ -578,12 +557,12 @@ int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, | |||
578 | } | 557 | } |
579 | } | 558 | } |
580 | 559 | ||
581 | printf("Reading sector %d...\n", sec); | 560 | DEBUG1("Reading sector %d...\n", sec); |
582 | /* Read the next sector in the current dir */ | 561 | /* Read the next sector in the current dir */ |
583 | err = ata_read_sectors(sec,1,buf); | 562 | err = ata_read_sectors(sec,1,buf); |
584 | if(err) | 563 | if(err) |
585 | { | 564 | { |
586 | fprintf(stderr, "fat_add_dir_entry() - Couldn't read dir sector" | 565 | DEBUG1( "add_dir_entry() - Couldn't read dir sector" |
587 | " (error code %i)\n", err); | 566 | " (error code %i)\n", err); |
588 | return -1; | 567 | return -1; |
589 | } | 568 | } |
@@ -591,7 +570,7 @@ int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, | |||
591 | if(need_to_update_last_empty_marker) | 570 | if(need_to_update_last_empty_marker) |
592 | { | 571 | { |
593 | /* All we need to do is to set the first entry to 0 */ | 572 | /* All we need to do is to set the first entry to 0 */ |
594 | printf("Clearing the first entry in sector %d\n", sec); | 573 | DEBUG1("Clearing the first entry in sector %d\n", sec); |
595 | buf[0] = 0; | 574 | buf[0] = 0; |
596 | done = 1; | 575 | done = 1; |
597 | } | 576 | } |
@@ -603,7 +582,7 @@ int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, | |||
603 | firstbyte = buf[i]; | 582 | firstbyte = buf[i]; |
604 | if(firstbyte == 0xe5 || firstbyte == 0) | 583 | if(firstbyte == 0xe5 || firstbyte == 0) |
605 | { | 584 | { |
606 | printf("Found free slot at entry %d in sector %d\n", | 585 | DEBUG2("Found free slot at entry %d in sector %d\n", |
607 | i/32, sec); | 586 | i/32, sec); |
608 | eptr = &buf[i]; | 587 | eptr = &buf[i]; |
609 | memset(eptr, 0, 32); | 588 | memset(eptr, 0, 32); |
@@ -648,7 +627,7 @@ int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, | |||
648 | err = ata_write_sectors(sec,1,buf); | 627 | err = ata_write_sectors(sec,1,buf); |
649 | if(err) | 628 | if(err) |
650 | { | 629 | { |
651 | fprintf(stderr, "fat_add_dir_entry() - " | 630 | DEBUG1( "add_dir_entry() - " |
652 | " Couldn't write dir" | 631 | " Couldn't write dir" |
653 | " sector (error code %i)\n", err); | 632 | " sector (error code %i)\n", err); |
654 | return -1; | 633 | return -1; |
@@ -664,7 +643,7 @@ int fat_add_dir_entry(struct bpb *bpb, unsigned int currdir, | |||
664 | return 0; | 643 | return 0; |
665 | } | 644 | } |
666 | 645 | ||
667 | unsigned char fat_char2dos(unsigned char c) | 646 | unsigned char char2dos(unsigned char c) |
668 | { | 647 | { |
669 | switch(c) | 648 | switch(c) |
670 | { | 649 | { |
@@ -701,7 +680,7 @@ unsigned char fat_char2dos(unsigned char c) | |||
701 | return c; | 680 | return c; |
702 | } | 681 | } |
703 | 682 | ||
704 | int fat_create_dos_name(unsigned char *name, unsigned char *newname) | 683 | static int create_dos_name(unsigned char *name, unsigned char *newname) |
705 | { | 684 | { |
706 | unsigned char n[12]; | 685 | unsigned char n[12]; |
707 | unsigned char c; | 686 | unsigned char c; |
@@ -731,7 +710,7 @@ int fat_create_dos_name(unsigned char *name, unsigned char *newname) | |||
731 | /* Name part */ | 710 | /* Name part */ |
732 | for(i = 0;n[i] && (i < 8);i++) | 711 | for(i = 0;n[i] && (i < 8);i++) |
733 | { | 712 | { |
734 | c = fat_char2dos(n[i]); | 713 | c = char2dos(n[i]); |
735 | if(c) | 714 | if(c) |
736 | { | 715 | { |
737 | newname[i] = toupper(c); | 716 | newname[i] = toupper(c); |
@@ -745,7 +724,7 @@ int fat_create_dos_name(unsigned char *name, unsigned char *newname) | |||
745 | /* Extension part */ | 724 | /* Extension part */ |
746 | for(i = 0;ext && ext[i] && (i < 3);i++) | 725 | for(i = 0;ext && ext[i] && (i < 3);i++) |
747 | { | 726 | { |
748 | c = fat_char2dos(ext[i]); | 727 | c = char2dos(ext[i]); |
749 | if(c) | 728 | if(c) |
750 | { | 729 | { |
751 | newname[8+i] = toupper(c); | 730 | newname[8+i] = toupper(c); |
@@ -763,21 +742,21 @@ int fat_create_dir(struct bpb *bpb, unsigned int currdir, char *name) | |||
763 | struct fat_direntry de; | 742 | struct fat_direntry de; |
764 | int err; | 743 | int err; |
765 | 744 | ||
766 | printf("fat_create_file()\n"); | 745 | DEBUG("fat_create_file()\n"); |
767 | memset(&de, 0, sizeof(struct fat_direntry)); | 746 | memset(&de, 0, sizeof(struct fat_direntry)); |
768 | if(fat_create_dos_name(name, de.name) < 0) | 747 | if(create_dos_name(name, de.name) < 0) |
769 | { | 748 | { |
770 | fprintf(stderr, "fat_create_file() - Illegal file name (%s)\n", name); | 749 | DEBUG1( "fat_create_file() - Illegal file name (%s)\n", name); |
771 | return -1; | 750 | return -1; |
772 | } | 751 | } |
773 | 752 | ||
774 | fat_getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); | 753 | getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); |
775 | de.wrtdate = de.crtdate; | 754 | de.wrtdate = de.crtdate; |
776 | de.wrttime = de.crttime; | 755 | de.wrttime = de.crttime; |
777 | de.filesize = 0; | 756 | de.filesize = 0; |
778 | de.attr = FAT_ATTR_DIRECTORY; | 757 | de.attr = FAT_ATTR_DIRECTORY; |
779 | 758 | ||
780 | err = fat_add_dir_entry(bpb, currdir, &de); | 759 | err = add_dir_entry(bpb, currdir, &de); |
781 | return 0; | 760 | return 0; |
782 | } | 761 | } |
783 | 762 | ||
@@ -786,23 +765,23 @@ int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name) | |||
786 | struct fat_direntry de; | 765 | struct fat_direntry de; |
787 | int err; | 766 | int err; |
788 | 767 | ||
789 | printf("fat_create_file()\n"); | 768 | DEBUG("fat_create_file()\n"); |
790 | memset(&de, 0, sizeof(struct fat_direntry)); | 769 | memset(&de, 0, sizeof(struct fat_direntry)); |
791 | if(fat_create_dos_name(name, de.name) < 0) | 770 | if(create_dos_name(name, de.name) < 0) |
792 | { | 771 | { |
793 | fprintf(stderr, "fat_create_file() - Illegal file name (%s)\n", name); | 772 | DEBUG1( "fat_create_file() - Illegal file name (%s)\n", name); |
794 | return -1; | 773 | return -1; |
795 | } | 774 | } |
796 | fat_getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); | 775 | getcurrdostime(&de.crtdate, &de.crttime, &de.crttimetenth); |
797 | de.wrtdate = de.crtdate; | 776 | de.wrtdate = de.crtdate; |
798 | de.wrttime = de.crttime; | 777 | de.wrttime = de.crttime; |
799 | de.filesize = 0; | 778 | de.filesize = 0; |
800 | 779 | ||
801 | err = fat_add_dir_entry(bpb, currdir, &de); | 780 | err = add_dir_entry(bpb, currdir, &de); |
802 | return err; | 781 | return err; |
803 | } | 782 | } |
804 | 783 | ||
805 | int fat_parse_direntry(struct fat_direntry *de, char *buf) | 784 | static int parse_direntry(struct fat_direntry *de, char *buf) |
806 | { | 785 | { |
807 | /* is this a long filename entry? */ | 786 | /* is this a long filename entry? */ |
808 | if ( ( buf[FATDIR_ATTR] & FAT_ATTR_LONG_NAME_MASK ) == | 787 | if ( ( buf[FATDIR_ATTR] & FAT_ATTR_LONG_NAME_MASK ) == |
@@ -824,7 +803,9 @@ int fat_parse_direntry(struct fat_direntry *de, char *buf) | |||
824 | return 1; | 803 | return 1; |
825 | } | 804 | } |
826 | 805 | ||
827 | int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir) | 806 | int fat_opendir(struct bpb *bpb, |
807 | struct fat_dirent *ent, | ||
808 | unsigned int currdir) | ||
828 | { | 809 | { |
829 | int is_rootdir = (currdir == 0); | 810 | int is_rootdir = (currdir == 0); |
830 | unsigned int sec; | 811 | unsigned int sec; |
@@ -832,18 +813,18 @@ int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir) | |||
832 | 813 | ||
833 | if(is_rootdir) | 814 | if(is_rootdir) |
834 | { | 815 | { |
835 | sec = fat_get_rootdir_sector(bpb); | 816 | sec = bpb->rootdirsector; |
836 | } | 817 | } |
837 | else | 818 | else |
838 | { | 819 | { |
839 | sec = fat_first_sector_of_cluster(bpb, currdir); | 820 | sec = first_sector_of_cluster(bpb, currdir); |
840 | } | 821 | } |
841 | 822 | ||
842 | /* Read the first sector in the current dir */ | 823 | /* Read the first sector in the current dir */ |
843 | err = ata_read_sectors(sec,1,ent->cached_buf); | 824 | err = ata_read_sectors(sec,1,ent->cached_buf); |
844 | if(err) | 825 | if(err) |
845 | { | 826 | { |
846 | fprintf(stderr, "fat_getfirst() - Couldn't read dir sector" | 827 | DEBUG1( "fat_getfirst() - Couldn't read dir sector" |
847 | " (error code %i)\n", err); | 828 | " (error code %i)\n", err); |
848 | return -1; | 829 | return -1; |
849 | } | 830 | } |
@@ -851,6 +832,7 @@ int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir) | |||
851 | ent->entry = 0; | 832 | ent->entry = 0; |
852 | ent->cached_sec = sec; | 833 | ent->cached_sec = sec; |
853 | ent->num_sec = 0; | 834 | ent->num_sec = 0; |
835 | |||
854 | return 0; | 836 | return 0; |
855 | } | 837 | } |
856 | 838 | ||
@@ -872,55 +854,64 @@ int fat_getnext(struct bpb *bpb, | |||
872 | if(firstbyte == 0xe5) | 854 | if(firstbyte == 0xe5) |
873 | continue; | 855 | continue; |
874 | 856 | ||
875 | if(firstbyte == 0) { | 857 | if(firstbyte == 0) |
876 | printf("Firstbyte == 0\n"); | 858 | /* no more entries */ |
877 | return -1; | 859 | return -1; |
878 | } | ||
879 | 860 | ||
880 | if ( fat_parse_direntry(entry, &ent->cached_buf[i*32]) ) { | 861 | if ( parse_direntry(entry, &ent->cached_buf[i*32]) ) { |
881 | done = 1; | 862 | done = 1; |
882 | break; | 863 | break; |
883 | } | 864 | } |
884 | } | 865 | } |
885 | 866 | ||
886 | /* Next sector? */ | 867 | /* Next sector? */ |
887 | if(i >= BLOCK_SIZE/32) | 868 | if(i < BLOCK_SIZE/32) |
869 | { | ||
870 | i++; | ||
871 | } | ||
872 | else | ||
888 | { | 873 | { |
889 | ent->num_sec++; | 874 | ent->num_sec++; |
890 | ent->cached_sec++; | 875 | |
891 | |||
892 | /* Do we need to advance one cluster? */ | 876 | /* Do we need to advance one cluster? */ |
893 | if(ent->num_sec >= bpb->bpb_secperclus) | 877 | if(ent->num_sec < bpb->bpb_secperclus) |
878 | { | ||
879 | ent->cached_sec++; | ||
880 | } | ||
881 | else | ||
894 | { | 882 | { |
895 | int cluster = fat_sec2cluster(bpb, ent->cached_sec); | 883 | int cluster = sec2cluster(bpb, ent->cached_sec); |
896 | if ( cluster < 0 ) { | 884 | if ( cluster < 0 ) { |
897 | printf("sec2cluster failed\n"); | 885 | DEBUG("sec2cluster failed\n"); |
898 | return -1; | 886 | return -1; |
899 | } | 887 | } |
900 | ent->num_sec = 0; | 888 | ent->num_sec = 0; |
901 | ent->cached_sec = fat_get_next_cluster( bpb, cluster ); | 889 | cluster = get_next_cluster( bpb, cluster ); |
902 | if(!ent->cached_sec) | 890 | if(!cluster) |
903 | { | 891 | { |
904 | printf("End of cluster chain.\n"); | 892 | DEBUG("End of cluster chain.\n"); |
893 | return -1; | ||
894 | } | ||
895 | ent->cached_sec = cluster2sec(bpb,cluster); | ||
896 | if ( ent->cached_sec < 0 ) | ||
897 | { | ||
898 | DEBUG1("Invalid cluster: %d\n",cluster); | ||
905 | return -1; | 899 | return -1; |
906 | } | 900 | } |
907 | } | ||
908 | 901 | ||
902 | } | ||
903 | |||
909 | /* Read the next sector */ | 904 | /* Read the next sector */ |
910 | err = ata_read_sectors(ent->cached_sec,1,ent->cached_buf); | 905 | err = ata_read_sectors(ent->cached_sec,1,ent->cached_buf); |
911 | if(err) | 906 | if(err) |
912 | { | 907 | { |
913 | fprintf(stderr, "fat_getnext() - Couldn't read dir sector" | 908 | DEBUG1( "fat_getnext() - Couldn't read dir sector" |
914 | " (error code %i)\n", err); | 909 | " (error code %i)\n", err); |
915 | return -1; | 910 | return -1; |
916 | } | 911 | } |
917 | 912 | ||
918 | i = 0; | 913 | i = 0; |
919 | } | 914 | } |
920 | else | ||
921 | { | ||
922 | i++; | ||
923 | } | ||
924 | ent->entry = i; | 915 | ent->entry = i; |
925 | } | 916 | } |
926 | return 0; | 917 | return 0; |
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h index 99b40ac284..b60b3d4164 100644 --- a/firmware/drivers/fat.h +++ b/firmware/drivers/fat.h | |||
@@ -22,38 +22,6 @@ | |||
22 | 22 | ||
23 | #define BLOCK_SIZE 512 | 23 | #define BLOCK_SIZE 512 |
24 | 24 | ||
25 | #define FATTYPE_FAT12 0 | ||
26 | #define FATTYPE_FAT16 1 | ||
27 | #define FATTYPE_FAT32 2 | ||
28 | |||
29 | #define BS_JMPBOOT 0 | ||
30 | #define BS_OEMNAME 3 | ||
31 | #define BPB_BYTSPERSEC 11 | ||
32 | #define BPB_SECPERCLUS 13 | ||
33 | #define BPB_RSVDSECCNT 14 | ||
34 | #define BPB_NUMFATS 16 | ||
35 | #define BPB_ROOTENTCNT 17 | ||
36 | #define BPB_TOTSEC16 19 | ||
37 | #define BPB_MEDIA 21 | ||
38 | #define BPB_FATSZ16 22 | ||
39 | #define BPB_SECPERTRK 24 | ||
40 | #define BPB_NUMHEADS 26 | ||
41 | #define BPB_HIDDSEC 28 | ||
42 | #define BPB_TOTSEC32 32 | ||
43 | |||
44 | #define BS_DRVNUM 36 | ||
45 | #define BS_RESERVED1 37 | ||
46 | #define BS_BOOTSIG 38 | ||
47 | #define BS_VOLID 39 | ||
48 | #define BS_VOLLAB 43 | ||
49 | #define BS_FILSYSTYPE 54 | ||
50 | |||
51 | #define BPB_FATSZ32 36 | ||
52 | |||
53 | #define BPB_LAST_WORD 510 | ||
54 | |||
55 | #define MIN(a,b) (((a) < (b))?(a):(b)) | ||
56 | |||
57 | struct bpb | 25 | struct bpb |
58 | { | 26 | { |
59 | char bs_oemname[9]; /* OEM string, ending with \0 */ | 27 | char bs_oemname[9]; /* OEM string, ending with \0 */ |
@@ -70,6 +38,8 @@ struct bpb | |||
70 | int bpb_hiddsec; /* Hidden sectors before the volume */ | 38 | int bpb_hiddsec; /* Hidden sectors before the volume */ |
71 | unsigned int bpb_totsec32; /* Number of sectors on the volume | 39 | unsigned int bpb_totsec32; /* Number of sectors on the volume |
72 | (new 32-bit) */ | 40 | (new 32-bit) */ |
41 | int last_word; /* 0xAA55 */ | ||
42 | |||
73 | /**** FAT12/16 specific *****/ | 43 | /**** FAT12/16 specific *****/ |
74 | int bs_drvnum; /* Drive number */ | 44 | int bs_drvnum; /* Drive number */ |
75 | int bs_bootsig; /* Is 0x29 if the following 3 fields are valid */ | 45 | int bs_bootsig; /* Is 0x29 if the following 3 fields are valid */ |
@@ -86,8 +56,27 @@ struct bpb | |||
86 | int bpb_bkbootsec; | 56 | int bpb_bkbootsec; |
87 | 57 | ||
88 | /* variables for internal use */ | 58 | /* variables for internal use */ |
89 | int fat_type; /* FAT12, FAT16 or FAT32 */ | 59 | int fatsize; |
90 | int last_word; /* must be 0xAA55 */ | 60 | int totalsectors; |
61 | int rootdirsector; | ||
62 | int firstdatasector; | ||
63 | }; | ||
64 | |||
65 | struct fat_direntry | ||
66 | { | ||
67 | unsigned char name[12]; /* Name plus \0 */ | ||
68 | unsigned short attr; /* Attributes */ | ||
69 | unsigned char crttimetenth; /* Millisecond creation | ||
70 | time stamp (0-199) */ | ||
71 | unsigned short crttime; /* Creation time */ | ||
72 | unsigned short crtdate; /* Creation date */ | ||
73 | unsigned short lstaccdate; /* Last access date */ | ||
74 | unsigned short fstclushi; /* High word of first cluster | ||
75 | (0 for FAT12/16) */ | ||
76 | unsigned short wrttime; /* Last write time */ | ||
77 | unsigned short wrtdate; /* Last write date */ | ||
78 | unsigned short fstcluslo; /* Low word of first cluster */ | ||
79 | unsigned int filesize; /* File size in bytes */ | ||
91 | }; | 80 | }; |
92 | 81 | ||
93 | #define FAT_ATTR_READ_ONLY 0x01 | 82 | #define FAT_ATTR_READ_ONLY 0x01 |
@@ -96,68 +85,21 @@ struct bpb | |||
96 | #define FAT_ATTR_VOLUME_ID 0x08 | 85 | #define FAT_ATTR_VOLUME_ID 0x08 |
97 | #define FAT_ATTR_DIRECTORY 0x10 | 86 | #define FAT_ATTR_DIRECTORY 0x10 |
98 | #define FAT_ATTR_ARCHIVE 0x20 | 87 | #define FAT_ATTR_ARCHIVE 0x20 |
99 | #define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \ | ||
100 | FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID) | ||
101 | #define FAT_ATTR_LONG_NAME_MASK (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \ | ||
102 | FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID | \ | ||
103 | FAT_ATTR_DIRECTORY | FAT_ATTR_ARCHIVE ) | ||
104 | |||
105 | |||
106 | #define FATDIR_NAME 0 | ||
107 | #define FATDIR_ATTR 11 | ||
108 | #define FATDIR_NTRES 12 | ||
109 | #define FATDIR_CRTTIMETENTH 13 | ||
110 | #define FATDIR_CRTTIME 14 | ||
111 | #define FATDIR_CRTDATE 16 | ||
112 | #define FATDIR_LSTACCDATE 18 | ||
113 | #define FATDIR_FSTCLUSHI 20 | ||
114 | #define FATDIR_WRTTIME 22 | ||
115 | #define FATDIR_WRTDATE 24 | ||
116 | #define FATDIR_FSTCLUSLO 26 | ||
117 | #define FATDIR_FILESIZE 28 | ||
118 | |||
119 | struct fat_direntry | ||
120 | { | ||
121 | unsigned char name[12]; /* Name plus \0 */ | ||
122 | unsigned short attr; /* Attributes */ | ||
123 | unsigned char crttimetenth; /* Millisecond creation | ||
124 | time stamp (0-199) */ | ||
125 | unsigned short crttime; /* Creation time */ | ||
126 | unsigned short crtdate; /* Creation date */ | ||
127 | unsigned short lstaccdate; /* Last access date */ | ||
128 | unsigned short fstclushi; /* High word of first cluster | ||
129 | (0 for FAT12/16) */ | ||
130 | unsigned short wrttime; /* Last write time */ | ||
131 | unsigned short wrtdate; /* Last write date */ | ||
132 | unsigned short fstcluslo; /* Low word of first cluster */ | ||
133 | unsigned int filesize; /* File size in bytes */ | ||
134 | }; | ||
135 | |||
136 | struct fat_context | ||
137 | { | ||
138 | unsigned int curr_dir_sec; /* Current directory sector */ | ||
139 | |||
140 | }; | ||
141 | |||
142 | struct disk_info | ||
143 | { | ||
144 | int num_sectors; | ||
145 | int sec_per_track; | ||
146 | int num_heads; | ||
147 | unsigned int hidden_sectors; | ||
148 | }; | ||
149 | 88 | ||
150 | struct fat_dirent | 89 | struct fat_dirent |
151 | { | 90 | { |
152 | int entry; | 91 | int entry; |
153 | unsigned int cached_sec; | 92 | unsigned int cached_sec; |
154 | unsigned int num_sec; | 93 | unsigned int num_sec; |
155 | char cached_buf[BLOCK_SIZE]; | 94 | char cached_buf[BLOCK_SIZE]; |
156 | }; | 95 | }; |
157 | 96 | ||
158 | extern int fat_create_file(struct bpb *bpb, | 97 | extern int fat_create_file(struct bpb *bpb, |
159 | unsigned int currdir, | 98 | unsigned int currdir, |
160 | char *name); | 99 | char *name); |
100 | extern int fat_create_dir(struct bpb *bpb, | ||
101 | unsigned int currdir, | ||
102 | char *name); | ||
161 | extern int fat_opendir(struct bpb *bpb, | 103 | extern int fat_opendir(struct bpb *bpb, |
162 | struct fat_dirent *ent, | 104 | struct fat_dirent *ent, |
163 | unsigned int currdir); | 105 | unsigned int currdir); |