📄 fat32.c
字号:
/*
Copyright (C) 2003 Bart Bilos <boombox666@yahoo.com>.
code adapted and modified from the yampp project
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 2
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.
*/
#include <stdio.h> /* prototype declarations for I/O functions */
#include <string.h> /* memory operations */
#include "IDE_LIB.h" /* IDE working variables */
#include "fat32.h"
#include "util.h"
// current BPB
Bpb CurrBPB;
// sector buffer
char sector_data[512];
// housekeeping vars
// first sector of FAT
unsigned long FirstFATSector;
// first data sector
unsigned long FirstDataSectorD;
// first directory cluster
unsigned long FirstDirCluster;
// how many sectors per cluster
unsigned int SecPerClust;
// fixes the BPB from big endian to little endian format
void fixBPB(Bpb *a_Bpb) {
a_Bpb->BPB_BytsPerSec = int_big_endian(a_Bpb->BPB_BytsPerSec);
a_Bpb->BPB_ResvdSecCnt = int_big_endian(a_Bpb->BPB_ResvdSecCnt);
a_Bpb->BPB_RootEntCnt = int_big_endian(a_Bpb->BPB_RootEntCnt);
a_Bpb->BPB_TotSec16 = int_big_endian(a_Bpb->BPB_TotSec16);
a_Bpb->BPB_FATSz16 = int_big_endian(a_Bpb->BPB_FATSz16);
a_Bpb->BPB_SecPerTrk = int_big_endian(a_Bpb->BPB_SecPerTrk);
a_Bpb->BPB_NumHeads = int_big_endian(a_Bpb->BPB_NumHeads);
a_Bpb->BPB_HiddSec = long_big_endian(a_Bpb->BPB_HiddSec);
a_Bpb->BPB_TotSec32 = long_big_endian(a_Bpb->BPB_TotSec32);
a_Bpb->BPB_FATSz32 = long_big_endian(a_Bpb->BPB_FATSz32);
a_Bpb->BPB_ExtFlags = int_big_endian(a_Bpb->BPB_ExtFlags);
a_Bpb->BPB_FSVer = int_big_endian(a_Bpb->BPB_FSVer);
a_Bpb->BPB_RootClus = long_big_endian(a_Bpb->BPB_RootClus);
a_Bpb->BPB_FSInfo = int_big_endian(a_Bpb->BPB_FSInfo);
a_Bpb->BPB_BkBootSec = int_big_endian(a_Bpb->BPB_BkBootSec);
a_Bpb->BS_VolID = long_big_endian(a_Bpb->BS_VolID);
}
// calculates the sector number from the cluster number
unsigned long clust2sect(unsigned long clust) {
return clust * SecPerClust + FirstDataSectorD;
}
// gives the cluster of the root dir
unsigned long rootdir() {
return FirstDirCluster;
}
// reads the harddrive MBR.
// locates the first partition.
// checks if its fat32
char init_fat32(void) {
Bootsector *startsect;
unsigned long int first_sector=0;
startsect = (Bootsector * ) sector_data;
// read sector 0
if(read_sector(first_sector,sector_data) != 0) {
return 1;
}
// locate partition and load BPB
first_sector = long_big_endian(startsect->BS_partition_start);
if(read_sector(first_sector,sector_data) != 0) {
return 1;
}
// copy relevant part of BPB from sector to the struct
memcpy(&CurrBPB,sector_data,90);
fixBPB(&CurrBPB);
FirstFATSector = CurrBPB.BPB_ResvdSecCnt + first_sector;
FirstDataSectorD = CurrBPB.BPB_ResvdSecCnt + (CurrBPB.BPB_NumFATs * CurrBPB.BPB_FATSz32) + first_sector; // This is FirstDataSector
FirstDirCluster = CurrBPB.BPB_RootClus;
SecPerClust = CurrBPB.BPB_SecPerClus;
FirstDataSectorD -= (2 * SecPerClust);
return 0;
}
// check if sector has suitable directory entries
char checksect(unsigned long a_sect_tocheck) {
read_sector(a_sect_tocheck,sector_data);
// just check if the first byte is non null
if(sector_data[0]!=0) return 1;
else return 0;
}
/*
// print out statistics about the specific entry
void FAT32entrydata(direntry *a_entry){
int i;
char fileentry[12];
for(i=0;i<12;i++)
fileentry[i] = a_entry->DE_Name[i];
fileentry[11]=0;
printf("%s ",fileentry);
if(ATTR_NORMAL & a_entry->DE_Attributes) {
printf("N");
} else {
printf("-");
}
if(ATTR_READONLY & a_entry->DE_Attributes) {
printf("R");
} else {
printf("-");
}
if(ATTR_HIDDEN & a_entry->DE_Attributes) {
printf("H");
} else {
printf("-");
}
if(ATTR_SYSTEM & a_entry->DE_Attributes) {
printf("S");
} else {
printf("-");
}
if(ATTR_VOLUME & a_entry->DE_Attributes) {
printf("V");
} else {
printf("-");
}
if(ATTR_LONG_FILENAME & a_entry->DE_Attributes) {
printf("L");
} else {
printf("-");
}
if(ATTR_ARCHIVE & a_entry->DE_Attributes) {
printf("A");
} else {
printf("-");
}
if(ATTR_DIRECTORY & a_entry->DE_Attributes) {
printf("D");
} else {
printf("-");
}
printf(" starting at %6x",int_big_endian(a_entry->DE_StartCluster));
printf(" %10lu bytes big \n",long_big_endian(a_entry->DE_FileSize));
}
// goes through an table at a_clust and returns the first directory it finds
// or 0 if the table has no directories
unsigned int traverse_dir(unsigned long int a_clust) {
direntry *de;
unsigned long nextdir=0;
int i;
unsigned long dwStartSector = clust2sect(a_clust);
while(checksect(dwStartSector)){
// sector read in and seems fine
de = (direntry * ) sector_data;
// reset sector pointer
for(i=0;i<16;i++){
if(de->DE_Name[0] != SLOT_EMPTY) {
FAT32entrydata(de);
if(ATTR_DIRECTORY&de->DE_Attributes) {
// check here for the . and .. directories
nextdir = int_big_endian(de->DE_StartCluster);
}
} else {
return nextdir;
}
de++;
}
dwStartSector++;
}
return nextdir;
}
*/
// seek a file in the cluster, if found return the direntry
direntry *getfileentry(unsigned long a_cluster, char * filename) {
direntry *de;
unsigned long startsect = clust2sect(a_cluster);
int i;
while(checksect(startsect)){
de = (direntry * ) sector_data;
for(i=0;i<16;i++){
if(de->DE_Name[0] != SLOT_EMPTY) {
if(memcmp (de->DE_Name,filename,11) == 0) {
return de;
}
}
de++;
}
}
return NULL;
}
// amount of open files
filehandle filehandles[FILES+1] = 0;
// initialise the file system
void initfiles(void) {
unsigned char i;
// clear all start sectors so they will all be free
for (i = 0; i < FILES+1;i++)
filehandles[i].fh_startsect = 0;
}
// open file in current dir with FAT 11 char filenotation
unsigned char fopen (char *a_filename) {
direntry *file;
int i;
file = getfileentry(rootdir(),a_filename);
// has a file been found?
if(file == NULL)
// no exit and report
return 0;
else {
// yes, seek first empty entry
for(i = 1;i < FILES; i++) {
if(filehandles[i].fh_startsect == 0) {
// fill empty handle
filehandles[i].fh_startsect = clust2sect(int_big_endian(file->DE_StartCluster) | int_big_endian(file->DE_HighClust<<16));
filehandles[i].fh_fileptr = 0;
filehandles[i].fh_size = long_big_endian(file->DE_FileSize);
// return with handle number
return i;
}
}
return 0;
}
}
// position the file pointer
unsigned long fseek(unsigned char a_handle, unsigned long pos, char mode) {
if(a_handle < FILES+1) {
// set file pointer to pos
if(mode == 0) {
if(pos < filehandles[a_handle].fh_size) {
filehandles[a_handle].fh_fileptr = pos;
} else
return pos;
}
// set file pointer to end of file
if(mode == 1){
filehandles[a_handle].fh_fileptr = filehandles[a_handle].fh_size;
return filehandles[a_handle].fh_size;
}
}
else
return 0;
}
// close the handle
unsigned char fclose (unsigned char a_handle) {
if(a_handle < FILES+1) {
filehandles[a_handle].fh_startsect = 0;
}
else
return 0;
}
// read from file
unsigned char fread (unsigned char a_handle, char *a_buffer,unsigned int a_bytes) {
filehandle * currfile = & filehandles[a_handle];
int sects = a_bytes >> 9;
int rest = (a_bytes & 0x01FF);
long int startsect = currfile->fh_startsect;
long int size = currfile->fh_size;
long int bytesread=0;
// is the amount of bytes read greater than the total size
if((a_bytes + currfile->fh_fileptr) > currfile->fh_size)
// yes return
return 0;
// no proceed
for(sects;sects != 0;sects--){
// read whole multiples of 512
read_sector(startsect,sector_data);
memcpy(a_buffer,sector_data,512);
a_buffer = a_buffer + 512;
bytesread = bytesread + 512;
startsect++;
}
if(rest != 0){
// read the remainder
read_sector(startsect,sector_data);
memcpy(a_buffer,sector_data,rest);
bytesread = bytesread + rest;
startsect++;
}
// update filepointer
currfile->fh_fileptr = currfile->fh_fileptr + bytesread;
// return amount of data read
return bytesread;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -