summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2002-04-26 16:44:58 +0000
committerBjörn Stenberg <bjorn@haxx.se>2002-04-26 16:44:58 +0000
commit1dff4b65f725c2174c65698e498b1d58d61e3968 (patch)
tree14403dd8415cc0fd6389bb873ae166ded43dd6ee
parentcfc2bbeef28cfd0159d59ef813ac2a7b956f13a8 (diff)
downloadrockbox-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
-rw-r--r--firmware/drivers/fat.c570
-rw-r--r--firmware/drivers/fat.h80
-rw-r--r--firmware/test/fat/Makefile25
-rw-r--r--firmware/test/fat/ata-sim.c52
-rw-r--r--firmware/test/fat/debug.c175
-rw-r--r--firmware/test/fat/debug.h9
6 files changed, 399 insertions, 512 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*/
56struct 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
71int fat_num_rootdir_sectors(struct bpb *bpb); 50int fat_num_rootdir_sectors(struct bpb *bpb);
72int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster); 51int fat_first_sector_of_cluster(struct bpb *bpb, unsigned int cluster);
73int fat_get_fatsize(struct bpb* bpb); 52int fat_get_fatsize(struct bpb* bpb);
@@ -84,7 +63,6 @@ int fat_update_entry(struct bpb *bpb, int entry, unsigned int val);
84unsigned int fat_getcurrdostime(unsigned short *dosdate, 63unsigned int fat_getcurrdostime(unsigned short *dosdate,
85 unsigned short *dostime, 64 unsigned short *dostime,
86 unsigned char *dostenth); 65 unsigned char *dostenth);
87int fat_create_root_dir(struct bpb *bpb);
88int fat_create_dos_name(unsigned char *name, unsigned char *newname); 66int fat_create_dos_name(unsigned char *name, unsigned char *newname);
89int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name); 67int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name);
90 68
@@ -94,14 +72,10 @@ char current_directory[256] = "\\";
94struct bpb *global_bpb; 72struct bpb *global_bpb;
95struct disk_info di; 73struct disk_info di;
96 74
97extern int yyparse(void);
98
99 75
100#ifdef TEST_FAT 76#ifdef TEST_FAT
101void prompt(void) 77
102{ 78#include "debug.h"
103 printf("C:%s>", current_directory);
104}
105 79
106int main(int argc, char *argv[]) 80int 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
151int 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
173int fat_cluster2sec(struct bpb *bpb, unsigned int cluster) 116int 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
215int fat_get_rootdir_sector(struct bpb *bpb) 158int 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
220int fat_first_data_sector(struct bpb* bpb) 163int 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
232int 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
344int fat_get_bpb(struct bpb *bpb) 175int 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
436int fat_bpb_is_sane(struct bpb *bpb) 268int 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
507int 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
576int fat_dbg_read_block(char *name, unsigned char *buf) 333int 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)
628int fat_update_entry(struct bpb *bpb, int entry, unsigned int val) 385int 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
710int fat_read_entry(struct bpb *bpb, int entry) 417int 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
846int 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
902int fat_get_next_cluster(struct bpb *bpb, unsigned int cluster) 505int 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
1201void fat_fill_direntry(struct fat_direntry *de, char *buf) 805int 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
1219int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir) 827int 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
1249int fat_getnext(struct bpb *bpb, struct fat_dirent *ent, 857int 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");
diff --git a/firmware/drivers/fat.h b/firmware/drivers/fat.h
index f1dc8dc5a0..99b40ac284 100644
--- a/firmware/drivers/fat.h
+++ b/firmware/drivers/fat.h
@@ -20,6 +20,8 @@
20#ifndef FAT_H 20#ifndef FAT_H
21#define FAT_H 21#define FAT_H
22 22
23#define BLOCK_SIZE 512
24
23#define FATTYPE_FAT12 0 25#define FATTYPE_FAT12 0
24#define FATTYPE_FAT16 1 26#define FATTYPE_FAT16 1
25#define FATTYPE_FAT32 2 27#define FATTYPE_FAT32 2
@@ -50,37 +52,42 @@
50 52
51#define BPB_LAST_WORD 510 53#define BPB_LAST_WORD 510
52 54
53#define MIN(a,b) (((a) < (b))?(a):(b))) 55#define MIN(a,b) (((a) < (b))?(a):(b))
54 56
55struct bpb 57struct bpb
56{ 58{
57 char bs_oemname[9]; /* OEM string, ending with \0 */ 59 char bs_oemname[9]; /* OEM string, ending with \0 */
58 int bpb_bytspersec; /* Bytes per sectory, typically 512 */ 60 int bpb_bytspersec; /* Bytes per sectory, typically 512 */
59 int bpb_secperclus; /* Sectors per cluster */ 61 int bpb_secperclus; /* Sectors per cluster */
60 int bpb_rsvdseccnt; /* Number of reserved sectors */ 62 int bpb_rsvdseccnt; /* Number of reserved sectors */
61 int bpb_numfats; /* Number of FAT structures, typically 2 */ 63 int bpb_numfats; /* Number of FAT structures, typically 2 */
62 int bpb_rootentcnt; /* Number of dir entries in the root */ 64 int bpb_rootentcnt; /* Number of dir entries in the root */
63 int bpb_totsec16; /* Number of sectors on the volume (old 16-bit) */ 65 int bpb_totsec16; /* Number of sectors on the volume (old 16-bit) */
64 int bpb_media; /* Media type (typically 0xf0 or 0xf8) */ 66 int bpb_media; /* Media type (typically 0xf0 or 0xf8) */
65 int bpb_fatsz16; /* Number of used sectors per FAT structure */ 67 int bpb_fatsz16; /* Number of used sectors per FAT structure */
66 int bpb_secpertrk; /* Number of sectors per track */ 68 int bpb_secpertrk; /* Number of sectors per track */
67 int bpb_numheads; /* Number of heads */ 69 int bpb_numheads; /* Number of heads */
68 int bpb_hiddsec; /* Hidden sectors before the volume */ 70 int bpb_hiddsec; /* Hidden sectors before the volume */
69 unsigned int bpb_totsec32; /* Number of sectors on the volume 71 unsigned int bpb_totsec32; /* Number of sectors on the volume
70 (new 32-bit) */ 72 (new 32-bit) */
71 /**** FAT12/16 specific *****/ 73 /**** FAT12/16 specific *****/
72 int bs_drvnum; /* Drive number */ 74 int bs_drvnum; /* Drive number */
73 int bs_bootsig; /* Is 0x29 if the following 3 fields are valid */ 75 int bs_bootsig; /* Is 0x29 if the following 3 fields are valid */
74 unsigned int bs_volid; /* Volume ID */ 76 unsigned int bs_volid; /* Volume ID */
75 char bs_vollab[12]; /* Volume label, 11 chars plus \0 */ 77 char bs_vollab[12]; /* Volume label, 11 chars plus \0 */
76 char bs_filsystype[9]; /* File system type, 8 chars plus \0 */ 78 char bs_filsystype[9]; /* File system type, 8 chars plus \0 */
77 79
78 /**** FAT32 specific *****/ 80 /**** FAT32 specific *****/
79 int bpb_fatsz32; 81 int bpb_fatsz32;
80 82 int bpb_extflags;
81 int last_word; /* Must be 0xaa55 */ 83 int bpb_fsver;
82 84 int bpb_rootclus;
83 int fat_type; /* What type of FAT is this? */ 85 int bpb_fsinfo;
86 int bpb_bkbootsec;
87
88 /* variables for internal use */
89 int fat_type; /* FAT12, FAT16 or FAT32 */
90 int last_word; /* must be 0xAA55 */
84}; 91};
85 92
86#define FAT_ATTR_READ_ONLY 0x01 93#define FAT_ATTR_READ_ONLY 0x01
@@ -91,6 +98,9 @@ struct bpb
91#define FAT_ATTR_ARCHIVE 0x20 98#define FAT_ATTR_ARCHIVE 0x20
92#define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \ 99#define FAT_ATTR_LONG_NAME (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \
93 FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID) 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 )
94 104
95 105
96#define FATDIR_NAME 0 106#define FATDIR_NAME 0
@@ -145,10 +155,14 @@ struct fat_dirent
145 char cached_buf[BLOCK_SIZE]; 155 char cached_buf[BLOCK_SIZE];
146}; 156};
147 157
148int fat_format(struct disk_info *di, char *vol_name); 158extern int fat_create_file(struct bpb *bpb,
149int fat_create_file(struct bpb *bpb, unsigned int currdir, char *name); 159 unsigned int currdir,
150int fat_opendir(struct bpb *bpb, struct fat_dirent *ent, unsigned int currdir); 160 char *name);
151int fat_getnext(struct bpb *bpb, struct fat_dirent *ent, 161extern int fat_opendir(struct bpb *bpb,
152 struct fat_direntry *entry); 162 struct fat_dirent *ent,
163 unsigned int currdir);
164extern int fat_getnext(struct bpb *bpb,
165 struct fat_dirent *ent,
166 struct fat_direntry *entry);
153 167
154#endif 168#endif
diff --git a/firmware/test/fat/Makefile b/firmware/test/fat/Makefile
new file mode 100644
index 0000000000..8b60aba99c
--- /dev/null
+++ b/firmware/test/fat/Makefile
@@ -0,0 +1,25 @@
1DRIVERS = ../../drivers
2
3CFLAGS = -g -Wall -DTEST_FAT -I$(DRIVERS) -I.
4
5TARGET = fat
6
7$(TARGET): fat.o ata-sim.o debug.o
8 gcc -g -o fat $+ -lfl
9
10fat.o: $(DRIVERS)/fat.c $(DRIVERS)/fat.h $(DRIVERS)/ata.h
11 $(CC) $(CFLAGS) -c $< -o $@
12
13ata-sim.o: ata-sim.c $(DRIVERS)/ata.h
14
15debug.o: debug.c debug.h $(DRIVERS)/ata.h
16
17clean:
18 rm -f *.o $(TARGET)
19 rm -f *~
20 rm -f cmd.tab.h lex.yy.c cmd.tab.c
21 rm -f core
22
23tar:
24 rm -f $(TARGET).tar
25 tar cvf $(TARGET).tar -C .. fat
diff --git a/firmware/test/fat/ata-sim.c b/firmware/test/fat/ata-sim.c
new file mode 100644
index 0000000000..d8c28d9467
--- /dev/null
+++ b/firmware/test/fat/ata-sim.c
@@ -0,0 +1,52 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5#include "ata.h"
6
7#define BLOCK_SIZE 512
8
9static FILE* file;
10
11int ata_read_sectors(unsigned long start, unsigned char count, void* buf)
12{
13 if(fseek(file,start*BLOCK_SIZE,SEEK_SET)) {
14 perror("fseek");
15 return -1;
16 }
17 if(!fread(buf,BLOCK_SIZE,count,file)) {
18 printf("Failed reading %d blocks starting at block %ld\n",count,start);
19 perror("fread");
20 return -1;
21 }
22 return 0;
23}
24
25int ata_write_sectors(unsigned long start, unsigned char count, void* buf)
26{
27 if(fseek(file,start*BLOCK_SIZE,SEEK_SET)) {
28 perror("fseek");
29 return -1;
30 }
31 if(!fwrite(buf,BLOCK_SIZE,count,file)) {
32 perror("fwrite");
33 return -1;
34 }
35 return 0;
36}
37
38int ata_init(void)
39{
40 /* check disk size */
41 file=fopen("disk.img","r+");
42 if(!file) {
43 fprintf(stderr, "read_disk() - Could not find \"disk.img\"\n");
44 return -1;
45 }
46 return 0;
47}
48
49void ata_exit(void)
50{
51 fclose(file);
52}
diff --git a/firmware/test/fat/debug.c b/firmware/test/fat/debug.c
new file mode 100644
index 0000000000..046a67e06c
--- /dev/null
+++ b/firmware/test/fat/debug.c
@@ -0,0 +1,175 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include "fat.h"
5#include "ata.h"
6#include "debug.h"
7
8void dbg_dump_sector(int sec)
9{
10 unsigned char buf[512];
11
12 ata_read_sectors(sec,1,buf);
13 printf("---< Sector %d >-----------------------------------------\n", sec);
14 dbg_dump_buffer(buf);
15}
16
17void dbg_dump_buffer(unsigned char *buf)
18{
19 int i, j;
20 unsigned char c;
21 unsigned char ascii[33];
22
23 for(i = 0;i < 512/32;i++)
24 {
25 for(j = 0;j < 32;j++)
26 {
27 c = buf[i*32+j];
28
29 printf("%02x ", c);
30 if(c < 32 || c > 127)
31 {
32 ascii[j] = '.';
33 }
34 else
35 {
36 ascii[j] = c;
37 }
38 }
39
40 ascii[j] = 0;
41 printf("%s\n", ascii);
42 }
43}
44
45void dbg_print_bpb(struct bpb *bpb)
46{
47 printf("bpb_oemname = \"%s\"\n", bpb->bs_oemname);
48 printf("bpb_bytspersec = %d\n", bpb->bpb_bytspersec);
49 printf("bpb_secperclus = %d\n", bpb->bpb_secperclus);
50 printf("bpb_rsvdseccnt = %d\n", bpb->bpb_rsvdseccnt);
51 printf("bpb_numfats = %d\n", bpb->bpb_numfats);
52 printf("bpb_rootentcnt = %d\n", bpb->bpb_rootentcnt);
53 printf("bpb_totsec16 = %d\n", bpb->bpb_totsec16);
54 printf("bpb_media = %02x\n", bpb->bpb_media);
55 printf("bpb_fatsz16 = %d\n", bpb->bpb_fatsz16);
56 printf("bpb_secpertrk = %d\n", bpb->bpb_secpertrk);
57 printf("bpb_numheads = %d\n", bpb->bpb_numheads);
58 printf("bpb_hiddsec = %u\n", bpb->bpb_hiddsec);
59 printf("bpb_totsec32 = %u\n", bpb->bpb_totsec32);
60
61 printf("bs_drvnum = %d\n", bpb->bs_drvnum);
62 printf("bs_bootsig = %02x\n", bpb->bs_bootsig);
63 if(bpb->bs_bootsig == 0x29)
64 {
65 printf("bs_volid = %xl\n", bpb->bs_volid);
66 printf("bs_vollab = \"%s\"\n", bpb->bs_vollab);
67 printf("bs_filsystype = \"%s\"\n", bpb->bs_filsystype);
68 }
69
70 printf("bpb_fatsz32 = %u\n", bpb->bpb_fatsz32);
71 printf("last_word = %04x\n", bpb->last_word);
72
73 switch(bpb->fat_type)
74 {
75 case FATTYPE_FAT12:
76 printf("fat_type = FAT12\n");
77 break;
78 case FATTYPE_FAT16:
79 printf("fat_type = FAT16\n");
80 break;
81 case FATTYPE_FAT32:
82 printf("fat_type = FAT32\n");
83 break;
84 default:
85 printf("fat_type = UNKNOWN (%d)\n", bpb->fat_type);
86 break;
87 }
88}
89
90void dbg_dir(struct bpb *bpb, int currdir)
91{
92 struct fat_dirent dent;
93 struct fat_direntry de;
94
95 if(fat_opendir(bpb, &dent, currdir) >= 0)
96 {
97 while(fat_getnext(bpb, &dent, &de) >= 0)
98 {
99 printf("%s\n", de.name);
100 }
101 }
102 else
103 {
104 fprintf(stderr, "Could not read dir on cluster %d\n", currdir);
105 }
106}
107
108extern char current_directory[];
109int last_secnum = 0;
110
111void dbg_prompt(void)
112{
113 printf("C:%s> ", current_directory);
114}
115
116void dbg_console(struct bpb* bpb)
117{
118 char cmd[32] = "";
119 char last_cmd[32] = "";
120 int quit = 0;
121 char *s;
122 int secnum;
123
124 while(!quit)
125 {
126 dbg_prompt();
127 if(fgets(cmd, sizeof(cmd) - 1, stdin))
128 {
129 if(strlen(cmd) == 1) /* empty command? */
130 {
131 strcpy(cmd, last_cmd);
132 }
133
134 /* Get the first token */
135 s = strtok(cmd, " \n");
136 if(s)
137 {
138 if(!strcasecmp(s, "dir"))
139 {
140 secnum = 0;
141 if((s = strtok(NULL, " \n")))
142 {
143 secnum = atoi(s);
144 }
145 dbg_dir(bpb, secnum);
146 continue;
147 }
148
149 if(!strcasecmp(s, "ds"))
150 {
151 /* Remember the command */
152 strcpy(last_cmd, s);
153
154 if((s = strtok(NULL, " \n")))
155 {
156 last_secnum = atoi(s);
157 }
158 else
159 {
160 last_secnum++;
161 }
162 printf("secnum: %d\n", last_secnum);
163 dbg_dump_sector(last_secnum);
164 continue;
165 }
166
167 if(!strcasecmp(s, "exit") ||
168 !strcasecmp(s, "x"))
169 {
170 quit = 1;
171 }
172 }
173 }
174 }
175}
diff --git a/firmware/test/fat/debug.h b/firmware/test/fat/debug.h
new file mode 100644
index 0000000000..ff786ab2b1
--- /dev/null
+++ b/firmware/test/fat/debug.h
@@ -0,0 +1,9 @@
1#ifndef DEBUG_H
2#define DEBUG_H
3
4void dbg_dump_sector(int sec);
5void dbg_dump_buffer(unsigned char *buf);
6void dbg_print_bpb(struct bpb *bpb);
7void dbg_console(struct bpb *bpb);
8
9#endif