/*------------------------------------------------------------------------------ -- This file is a part of the libuc, microcontroler library -- Copyright (C) 2012, Alexis Jeandet -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------------- -- Author : Alexis Jeandet -- Mail : alexis.jeandet@gmail.com -------------------------------------------------------------------------------*/ #define FAT32_PRIVATE #include #include #include #include char fat32buff[512]; uint32_t lastSecAddrs=-1; FAT32fs* lastFATFS=0; int fat32open(FAT32fs* fs,dikpartition* part) { char sector[512]; fs->part = part; if(!isFat32(fs->part->TypeCode))return FATBadpart; if(fs->part->phy->read(fs->part->phy,sector,fs->part->LBABegin,1)!=RES_OK)return FATReadErr; fs->BPB_BytsPerSec = fat32Ui8_2_Ui16(sector,BPB_BytsPerSecoff); fs->BPB_RsvdSecCnt = fat32Ui8_2_Ui16(sector,BPB_RsvdSecCntoff); fs->BPB_FATSz32 = fat32Ui8_2_Ui32(sector,BPB_FATSz32off); fs->BPB_RootClus = fat32Ui8_2_Ui32(sector,BPB_RootClusoff); fs->BPB_SecPerClus = sector[BPB_SecPerClusoff]; fs->BPB_NumFATs = sector[BPB_NumFATsoff]; fs->fat_begin_lba = (unsigned int)fs->part->LBABegin + (unsigned int)(unsigned short)fs->BPB_RsvdSecCnt; fs->cluster_begin_lba = (unsigned int)fs->fat_begin_lba + ((unsigned int)fs->BPB_NumFATs * (unsigned int)fs->BPB_FATSz32 ); return FATnoErr; } int fat32mkdirent(FAT32fs* fs,ucdirent* dirent) { if(fs==0) return DIRENT_BabArg; if(dirent==0) return DIRENT_BabArg; dirent->fs = (UHANDLE)fs; dirent->getrootfirstent = &fat32getrootfirstent; dirent->nextdirent = &fat32nextdirent; return DIRENT_noErr; } int fat32getrootfirstent(ucdirent* entry) { if(entry==0) return DIRENT_BabArg; entry->CurrentSec = ((FAT32fs*)entry->fs)->cluster_begin_lba; entry->Currententry = 0; return fat32nextdirent(entry); } int fat32getVolName(FAT32fs* fs,char* Name) { if(fs==0) return DIRENT_BabArg; if(Name==0) return DIRENT_BabArg; int i=0; ucdirent entry; if(DIRENT_noErr==fat32mkdirent(fs,&entry)) { entry.CurrentSec = ((FAT32fs*)entry.fs)->cluster_begin_lba; entry.Currententry = -1; if(DIRENT_noErr!=fat32nextdirent(&entry))return DIRENT_ReadErr; for(i=0;i<16;i++) { Name[i] = entry.DIR_Name[i]; } return DIRENT_noErr; } return DIRENT_ReadErr; } int fat32enterdirent(ucdirent* currententry,ucdirent* firstentry) { if(firstentry==0) return DIRENT_BabArg; if(currententry==0) return DIRENT_BabArg; fat32mkdirent(((FAT32fs*)currententry->fs),firstentry); firstentry->CurrentSec = fat32getdirentlba(currententry); firstentry->Currententry = -1; return fat32nextdirent(firstentry); } int fat32nextdirent(ucdirent* entry) { uint32_t n=0,res=DIRENT_noErr,k,j; k=(((signed char)entry->Currententry)+1)*32; /*Restart at last dir entry*/ j=entry->CurrentSec;// /*Restart at last sector*/ do { fat32sectorreadout(((FAT32fs*)entry->fs),j); for(k=k;k<(512);k+=32) /*512 Bytes per sector and 32 bytes per entry*/ { if((fat32buff[DIR_Nameoff+k]!=(char)0xE5)) /*0xE5 = free entry*/ { if(fat32buff[DIR_Nameoff+k]==(char)0) return DIRENT_EndOfDir; /*0x00 = end of dir*/ else if((fat32buff[DIR_Attroff + k]==ATTR_DIRECTORY)||(fat32buff[DIR_Attroff + k]==ATTR_ARCHIVE)||(fat32buff[DIR_Attroff + k]==(ATTR_READ_ONLY))) { for(n=0;n<16;n++)entry->DIR_Name[n] = '\0'; for(n=0;n<11;n++)entry->DIR_Name[n] = fat32buff[n+DIR_Nameoff + k]; entry->DIR_Attr = (uint8_t)fat32buff[DIR_Attroff + k]; entry->DIR_CrtTimeTenth = (uint8_t)fat32buff[DIR_CrtTimeTenthoff + k]; entry->DIR_CrtTime = fat32extract16b(fat32buff,(DIR_CrtTimeoff + k)); entry->DIR_CrtDate = fat32extract16b(fat32buff,(DIR_CrtDateoff + k)); entry->DIR_LstAccDate = fat32extract16b(fat32buff,(DIR_LstAccDateoff + k)); entry->DIR_FstClusHI = fat32extract16b(fat32buff, (DIR_FstClusHIoff + k)); entry->DIR_WrtTime = fat32extract16b(fat32buff,(DIR_WrtTimeoff + k)); entry->DIR_FstClustLO = fat32extract16b(fat32buff, (DIR_FstClusLOoff + k)); entry->DIR_FileSize = fat32extract32b(fat32buff,(DIR_FileSizeoff + k)); entry->CurrentSec = j; entry->Currententry = (unsigned char)(k/32); return DIRENT_noErr; } } } j=fat32nextsectorlba(((FAT32fs*)entry->fs),j,&k); if(j!=DIRENT_noErr) { if(j==DIRENT_LastSect) return DIRENT_EndOfDir; /*Not clean but can avoid some bugs*/ return j; } j=k; k=0; }while(res==DIRENT_noErr); return res; } int fat32getdirentname(ucdirent* entry,char* nameBuffer) { uint32_t j; int k,n,i; int res=DIRENT_noErr; char longName=0; k=(((signed char)entry->Currententry))*32; j=entry->CurrentSec; fat32sectorreadout(((FAT32fs*)entry->fs),j); longName |= fat32buff[DIR_Nameoff + 6 + k]=='~'; if(k>=32) { longName |= ((fat32buff[DIR_Nameoff + k-32]&0x40)==0x40)&((fat32buff[DIR_Nameoff + k-32 +11])==ATTR_LONGNAME); } else { uint32_t j_old=j; if(fat32prevsectorlba((FAT32fs*)entry->fs, j,&j)!=DIRENT_noErr)return DIRENT_ReadErr; fat32sectorreadout(((FAT32fs*)entry->fs),j); k=512; longName |= ((fat32buff[DIR_Nameoff + k-32]&0x40)==0x40)&((fat32buff[DIR_Nameoff + k-32 +11])==ATTR_LONGNAME); if(!longName) { k=0; j=j_old; fat32sectorreadout(((FAT32fs*)entry->fs),j); k=0; } } if(longName) //long Name? or lower case name { i=0; do{ if(k==0) { //get previous sector if(fat32prevsectorlba((FAT32fs*)entry->fs, j,&j)!=DIRENT_noErr)return DIRENT_ReadErr; fat32sectorreadout(((FAT32fs*)entry->fs),j); k=512-32; for(n=0;n<5;n++)nameBuffer[i++] = fat32buff[((n<<1)|1) + k]; for(n=14;n<26;n+=2)nameBuffer[i++] = fat32buff[n + k]; for(n=28;n<32;n+=2)nameBuffer[i++] = fat32buff[n + k]; } else { k-=32; for(n=0;n<5;n++)nameBuffer[i++] = fat32buff[((n<<1)|1) + k]; for(n=14;n<26;n+=2)nameBuffer[i++] = fat32buff[n + k]; for(n=28;n<32;n+=2)nameBuffer[i++] = fat32buff[n + k]; } }while((fat32buff[k]&0x40)!=0x40); nameBuffer[i]='\0'; } else { i=0; for(n=0;n<8;n++) { nameBuffer[i] = 0x20 | fat32buff[n+DIR_Nameoff + k]; if(nameBuffer[i]!=0x20)i++; } if((((fat32buff[DIR_Nameoff + k +11])&ATTR_DIRECTORY)!=ATTR_DIRECTORY)&&(fat32buff[8+DIR_Nameoff + k]!=0x20)) nameBuffer[i++]='.'; for(n=8;n<11;n++) { nameBuffer[i] = 0x20 | fat32buff[n+DIR_Nameoff + k]; if(nameBuffer[i]!=0x20)i++; } nameBuffer[i]='\0'; } return res; } uint32_t fat32getdirentlba(ucdirent* entry) { uint32_t clusterNum = (uint32_t)((uint16_t)entry->DIR_FstClustLO) + ((uint32_t)((uint16_t)entry->DIR_FstClusHI) <<16); uint32_t lba=clusterlba(((FAT32fs*)entry->fs),clusterNum); return lba; } int fat32nextsectorlba(FAT32fs* fs,uint32_t lastsector_lba,uint32_t *nextsector_lba) { if(((lastsector_lba + 1 - fs->cluster_begin_lba) & (fs->BPB_SecPerClus-1))!=0) /*Is it the last sector of the cluster?*/ { *nextsector_lba = lastsector_lba+1; /*if not just increment lba*/ return DIRENT_noErr; } uint32_t clusternum=fat32sectorlbatoclusternum(fs,lastsector_lba); /*Get cluster Number from sector number*/ uint32_t fatsec=fat32clusterinfatsect(fs,clusternum); /*Get FAT sector number*/ fat32sectorreadout(fs,fatsec); int i= fat32clusterinfatoff(clusternum); *nextsector_lba=fat32Ui8_2_Ui32(fat32buff,i); if(*nextsector_lba==0xFFFFFFF7)return DIRENT_BadSect; if(*nextsector_lba>=0xFFFFFFF6)return DIRENT_LastSect; *nextsector_lba = clusterlba(fs,*nextsector_lba); return DIRENT_noErr; } int fat32prevsectorlba(FAT32fs* fs,uint32_t lastsector_lba,uint32_t *nextsector_lba) { uint32_t i=0,fatsec=0; if(((lastsector_lba - 1 - fs->cluster_begin_lba) & (fs->BPB_SecPerClus-1))!=0) /*Is it the first sector of the cluster?*/ { *nextsector_lba = lastsector_lba-1; /*if not just decrement lba*/ return DIRENT_noErr; } uint32_t clusternum=fat32sectorlbatoclusternum(fs,lastsector_lba); /*Get cluster Number from sector number*/ fatsec=fat32clusterinfatsect(fs,clusternum); /*Get FAT sector number*/ do { fat32sectorreadout(fs,fatsec); fatsec--; for(i=511;i>3;i-=4) { *nextsector_lba = fat32Ui8_2_Ui32(fat32buff,i-3); if (*nextsector_lba ==clusternum) { *nextsector_lba = clusterlba(fs,*nextsector_lba); return DIRENT_noErr; } } }while(fatsec>=fs->fat_begin_lba); clusternum=fat32sectorlbatoclusternum(fs,lastsector_lba); /*Get cluster Number from sector number*/ fatsec=fat32clusterinfatsect(fs,clusternum); /*Get FAT sector number*/ do { fat32sectorreadout(fs,fatsec); fatsec++; for(i=0;i<512;i+=4) { *nextsector_lba = fat32Ui8_2_Ui32(fat32buff,i); if (*nextsector_lba ==clusternum) { *nextsector_lba = clusterlba(fs,*nextsector_lba); return DIRENT_noErr; } } }while(fatsec<=(fs->fat_begin_lba+fs->BPB_FATSz32)); return DIRENT_ReadErr; }