00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "src/common/shared.hpp"
00018 #include "src/memory/memset.hpp"
00019 #include "src/memory/align.hpp"
00020 #include "src/memory/heap.hpp"
00021 #include "src/ata.hpp"
00022 #include "src/fat.hpp"
00023 const uint32 FA_DIR = 0x0001;
00024 const uint32 FA_RO = 0x0002;
00025 const uint32 FA_NON_DIR = 0x0000;
00026 const uint32 FA_RW = 0x0000;
00027 const int ESKIP = -0x0003;
00028 const int ENOTIMPLEMENTED=-0x0004;
00029 const int EPROTECTED = -0x0005;
00030 const int ENOTFOUND = -0x0002;
00031 const uint32 DEF_ERROR = EINVAL; const uint32 SEEK_SET=0;
00032 #define fs_lseek(ptr,l,i) do { source=l; } while (0)
00033 uint32 fs_read(uint32 *ptr,char *buf,int count)
00034 { ATAReadSector(ATA_PRIMARY, buf, *ptr/0x200, 0, count);*ptr+=count;
00035 return ESUCCESS;
00036 }
00037 uint32 block_read(uint32*source, char*buf,uint32 offset, uint32 count)
00038 {
00039 *source=offset;
00040 return fs_read(source,buf,count);
00041 }
00042
00043
00044
00045
00046
00047
00048
00049 void sub2()
00050 {
00051 class fat_t f;
00052 f.init("elo");
00053 for(;;);
00054 }
00055
00056
00057 inline char *kmalloc(uint32 size)
00058 {
00059 return (char*)Memory::Heap::heap0.malloc(size, NO_ALIGN, "elo", NULL);
00060 }
00061
00062 inline void kfree(void *ptr)
00063 {
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 uint32 fat_probe (uint32 arg)
00080 {
00081
00082 fat_t fat;
00083 char *ch;
00084 ch = kmalloc(4096);
00085 fat.source=0;
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136 return 1;
00137 }
00138
00139
00140
00141
00142 fat_t::fat_t()
00143 {
00144 init();
00145 }
00146
00147
00148 void fat_t::init()
00149 {
00150 inval();
00151 }
00152
00153
00154 fat_t::fat_t(char *ph)
00155 {
00156 init(ph);
00157 }
00158
00159
00160 void fat_t::init(char *ph)
00161 {
00162
00163 inval();
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 valid = verify();
00174 }
00175
00176
00177 fat_t::~fat_t()
00178 {
00179 done();
00180 }
00181
00182
00183 void fat_t::done()
00184 {
00185
00186 kfree(path);
00187 inval();
00188 }
00189
00190
00191 void fat_t::inval()
00192 {
00193
00194 source=0;
00195 path=NULL; valid=-1; sector_size = cluster_size = 0;
00196 FirstDataSector=0;
00197 RootDirSectors=0;TotSec=0; DataSec=0;
00198 CountofClusters=0; SecPerClus = 0;
00199 FirstRootDirSecNum = 0; ResvdSecCnt=0;
00200 active_fat = 0;fat_type=0;
00201 }
00202
00203
00204
00205 uint8 FAT_DIRENT_ILLEGAL[]=
00206 {0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
00207 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
00208 0x22, 0x2a, 0x2b, 0x2c, 0x2e, 0x2f, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
00209 0x5b, 0x5c, 0x5d, 0x7c};
00210
00211
00212
00213 int fat_t::verify()
00214 {
00215 union
00216 {
00217 char ch[0x200];
00218 bootsect_t bpb;
00219 } sect;
00220 int i;
00221
00222 fs_lseek(source, 0, SEEK_SET);
00223 i= fs_read(&source, (char*) §, 0x200);
00224 if (i != ESUCCESS)
00225 return EINVAL;
00226
00227
00228
00229 sector_size=sect.bpb.BPB_BytsPerSec;
00230 switch (sector_size) {
00231 case 512:
00232 case 1024:
00233 case 2048:
00234 case 4096:
00235 break;
00236 default:
00237 sector_size = 0;
00238 return EINVAL;
00239 break; }
00240
00241
00242 cluster_size=sector_size * sect.bpb.BPB_SecPerClus;
00243 switch (sect.bpb.BPB_SecPerClus){
00244
00245 case 1: case 2: case 4: case 8:
00246 case 16:case 32: case 64: case 128:
00247 break;
00248
00249 active_fat = 0;
00250
00251 default:
00252 cluster_size = 0;
00253 return EINVAL;
00254 break;}
00255
00256 RootDirSectors = ((sect.bpb.BPB_RootEntCnt * sizeof(fatdirent_t)) + (sector_size - 1)) / sector_size;
00257
00258 ResvdSecCnt = sect.bpb.BPB_ResvdSecCnt;
00259
00260 if (sect.bpb.BPB_FATSz16 != 0)
00261 FATSz = sect.bpb.BPB_FATSz16;
00262 else
00263 FATSz = sect.bpb.ext.bpb32.BPB_FATSz32;
00264 if (FATSz == 0)
00265 return EINVAL;
00266
00267 FirstDataSector = ResvdSecCnt + (sect.bpb.BPB_NumFATs * FATSz) + RootDirSectors;
00268
00269 if (sect.bpb.BPB_TotSec16 != 0)
00270 TotSec = sect.bpb.BPB_TotSec16;
00271 else
00272 TotSec = sect.bpb.BPB_TotSec32;
00273 if (TotSec == 0)
00274 return EINVAL;
00275
00276 DataSec = TotSec - (ResvdSecCnt + (sect.bpb.BPB_NumFATs * FATSz) + RootDirSectors);
00277 if (DataSec == 0)
00278 return EINVAL;
00279
00280 CountofClusters = DataSec / sect.bpb.BPB_SecPerClus;
00281
00282 if (CountofClusters < 4085)
00283 fat_type = FAT_FAT12;
00284 else if (CountofClusters < 65525)
00285 fat_type = FAT_FAT16;
00286 else
00287 fat_type = FAT_FAT32;
00288
00289 SecPerClus = sect.bpb.BPB_SecPerClus;
00290
00291 if (fat_type == FAT_FAT32)
00292 FirstRootDirSecNum = clus2sect(sect.bpb.ext.bpb32.BPB_RootClus);
00293 else
00294 FirstRootDirSecNum = sect.bpb.BPB_ResvdSecCnt + (sect.bpb.BPB_NumFATs * sect.bpb.BPB_FATSz16);
00295
00296
00297 return ESUCCESS;
00298 }
00299
00300
00301 int fat_t::fat_rawrw(uint32 sector, char *ch, uint32 count, uint32 read_write)
00302 {
00303 int i = 0;
00304 switch (read_write)
00305 {
00306 case FAT_READ:
00307 i = block_read(&source, ch, sector * sector_size, count * sector_size);
00308 break;
00309 case FAT_WRITE:
00310
00311 break;
00312 default:
00313 return EINVAL;
00314 break;
00315 }
00316
00317 return i;
00318 }
00319
00320
00321 int fat_t::cluster_rw(uint32 block, char *ch, uint32 count, uint32 read_write)
00322 {
00323 return fat_rawrw(
00324 (block * SecPerClus) + FirstDataSector - (2 * SecPerClus),
00325 ch,
00326 count * SecPerClus,
00327 read_write);
00328 }
00329
00330
00331 int fat_t::rootdir_rw(char *ch, uint32 read_write)
00332 {
00333 return fat_rawrw(
00334 FirstRootDirSecNum,
00335 ch,
00336 RootDirSectors,
00337 read_write);
00338 }
00339
00340
00341 uint32 fat_t::clus2sect(uint32 cluster)
00342 {
00343 return (cluster-2) * SecPerClus + FirstDataSector;
00344 }
00345
00346
00347
00348
00349 uint32 fat_t::read_next_clust(uint32 table, uint32 cluster)
00350 {
00351 uint32 FATOffset;
00352 uint32 ThisFATSecNum, ThisFATEntOffset;
00353 char *SecBuff;
00354 uint32 i;
00355 union
00356 {
00357 uint32 entry32;
00358 uint16 entry16;
00359 } ee;
00360 ee.entry32=0;
00361
00362 if (fat_type == FAT_FAT16)
00363 FATOffset=cluster * 2;
00364 if (fat_type == FAT_FAT32)
00365 FATOffset=cluster * 4;
00366 if (fat_type == FAT_FAT12)
00367 FATOffset = cluster + (cluster / 2);
00368
00369
00370 ThisFATSecNum = ResvdSecCnt + (FATOffset / sector_size) + table * FATSz;
00371 ThisFATEntOffset = FATOffset - ((FATOffset / sector_size) * sector_size);
00372
00373
00374 if (fat_type != FAT_FAT12)
00375 {
00376
00377 SecBuff = kmalloc(sector_size);
00378
00379 if (fat_rawrw(ThisFATSecNum, SecBuff, 1, FAT_READ) != 1)
00380 return DEF_ERROR;
00381
00382 if (fat_type == FAT_FAT16)
00383 ee.entry16= (*(uint16*) &SecBuff[ThisFATEntOffset]);
00384 else
00385 ee.entry32= (*(uint32*) &SecBuff[ThisFATEntOffset]) & 0x0FFFFFFF;
00386
00387 kfree(SecBuff);
00388
00389 return ee.entry32;
00390 }
00391
00392
00393
00394 if (ThisFATEntOffset == sector_size - 1)
00395 i = 2;
00396 else
00397 i = 1;
00398
00399
00400 SecBuff = kmalloc(sector_size * i);
00401
00402 if (fat_rawrw(ThisFATSecNum, SecBuff, i, FAT_READ) != 1)
00403 return DEF_ERROR;
00404
00405
00406 ee.entry16 = (*(uint16*) &SecBuff[ThisFATEntOffset]);
00407
00408 if (cluster & 0x001)
00409 ee.entry16 = ee.entry16 >> 4;
00410 else
00411 ee.entry16 = ee.entry16 & 0x0FFF;
00412
00413 kfree(SecBuff);
00414
00415 return ee.entry32;
00416 }
00417
00418
00419 int fat_t::write_next_clust(uint32 table, uint32 cluster, uint32 val)
00420 {
00421 uint32 FATOffset;
00422 uint32 ThisFATSecNum, ThisFATEntOffset;
00423 char *SecBuff;
00424 uint32 i;
00425 union
00426 {
00427 uint32 entry32;
00428 uint16 entry16;
00429 } ee;
00430 ee.entry32=0;
00431
00432 if (fat_type == FAT_FAT16)
00433 FATOffset=cluster * 2;
00434 if (fat_type == FAT_FAT32)
00435 FATOffset=cluster * 4;
00436 if (fat_type == FAT_FAT12)
00437 FATOffset = cluster + (cluster / 2);
00438
00439
00440 ThisFATSecNum = ResvdSecCnt + (FATOffset / sector_size) + table * FATSz;
00441 ThisFATEntOffset = FATOffset - ((FATOffset / sector_size) * sector_size);
00442
00443
00444 if (fat_type != FAT_FAT12)
00445 {
00446
00447 SecBuff = kmalloc(sector_size);
00448
00449 if (fat_rawrw(ThisFATSecNum, SecBuff, 1, FAT_READ) != 1)
00450 return DEF_ERROR;
00451
00452 if (fat_type == FAT_FAT16)
00453 (*(uint16*) &SecBuff[ThisFATEntOffset]) = val;
00454 else
00455 (*(uint32*) &SecBuff[ThisFATEntOffset]) =
00456 (*(uint32*) &SecBuff[ThisFATEntOffset]& 0xF0000000) | val;
00457
00458 if (fat_rawrw(ThisFATSecNum, SecBuff, 1, FAT_WRITE) != 1)
00459 return DEF_ERROR;
00460
00461 kfree(SecBuff);
00462
00463 return ee.entry32;
00464 }
00465
00466
00467
00468 if (ThisFATEntOffset == sector_size - 1)
00469 i = 2;
00470 else
00471 i = 1;
00472
00473
00474 SecBuff = kmalloc(sector_size * i);
00475
00476 if (fat_rawrw(ThisFATSecNum, SecBuff, i, FAT_READ) != 1)
00477 return DEF_ERROR;
00478
00479
00480 if (cluster & 0x001)
00481 {
00482 val = val << 4;
00483 (*(uint16*) &SecBuff[ThisFATEntOffset]) &= 0x000F;
00484 }
00485 else
00486 {
00487 val = val & 0x0FFF;
00488 (*(uint16*) &SecBuff[ThisFATEntOffset]) &= 0xFFF0;
00489 }
00490 (*(uint16*) &SecBuff[ThisFATEntOffset]) |= val;
00491 if (fat_rawrw(ThisFATSecNum, SecBuff, i, FAT_WRITE) != 1)
00492 return DEF_ERROR;
00493
00494
00495 kfree(SecBuff);
00496
00497 return ee.entry32;
00498 }
00499
00500
00501 uint32 fat_t::cluster_no (uint32 table, uint32 first, uint32 n)
00502 {
00503 uint32 i;
00504 uint32 clus = first;
00505 for (i=0;i<n;i++)
00506 {
00507 clus = read_next_clust(table, clus);
00508 if (isEOF(clus) == ESUCCESS)
00509 break;
00510 }
00511
00512 return clus;
00513 }
00514
00515
00516 int fat_t::isEOF(uint32 val)
00517 {
00518 int isEOF = -1;
00519 if (fat_type == FAT_FAT12)
00520 if (val >= 0xff8)
00521 isEOF = 1;
00522 if (fat_type == FAT_FAT16)
00523 if (val >= 0xFFF8)
00524 isEOF = 1;
00525 if (fat_type == FAT_FAT32)
00526 if (val >= 0x0FFFFFF8)
00527 isEOF = 1;
00528
00529 return isEOF;
00530 }
00531
00532
00533 uint32 fat_t::chain_length(uint32 first)
00534 {
00535 uint32 cluster = first;
00536 uint32 i=1;
00537
00538
00539
00540
00541
00542 while (isEOF(cluster=read_next_clust(active_fat, cluster)) != ESUCCESS)
00543 i++;
00544
00545
00546 return i;
00547 }
00548
00549
00550 int fat_t::read_chain(uint32 first, uint32 count, char *buff)
00551 {
00552 uint32 cluster = first;
00553 uint32 i = 0;
00554 int flag ;
00555
00556 while (ESUCCESS)
00557 {
00558 if (i > count-1)
00559 break;
00560
00561 flag = cluster_rw(cluster, buff, 1, FAT_READ);
00562
00563 if (!flag)
00564 return EINVAL;
00565
00566 i++;
00567 buff += cluster_size;
00568
00569 if (isEOF(cluster) == ESUCCESS)
00570 return ESUCCESS;
00571
00572 cluster = read_next_clust(active_fat, cluster);
00573 }
00574
00575 return ESUCCESS;
00576 }
00577
00578
00579
00580
00581 int fat_t::lfn_parse_dir (char *cluster_buffer, uint32 clus, dirent *ent, uint32 *entry)
00582 {
00583
00584
00585
00586
00587
00588
00589 if (fat_type == 0)
00590 return EINVAL;
00591 fatdirent_t *quux;
00592 int flag = EINVAL;
00593 int collect_lfn = EINVAL;
00594 fatdirent_t *lfn_start;
00595 int i;
00596
00597
00598 quux = ((fatdirent_t*) cluster_buffer);
00599 quux += (*entry);
00600
00601 while (ESUCCESS)
00602 {
00603
00604 if ((*entry) * sizeof(fatdirent_t) >= cluster_size * clus)
00605 return ENOTFOUND;
00606 if (cluster_buffer == NULL)
00607 return EINVAL;
00608
00609 if (valid_lfn (quux) == ESUCCESS)
00610 {
00611 if (collect_lfn == EINVAL)
00612 {collect_lfn = 1;lfn_start=quux;}
00613 else
00614 collect_lfn++;
00615 } else
00616 {
00617 i = valid_sfn(quux);
00618
00619 switch (i)
00620 {
00621 case ESUCCESS:
00622
00623 if (collect_lfn != EINVAL)
00624 lfn2name(lfn_start, collect_lfn, ent->name);
00625 else
00626 sfn2name (quux->sfn.DIR_Name, ent->name);
00627
00628 ent->resvd = NULL;
00629 ent->size = quux->sfn.DIR_FileSize;
00630 ent->parent = DEF_ERROR;
00631 ent->block = (quux->sfn.DIR_FstClusLO) + ((quux->sfn.DIR_FstClusHI) << 16);
00632 ent->entry_in_dir = *entry;
00633
00634 ent->flags = 0;
00635 if (quux->sfn.DIR_Attr & FAT_ATTR_DIR)
00636 {ent->flags |= FA_DIR;
00637 ent->size = chain_length(ent->block) * cluster_size;}
00638 if (quux->sfn.DIR_Attr & FAT_ATTR_RO)
00639 ent->flags |= FA_RO;
00640
00641 flag = ESUCCESS;
00642 break;
00643 case ESKIP:
00644 collect_lfn = EINVAL;
00645 break;
00646 case ENOTFOUND:
00647 return ENOTFOUND;
00648 default:
00649 collect_lfn = EINVAL;
00650 break;
00651 }
00652 }
00653
00654
00655 (*entry)++;
00656 quux++;
00657
00658 if (flag == ESUCCESS)
00659 return ESUCCESS;
00660 }
00661
00662
00663 return EINVAL;
00664 }
00665
00666
00667 int fat_t::valid_lfn(fatdirent_t *ent)
00668 {
00669
00670 if (ent == NULL)
00671 return EINVAL;
00672
00673 if (ent->lfn.DIR_Attr != FAT_ATTR_LFN)
00674 return -1;
00675
00676 if (ent->lfn.DIR_First != 0)
00677 return -1;
00678
00679
00680 return ESUCCESS;
00681 }
00682
00683
00684 int fat_t::valid_sfn(fatdirent_t *ent)
00685 {
00686
00687 if (ent == NULL)
00688 return EINVAL;
00689
00690 if (ent->sfn.DIR_Attr & FAT_ATTR_VOLUME)
00691 return -1;
00692
00693 switch (ent->sfn.DIR_Name[0])
00694 {
00695
00696 case FAT_DIRENT_FREE:
00697 case FAT_DIRENT_FREE2:
00698 return ESKIP;
00699 case FAT_DIRENT_ALL_FREE:
00700 return ENOTFOUND;
00701
00702 default:
00703 break;
00704 };
00705
00706
00707 return ESUCCESS;
00708 }
00709
00710
00711 int fat_t::sfn2name (char *raw, char *buff)
00712 {
00713 uint32 n,i;
00714
00715 n=0;
00716 while ( (raw[n] != FAT_DIRENT_PAD) && (n<8) )
00717 {buff[n]=raw[n]; n++;}
00718
00719 if (raw[8] != FAT_DIRENT_PAD)
00720 buff[n++] = '.';
00721
00722 i=8;
00723 while ( (raw[i] != FAT_DIRENT_PAD) && (i<11) )
00724 buff[n++]=raw[i++];
00725
00726 buff[n]=0;
00727
00728 return ESUCCESS;
00729 }
00730
00731
00732 int fat_t::lfn2name (fatdirent_t *first, uint32 count, char *buff)
00733 {
00734 fatdirent_t *quux;
00735 uint32 i, n, z = 0;
00736
00737 quux = first + count - 1;
00738
00739 for (i=0;i<count;i++)
00740 {
00741
00742 for (n=0; n < sizeof(quux->lfn.DIR_LName1) / 2; n++)
00743 buff[z++] = quux->lfn.DIR_LName1[n * 2];
00744
00745 for (n=0; n < sizeof(quux->lfn.DIR_LName2) / 2; n++)
00746 buff[z++] = quux->lfn.DIR_LName2[n * 2];
00747
00748 for (n=0; n < sizeof(quux->lfn.DIR_LName3) / 2; n++)
00749 buff[z++] = quux->lfn.DIR_LName3[n * 2];
00750 quux--;
00751 }
00752
00753 buff[z] = 0;
00754
00755 return ESUCCESS;
00756 }
00757
00758
00759
00760 int fat_t::find_entry(char *name, dirent *ent)
00761 {
00762
00763 if (fat_type == 0)
00764 return EINVAL;
00765
00766 if ((name[0] == '/') && (name[1] == 0))
00767 {
00768 ent -> name[0] = '/';
00769 ent -> name[1] = 0;
00770 ent -> size = RootDirSectors * sector_size;
00771 ent -> parent = 0;
00772 ent -> block = 0;
00773 ent -> flags = FA_DIR;
00774 ent -> resvd = NULL;
00775 ent -> entry_in_dir = 0;
00776 return ESUCCESS;
00777 }
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 return 1;
00830 }
00831
00832
00833 int fat_t::get_file(char *name, char *buffer, uint32 clus, dirent *ent)
00834 {
00835
00836 if (fat_type == 0)
00837 return EINVAL;
00838
00839 int flag;
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 return flag;
00860 }
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 int fat_t::write ( struct file_handle_t *file, char *buff, int nbytes)
00937 {
00938 return -1;
00939 }
00940
00941
00942 int fat_t::readdir ( struct file_handle_t *file, struct dirent *entry, int count )
00943 {
00944 char *buff;
00945 int i;
00946
00947
00948
00949
00950
00951
00952
00953 i=rootdir_rw (buff, FAT_READ);
00954
00955
00956
00957
00958
00959
00960
00961
00962 if (i!= ESUCCESS)
00963 return i;
00964
00965 kfree(buff);
00966
00967 return i;
00968 }
00969
00970
00971 int fat_t::open ( struct file_handle_t *file )
00972 {
00973 int i;
00974 dirent entry;
00975 char *ch;
00976
00977 if (fat_type == 0)
00978 return EINVAL;
00979
00980
00981
00982 i= find_entry(ch, &entry);
00983 kfree(ch);
00984 if (i != ESUCCESS)
00985 return EINVAL;
00986
00987
00988
00989
00990 return ESUCCESS;
00991 }
00992
00993
00994 int fat_t::close ( struct file_handle_t *file )
00995 {
00996 return -1;
00997 }
00998
00999
01000
01001
01002 int fat_lseek ( struct file_handle_t *file, sint64 count, int whence )
01003 {
01004
01005 uint32 ret;
01006
01007
01008
01009
01010 return ret;
01011 }
01012
01013
01014 int fat_read ( struct file_handle_t *file, char *buff, int nbytes)
01015 {
01016
01017 uint32 ret;
01018
01019
01020
01021
01022
01023 return ret;
01024 }
01025
01026
01027 int fat_write ( struct file_handle_t *file, char *buff, int nbytes)
01028 {
01029
01030 uint32 ret;
01031
01032
01033
01034
01035 return ret;
01036 }
01037
01038
01039 int fat_readdir ( struct file_handle_t *file, struct dirent *entry, int n)
01040 {
01041
01042 uint32 ret;
01043
01044
01045
01046
01047 return ret;
01048 }
01049
01050
01051 int fat_open ( struct file_handle_t *file )
01052 {
01053
01054 uint32 ret;
01055
01056
01057
01058
01059 return ret;
01060 }
01061
01062
01063 int fat_close ( struct file_handle_t *file )
01064 {
01065
01066 uint32 ret;
01067
01068
01069
01070
01071 return ret;
01072 }
01073
01074
01075
01076
01077
01078
01079
01080