diff options
author | Björn Stenberg <bjorn@haxx.se> | 2002-04-26 16:44:58 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2002-04-26 16:44:58 +0000 |
commit | 1dff4b65f725c2174c65698e498b1d58d61e3968 (patch) | |
tree | 14403dd8415cc0fd6389bb873ae166ded43dd6ee /firmware/drivers/fat.c | |
parent | cfc2bbeef28cfd0159d59ef813ac2a7b956f13a8 (diff) | |
download | rockbox-1dff4b65f725c2174c65698e498b1d58d61e3968.tar.gz rockbox-1dff4b65f725c2174c65698e498b1d58d61e3968.zip |
FAT update
Added fat test code
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@254 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers/fat.c')
-rw-r--r-- | firmware/drivers/fat.c | 570 |
1 files changed, 91 insertions, 479 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index 328428a941..a4cd77dc89 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -30,6 +30,12 @@ | |||
30 | #include "fat.h" | 30 | #include "fat.h" |
31 | #include "ata.h" | 31 | #include "ata.h" |
32 | 32 | ||
33 | #define BYTES2INT16(array,pos) \ | ||
34 | (array[pos] | (array[pos+1] << 8 )) | ||
35 | #define BYTES2INT32(array,pos) \ | ||
36 | (array[pos] | (array[pos+1] << 8 ) | \ | ||
37 | (array[pos+2] << 16 ) | (array[pos+3] << 24 )) | ||
38 | |||
33 | #define NUM_ROOT_DIR_ENTRIES 512 | 39 | #define NUM_ROOT_DIR_ENTRIES 512 |
34 | #define NUM_FATS 2 | 40 | #define NUM_FATS 2 |
35 | #define NUM_RESERVED_SECTORS 1 | 41 | #define NUM_RESERVED_SECTORS 1 |
@@ -41,33 +47,6 @@ struct dsksz2secperclus | |||
41 | unsigned int sec_per_cluster; | 47 | unsigned int sec_per_cluster; |
42 | }; | 48 | }; |
43 | 49 | ||
44 | /* | ||
45 | ** This is the table for FAT16 drives. NOTE that this table includes | ||
46 | ** entries for disk sizes larger than 512 MB even though typically | ||
47 | ** only the entries for disks < 512 MB in size are used. | ||
48 | ** The way this table is accessed is to look for the first entry | ||
49 | ** in the table for which the disk size is less than or equal | ||
50 | ** to the DiskSize field in that table entry. For this table to | ||
51 | ** work properly BPB_RsvdSecCnt must be 1, BPB_NumFATs | ||
52 | ** must be 2, and BPB_RootEntCnt must be 512. Any of these values | ||
53 | ** being different may require the first table entries DiskSize value | ||
54 | ** to be changed otherwise the cluster count may be to low for FAT16. | ||
55 | */ | ||
56 | struct dsksz2secperclus dsk_table_fat16 [] = | ||
57 | { | ||
58 | { 8400, 0}, /* disks up to 4.1 MB, the 0 value for SecPerClusVal | ||
59 | trips an error */ | ||
60 | { 32680, 2}, /* disks up to 16 MB, 1k cluster */ | ||
61 | { 262144, 4}, /* disks up to 128 MB, 2k cluster */ | ||
62 | { 524288, 8}, /* disks up to 256 MB, 4k cluster */ | ||
63 | { 1048576, 16}, /* disks up to 512 MB, 8k cluster */ | ||
64 | /* The entries after this point are not used unless FAT16 is forced */ | ||
65 | { 2097152, 32}, /* disks up to 1 GB, 16k cluster */ | ||
66 | { 4194304, 64}, /* disks up to 2 GB, 32k cluster */ | ||
67 | { 0xFFFFFFFF, 0} /* any disk greater than 2GB, | ||
68 | 0 value for SecPerClusVal trips an error */ | ||
69 | }; | ||
70 | |||
71 | int fat_num_rootdir_sectors(struct bpb *bpb); | 50 | int fat_num_rootdir_sectors(struct bpb *bpb); |
72 | int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster); | 51 | int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster); |
73 | int fat_get_fatsize(struct bpb* bpb); | 52 | int fat_get_fatsize(struct bpb* bpb); |
@@ -84,7 +63,6 @@ int fat_update_entry(struct bpb *bpb, int entry, unsigned int val); | |||
84 | unsigned int fat_getcurrdostime(unsigned short *dosdate, | 63 | unsigned int fat_getcurrdostime(unsigned short *dosdate, |
85 | unsigned short *dostime, | 64 | unsigned short *dostime, |
86 | unsigned char *dostenth); | 65 | unsigned char *dostenth); |
87 | int fat_create_root_dir(struct bpb *bpb); | ||
88 | int fat_create_dos_name(unsigned char *name, unsigned char *newname); | 66 | int fat_create_dos_name(unsigned char *name, unsigned char *newname); |
89 | int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name); | 67 | int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name); |
90 | 68 | ||
@@ -94,14 +72,10 @@ char current_directory[256] = "\\"; | |||
94 | struct bpb *global_bpb; | 72 | struct bpb *global_bpb; |
95 | struct disk_info di; | 73 | struct disk_info di; |
96 | 74 | ||
97 | extern int yyparse(void); | ||
98 | |||
99 | 75 | ||
100 | #ifdef TEST_FAT | 76 | #ifdef TEST_FAT |
101 | void prompt(void) | 77 | |
102 | { | 78 | #include "debug.h" |
103 | printf("C:%s>", current_directory); | ||
104 | } | ||
105 | 79 | ||
106 | int main(int argc, char *argv[]) | 80 | int main(int argc, char *argv[]) |
107 | { | 81 | { |
@@ -110,27 +84,18 @@ int main(int argc, char *argv[]) | |||
110 | memset(fat_cache, 0, sizeof(fat_cache)); | 84 | memset(fat_cache, 0, sizeof(fat_cache)); |
111 | memset(fat_cache_dirty, 0, sizeof(fat_cache_dirty)); | 85 | memset(fat_cache_dirty, 0, sizeof(fat_cache_dirty)); |
112 | 86 | ||
113 | disk_init(NUM_BLOCKS); | ||
114 | |||
115 | di.num_sectors = NUM_BLOCKS; | 87 | di.num_sectors = NUM_BLOCKS; |
116 | di.sec_per_track = 40; | 88 | di.sec_per_track = 40; |
117 | di.num_heads = 250; | 89 | di.num_heads = 250; |
118 | di.hidden_sectors = 0; | 90 | di.hidden_sectors = 0; |
119 | 91 | ||
120 | if(read_disk("diskdump.dmp") < 0) | 92 | if(ata_init()) |
121 | { | ||
122 | printf("*** Warning! The disk is uninitialized\n"); | 93 | printf("*** Warning! The disk is uninitialized\n"); |
123 | } | ||
124 | else | 94 | else |
125 | { | ||
126 | fat_get_bpb(&bpb); | 95 | fat_get_bpb(&bpb); |
127 | } | ||
128 | 96 | ||
129 | global_bpb = &bpb; | 97 | global_bpb = &bpb; |
130 | prompt(); | 98 | dbg_console(&bpb); |
131 | yyparse(); | ||
132 | |||
133 | dump_disk("diskdump.dmp"); | ||
134 | return 0; | 99 | return 0; |
135 | } | 100 | } |
136 | #endif | 101 | #endif |
@@ -148,28 +113,6 @@ int fat_sec2cluster(struct bpb *bpb, unsigned int sec) | |||
148 | return ((sec - first_sec) / bpb->bpb_secperclus) + 2; | 113 | return ((sec - first_sec) / bpb->bpb_secperclus) + 2; |
149 | } | 114 | } |
150 | 115 | ||
151 | int fat_last_cluster_in_chain(struct bpb *bpb, unsigned int cluster) | ||
152 | { | ||
153 | int iseof = 0; | ||
154 | |||
155 | switch(bpb->fat_type) | ||
156 | { | ||
157 | case FATTYPE_FAT12: | ||
158 | if(cluster >= 0x0ff8) | ||
159 | iseof = 1; | ||
160 | break; | ||
161 | case FATTYPE_FAT16: | ||
162 | if(cluster >= 0xfff8) | ||
163 | iseof = 1; | ||
164 | break; | ||
165 | case FATTYPE_FAT32: | ||
166 | if(cluster >= 0x0ffffff8) | ||
167 | iseof = 1; | ||
168 | break; | ||
169 | } | ||
170 | return iseof; | ||
171 | } | ||
172 | |||
173 | int fat_cluster2sec(struct bpb *bpb, unsigned int cluster) | 116 | int fat_cluster2sec(struct bpb *bpb, unsigned int cluster) |
174 | { | 117 | { |
175 | int max_cluster = (fat_get_totsec(bpb) - fat_first_data_sector(bpb)) / | 118 | int max_cluster = (fat_get_totsec(bpb) - fat_first_data_sector(bpb)) / |
@@ -214,7 +157,7 @@ int fat_get_totsec(struct bpb* bpb) | |||
214 | 157 | ||
215 | int fat_get_rootdir_sector(struct bpb *bpb) | 158 | int fat_get_rootdir_sector(struct bpb *bpb) |
216 | { | 159 | { |
217 | return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fat_get_fatsize(bpb); | 160 | return bpb->bpb_rootclus; |
218 | } | 161 | } |
219 | 162 | ||
220 | int fat_first_data_sector(struct bpb* bpb) | 163 | int fat_first_data_sector(struct bpb* bpb) |
@@ -229,118 +172,6 @@ int fat_first_data_sector(struct bpb* bpb) | |||
229 | return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz + rootdirsectors; | 172 | return bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz + rootdirsectors; |
230 | } | 173 | } |
231 | 174 | ||
232 | int fat_format(struct disk_info *di, char *vol_name) | ||
233 | { | ||
234 | unsigned char buf[BLOCK_SIZE]; | ||
235 | struct bpb bpb; | ||
236 | unsigned int root_dir_sectors; | ||
237 | unsigned int tmp1, tmp2; | ||
238 | int sec_per_clus = 0; | ||
239 | int fat_size; | ||
240 | int i = 0; | ||
241 | int err; | ||
242 | |||
243 | while(di->num_sectors > dsk_table_fat16[i].disk_size) | ||
244 | { | ||
245 | i++; | ||
246 | } | ||
247 | |||
248 | sec_per_clus = dsk_table_fat16[i].sec_per_cluster; | ||
249 | |||
250 | if(sec_per_clus == 0) | ||
251 | { | ||
252 | fprintf(stderr, "fat_format() - Bad disk size (%u)\n", | ||
253 | di->num_sectors); | ||
254 | return -1; | ||
255 | } | ||
256 | |||
257 | /* First calculate how many sectors we need for | ||
258 | the root directory */ | ||
259 | root_dir_sectors = ((NUM_ROOT_DIR_ENTRIES * 32) + | ||
260 | (BLOCK_SIZE - 1)) / BLOCK_SIZE; | ||
261 | |||
262 | /* Now calculate the FAT size */ | ||
263 | tmp1 = di->num_sectors - (NUM_RESERVED_SECTORS + root_dir_sectors); | ||
264 | tmp2 = (256 * sec_per_clus) + NUM_FATS; | ||
265 | |||
266 | fat_size = (tmp1 + (tmp2 - 1)) / tmp2; | ||
267 | |||
268 | /* Now create the BPB. We must be careful, so we really make | ||
269 | it little endian. */ | ||
270 | memset(buf, 0xff, BLOCK_SIZE); | ||
271 | |||
272 | strncpy(&buf[BS_OEMNAME], "MSWIN4.1", 8); | ||
273 | buf[BPB_BYTSPERSEC] = BLOCK_SIZE & 0xff; | ||
274 | buf[BPB_BYTSPERSEC+1] = BLOCK_SIZE >> 8; | ||
275 | buf[BPB_SECPERCLUS] = sec_per_clus; | ||
276 | buf[BPB_RSVDSECCNT] = 1; | ||
277 | buf[BPB_RSVDSECCNT+1] = 0; | ||
278 | buf[BPB_NUMFATS] = 2; | ||
279 | buf[BPB_ROOTENTCNT] = NUM_ROOT_DIR_ENTRIES & 0xff; | ||
280 | buf[BPB_ROOTENTCNT+1] = NUM_ROOT_DIR_ENTRIES >> 8; | ||
281 | buf[BPB_TOTSEC16] = di->num_sectors & 0xff; | ||
282 | buf[BPB_TOTSEC16+1] = di->num_sectors >> 8; | ||
283 | buf[BPB_MEDIA] = 0xf0; | ||
284 | buf[BPB_FATSZ16] = fat_size & 0xff; | ||
285 | buf[BPB_FATSZ16+1] = fat_size >> 8; | ||
286 | buf[BPB_SECPERTRK] = di->sec_per_track & 0xff; | ||
287 | buf[BPB_SECPERTRK+1] = di->sec_per_track >> 8; | ||
288 | buf[BPB_NUMHEADS] = di->num_heads & 0xff; | ||
289 | buf[BPB_NUMHEADS+1] = di->num_heads >> 8; | ||
290 | buf[BPB_HIDDSEC] = di->hidden_sectors & 0xff; | ||
291 | buf[BPB_HIDDSEC+1] = (di->hidden_sectors >> 8) & 0xff; | ||
292 | buf[BPB_HIDDSEC+2] = (di->hidden_sectors >> 16) & 0xff; | ||
293 | buf[BPB_HIDDSEC+3] = (di->hidden_sectors >> 24) & 0xff; | ||
294 | buf[BPB_TOTSEC32] = 0; | ||
295 | buf[BPB_TOTSEC32+1] = 0; | ||
296 | buf[BPB_TOTSEC32+2] = 0; | ||
297 | buf[BPB_TOTSEC32+3] = 0; | ||
298 | |||
299 | buf[BS_DRVNUM] = 0; | ||
300 | buf[BS_RESERVED1] = 0; | ||
301 | buf[BS_BOOTSIG] = 0x29; | ||
302 | buf[BS_VOLID] = 0x78; | ||
303 | buf[BS_VOLID+1] = 0x56; | ||
304 | buf[BS_VOLID+2] = 0x34; | ||
305 | buf[BS_VOLID+3] = 0x12; | ||
306 | memset(&buf[BS_VOLLAB], ' ', 11); | ||
307 | strncpy(&buf[BS_VOLLAB], vol_name, MIN(11, strlen(vol_name)); | ||
308 | strncpy(&buf[BS_FILSYSTYPE], "FAT16 ", 8); | ||
309 | |||
310 | /* The final signature */ | ||
311 | buf[BPB_LAST_WORD] = 0x55; | ||
312 | buf[BPB_LAST_WORD+1] = 0xaa; | ||
313 | |||
314 | /* Now write the sector to disk */ | ||
315 | err = ata_write_sectors(0,1,buf); | ||
316 | if(err) | ||
317 | { | ||
318 | fprintf(stderr, "fat_format() - Couldn't write BSB (error code %i)\n", | ||
319 | err); | ||
320 | return -1; | ||
321 | } | ||
322 | |||
323 | if(fat_get_bpb(&bpb) < 0) | ||
324 | { | ||
325 | fprintf(stderr, "fat_format() - Couldn't read BPB\n"); | ||
326 | return -1; | ||
327 | } | ||
328 | |||
329 | if(fat_create_fat(&bpb) < 0) | ||
330 | { | ||
331 | fprintf(stderr, "fat_format() - Couldn't create FAT\n"); | ||
332 | return -1; | ||
333 | } | ||
334 | |||
335 | if(fat_create_root_dir(&bpb) < 0) | ||
336 | { | ||
337 | fprintf(stderr, "fat_format() - Couldn't write root dir sector\n"); | ||
338 | return -1; | ||
339 | } | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | int fat_get_bpb(struct bpb *bpb) | 175 | int fat_get_bpb(struct bpb *bpb) |
345 | { | 176 | { |
346 | unsigned char buf[BLOCK_SIZE]; | 177 | unsigned char buf[BLOCK_SIZE]; |
@@ -365,40 +196,34 @@ int fat_get_bpb(struct bpb *bpb) | |||
365 | strncpy(bpb->bs_oemname, &buf[BS_OEMNAME], 8); | 196 | strncpy(bpb->bs_oemname, &buf[BS_OEMNAME], 8); |
366 | bpb->bs_oemname[8] = 0; | 197 | bpb->bs_oemname[8] = 0; |
367 | 198 | ||
368 | bpb->bpb_bytspersec = buf[BPB_BYTSPERSEC] | (buf[BPB_BYTSPERSEC+1] << 8); | 199 | bpb->bpb_bytspersec = BYTES2INT16(buf,BPB_BYTSPERSEC); |
369 | bpb->bpb_secperclus = buf[BPB_SECPERCLUS]; | 200 | bpb->bpb_secperclus = buf[BPB_SECPERCLUS]; |
370 | bpb->bpb_rsvdseccnt = buf[BPB_RSVDSECCNT] | (buf[BPB_RSVDSECCNT+1] << 8); | 201 | bpb->bpb_rsvdseccnt = BYTES2INT16(buf,BPB_RSVDSECCNT); |
371 | bpb->bpb_numfats = buf[BPB_NUMFATS]; | 202 | bpb->bpb_numfats = buf[BPB_NUMFATS]; |
372 | bpb->bpb_rootentcnt = buf[BPB_ROOTENTCNT] | (buf[BPB_ROOTENTCNT+1] << 8); | 203 | bpb->bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT); |
373 | bpb->bpb_totsec16 = buf[BPB_TOTSEC16] | (buf[BPB_TOTSEC16+1] << 8); | 204 | bpb->bpb_totsec16 = BYTES2INT16(buf,BPB_TOTSEC16); |
374 | bpb->bpb_media = buf[BPB_MEDIA]; | 205 | bpb->bpb_media = buf[BPB_MEDIA]; |
375 | bpb->bpb_fatsz16 = buf[BPB_FATSZ16] | (buf[BPB_FATSZ16+1] << 8); | 206 | bpb->bpb_fatsz16 = BYTES2INT16(buf,BPB_FATSZ16); |
376 | bpb->bpb_secpertrk = buf[BPB_SECPERTRK] | (buf[BPB_SECPERTRK+1] << 8); | 207 | bpb->bpb_secpertrk = BYTES2INT16(buf,BPB_SECPERTRK); |
377 | bpb->bpb_numheads = buf[BPB_NUMHEADS] | (buf[BPB_NUMHEADS+1] << 8); | 208 | bpb->bpb_numheads = BYTES2INT16(buf,BPB_NUMHEADS); |
378 | bpb->bpb_hiddsec = buf[BPB_HIDDSEC] | (buf[BPB_HIDDSEC+1] << 8) | | 209 | bpb->bpb_hiddsec = BYTES2INT32(buf,BPB_HIDDSEC); |
379 | (buf[BPB_HIDDSEC+2] << 16) | (buf[BPB_HIDDSEC+3] << 24); | 210 | bpb->bpb_totsec32 = BYTES2INT32(buf,BPB_TOTSEC32); |
380 | bpb->bpb_totsec32 = buf[BPB_TOTSEC32] | (buf[BPB_TOTSEC32+1] << 8) | | 211 | bpb->bs_drvnum = buf[BS_DRVNUM]; |
381 | (buf[BPB_TOTSEC32+2] << 16) | (buf[BPB_TOTSEC32+3] << 24); | 212 | bpb->bs_bootsig = buf[BS_BOOTSIG]; |
382 | 213 | bpb->bpb_fatsz32 = BYTES2INT32(buf,BPB_FATSZ32); | |
383 | bpb->bs_drvnum = buf[BS_DRVNUM]; | 214 | bpb->last_word = BYTES2INT16(buf,BPB_LAST_WORD); |
384 | bpb->bs_bootsig = buf[BS_BOOTSIG]; | 215 | |
385 | if(bpb->bs_bootsig == 0x29) | 216 | if(bpb->bs_bootsig == 0x29) |
386 | { | 217 | { |
387 | bpb->bs_volid = buf[BS_VOLID] | (buf[BS_VOLID+1] << 8) | | 218 | bpb->bs_volid = BYTES2INT32(buf,BS_VOLID); |
388 | (buf[BS_VOLID+2] << 16) | (buf[BS_VOLID+3] << 24); | ||
389 | strncpy(bpb->bs_vollab, &buf[BS_VOLLAB], 11); | 219 | strncpy(bpb->bs_vollab, &buf[BS_VOLLAB], 11); |
390 | strncpy(bpb->bs_filsystype, &buf[BS_FILSYSTYPE], 8); | 220 | strncpy(bpb->bs_filsystype, &buf[BS_FILSYSTYPE], 8); |
391 | } | 221 | } |
392 | 222 | ||
393 | bpb->bpb_fatsz32 = (buf[BPB_FATSZ32] + (buf[BPB_FATSZ32+1] << 8)) | | ||
394 | (buf[BPB_FATSZ32+2] << 16) | (buf[BPB_FATSZ32+3] << 24); | ||
395 | |||
396 | bpb->last_word = buf[BPB_LAST_WORD] | (buf[BPB_LAST_WORD+1] << 8); | ||
397 | |||
398 | /* Determine FAT type */ | 223 | /* Determine FAT type */ |
399 | fatsz = fat_get_fatsize(bpb); | 224 | fatsz = fat_get_fatsize(bpb); |
400 | 225 | ||
401 | if(bpb->bpb_totsec16 != 0) | 226 | if (bpb->bpb_totsec16 != 0) |
402 | totsec = bpb->bpb_totsec16; | 227 | totsec = bpb->bpb_totsec16; |
403 | else | 228 | else |
404 | totsec = bpb->bpb_totsec32; | 229 | totsec = bpb->bpb_totsec32; |
@@ -408,23 +233,30 @@ int fat_get_bpb(struct bpb *bpb) | |||
408 | rootdirsectors); | 233 | rootdirsectors); |
409 | countofclusters = datasec / bpb->bpb_secperclus; | 234 | countofclusters = datasec / bpb->bpb_secperclus; |
410 | 235 | ||
411 | if(countofclusters < 4085) | 236 | |
412 | { | 237 | /* Determining FAT type: |
413 | bpb->fat_type = FATTYPE_FAT12; | 238 | |
414 | } | 239 | This is the "proper way" to do it: |
415 | else | 240 | |
416 | { | 241 | if (countofclusters < 4085) |
417 | if(countofclusters < 65525) | 242 | fat12 |
418 | { | 243 | else |
419 | bpb->fat_type = FATTYPE_FAT16; | 244 | if (countofclusters < 65525) |
420 | } | 245 | fat16 |
421 | else | 246 | else |
422 | { | 247 | fat32 |
423 | bpb->fat_type = FATTYPE_FAT32; | 248 | */ |
424 | } | 249 | |
250 | /* | ||
251 | This is the "real world way" to do it | ||
252 | (since not all FAT32 partitions have >65524 clusters) | ||
253 | */ | ||
254 | if ( bpb->bpb_fatsz16 ) { | ||
255 | printf("This is not FAT32. Go away!\n"); | ||
256 | return -1; | ||
425 | } | 257 | } |
426 | 258 | ||
427 | if(fat_bpb_is_sane(bpb) < 0) | 259 | if (fat_bpb_is_sane(bpb) < 0) |
428 | { | 260 | { |
429 | fprintf(stderr, "fat_get_bpb() - BPB is not sane\n"); | 261 | fprintf(stderr, "fat_get_bpb() - BPB is not sane\n"); |
430 | return -1; | 262 | return -1; |
@@ -435,12 +267,6 @@ int fat_get_bpb(struct bpb *bpb) | |||
435 | 267 | ||
436 | int fat_bpb_is_sane(struct bpb *bpb) | 268 | int fat_bpb_is_sane(struct bpb *bpb) |
437 | { | 269 | { |
438 | if(bpb->fat_type == FATTYPE_FAT32) | ||
439 | { | ||
440 | fprintf(stderr, "fat_bpb_is_sane() - Error: FAT32 not supported\n"); | ||
441 | return -1; | ||
442 | } | ||
443 | |||
444 | if(bpb->bpb_bytspersec != 512) | 270 | if(bpb->bpb_bytspersec != 512) |
445 | { | 271 | { |
446 | fprintf(stderr, | 272 | fprintf(stderr, |
@@ -504,75 +330,6 @@ int fat_bpb_is_sane(struct bpb *bpb) | |||
504 | return 0; | 330 | return 0; |
505 | } | 331 | } |
506 | 332 | ||
507 | int fat_create_fat(struct bpb* bpb) | ||
508 | { | ||
509 | unsigned char *sec; | ||
510 | int i; | ||
511 | int secnum = 0; | ||
512 | int fatsz; | ||
513 | |||
514 | if(fat_bpb_is_sane(bpb) < 0) | ||
515 | { | ||
516 | fprintf(stderr, "fat_create_fat() - BPB is not sane\n"); | ||
517 | return -1; | ||
518 | } | ||
519 | |||
520 | if(bpb->bpb_fatsz16 != 0) | ||
521 | fatsz = bpb->bpb_fatsz16; | ||
522 | else | ||
523 | fatsz = bpb->bpb_fatsz32; | ||
524 | |||
525 | sec = fat_cache_fat_sector(bpb, secnum); | ||
526 | if(!sec) | ||
527 | { | ||
528 | fprintf(stderr, "fat_create_fat() - Couldn't cache fat sector" | ||
529 | " (%d)\n", secnum); | ||
530 | return -1; | ||
531 | } | ||
532 | |||
533 | fat_cache_dirty[secnum] = 1; | ||
534 | |||
535 | /* First entry should have the media type in the | ||
536 | low byte and the rest of the bits set to 1. | ||
537 | The second should be the EOC mark. */ | ||
538 | memset(sec, 0, BLOCK_SIZE); | ||
539 | sec[0] = bpb->bpb_media; | ||
540 | if(bpb->fat_type == FATTYPE_FAT12) | ||
541 | { | ||
542 | sec[1] = 0xff; | ||
543 | sec[2] = 0xff; | ||
544 | } | ||
545 | if(bpb->fat_type == FATTYPE_FAT16) | ||
546 | { | ||
547 | sec[0] = bpb->bpb_media; | ||
548 | sec[1] = 0xff; | ||
549 | sec[2] = 0xff; | ||
550 | sec[3] = 0xff; | ||
551 | } | ||
552 | secnum++; | ||
553 | |||
554 | for(i = 0; i < fatsz - 1;i++) | ||
555 | { | ||
556 | sec = fat_cache_fat_sector(bpb, secnum); | ||
557 | if(!sec) | ||
558 | { | ||
559 | fprintf(stderr, "fat_create_fat() - Couldn't cache fat sector" | ||
560 | " (%d)\n", i); | ||
561 | return -1; | ||
562 | } | ||
563 | fat_cache_dirty[secnum] = 1; | ||
564 | secnum++; | ||
565 | memset(sec, 0, BLOCK_SIZE); | ||
566 | } | ||
567 | |||
568 | if(fat_flush_fat(bpb) < 0) | ||
569 | { | ||
570 | fprintf(stderr, "fat_create_fat() - Couldn't flush fat\n"); | ||
571 | return -1; | ||
572 | } | ||
573 | return 0; | ||
574 | } | ||
575 | |||
576 | int fat_dbg_read_block(char *name, unsigned char *buf) | 333 | int fat_dbg_read_block(char *name, unsigned char *buf) |
577 | { | 334 | { |
578 | FILE *f; | 335 | FILE *f; |
@@ -628,7 +385,6 @@ unsigned char *fat_cache_fat_sector(struct bpb *bpb, int secnum) | |||
628 | int fat_update_entry(struct bpb *bpb, int entry, unsigned int val) | 385 | int fat_update_entry(struct bpb *bpb, int entry, unsigned int val) |
629 | { | 386 | { |
630 | unsigned char *sec; | 387 | unsigned char *sec; |
631 | unsigned char *sec2; | ||
632 | int fatsz; | 388 | int fatsz; |
633 | int fatoffset; | 389 | int fatoffset; |
634 | int thisfatsecnum; | 390 | int thisfatsecnum; |
@@ -636,18 +392,7 @@ int fat_update_entry(struct bpb *bpb, int entry, unsigned int val) | |||
636 | unsigned int tmp; | 392 | unsigned int tmp; |
637 | 393 | ||
638 | fatsz = fat_get_fatsize(bpb); | 394 | fatsz = fat_get_fatsize(bpb); |
639 | 395 | fatoffset = entry * 4; | |
640 | if(bpb->fat_type == FATTYPE_FAT12) | ||
641 | { | ||
642 | fatoffset = entry + (entry / 2); | ||
643 | } | ||
644 | else | ||
645 | { | ||
646 | if(bpb->fat_type == FATTYPE_FAT16) | ||
647 | fatoffset = entry * 2; | ||
648 | else | ||
649 | fatoffset = entry * 4; | ||
650 | } | ||
651 | thisfatsecnum = fatoffset / bpb->bpb_bytspersec; | 396 | thisfatsecnum = fatoffset / bpb->bpb_bytspersec; |
652 | thisfatentoffset = fatoffset % bpb->bpb_bytspersec; | 397 | thisfatentoffset = fatoffset % bpb->bpb_bytspersec; |
653 | 398 | ||
@@ -662,55 +407,16 @@ int fat_update_entry(struct bpb *bpb, int entry, unsigned int val) | |||
662 | 407 | ||
663 | fat_cache_dirty[thisfatsecnum] = 1; | 408 | fat_cache_dirty[thisfatsecnum] = 1; |
664 | 409 | ||
665 | switch(bpb->fat_type) | 410 | tmp = *(unsigned short *)(&sec[thisfatentoffset]) & 0xf000000; |
666 | { | 411 | val = tmp | (val & 0x0fffffff); |
667 | case FATTYPE_FAT12: | 412 | *(unsigned short *)(&sec[thisfatentoffset]) = val; |
668 | if(thisfatentoffset == bpb->bpb_bytspersec - 1) | 413 | |
669 | { | ||
670 | /* This entry spans a sector boundary. Take care */ | ||
671 | sec2 = fat_cache_fat_sector(bpb, thisfatsecnum + 1); | ||
672 | /* Load the sector if it is not cached */ | ||
673 | if(!sec2) | ||
674 | { | ||
675 | fprintf(stderr, "fat_update_entry() - Could not " | ||
676 | "cache sector %d\n", | ||
677 | thisfatsecnum + 1); | ||
678 | return -1; | ||
679 | } | ||
680 | fat_cache_dirty[thisfatsecnum + 1] = 1; | ||
681 | } | ||
682 | else | ||
683 | { | ||
684 | if(entry & 1) /* Odd entry number? */ | ||
685 | { | ||
686 | tmp = sec[thisfatentoffset] & 0xf0; | ||
687 | sec[thisfatentoffset] = tmp | (val & 0x0f); | ||
688 | sec[thisfatentoffset+1] = (val >> 4) & 0xff; | ||
689 | } | ||
690 | else | ||
691 | { | ||
692 | sec[thisfatentoffset] = val & 0xff; | ||
693 | tmp = sec[thisfatentoffset+1] & 0x0f; | ||
694 | sec[thisfatentoffset+1] = tmp | ((val >> 4) & 0xf0); | ||
695 | } | ||
696 | } | ||
697 | break; | ||
698 | case FATTYPE_FAT16: | ||
699 | *(unsigned short *)(&sec[thisfatentoffset]) = val; | ||
700 | break; | ||
701 | case FATTYPE_FAT32: | ||
702 | tmp = *(unsigned short *)(&sec[thisfatentoffset]) & 0xf000000; | ||
703 | val = tmp | (val & 0x0fffffff); | ||
704 | *(unsigned short *)(&sec[thisfatentoffset]) = val; | ||
705 | break; | ||
706 | } | ||
707 | return 0; | 414 | return 0; |
708 | } | 415 | } |
709 | 416 | ||
710 | int fat_read_entry(struct bpb *bpb, int entry) | 417 | int fat_read_entry(struct bpb *bpb, int entry) |
711 | { | 418 | { |
712 | unsigned char *sec; | 419 | unsigned char *sec; |
713 | unsigned char *sec2; | ||
714 | int fatsz; | 420 | int fatsz; |
715 | int fatoffset; | 421 | int fatoffset; |
716 | int thisfatsecnum; | 422 | int thisfatsecnum; |
@@ -718,18 +424,7 @@ int fat_read_entry(struct bpb *bpb, int entry) | |||
718 | int val = -1; | 424 | int val = -1; |
719 | 425 | ||
720 | fatsz = fat_get_fatsize(bpb); | 426 | fatsz = fat_get_fatsize(bpb); |
721 | 427 | fatoffset = entry * 4; | |
722 | if(bpb->fat_type == FATTYPE_FAT12) | ||
723 | { | ||
724 | fatoffset = entry + (entry / 2); | ||
725 | } | ||
726 | else | ||
727 | { | ||
728 | if(bpb->fat_type == FATTYPE_FAT16) | ||
729 | fatoffset = entry * 2; | ||
730 | else | ||
731 | fatoffset = entry * 4; | ||
732 | } | ||
733 | thisfatsecnum = fatoffset / bpb->bpb_bytspersec; | 428 | thisfatsecnum = fatoffset / bpb->bpb_bytspersec; |
734 | thisfatentoffset = fatoffset % bpb->bpb_bytspersec; | 429 | thisfatentoffset = fatoffset % bpb->bpb_bytspersec; |
735 | 430 | ||
@@ -742,43 +437,7 @@ int fat_read_entry(struct bpb *bpb, int entry) | |||
742 | return -1; | 437 | return -1; |
743 | } | 438 | } |
744 | 439 | ||
745 | switch(bpb->fat_type) | 440 | val = *(unsigned int *)(&sec[thisfatentoffset]); |
746 | { | ||
747 | case FATTYPE_FAT12: | ||
748 | if(thisfatentoffset == bpb->bpb_bytspersec - 1) | ||
749 | { | ||
750 | /* This entry spans a sector boundary. Take care */ | ||
751 | sec2 = fat_cache_fat_sector(bpb, thisfatsecnum + 1); | ||
752 | /* Load the sector if it is not cached */ | ||
753 | if(!sec2) | ||
754 | { | ||
755 | fprintf(stderr, "fat_update_entry() - Could not " | ||
756 | "cache sector %d\n", | ||
757 | thisfatsecnum + 1); | ||
758 | return -1; | ||
759 | } | ||
760 | } | ||
761 | else | ||
762 | { | ||
763 | if(entry & 1) /* Odd entry number? */ | ||
764 | { | ||
765 | val = (sec[thisfatentoffset] & 0x0f) | | ||
766 | (sec[thisfatentoffset+1] << 4); | ||
767 | } | ||
768 | else | ||
769 | { | ||
770 | val = (sec[thisfatentoffset] & 0xff) | | ||
771 | ((sec[thisfatentoffset+1] & 0x0f) << 8); | ||
772 | } | ||
773 | } | ||
774 | break; | ||
775 | case FATTYPE_FAT16: | ||
776 | val = *(unsigned short *)(&sec[thisfatentoffset]); | ||
777 | break; | ||
778 | case FATTYPE_FAT32: | ||
779 | val = *(unsigned int *)(&sec[thisfatentoffset]); | ||
780 | break; | ||
781 | } | ||
782 | return val; | 441 | return val; |
783 | } | 442 | } |
784 | 443 | ||
@@ -843,67 +502,12 @@ unsigned int fat_getcurrdostime(unsigned short *dosdate, | |||
843 | return 0; | 502 | return 0; |
844 | } | 503 | } |
845 | 504 | ||
846 | int fat_create_root_dir(struct bpb *bpb) | ||
847 | { | ||
848 | unsigned char buf[BLOCK_SIZE]; | ||
849 | int fatsz; | ||
850 | int sec; | ||
851 | int res; | ||
852 | int i; | ||
853 | unsigned short dosdate; | ||
854 | unsigned short dostime; | ||
855 | unsigned char dostenth; | ||
856 | int num_root_sectors; | ||
857 | |||
858 | fatsz = fat_get_fatsize(bpb); | ||
859 | |||
860 | sec = bpb->bpb_rsvdseccnt + bpb->bpb_numfats * fatsz; | ||
861 | |||
862 | memset(buf, 0, sizeof(buf)); | ||
863 | |||
864 | strncpy(&buf[FATDIR_NAME], bpb->bs_vollab, 11); | ||
865 | buf[FATDIR_ATTR] = FAT_ATTR_VOLUME_ID; | ||
866 | buf[FATDIR_NTRES] = 0; | ||
867 | |||
868 | fat_getcurrdostime(&dosdate, &dostime, &dostenth); | ||
869 | buf[FATDIR_WRTDATE] = dosdate & 0xff; | ||
870 | buf[FATDIR_WRTDATE+1] = dosdate >> 8; | ||
871 | buf[FATDIR_WRTTIME] = dostime & 0xff; | ||
872 | buf[FATDIR_WRTTIME+1] = dostime >> 8; | ||
873 | |||
874 | printf("Writing rootdir to sector %d...\n", sec); | ||
875 | |||
876 | res = ata_write_sectors(sec,1,buf); | ||
877 | if(res) | ||
878 | { | ||
879 | fprintf(stderr, "fat_create_root_dir() - Couldn't write sector (%d)\n", | ||
880 | sec); | ||
881 | return -1; | ||
882 | } | ||
883 | |||
884 | printf("Clearing the rest of the root dir.\n"); | ||
885 | sec++; | ||
886 | num_root_sectors = bpb->bpb_rootentcnt * 32 / bpb->bpb_bytspersec; | ||
887 | memset(buf, 0, BLOCK_SIZE); | ||
888 | |||
889 | for(i = 1;i < num_root_sectors;i++) | ||
890 | { | ||
891 | if(ata_write_sectors(sec++,1,buf)) | ||
892 | { | ||
893 | fprintf(stderr, "fat_create_root_dir() - " | ||
894 | " Couldn't write sector (%d)\n", sec); | ||
895 | return -1; | ||
896 | } | ||
897 | } | ||
898 | |||
899 | return 0; | ||
900 | } | ||
901 | |||
902 | int fat_get_next_cluster(struct bpb *bpb, unsigned int cluster) | 505 | int fat_get_next_cluster(struct bpb *bpb, unsigned int cluster) |
903 | { | 506 | { |
904 | int next_cluster = fat_read_entry(bpb, cluster); | 507 | int next_cluster = fat_read_entry(bpb, cluster); |
905 | 508 | ||
906 | if(fat_last_cluster_in_chain(bpb, next_cluster)) | 509 | /* is this last cluster in chain? */ |
510 | if ( next_cluster >= 0x0ffffff8 ) | ||
907 | return 0; | 511 | return 0; |
908 | else | 512 | else |
909 | return next_cluster; | 513 | return next_cluster; |
@@ -1198,22 +802,26 @@ int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name) | |||
1198 | return err; | 802 | return err; |
1199 | } | 803 | } |
1200 | 804 | ||
1201 | void fat_fill_direntry(struct fat_direntry *de, char *buf) | 805 | int fat_parse_direntry(struct fat_direntry *de, char *buf) |
1202 | { | 806 | { |
1203 | memset(de, 0, sizeof(struct fat_direntry)); | 807 | /* is this a long filename entry? */ |
808 | if ( ( buf[FATDIR_ATTR] & FAT_ATTR_LONG_NAME_MASK ) == | ||
809 | FAT_ATTR_LONG_NAME ) | ||
810 | { | ||
811 | return 0; | ||
812 | } | ||
1204 | 813 | ||
1205 | strncpy(de->name, &buf[FATDIR_NAME], 11); | 814 | memset(de, 0, sizeof(struct fat_direntry)); |
1206 | de->attr = buf[FATDIR_ATTR]; | 815 | de->attr = buf[FATDIR_ATTR]; |
1207 | de->crttimetenth = buf[FATDIR_CRTTIMETENTH]; | 816 | de->crttimetenth = buf[FATDIR_CRTTIMETENTH]; |
1208 | de->crtdate = buf[FATDIR_CRTDATE] | (buf[FATDIR_CRTDATE+1] << 8); | 817 | de->crtdate = BYTES2INT16(buf,FATDIR_CRTDATE); |
1209 | de->crttime = buf[FATDIR_CRTTIME] | (buf[FATDIR_CRTTIME+1] << 8); | 818 | de->crttime = BYTES2INT16(buf,FATDIR_CRTTIME); |
1210 | de->wrtdate = buf[FATDIR_WRTDATE] | (buf[FATDIR_WRTDATE+1] << 8); | 819 | de->wrtdate = BYTES2INT16(buf,FATDIR_WRTDATE); |
1211 | de->wrttime = buf[FATDIR_WRTTIME] | (buf[FATDIR_WRTTIME+1] << 8); | 820 | de->wrttime = BYTES2INT16(buf,FATDIR_WRTTIME); |
1212 | 821 | de->filesize = BYTES2INT32(buf,FATDIR_FILESIZE); | |
1213 | de->filesize = buf[FATDIR_FILESIZE] | | 822 | strncpy(de->name, &buf[FATDIR_NAME], 11); |
1214 | (buf[FATDIR_FILESIZE+1] << 8) | | 823 | |
1215 | (buf[FATDIR_FILESIZE+2] << 16) | | 824 | return 1; |
1216 | (buf[FATDIR_FILESIZE+3] << 24); | ||
1217 | } | 825 | } |
1218 | 826 | ||
1219 | int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir) | 827 | int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir) |
@@ -1246,8 +854,9 @@ int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir) | |||
1246 | return 0; | 854 | return 0; |
1247 | } | 855 | } |
1248 | 856 | ||
1249 | int fat_getnext(struct bpb *bpb, struct fat_dirent *ent, | 857 | int fat_getnext(struct bpb *bpb, |
1250 | struct fat_direntry *entry) | 858 | struct fat_dirent *ent, |
859 | struct fat_direntry *entry) | ||
1251 | { | 860 | { |
1252 | int done = 0; | 861 | int done = 0; |
1253 | int i; | 862 | int i; |
@@ -1261,18 +870,17 @@ int fat_getnext(struct bpb *bpb, struct fat_dirent *ent, | |||
1261 | { | 870 | { |
1262 | firstbyte = ent->cached_buf[i*32]; | 871 | firstbyte = ent->cached_buf[i*32]; |
1263 | if(firstbyte == 0xe5) | 872 | if(firstbyte == 0xe5) |
1264 | { | ||
1265 | continue; | 873 | continue; |
1266 | } | ||
1267 | 874 | ||
1268 | if(firstbyte == 0) | 875 | if(firstbyte == 0) { |
1269 | { | 876 | printf("Firstbyte == 0\n"); |
1270 | return -1; | 877 | return -1; |
1271 | } | 878 | } |
1272 | 879 | ||
1273 | fat_fill_direntry(entry, &ent->cached_buf[i*32]); | 880 | if ( fat_parse_direntry(entry, &ent->cached_buf[i*32]) ) { |
1274 | done = 1; | 881 | done = 1; |
1275 | break; | 882 | break; |
883 | } | ||
1276 | } | 884 | } |
1277 | 885 | ||
1278 | /* Next sector? */ | 886 | /* Next sector? */ |
@@ -1284,9 +892,13 @@ int fat_getnext(struct bpb *bpb, struct fat_dirent *ent, | |||
1284 | /* Do we need to advance one cluster? */ | 892 | /* Do we need to advance one cluster? */ |
1285 | if(ent->num_sec >= bpb->bpb_secperclus) | 893 | if(ent->num_sec >= bpb->bpb_secperclus) |
1286 | { | 894 | { |
895 | int cluster = fat_sec2cluster(bpb, ent->cached_sec); | ||
896 | if ( cluster < 0 ) { | ||
897 | printf("sec2cluster failed\n"); | ||
898 | return -1; | ||
899 | } | ||
1287 | ent->num_sec = 0; | 900 | ent->num_sec = 0; |
1288 | ent->cached_sec = fat_get_next_cluster( | 901 | ent->cached_sec = fat_get_next_cluster( bpb, cluster ); |
1289 | bpb, fat_sec2cluster(bpb, ent->cached_sec)); | ||
1290 | if(!ent->cached_sec) | 902 | if(!ent->cached_sec) |
1291 | { | 903 | { |
1292 | printf("End of cluster chain.\n"); | 904 | printf("End of cluster chain.\n"); |