##// END OF EJS Templates
Fixed some issues on SCARD driver!
Fixed some issues on SCARD driver!

File last commit:

r18:bd9ab647f70a default
r61:efd3992e476b dev_alexis
Show More
fat32.c
326 lines | 10.5 KiB | text/x-c | CLexer
/*------------------------------------------------------------------------------
-- 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 <fat32.h>
#include <stdio.h>
#include <stdint.h>
#include <hexviewer.h>
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;
}