##// END OF EJS Templates
Added Simulator target to run code on x86 and debug functions....
Added Simulator target to run code on x86 and debug functions. Fixed some bugs on terminal widget.

File last commit:

r63:68dfbccdd813 dev_alexis
r63:68dfbccdd813 dev_alexis
Show More
fat32.c
383 lines | 13.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@gmail.com
-------------------------------------------------------------------------------*/
#define FAT32_PRIVATE
#include <fat32.h>
#include <stdio.h>
#include <stdint.h>
#include <hexviewer.h>
char fat32buff[512]__attribute__ ((aligned (4)));
uint32_t lastSecAddrs=-1;
FAT32fs* lastFATFS=0;
int fat32open(FAT32fs* fs,dikpartition* part)
{
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;
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 );
fs->valide=1;
return FATnoErr;
}
int fat32mkdirent(FAT32fs* fs,ucdirent* dirent)
{
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;
}
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) || (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;
}
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
{
//printf("reading new secotr\n",k);
fat32sectorreadout(((FAT32fs*)entry->fs),j);
//printf("done\n",k);
/*512 Bytes per sector and 32 bytes per entry*/
for(k=k;k<(512);k+=32)
{
if((fat32buff[DIR_Nameoff+k]!=(char)0xE5)) /*0xE5 = free entry*/
{
//printf("Fount dir entry = %d, 0x%X\n",0xff & ((int)fat32buff[DIR_Nameoff+k]),0xff & ((int)fat32buff[DIR_Attroff+k]));
if(fat32buff[DIR_Nameoff+k]==(char)0)
{
//printf("end of directory reached\n",k);
return DIRENT_EndOfDir; /*0x00 = end of dir*/
}
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;
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 = (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;
}
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(fat32prevsectorlba2((FAT32fs*)entry->fs,entry, 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)
{
return DIRENT_BadSect;
}
if((uint32_t)(*nextsector_lba)>=(uint32_t)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*/
while(fatsec>=fs->fat_begin_lba)
{
fat32sectorreadout(fs,fatsec);
fatsec--;
for(i=508;i>2;i-=4)
{
*nextsector_lba = fat32Ui8_2_Ui32(fat32buff,i);
if (*nextsector_lba ==clusternum)
{
*nextsector_lba = clusterlba(fs,*nextsector_lba);
return DIRENT_noErr;
}
}
}
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;
}
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;
}
}
return DIRENT_ReadErr;
}