📄 fat.c
字号:
#include "datatype.h"
#include "file.h" /* file function definition */
#include "fat.h"
#include "hard.h"
/* fat file-system definition */
extern Uchar reserved_disk_space;
extern Byte gl_buffer[];
extern Byte fat_buf_sector[]; /* 512 bytes buffer */
extern Uint32 total_capacity;
extern char lfn_name[]; /* long filename limited to MAX_FILENAME_LEN chars */
extern char song_name[];
/* disk management */
extern Uint32 fat_ptr_fats; /* address of the first byte of FAT */
extern Uint32 fat_ptr_rdir; /* address of the first byte of root dir */
extern Uint32 fat_ptr_data; /* address of the first byte of data */
extern Byte fat_cluster_size; /* cluster size (sector count) */
extern Byte fat_cluster_mask; /* mask for end of cluster test */
extern Uchar dir_is_root; /* TRUE: point the root directory */
extern Uchar fat_is_fat16; /* TRUE: FAT16 - FALSE: FAT12 */
extern Uchar fat_is_fat32; /* TRUE: FAT32 - FALSE: FAT12/FAT16 */
extern Uchar fat_open_mode; /* READ or WRITE */
extern Uchar fat_2_is_present; /* TRUE: 2 FATs - FALSE: 1 FAT */
extern Uchar flag_end_disk_file;
extern Uint32 fat_count_of_clusters;/* number of cluster - 2 */
extern Uint16 fat_root_entry; /* position in root dir */
extern Union32 fat_file_size;
extern Uint16 fat_fat_size; /* FAT size in sector count */
extern Uint32 fat_nb_sector;
/* directory management */
extern Uint32 fat_dir_current_sect; /* sector of selected entry in dir list */
extern Uint16 fat_dir_list_index; /* index of current entry in dir list */
extern Uint16 fat_dir_list_last; /* index of last entry in dir list */
extern Uint16 fat_dclust_byte_count;/* byte counter in directory sector */
extern Uint16 fat_dchain_index; /* the number of the fragment of the dir, in fact*/
/* the index of the table in the cluster chain */
extern Byte fat_dchain_nb_clust; /* the offset of the cluster from the first cluster*/
/* of the dir fragment */
extern Uint32 fat_dir_start_sect; /* start sector of dir list */
extern Uint16 fat_dir_current_offs; /* entry offset from fat_dir_current_sect */
extern Byte fat_last_dclust_index;/* index of the last cluster in directory chain */
extern fat_st_cache fat_cache; /* The cache structure, see the .h for more info */
extern fat_st_clust_chain dclusters[MAX_DIR_FRAGMENT_NUMBER];
/* cluster chain for the current directory */
extern char ext[3]; /* file extension (limited to 3 characters) */
extern Byte fat_dir_entry_list[512];
//#define fat_dir_entry_list fat_buf_sector /* manual variable overlay */
/* file management */
extern Uint16 fat_fclust_byte_count;/* byte counter in file cluster */
extern Byte fat_last_clust_index; /* index of the last cluster in file chain */
extern Byte fat_fchain_index; /* the number of the fragment of the file, in fact*/
/*the index of the table in the cluster chain */
extern Uint16 fat_fchain_nb_clust; /* the offset of the cluster from the first cluster*/
/*of the file fragment */
extern fat_st_clust_chain fclusters[MAX_FILE_FRAGMENT_NUMBER];
/* cluster chain for the current file */
/* Mode repeat A/B variables */
extern Byte fat_fchain_index_save;
extern Byte fat_fchain_nb_clust_save;
extern Uint16 fat_fclust_byte_count_save;
extern Uint32 fat_bpb_add;
extern fat_st_free_space free_space;
//----------------------------------------------------------------------------
INT32U fat_caculate_offset(INT8U data0, INT8U data1, INT8U data2, INT8U data3)
{
INT32U u32Temp0;
INT32U u32Temp1;
INT32U u32Temp2;
INT32U u32Temp3;
u32Temp0 = data0;
u32Temp1 = data1;
u32Temp2 = data2;
u32Temp3 = data3;
u32Temp1 <<= 8;
u32Temp2 <<= 16;
u32Temp3 <<= 24;
return(u32Temp0 + u32Temp1 + u32Temp2 + u32Temp3);
}
/*F**************************************************************************
* NAME: fat_load_sector
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE:
* This function load a sector in fat_buf_sector
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*
*****************************************************************************/
INT8U fat_load_sector(Uint32 sector)
{
Uint16 i;
if(Hard_read_open(sector) == OK)
{
for (i = 0; i < (SECTOR_SIZE); i++)
{
fat_buf_sector[i] = gl_buffer[i];
}
return OK;
}
else
{
return KO;
}
}
/*F**************************************************************************
* NAME: fat_install
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
* - OK: intallation succeeded
* - KO: - partition 1 signature not recognized
* - FAT type is not FAT12/FAT16
* - sector size is not 512 bytes
* - MBR or PBR signatures are not correct
* - low level read open failure
*----------------------------------------------------------------------------
* PURPOSE:
* Install the fat system, read mbr, bootrecords...
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
* if MBR not found, try to mount unpartitionned FAT
* sector size is fixed to 512 bytes to simplify low level drivers
* fat_ptr_fats = partition offset + nb_reserved_sector
* fat_ptr_rdir = fat_ptr_fat + fat_size * nb_fat
* fat_ptr_data = fat_ptr_rdir + nb_root_entries * 32 / 512
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
INT8U fat_install (void)
{
Uint32 fat_nb_sector;
/* MBR/PBR determination */
fat_ptr_fats = 1;
if (fat_load_sector(MBR_ADDRESS) == OK)
{
if ((fat_buf_sector[0] == 0xEB) && /* PBR Byte 0 */
(fat_buf_sector[2] == 0x90) && /* PBR Byte 2 */
((fat_buf_sector[21] & 0xF0) == 0xF0)) /* PBR Byte 21 : Media byte */
{
if ((fat_buf_sector[510] != LOW(BR_SIGNATURE)) && /* check PBR signature */
(fat_buf_sector[511] != HIGH(BR_SIGNATURE)))
{
return KO;
}
else
{
fat_ptr_fats = 0x00000000; /* first sector is PBR */
}
}
else
{ /* first sector is MBR */
if ((fat_buf_sector[446] != PARTITION_ACTIVE) &&
(fat_buf_sector[446] != 0x00))
{
return KO; /* not a MBR */
}
else
{
/* read partition offset (in sectors) at offset 8 */
fat_ptr_fats = fat_caculate_offset(fat_buf_sector[454],
fat_buf_sector[455],
fat_buf_sector[456],
fat_buf_sector[457]
);
fat_bpb_add = fat_ptr_fats;
if ((fat_buf_sector[510] != LOW(BR_SIGNATURE)) && /* check PBR signature */
(fat_buf_sector[511] != HIGH(BR_SIGNATURE)))
{
return KO;
}
}
}
}
else
{
return KO;
}
/* read and check usefull PBR info */
if (fat_load_sector(fat_ptr_fats) == OK)
{
if ((fat_buf_sector[11] != LOW(SECTOR_SIZE)) || /* read sector size (in bytes) */
(fat_buf_sector[12] != HIGH(SECTOR_SIZE)))
{
return KO;
}
/* read cluster size (in sector) */
fat_cluster_size = fat_buf_sector[13];
fat_cluster_mask = HIGH((Uint16)fat_cluster_size * SECTOR_SIZE) - 1;
/* compute FATs sector address: add reserved sector number */
fat_ptr_fats += fat_buf_sector[14];
fat_ptr_fats += (Uint16)fat_buf_sector[15] << 8;
/* read number of FATs */
if (fat_buf_sector[16] == 2)
fat_2_is_present = TRUE;
else
fat_2_is_present = FALSE;
/* read number of dir entries and compute rdir offset */
fat_ptr_data = fat_caculate_offset(fat_buf_sector[17],fat_buf_sector[18],0,0);
fat_ptr_data = (fat_ptr_data * DIR_SIZE) / SECTOR_SIZE;
/* read number of sector in partition (<32Mb) */
fat_nb_sector = fat_caculate_offset(fat_buf_sector[19],fat_buf_sector[20],0,0);
/* compute root directory sector address */
fat_fat_size = (INT16U)fat_caculate_offset(fat_buf_sector[22],fat_buf_sector[23],0,0);
fat_ptr_rdir = fat_buf_sector[16] * fat_fat_size;
fat_ptr_rdir += fat_ptr_fats;
/* read number of sector in partition (>32Mb) */
if (!fat_nb_sector)
{
fat_nb_sector = fat_caculate_offset(fat_buf_sector[32],fat_buf_sector[33],fat_buf_sector[34],fat_buf_sector[35]);
// ((Byte*)&fat_nb_sector)[3] = fat_buf_sector[32];
// ((Byte*)&fat_nb_sector)[2] = fat_buf_sector[33];
// ((Byte*)&fat_nb_sector)[1] = fat_buf_sector[34];
// ((Byte*)&fat_nb_sector)[0] = fat_buf_sector[35];
}
total_capacity = fat_nb_sector;
fat_count_of_clusters = (fat_nb_sector - (1 + (fat_buf_sector[16] * fat_fat_size) + fat_ptr_data)) / fat_cluster_size;
if (fat_count_of_clusters <= MAX_CLUSTERS12)
{
fat_is_fat16 = FALSE;
fat_is_fat32 = FALSE;
}
else if(fat_count_of_clusters <= MAX_CLUSTERS16)
{
fat_is_fat16 = TRUE;
fat_is_fat32 = FALSE;
}
else
{
fat_is_fat16 = FALSE;
fat_is_fat32 = TRUE;
}/* else is FAT32 not supported */
/* compute data sector address */
fat_ptr_data += fat_ptr_rdir;
/* check partition signature */
if ((fat_buf_sector[510] != LOW(BR_SIGNATURE)) &&
(fat_buf_sector[511] != HIGH(BR_SIGNATURE)))
{
return KO;
}
return OK;
}
else
{ /* low level error */
return KO;
}
}
/*F**************************************************************************
* NAME: fat_dseek
*----------------------------------------------------------------------------
* PARAMS:
* offset: offset to current position in signed word value
*
* return:
*----------------------------------------------------------------------------
* PURPOSE:
* Seek from the current position to a new offset computing relative
* poisition +/- scan size limited to a 16 bit offset
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
* We consider here that the seek size is minor to the cluster size !!!
* if you want to do a more than a cluster seek, issue two successive
* dseek commands
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
Byte fat_dseek (Int16 offset)
{
Byte nb_sect; /* number of sectors to seek */
Uint16 nb_byte; /* number of bytes to seek */
Uint16 target_cluster; /* the cluster to reach */
Uint16 i;
fat_dir_current_offs += offset; /* Calculate the absolute byte pos */
nb_sect = (Byte)((fat_dir_current_offs) / SECTOR_SIZE);
fat_dir_current_sect = fat_dir_start_sect + nb_sect;
nb_byte = (Uint16)((fat_dir_current_offs) % (SECTOR_SIZE * fat_cluster_size));
fat_dclust_byte_count = nb_byte;
nb_byte %= SECTOR_SIZE;
if (dir_is_root == FALSE) /* Sub-directory ? */
{ /* Find the # cluster */
target_cluster = (nb_sect / fat_cluster_size);
fat_dchain_index = 0;
fat_dchain_nb_clust = 0;
for (i = 0; i <= target_cluster; i++)
{
if (dclusters[fat_dchain_index].number == fat_dchain_nb_clust)
{
fat_dchain_index++; /* next fragment */
fat_dchain_nb_clust = 1; /* reset the nb cluster in this new fragment */
}
else
{
fat_dchain_nb_clust++; /* next contiguous cluster */
}
}
/* update fat_dir_current_sect value */
fat_dir_current_sect = (((Uint32)(dclusters[fat_dchain_index].cluster + fat_dchain_nb_clust - 1) * fat_cluster_size)
+ fat_ptr_data + (nb_sect % fat_cluster_size));
if (!fat_dclust_byte_count)
{
if ((target_cluster == 0) || (dclusters[fat_dchain_index].number == 1)) /* If seek is first directory byte, reset */
{ /* fat_dchain_nb_clust (see fat_dgetc()) */
fat_dchain_nb_clust = 0;
}
}
}
Hard_read_close();
if (Hard_read_open(fat_dir_current_sect) == OK)
{ /* seek in current sector */
for (i = 0; i < nb_byte; i += 2)
{
Hard_read_byte(); /* dummy reads */
Hard_read_byte();
}
return OK;
}
else
{
return KO; /* low level error */
}
}
/*F**************************************************************************
* NAME: fat_dgetc
*----------------------------------------------------------------------------
* PARAMS:
*
* return:
*----------------------------------------------------------------------------
* PURPOSE:
* Return the directory data byte at the current position
*----------------------------------------------------------------------------
* EXAMPLE:
*----------------------------------------------------------------------------
* NOTE:
*----------------------------------------------------------------------------
* REQUIREMENTS:
*****************************************************************************/
Byte fat_dgetc (void)
{
/* check if we are at the end of a cluster */
if( ((Byte)(fat_dclust_byte_count) == 0x00) &&
((((Byte)(fat_dclust_byte_count >> 8)) & fat_cluster_mask) == 0x00) )
//if ((((Byte*)&fat_dclust_byte_count)[1] == 0x00) &&
// ((((Byte*)&fat_dclust_byte_count)[0] & fat_cluster_mask) == 0x00))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -