📄 fat16.c
字号:
/* Includes ------------------------------------------------------------------*/
#include "fat16.h"
#include <string.h>
#if USE_DYNAMIC_MEMORY
#include <stdlib.h>
#endif
#define FAT16_CLUSTER_FREE 0x0000
#define FAT16_CLUSTER_RESERVED_MIN 0xfff0
#define FAT16_CLUSTER_RESERVED_MAX 0xfff6
#define FAT16_CLUSTER_BAD 0xfff7
#define FAT16_CLUSTER_LAST_MIN 0xfff8
#define FAT16_CLUSTER_LAST_MAX 0xffff
#define FAT16_DIRENTRY_DELETED 0xe5
#define FAT16_DIRENTRY_LFNLAST (1 << 6)
#define FAT16_DIRENTRY_LFNSEQMASK ((1 << 6) - 1)
/* Each entry within the directory table has a size of 32 bytes
* and either contains a 8.3 DOS-style file name or a part of a
* long file name, which may consist of several directory table
* entries at once.
*
* multi-byte integer values are stored little-endian!
*
* 8.3 file name entry:
* ====================
* offset length description
* 0 8 name (space padded)
* 8 3 extension (space padded)
* 11 1 Attributes (FAT16_ATTRIB_*)
*
* long file name (lfn) entry ordering for a single file name:
* ===========================================================
* LFN entry n
* ...
* LFN entry 2
* LFN entry 1
* 8.3 entry (see above)
*
* lfn entry:
* ==========
* offset length description
* 0 1 ordinal field
* 1 2 unicode character 1
* 3 3 unicode character 2
* 5 3 unicode character 3
* 7 3 unicode character 4
* 9 3 unicode character 5
* 11 1 attribute (always 0x0f)
* 12 1 type (reserved, always 0)
* 13 1 checksum
* 14 2 unicode character 6
* 16 2 unicode character 7
* 18 2 unicode character 8
* 20 2 unicode character 9
* 22 2 unicode character 10
* 24 2 unicode character 11
* 26 2 Cluster (unused, always 0)
* 28 2 unicode character 12
* 30 2 unicode character 13
*
* The ordinal field contains a descending number, from n to 1.
* For the n'th lfn entry the ordinal field is or'ed with 0x40.
* For deleted lfn entries, the ordinal field is set to 0xe5.
*/
struct Fat16_Header_Struct
{
u32 Size;
u32 Fat_Offset;
u32 Fat_Size;
u16 Sector_Size;
u16 Cluster_Size;
u32 Root_Dir_Offset;
u32 Cluster_Zero_Offset;
};
struct Fat16_FS_Struct
{
struct Partition_Struct* partition;
struct Fat16_Header_Struct header;
};
struct Fat16_File_Struct
{
struct Fat16_FS_Struct* fs;
struct Fat16_Dir_Entry_Struct dir_entry;
u32 pos;
u16 pos_cluster;
};
struct Fat16_Dir_Struct
{
struct Fat16_FS_Struct* fs;
struct Fat16_Dir_Entry_Struct dir_entry;
u16 entry_next;
};
struct Fat16_Read_CallBack_Arg
{
u16 Entry_Cur;
u16 Entry_Num;
u32 Entry_Offset;
u8 Byte_Count;
};
struct Fat16_Usage_Count_CallBack_Arg
{
u16 cluster_count;
u8 buffer_size;
};
#if !USE_DYNAMIC_MEMORY
static struct Fat16_FS_Struct fat16_fs_handlers[FAT16_FS_COUNT];
static struct Fat16_File_Struct fat16_file_handlers[FAT16_FILE_COUNT];
static struct Fat16_Dir_Struct fat16_dir_handlers[FAT16_DIR_COUNT];
#endif
static u8 Fat16_Read_Header(struct Fat16_FS_Struct* fs);
static u8 Fat16_Read_Root_Dir_Entry(const struct Fat16_FS_Struct* fs,
u16 Entry_Num,
struct Fat16_Dir_Entry_Struct* dir_entry);
static u8 Fat16_Read_Sub_Dir_Entry(const struct Fat16_FS_Struct* fs,
u16 Entry_Num,
const struct Fat16_Dir_Entry_Struct* parent,
struct Fat16_Dir_Entry_Struct* dir_entry);
static u8 Fat16_Dir_Entry_Seek_CallBack(u8* buffer, u32 offset, void* p);
static u8 Fat16_Dir_Entry_Read_CallBack(u8* buffer, u32 offset, void* p);
static u8 Fat16_Interpret_Dir_Entry(struct Fat16_Dir_Entry_Struct* dir_entry, const u8* raw_entry);
static u16 Fat16_Get_Next_Cluster(const struct Fat16_FS_Struct* fs, u16 cluster_num);
static u16 Fat16_Append_Clusters(const struct Fat16_FS_Struct* fs, u16 cluster_num, u16 count);
static u8 Fat16_Free_Clusters(const struct Fat16_FS_Struct* fs, u16 cluster_num);
static u8 Fat16_Terminate_Clusters(const struct Fat16_FS_Struct* fs, u16 cluster_num);
static u8 Fat16_Clear_Cluster(const struct Fat16_FS_Struct* fs, u16 cluster_num);
static u16 Fat16_Clear_Cluster_CallBack(u8* buffer, u32 offset, void* p);
static u32 Fat16_Find_Offset_For_Dir_Entry(const struct Fat16_FS_Struct* fs,
const struct Fat16_Dir_Struct* parent,
const struct Fat16_Dir_Entry_Struct* dir_entry);
static u8 Fat16_Write_Dir_Entry(const struct Fat16_FS_Struct* fs,
struct Fat16_Dir_Entry_Struct* dir_entry);
static u8 Fat16_Get_FS_Free_CallBack(u8* buffer, u32 offset, void* p);
//static void fat16_set_file_modification_date(struct Fat16_Dir_Entry_Struct* dir_entry, u16 year, u8 month, u8 day);
//static void fat16_set_file_modification_time(struct Fat16_Dir_Entry_Struct* dir_entry, u8 hour, u8 min, u8 sec);
/**********************************************************************
* 函数 Fat16_Open --- 打开FAT16文件系统
* 输入参数 partition:文件系统所在的分区
* 返回值 0 ---打开错误
* 其他 ---文件系统信息
**********************************************************************/
struct Fat16_FS_Struct*
Fat16_Open(struct Partition_Struct* partition)
{
if(!partition ||
#if FAT16_WRITE_SUPPORT
!partition->device_write ||
!partition->device_write_interval
#else
False
#endif
)
return False;
#if USE_DYNAMIC_MEMORY
struct Fat16_FS_Struct* fs = malloc(sizeof(*fs));
if(!fs) return False;
#else
struct Fat16_FS_Struct* fs = fat16_fs_handlers;
u8 i;
for(i = 0; i < FAT16_FS_COUNT; ++i)
{
if(!fs->partition)
break;
++fs;
}
if(i >= FAT16_FS_COUNT) return False;
#endif
memset(fs, 0, sizeof(*fs));
fs->partition = partition;
if(!Fat16_Read_Header(fs))
{
#if USE_DYNAMIC_MEMORY
free(fs);
#else
fs->partition = 0;
#endif
return False;
}
return fs;
}
/**********************************************************************
* 函数 Fat16_Close --- 关闭FAT16文件系统
* 输入参数 fs:所需关闭的文件系统
* 返回值 无
**********************************************************************/
void
Fat16_Close(struct Fat16_FS_Struct* fs)
{
if(!fs)
return;
#if USE_DYNAMIC_MEMORY
free(fs);
#else
fs->partition = 0;
#endif
}
/**********************************************************************
* 函数 Fat16_Read_Header --- 读取并解释 the header of a FAT16 filesystem
* 输出参数 fs:The filesystem for which to parse the header.
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Read_Header(struct Fat16_FS_Struct* fs)
{
if(!fs)
return False;
struct Partition_Struct* partition = fs->partition;
if(!partition)
return False;
/* read fat parameters */
u8 buffer[25];
u32 partition_offset = partition->offset * 512;
if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer)))
return False;
u16 bytes_per_sector = ((u16) buffer[0x00]) |
((u16) buffer[0x01] << 8);
u8 sectors_per_cluster = buffer[0x02];
u16 reserved_sectors = ((u16) buffer[0x03]) |
((u16) buffer[0x04] << 8);
u8 fat_copies = buffer[0x05];
u16 max_root_entries = ((u16) buffer[0x06]) |
((u16) buffer[0x07] << 8);
u16 sector_count_16 = ((u16) buffer[0x08]) |
((u16) buffer[0x09] << 8);
u16 sectors_per_fat = ((u16) buffer[0x0b]) |
((u16) buffer[0x0c] << 8);
u32 sector_count = ((u32) buffer[0x15]) |
((u32) buffer[0x16] << 8) |
((u32) buffer[0x17] << 16) |
((u32) buffer[0x18] << 24);
if(sectors_per_fat == 0)
/* this is not a FAT16 */
return False;
if(sector_count == 0)
{
if(sector_count_16 == 0)
/* illegal volume size */
return False;
else
sector_count = sector_count_16;
}
/* ensure we really have a FAT16 fs here */
u32 data_sector_count = sector_count
- reserved_sectors
- (u32) sectors_per_fat * fat_copies
- ((max_root_entries * 32 + bytes_per_sector - 1) / bytes_per_sector);
u32 data_cluster_count = data_sector_count / sectors_per_cluster;
if(data_cluster_count < 4085 || data_cluster_count >= 65525)
/* this is not a FAT16 */
return False;
partition->type = PARTITION_TYPE_FAT16;
/* fill header information */
struct Fat16_Header_Struct* header = &fs->header;
memset(header, 0, sizeof(*header));
header->Size = sector_count * bytes_per_sector;
header->Fat_Offset = /* jump to partition */
partition_offset +
/* jump to fat */
(u32) reserved_sectors * bytes_per_sector;
header->Fat_Size = (data_cluster_count + 2) * 2;
header->Sector_Size = bytes_per_sector;
header->Cluster_Size = (u32) bytes_per_sector * sectors_per_cluster;
header->Root_Dir_Offset = /* jump to fats */
header->Fat_Offset +
/* jump to root directory entries */
(u32) fat_copies * sectors_per_fat * bytes_per_sector;
header->Cluster_Zero_Offset = /* jump to root directory entries */
header->Root_Dir_Offset +
/* skip root directory entries */
(u32) max_root_entries * 32;
return True;
}
/**********************************************************************
* 函数 Fat16_Read_Root_Dir_Entry
* --- 读取目录项的根目录
* 输入参数 fs:文件系统
* Entry_Num:目录项标号
* 输出参数 dir_entry:输出目录结构参数
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Read_Root_Dir_Entry(const struct Fat16_FS_Struct* fs,
u16 Entry_Num,
struct Fat16_Dir_Entry_Struct* dir_entry)
{
if(!fs || !dir_entry)
return 0;
/* we read from the root directory entry */
const struct Fat16_Header_Struct* header = &fs->header;
device_read_interval_t device_read_interval = fs->partition->device_read_interval;
u8 buffer[32];
/* seek to the n-th entry */
struct Fat16_Read_CallBack_Arg arg;
memset(&arg, 0, sizeof(arg));
arg.Entry_Num = Entry_Num;
if(!device_read_interval(header->Root_Dir_Offset,
buffer,
sizeof(buffer),
header->Cluster_Zero_Offset - header->Root_Dir_Offset,
Fat16_Dir_Entry_Seek_CallBack,
&arg) ||
arg.Entry_Offset == 0
)
return 0;
/* read entry */
memset(dir_entry, 0, sizeof(*dir_entry));
if(!device_read_interval(arg.Entry_Offset,
buffer,
sizeof(buffer),
arg.Byte_Count,
Fat16_Dir_Entry_Read_CallBack,
dir_entry))
return 0;
return dir_entry->Long_Name[0] != '\0' ? 1 : 0;
}
/**********************************************************************
* 函数 Fat16_Read_Sub_Dir_Entry
* --- 读取下级目录
* 输入参数 fs:文件系统
* Entry_Num:子目录项标号
* parent:父目录
* 输出参数 dir_entry:输出目录结构参数
* 返回值 0 --- 失败
* 1 --- 成功
**********************************************************************/
u8
Fat16_Read_Sub_Dir_Entry(const struct Fat16_FS_Struct* fs,
u16 Entry_Num,
const struct Fat16_Dir_Entry_Struct* parent,
struct Fat16_Dir_Entry_Struct* dir_entry)
{
if(!fs || !parent || !dir_entry)
return 0;
/* we are in a parent directory and want to search within its directory entry table */
if(!(parent->Attributes & FAT16_ATTRIB_DIR))
return 0;
/* loop through all clusters of the directory */
u8 buffer[32];
u32 cluster_offset;
u16 Cluster_Size = fs->header.Cluster_Size;
u16 cluster_num = parent->Cluster;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -