📄 fatfs_supp.c
字号:
//==========================================================================
//
// fatfs_supp.c
//
// FAT file system support functions
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
//
// eCos 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 or (at your option) any later version.
//
// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// 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.
//
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Savin Zlobec <savin@elatec.si>
// Date: 2003-06-30
//
//####DESCRIPTIONEND####
//
//==========================================================================
#include <pkgconf/fs_fat.h>
#include <pkgconf/infra.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/infra/cyg_ass.h>
#include <cyg/infra/cyg_trac.h>
#include <cyg/infra/diag.h>
#include <cyg/io/io.h>
#include <cyg/fs/fatfs.h>
#include <blib/blib.h>
#include <cyg/io/Disk.h>
#include <cyg/io/Diskio.h>
#include <sys/types.h>
#include <ctype.h>
#include "fatfs.h"
//==========================================================================
// FAT defines & macros
// -------------------------------------------------------------------------
// FAT dir entry attributes macros
#define DENTRY_IS_RDONLY(_dentry_) (S_FATFS_ISRDONLY((_dentry_)->attr))
#define DENTRY_IS_HIDDEN(_dentry_) (S_FATFS_ISHIDDEN((_dentry_)->attr))
#define DENTRY_IS_SYSTEM(_dentry_) (S_FATFS_ISSYSTEM((_dentry_)->attr))
#define DENTRY_IS_VOLUME(_dentry_) (S_FATFS_ISVOLUME((_dentry_)->attr))
#define DENTRY_IS_DIR(_dentry_) (S_FATFS_ISDIR((_dentry_)->attr))
#define DENTRY_IS_ARCHIVE(_dentry_) (S_FATFS_ISARCHIVE((_dentry_)->attr))
#define DENTRY_IS_LONG_NAME(_dentry_) (S_FATFS_ISLONG_NAME((_dentry_)->attr))
#define DENTRY_IS_LONG_NAME_MASK(_dentry_) (S_FATFS_ISLONG_NAME_MASK((_dentry_)->attr))
#define DENTRY_IS_DELETED(_dentry_) \
(0xE5 == (cyg_uint8)((_dentry_)->name[0]))
#define DENTRY_IS_ZERO(_dentry_) \
(0x00 == (cyg_uint8)((_dentry_)->name[0]))
// -------------------------------------------------------------------------
// FAT disk data access macros
// FIXME: support big endian machines!
#define GET_BYTE(_data_, _var_, _off_) \
(_var_ = *( ((cyg_uint8 *)_data_) + (_off_) ) )
#define GET_WORD(_data_, _var_, _off_) \
(_var_ = *( ((cyg_uint8 *)_data_) + (_off_) ) | \
*( ((cyg_uint8 *)_data_) + (_off_) + 1 ) << 8)
#define GET_DWORD(_data_, _var_, _off_) \
(_var_ = *( ((cyg_uint8 *)_data_) + (_off_)) | \
*( ((cyg_uint8 *)_data_) + (_off_) + 1 ) << 8 | \
*( ((cyg_uint8 *)_data_) + (_off_) + 2 ) << 16 | \
*( ((cyg_uint8 *)_data_) + (_off_) + 3 ) << 24)
#define GET_BYTES(_data_, _var_, _size_, _off_) \
memcpy((void *)(_var_), (void*)(((cyg_uint8 *)_data_)+(_off_)),_size_)
#define SET_BYTE(_data_, _val_, _off_) \
(*( ((cyg_uint8 *)_data_) + (_off_) ) = _val_)
#define SET_WORD(_data_, _val_, _off_) \
do { \
*( ((cyg_uint8 *)_data_) + (_off_) ) = _val_ & 0xFF; \
*( ((cyg_uint8 *)_data_) + (_off_) + 1 ) = (_val_ >> 8) & 0xFF; \
} while (0)
#define SET_DWORD(_data_, _val_, _off_) \
do { \
*( ((cyg_uint8 *)_data_) + (_off_) ) = _val_ & 0xFF; \
*( ((cyg_uint8 *)_data_) + (_off_) + 1 ) = (_val_ >> 8) & 0xFF; \
*( ((cyg_uint8 *)_data_) + (_off_) + 2 ) = (_val_ >> 16) & 0xFF; \
*( ((cyg_uint8 *)_data_) + (_off_) + 3 ) = (_val_ >> 24) & 0xFF; \
} while (0)
#define SET_BYTES(_data_, _var_, _size_, _off_) \
memcpy((void *)(((cyg_uint8 *)_data_)+(_off_)), (void *)(_var_), _size_)
// -------------------------------------------------------------------------
// FAT table entries types
#define TENTRY_REGULAR 0 // Used when entry points to next file cluster
#define TENTRY_FREE 1 // Free cluster
#define TENTRY_LAST 2 // Last cluster of file
#define TENTRY_RESERVED 3 // Reserved cluster
#define TENTRY_BAD 4 // Bad cluster
// -------------------------------------------------------------------------
// FAT table structures size
#define DENTRY_SIZE 0x20 // Dir entry size
// -------------------------------------------------------------------------
// Time & date defines
#define JD_1_JAN_1970 2440588 // 1 Jan 1970 in Julian day number
// -------------------------------------------------------------------------
// Code tracing defines
#ifdef FATFS_TRACE_DIR_ENTRY
# define TDE 1
#else
# define TDE 0
#endif
#ifdef FATFS_TRACE_CLUSTER
# define TCL 1
#else
# define TCL 0
#endif
#ifdef FATFS_TRACE_DATA
# define TDO 1
#else
# define TDO 0
#endif
//==========================================================================
// FAT structures
// -------------------------------------------------------------------------
// FAT table boot record structure
typedef struct fat_boot_record_s
{
cyg_uint16 jump; // 00h : Jump code
// cyg_uint8 jump0; // + NOP
char oem_name[8+1]; // 03h : OEM name
cyg_uint16 bytes_per_sec; // 0Bh : cyg_bytes per sector
cyg_uint8 sec_per_clu; // 0Dh : Sectors per cluster
cyg_uint16 res_sec_num; // 0Eh : Number of reserved sectors
cyg_uint8 fat_tbls_num; // 10h : Number of copies of fat
cyg_uint16 max_root_dents; // 11h : Maximum number of root dir entries
cyg_uint16 sec_num_32; // 13h : Number of sectors in partition < 32MB
cyg_uint8 media_desc; // 15h : Media descriptor
cyg_uint16 sec_per_fat; // 16h : Sectors per FAT
cyg_uint16 sec_per_track; // 18h : Sectors per track
cyg_uint16 heads_num; // 1Ah : Number of heads
cyg_uint32 hsec_num; // 1Ch : Number of hidden sectors
cyg_uint32 sec_num; // 20h : Number of sectors in partition
cyg_uint8 exe_marker[2]; // 1FEh: Executable marker (55h AAh)
// FAT32 specific fields
cyg_uint32 sec_per_fat_32; // 24h : Sectors per FAT
cyg_uint16 ext_flags; // 28h : Flags
cyg_uint16 fs_ver; // 2Ah : FS version
cyg_uint32 root_cluster; // 2Ch : Root dir cluster
cyg_uint16 fs_info_sec; // 30h : Sector number of FSINFO structure
cyg_uint16 bk_boot_sec; // 32h : Sector number of backup boot record
// cyg_uint8 reserved[12]; // 34h : Reserved
// Fields with different locations on FAT12/16 and FAT32
cyg_uint8 drv_num; // 24h (40h) : Drive number of partition
// cyg_uint8 reserved1; // 25h (41h) : Reserved 1
cyg_uint8 ext_sig; // 26h (42h) : Extended signature
cyg_uint32 ser_num; // 27h (43h) : Serial number of partition
char vol_name[11+1]; // 2Bh (47h) : Volume name of partition
char fat_name[8+1]; // 36h (52h) : FAT name
} fat_boot_record_t;
// -------------------------------------------------------------------------
// FAT dir entry structure
#pragma pack(1)
typedef struct fat_raw_short_dir_entry_s
{
char name[8+1]; // 00h : Name
char ext[3+1]; // 08h : Extension
cyg_uint8 attr; // 0Bh : Attribute
cyg_uint8 nt_reserved; // 0Ch : Win NT Reserved field
cyg_uint8 crt_sec_100; // 0Dh : Creation time ms stamp 0 - 199
cyg_uint16 crt_time; // 0Eh : Creation time
cyg_uint16 crt_date; // 10h : Creation date
cyg_uint16 acc_date; // 12h : Last access date
cyg_uint16 cluster_HI; // 14h : Starting cluster HI WORD (FAT32)
cyg_uint16 wrt_time; // 16h : Time
cyg_uint16 wrt_date; // 18h : Date
cyg_uint16 cluster; // 1Ah : Starting cluster
cyg_uint32 size; // 1Ch : Size of the file
} fat_raw_short_dir_entry_t;
typedef struct fat_raw_long_dir_entry_s
{
cyg_uint8 LDIR_Ord;
cyg_uint16 LDIR_Name1[5];
cyg_uint16 reserved;
cyg_uint8 attr;
cyg_uint8 LDIR_Type;
cyg_uint8 LDIR_Chksum;
cyg_uint16 LDIR_Name2[6];
unsigned short LDIR_FstClusLO;
cyg_uint16 LDIR_Name3[2];
}fat_raw_long_dir_entry_t;
#pragma pack(0)
// -------------------------------------------------------------------------
// FAT cluster opts
typedef enum cluster_opts_e
{
CO_NONE = 0x00, // NULL option
CO_EXTEND = 0x01, // Extend cluster chain if one cluster too short
CO_ERASE_NEW = 0x02, // Erase newly allocated cluster
CO_MARK_LAST = 0x04 // Mark newly allocated cluster as last
} cluster_opts_t;
//==========================================================================
// Utility functions
// -------------------------------------------------------------------------
// get_val_log2()
// Gets the log2 of given value or returns 0 if value is not a power of 2.
static cyg_uint32
get_val_log2(cyg_uint32 val)
{
cyg_uint32 i, log2;
i = val;
log2 = 0;
while (0 == (i & 1))
{
i >>= 1;
log2++;
}
if (i != 1) return 0;
else return log2;
}
static cyg_uint8 fatfs_chksum(cyg_uint8 *pFcbname)
{
short fcbname_len=0,pos=0;
cyg_uint8 sum,flag;
sum=0;
flag=0;
cyg_uint8 fs_name[11];
cyg_uint8 *p;
p=fs_name;
for(fcbname_len=0;fcbname_len<8;fcbname_len++)
{
if((pFcbname[fcbname_len]=='.'||pFcbname[fcbname_len]==0)&&
flag==0)
{
flag=1;
pos=fcbname_len;
}
if(flag==1)
{
fs_name[fcbname_len]=' ';
}
else
{
fs_name[fcbname_len]=pFcbname[fcbname_len];
}
}
if(pFcbname[pos]==0)
{
flag=1;
}
else
{
flag=0;
}
for(fcbname_len=8;fcbname_len<11;fcbname_len++)
{
if(pFcbname[fcbname_len]==0&&flag==0)
{
flag=1;
}
if(flag==1)
{
fs_name[fcbname_len]=' ';
}
if(pFcbname[fcbname_len]!='.'&& flag==0)
{
fs_name[fcbname_len]=pFcbname[fcbname_len];
}
}
for(fcbname_len=0;fcbname_len<11;fcbname_len++)
{
fs_name[fcbname_len]=toupper(fs_name[fcbname_len]);
}
for(fcbname_len=11;fcbname_len!=0;fcbname_len--)
{
sum=((sum&1)?0x80:0) +(sum>>1) + *p++;
}
return sum;
}
// -------------------------------------------------------------------------
// cluster_to_block_pos()
// Converts cluster position to blib block position.
static void
cluster_to_block_pos(fatfs_disk_t *disk,
cyg_uint32 cluster,
cyg_uint32 cluster_pos,
cyg_uint32 *block,
cyg_uint32 *block_pos)
{
cyg_uint32 block_size = cyg_blib_get_block_size(&disk->blib);
cyg_uint32 block_size_log2 = cyg_blib_get_block_size_log2(&disk->blib);
*block = (cluster - 2) << (disk->cluster_size_log2 - block_size_log2);
*block_pos = disk->fat_data_pos + cluster_pos;
if (*block_pos > block_size)
{
*block += *block_pos >> block_size_log2;
*block_pos = *block_pos & (block_size - 1);
}
}
// -------------------------------------------------------------------------
// disk_write()
// Writes data to disk.
static __inline__ int
disk_write(fatfs_disk_t *disk,
void *buf,
cyg_uint32 *len,
cyg_uint32 pos)
{
return cyg_blib_write(&disk->blib, buf, len, 0, pos);
}
// -------------------------------------------------------------------------
// disk_read()
// Reads data from disk.
static __inline__ int
disk_read(fatfs_disk_t *disk,
void *buf,
cyg_uint32 *len,
cyg_uint32 pos)
{
return cyg_blib_read(&disk->blib, buf, len, 0, pos);
}
//------------------
// disk_cluster_write()
// Writes data to disk at specified cluster position.
static __inline__ int
disk_cluster_write(fatfs_disk_t *disk,
void *buf,
cyg_uint32 *len,
cyg_uint32 cluster,
cyg_uint32 cluster_pos)
{
cyg_uint32 block, block_pos;
cluster_to_block_pos(disk, cluster, cluster_pos, &block, &block_pos);
return cyg_blib_write(&disk->blib, buf, len, block, block_pos);
}
// -------------------------------------------------------------------------
// disk_cluster_read()
// Reads data from disk at specified cluster position.
static __inline__ int
disk_cluster_read(fatfs_disk_t *disk,
void *buf,
cyg_uint32 *len,
cyg_uint32 cluster,
cyg_uint32 cluster_pos)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -