fat32.c
383 lines
| 13.2 KiB
| text/x-c
|
CLexer
r12 | /*------------------------------------------------------------------------------ | |||
-- 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 | ||||
Jeandet Alexis
|
r64 | -- Mail : alexis.jeandet@member.fsf.org | ||
r12 | -------------------------------------------------------------------------------*/ | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | #define FAT32_PRIVATE | ||
#include <fat32.h> | ||||
#include <stdio.h> | ||||
#include <stdint.h> | ||||
#include <hexviewer.h> | ||||
r12 | ||||
r63 | char fat32buff[512]__attribute__ ((aligned (4))); | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | uint32_t lastSecAddrs=-1; | ||
r12 | FAT32fs* lastFATFS=0; | |||
int fat32open(FAT32fs* fs,dikpartition* part) | ||||
{ | ||||
r63 | fs->valide = 0; | |||
if(part->valide==0)return FATBadpart; | ||||
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; | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | 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); | ||||
r63 | 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 ); | ||||
fs->valide=1; | ||||
return FATnoErr; | ||||
r12 | } | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | |||
r12 | int fat32mkdirent(FAT32fs* fs,ucdirent* dirent) | |||
{ | ||||
r63 | if((fs==0) || (fs->valide==0)) return DIRENT_BabArg; | |||
if(dirent==0) return DIRENT_BabArg; | ||||
dirent->fs = (UHANDLE)fs; | ||||
dirent->getrootfirstent = &fat32getrootfirstent; | ||||
dirent->nextdirent = &fat32nextdirent; | ||||
return DIRENT_noErr; | ||||
r12 | } | |||
int fat32getrootfirstent(ucdirent* entry) | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | { | ||
r63 | if(entry==0) return DIRENT_BabArg; | |||
entry->CurrentSec = ((FAT32fs*)entry->fs)->cluster_begin_lba; | ||||
entry->Currententry = 0; | ||||
return fat32nextdirent(entry); | ||||
r12 | } | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | int fat32getVolName(FAT32fs* fs,char* Name) | ||
{ | ||||
r63 | if((fs==0) || (fs->valide==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; | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | } | ||
int fat32enterdirent(ucdirent* currententry,ucdirent* firstentry) | ||||
{ | ||||
r63 | if(firstentry==0) return DIRENT_BabArg; | |||
if(currententry==0) return DIRENT_BabArg; | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | fat32mkdirent(((FAT32fs*)currententry->fs),firstentry); | ||
r63 | firstentry->CurrentSec = fat32getdirentlba(currententry); | |||
firstentry->Currententry = -1; | ||||
return fat32nextdirent(firstentry); | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | } | ||
r12 | int fat32nextdirent(ucdirent* entry) | |||
{ | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | uint32_t n=0,res=DIRENT_noErr,k,j; | ||
r62 | k=(0xFF&((signed char)entry->Currententry)+1)*32; /*Restart at last dir entry*/ | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | j=entry->CurrentSec;// /*Restart at last sector*/ | ||
r63 | do | |||
{ | ||||
//printf("reading new secotr\n",k); | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | fat32sectorreadout(((FAT32fs*)entry->fs),j); | ||
r63 | //printf("done\n",k); | |||
/*512 Bytes per sector and 32 bytes per entry*/ | ||||
for(k=k;k<(512);k+=32) | ||||
{ | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | if((fat32buff[DIR_Nameoff+k]!=(char)0xE5)) /*0xE5 = free entry*/ | ||
r63 | { | |||
//printf("Fount dir entry = %d, 0x%X\n",0xff & ((int)fat32buff[DIR_Nameoff+k]),0xff & ((int)fat32buff[DIR_Attroff+k])); | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | if(fat32buff[DIR_Nameoff+k]==(char)0) | ||
r63 | { | |||
//printf("end of directory reached\n",k); | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | return DIRENT_EndOfDir; /*0x00 = end of dir*/ | ||
r63 | } | |||
else | ||||
{ | ||||
uint8_t attribute=fat32buff[DIR_Attroff + k]; | ||||
if( (attribute==ATTR_DIRECTORY) | ||||
||(attribute==ATTR_ARCHIVE) | ||||
||(attribute==ATTR_READ_ONLY) | ||||
||(attribute==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 = attribute; | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | 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)); | ||||
r63 | entry->CurrentSec = j; | |||
entry->Currententry = (uint8_t)(0xFF&(k>>5)); | ||||
return DIRENT_noErr; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
//printf("asking for next sector\n"); | ||||
//printf("current = 0x%X\n",j); | ||||
j=fat32nextsectorlba(((FAT32fs*)entry->fs),j,&k); | ||||
//printf("got it 0x%x\n",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; | ||||
r12 | } | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | int fat32getdirentname(ucdirent* entry,char* nameBuffer) | ||
r12 | { | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | 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 | ||||
r63 | if(fat32prevsectorlba2((FAT32fs*)entry->fs,entry, j,&j)!=DIRENT_noErr)return DIRENT_ReadErr; | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | 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); | ||||
r63 | return lba; | |||
r12 | } | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | |||
int fat32nextsectorlba(FAT32fs* fs,uint32_t lastsector_lba,uint32_t *nextsector_lba) | ||||
r12 | { | |||
r62 | if(((lastsector_lba + 1 - fs->cluster_begin_lba) & ((uint32_t)(fs->BPB_SecPerClus)-1))!=0) /*Is it the last sector of the cluster?*/ | |||
r63 | { | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | *nextsector_lba = lastsector_lba+1; /*if not just increment lba*/ | ||
r63 | return DIRENT_noErr; | |||
r62 | } | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | 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); | ||||
r62 | if(*nextsector_lba==0xFFFFFFF7) | |||
{ | ||||
return DIRENT_BadSect; | ||||
} | ||||
if((uint32_t)(*nextsector_lba)>=(uint32_t)0xFFFFFFF6) | ||||
{ | ||||
return DIRENT_LastSect; | ||||
} | ||||
r63 | *nextsector_lba = clusterlba(fs,*nextsector_lba); | |||
return DIRENT_noErr; | ||||
r12 | } | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | 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; | ||||
} | ||||
r63 | ||||
uint32_t clusternum = fat32sectorlbatoclusternum(fs,lastsector_lba); /*Get cluster Number from sector number*/ | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | fatsec=fat32clusterinfatsect(fs,clusternum); /*Get FAT sector number*/ | ||
r63 | while(fatsec>=fs->fat_begin_lba) | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | { | ||
fat32sectorreadout(fs,fatsec); | ||||
fatsec--; | ||||
r63 | for(i=508;i>2;i-=4) | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | { | ||
r63 | *nextsector_lba = fat32Ui8_2_Ui32(fat32buff,i); | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | if (*nextsector_lba ==clusternum) | ||
{ | ||||
*nextsector_lba = clusterlba(fs,*nextsector_lba); | ||||
return DIRENT_noErr; | ||||
} | ||||
} | ||||
r63 | } | |||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | |||
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; | ||||
} | ||||
} | ||||
r63 | }while(fatsec<=(fs->fat_begin_lba+fs->BPB_FATSz32)); | |||
return DIRENT_ReadErr; | ||||
} | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | |||
r63 | ||||
int fat32prevsectorlba2(FAT32fs* fs,ucdirent* entry,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*/ | ||||
uint32_t currentClusternum = fat32sectorlbatoclusternum(fs,(fat32getdirentlba(entry))); | ||||
fatsec=fat32clusterinfatsect(fs,currentClusternum); /*Get FAT sector number*/ | ||||
*nextsector_lba = fat32getdirentlba(entry); | ||||
while(fatsec<=(fs->fat_begin_lba+fs->BPB_FATSz32)) | ||||
{ | ||||
uint32_t currentClusternum = fat32sectorlbatoclusternum(fs,(*nextsector_lba)); | ||||
fatsec=fat32clusterinfatsect(fs,currentClusternum); /*Get FAT sector number*/ | ||||
fat32sectorreadout(fs,fatsec); | ||||
i= fat32clusterinfatoff(currentClusternum); | ||||
if(i==clusternum) | ||||
{ | ||||
return DIRENT_noErr; | ||||
} | ||||
*nextsector_lba=fat32Ui8_2_Ui32(fat32buff,i); | ||||
if(*nextsector_lba==0xFFFFFFF7) | ||||
{ | ||||
return DIRENT_BadSect; | ||||
} | ||||
if((uint32_t)(*nextsector_lba)>=(uint32_t)0xFFFFFFF6) | ||||
{ | ||||
return DIRENT_LastSect; | ||||
} | ||||
} | ||||
jeandet@pc-de-jeandet3.LAB-LPP.LOCAL
|
r18 | return DIRENT_ReadErr; | ||
} | ||||
r12 | ||||