📄 fat.c
字号:
/*****************************************************************************\* EFSL - Embedded Filesystems Library ** ----------------------------------- ** ** Filename : fat.c ** Release : 0.3 - devel ** Description : This file contains all the functions dealing with the FAT ** in a Microsoft FAT filesystem. It belongs under fs.c ** ** 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; version 2 ** of the License. ** ** 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. ** ** As a special exception, if other files instantiate templates or ** use macros or inline functions from this file, or you compile this ** file and link it with other works to produce a work based on this file, ** this file does not by itself cause the resulting work to be covered ** by the GNU General Public License. However the source code for this ** file must still be made available in accordance with section (3) of ** the GNU General Public License. ** ** This exception does not invalidate any other reasons why a work based ** on this file might be covered by the GNU General Public License. ** ** (c)2006 Lennart Yseboodt ** (c)2006 Michael De Nil *\*****************************************************************************//*****************************************************************************/#include "fs.h"/*****************************************************************************//* **************************************************************************** * unsigned long fat_getSectorAddressFatEntry(FileSystem *fs,unsigned long cluster_addr) * Description: Returns the sectornumber that holds the fat entry for cluster cluster_addr. * This works for all FAT types. * Return value: Sectornumber, or 0. Warning, no boundary check.*/euint32 fat_getSectorAddressFatEntry(FileSystem *fs,euint32 cluster_addr){ euint32 base = fs->volumeId.ReservedSectorCount,res; switch(fs->type){ case FAT12: res=(cluster_addr*3/1024); if(res>=fs->FatSectorCount){ return(0); }else{ return(base+res); } break; case FAT16: res=cluster_addr/256; if(res>=fs->FatSectorCount){ return(0); }else{ return(base+res); } break; case FAT32: res=cluster_addr/128; if(res>=fs->FatSectorCount){ return(0); }else{ return(base+res); } break; } return(0);}/*****************************************************************************/ /* **************************************************************************** * unsigned long fat_getNextClusterAddress(FileSystem *fs,unsigned long cluster_addr * Description: This function loads the sector of the fat which contains the entry * for cluster_addr. It then fetches and (if required) calculates it's value. * This value is the EoC marker -or- the number of the next cluster in the chain. * Return value: Clusternumber or EoC*/euint32 fat_getNextClusterAddress(FileSystem *fs,euint32 cluster_addr,euint16 *linear){ euint8 *buf; euint8 hb,lb; euint16 offset; euint32 sector; euint32 nextcluster=0; sector=fat_getSectorAddressFatEntry(fs,cluster_addr); if( (fs->FatSectorCount <= (sector-fs->volumeId.ReservedSectorCount)) || sector==0 ) { return(0); } buf=part_getSect(fs->part,sector,IOM_MODE_READONLY); switch(fs->type) { case FAT12: offset = ((cluster_addr%1024)*3/2)%512; hb = buf[offset]; if(offset == 511){ part_relSect(fs->part,buf); buf=part_getSect(fs->part,sector+1,IOM_MODE_READONLY); lb = buf[0]; }else{ lb = buf[offset + 1]; } if(cluster_addr%2==0){ nextcluster = ( ((lb&0x0F)<<8) + (hb) ); }else{ nextcluster = ( (lb<<4) + (hb>>4) ); } break; case FAT16: offset=cluster_addr%256; nextcluster = *((euint16 *)buf + offset); break; case FAT32: offset=cluster_addr%128; nextcluster = *((euint32 *)buf + offset); break; } part_relSect(fs->part,buf); return(nextcluster);}/*****************************************************************************/ /* **************************************************************************** * void fat_setNextClusterAddress(FileSystem *fs,unsigned long cluster_addr,unsigned long next_cluster_addr) * Description: This function makes an entry in the fattable for cluster_addr. The value it puts there * is next_cluster_addr. */void fat_setNextClusterAddress(FileSystem *fs,euint32 cluster_addr,euint32 next_cluster_addr){ euint8 *buf,*buf2; euint16 offset; euint32 sector; sector=fat_getSectorAddressFatEntry(fs,cluster_addr); if(fs->FatSectorCount<sector){ DBG((TXT("HARDERROR:::fat_getNextClusterAddress READ PAST FAT BOUNDARY\n"))); return; } buf=part_getSect(fs->part,sector,IOM_MODE_READWRITE); switch(fs->type){ case FAT12: offset = ((cluster_addr%1024)*3/2)%512; if(offset == 511){ if(cluster_addr%2==0){ buf[offset]=next_cluster_addr&0xFF; }else{ buf[offset]=(buf[offset]&0xF)+((next_cluster_addr<<4)&0xF0); } buf2=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,cluster_addr)+1,IOM_MODE_READWRITE); if(cluster_addr%2==0){ buf2[0]=(buf2[0]&0xF0)+((next_cluster_addr>>8)&0xF); }else{ buf2[0]=(next_cluster_addr>>4)&0xFF; } part_relSect(fs->part,buf2); }else{ if(cluster_addr%2==0){ buf[offset]=next_cluster_addr&0xFF; buf[offset+1]=(buf[offset+1]&0xF0)+((next_cluster_addr>>8)&0xF); }else{ buf[offset]=(buf[offset]&0xF)+((next_cluster_addr<<4)&0xF0); buf[offset+1]=(next_cluster_addr>>4)&0xFF; } } part_relSect(fs->part,buf); break; case FAT16: offset=cluster_addr%256; *((euint16*)buf+offset)=next_cluster_addr; part_relSect(fs->part,buf); break; case FAT32: offset=cluster_addr%128; *((euint32*)buf+offset)=next_cluster_addr; part_relSect(fs->part,buf); break; } }/*****************************************************************************/ /* **************************************************************************** * short fat_isEocMarker(FileSystem *fs,unsigned long fat_entry) * Description: Checks if a certain value is the EoC marker for the filesystem * noted in fs->type. * Return value: Returns 0 when it is the EoC marker, and 1 otherwise.*/eint16 fat_isEocMarker(FileSystem *fs,euint32 fat_entry){ switch(fs->type){ case FAT12: if(fat_entry<0xFF8){ return(0); } break; case FAT16: if(fat_entry<0xFFF8){ return(0); } break; case FAT32: if((fat_entry&0x0FFFFFFF)<0xFFFFFF8){ return(0); } break; } return(1);}/*****************************************************************************/ /* **************************************************************************** * unsigned long fat_giveEocMarker(FileSystem *fs) * Description: Returns an EoC markernumber valid for the filesystem noted in * fs->type. * Note, for FAT32, the upper 4 bits are set to zero, although they should be un * touched according to MicroSoft specifications. I didn't care. * Return value: The EoC marker cast to an ulong.*/euint32 fat_giveEocMarker(FileSystem *fs){ switch(fs->type) { case FAT12: return(0xFFF); break; case FAT16: return(0xFFFF); break; case FAT32: return(0x0FFFFFFF); break; } return(0);}/*****************************************************************************/ /* **************************************************************************** * euint32 fat_getNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr, euint8* buf) * Description: This function retrieves the contents of a FAT field. It does not fetch * it's own buffer, it is given as a parameter. (ioman makes this function rather obsolete) * Only in the case of a FAT12 crosssector data entry a sector is retrieved here. * Return value: The value of the clusterfield is returned.*/euint32 fat_getNextClusterAddressWBuf(FileSystem *fs,euint32 cluster_addr, euint8* buf){ euint8 *buf2; /* For FAT12 fallover only */ euint8 hb,lb; euint16 offset; euint32 nextcluster=0; switch(fs->type) { case FAT12: offset = ((cluster_addr%1024)*3/2)%512; hb = buf[offset]; if(offset == 511){ buf2=part_getSect(fs->part,fat_getSectorAddressFatEntry(fs,cluster_addr)+1,IOM_MODE_READONLY); lb = buf2[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -