##// END OF EJS Templates
Removed error on fat32 library, seems now to be able navigate among sectors in...
Removed error on fat32 library, seems now to be able navigate among sectors in both directions. Improved SDLCD drawing performances by almost 1000x.

File last commit:

r68:104125d87b89 dev_alexis
r68:104125d87b89 dev_alexis
Show More
fat32.c
336 lines | 11.2 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@member.fsf.org
-------------------------------------------------------------------------------*/
#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;
fat32sectorreadout(fs,fs->part->LBABegin);
fs->BPB_BytsPerSec = fat32Ui8_2_Ui16(fat32buff,BPB_BytsPerSecoff);
fs->BPB_RsvdSecCnt = fat32Ui8_2_Ui16(fat32buff,BPB_RsvdSecCntoff);
fs->BPB_FATSz32 = fat32Ui8_2_Ui32(fat32buff,BPB_FATSz32off);
fs->BPB_RootClus = fat32Ui8_2_Ui32(fat32buff,BPB_RootClusoff);
fs->BPB_SecPerClus = fat32buff[BPB_SecPerClusoff];
fs->BPB_NumFATs = fat32buff[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=(0xFF&((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]==(char)ATTR_DIRECTORY)||(fat32buff[DIR_Attroff + k]==(char)ATTR_ARCHIVE)||(fat32buff[DIR_Attroff + k]==(char)(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) & ((uint32_t)(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)
{
printf("DIRENT_BadSect\n");
return DIRENT_BadSect;
}
if((uint32_t)(*nextsector_lba)>=(uint32_t)0xFFFFFFF6)
{
printf("DIRENT_LastSect\n");
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 - 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;
}