⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.c

📁 s3c6400 ADS下官方测试程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/*----------------------------------------------------------------------
 *
 * Filename: fat.cpp
 *
 * Contents:
 *
 * Contributors: Lee Yoonsu, Kang sungtae
 *
 * Copyright (c) 2006 SAMSUNG Electronics.
 *
 *----------------------------------------------------------------------
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "library.h"
#include "system.h"
#include "fat.h"

/*------------------------
 * FAT Data Structure
 *------------------------
 *
 * Boot Sector and BPB Structure (p.9)
 *------------------------------------
 *
 * m_usBpbBytsPerSec;
 *
 *   Count of bytes per sector.
 *   This value may take on only the following values: 512, 1024, 2048 or 4096.
 *   If maximum compatibility with old implementations is desired,
 *   only the value 512 should be used.
 *   There is a lot of FAT code in the world that is basically "hard wired" to 512 bytes per sector
 *   and doesn't bother to check this field to make sure it is 512.
 *   Microsoft operating systems will properly support 1024, 2048, and 4096.
 *   Note: Do not misinterpret these statements about maximum compatibility.
 *   If the media being recorded has a physical sector size N,
 *   you must use N and this must still be less than or equal to 4096.
 *   Maximum compatibility is achieved by only using media with specific sector sizes.
 *
 * m_ucBpbSecPerClus;
 *
 *   Number of sectors per allocation unit.
 *   This value must be a power of 2 that is greater than 0.
 *   The legal values are 1, 2, 4, 8, 16, 32, 64, and 128.
 *   Note however, that a value should never be used that results in
 *   a "bytes per cluster" value (m_usBpbBytsPerSec * m_ucBpbSecPerClus) greater than 32K (32 * 1024).
 *   There is a misconception that values greater than this are OK.
 *   Values that cause a cluster size greater than 32K bytes do not work properly; do not try to define one.
 *   Some versions of some systems allow 64K bytes per cluster value.
 *
 * m_usBpbRsvdSecCnt;
 *
 *   Number of reserved sectors in the Reserved region of the volume
 *   starting at the first sector of the volume.
 *   This field must not be 0.
 *   For FAT12 and FAT16 volumes, this value should never be anything
 *   other than 1. For FAT32 volumes, this value is typically 32.
 *   There is a lot of FAT code in the world "hard wired"
 *   to 1 reserved sector for FAT12 and FAT16 volumes and
 *   that doesn't bother to check this field to make sure it is 1.
 *   Microsoft operating systems will properly support any non-zero value in this field.
 *   Many application setup programs will not work correctly on such a FAT volume.
 *
 * m_usBpbRootEntCnt;
 *
 *   For FAT12 and FAT16 volumes,
 *   this field contains the count of 32-byte directory entries in the root directory.
 *   For FAT32 volumes, this field must be set to 0.
 *   For FAT12 and FAT16 volumes,
 *   this value should always specify a count that
 *   when multiplied by 32 results in an even multiple of m_usBpbBytsPerSec.
 *   For maximum compatibility, FAT16 volumes should use the value 512.
 *
 * USHORT BpbTotSec16;
 *
 *   This field is the old 16-bit total count of sectors on the volume.
 *   This count includes the count of all sectors in all four regions of the volume.
 *   This field can be 0; if it is 0, then BPB_TotSec32 must be non-zero.
 *   For FAT32 volumes, this field must be 0.
 *   For FAT12 and FAT16 volumes, this field contains the sector count,
 *   and BPB_TotSec32 is 0 if the total sector count "fits" (is less than 0x10000).
 *
 * m_ucBpbMedia;
 *
 *   non-removable(fixed) media - 0xF8
 *   removable media - 0xF0
 *   legal values - 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF.
 *
 * m_uBpbHiddSec;
 *
 *   Count of hidden sectors preceding the partition
 *   that contains this FAT volume.
 *   This field is generally only relevant for media visible on interrupt 0x13.
 *   This field should always be zero on media that are not partitioned.
 *   Exactly what value is appropriate is operating system specific.
 *
 * DWORD BPB_TotSec32;
 *
 *   new 32-bit total count of sectors on the volume.
 *   This count includes the count of all sectors in all four regions of the volume.
 *   This field can be 0; if it is 0, then BpbTotSec16 must be non-zero.
 *   For FAT32 volumes, this field must be non-zero.
 *   For FAT12/FAT16 volumes, this field contains the sector count
 *   if BpbTotSec16 is 0 (count is greater than or equal to 0x10000).
 *
 * m_uBpbTotSectors;
 *
 *   Integration of BpbTotSec16 and BPB_TotSec32
 *
 * m_uBpbRootClus;
 *
 *   FAT32 only.
 *   This is set to the cluster number of the first cluster of the root directory,
 *   usually 2 but not required to be 2.
 *
 * m_nEOC;
 *
 *   End of Cluster Mark
 *
 * FAT32 FSInfo Sector Structure and Backup Boot Sector (pp.21-22)
 *-----------------------------------------------------------------
 *
 * m_uFsiFreeCount;
 *
 *   the last known free cluster count on the volume.
 *   0xFFFFFFFF --> free count: unknown, so must be computed.
 *   range check: field value <= volume cluster count
 *
 * m_uFsiNxtFree;
 *
 *   This is a hint for the FAT driver.
 *   It indicates the cluster number at which the driver should start looking for free clusters.
 *   Because a FAT32 FAT is large, it can be rather time consuming
 *   if there are a lot of allocated clusters at the start of the FAT
 *   and the driver starts looking for a free cluster starting at cluster 2.
 *   Typically this value is set to the last cluster number that the driver allocated.
 *   0xFFFFFFFF --> there is no hint and the driver should start looking at cluster 2.
 *   Any other value can be used, but should be checked first
 *   to make sure it is a valid cluster number for the volume.
 *
 * m_uFsiLeadSig;
 *
 *   Value 0x41615252.
 *   This lead signature is used to validate that this is in fact an FSInfo sector.
 *
 * m_ucFileEntryHead replace the below data structure..
 *
 *   char DIR_Name[11];     	// p.23 refer to algorithm (DIR_Name[0])
 *   BYTE DIR_CrtTimeTenth; 	// file creation time millisecond stamp, valid: 0~199
 *   USHORT DIR_CrtTime;    	// Time file was created.
 *   USHORT DIR_CrtDate;    	// Date file was created.
 *   USHORT DIR_LstAccDate; 	// Last access date (read or write)
 *   USHORT DIR_WrtTime;    	// Time of last write. file creation is included in this case.
 *   USHORT DIR_WrtDate;    	// Date of last write. file creation is included in this case.
 *
 * FAT Long Directory Entry Structure (p.26~27)
 *---------------------------------------------
 *
 * m_ucLDirOrd;
 *
 *   The nOrder of this entry in the sequence of long dir entries
 *   associated with the short dir entry at the end of the long dir set.
 *   If masked with 0x40 (LAST_LONG_ENTRY),
 *   this indicates the entry is the last long dir entry in a set of long dir entries.
 *   All valid sets of long dir entries must begin with an entry having this mask.
 *
 * m_ucLDirAttr;
 *
 *   Attributes - must be ATTR_LONG_NAME
 */

typedef enum
{
 	IS_FAT12 = 3,
 	IS_FAT16 = 4,
 	IS_FAT32 = 8
} FATTYPE_T;

#if 0
typedef enum
{
	BUFF_READ,
	BUFF_WRITE
} BUFF_STATE;
#endif

typedef enum
{
	CLUSTER_CHAIN,
	CLUSTER_BPLUS,
	CLUSTER_BMINUS
} COPY_MODE;

#define UNICODE2CHAR 0
#define CHAR2UNICODE 1


#define FAT_FREE_CLUSTER 0x0
#define LAST_CLUSTER(x) (((x&oFat.m_nEOC)==oFat.m_nEOC)?1:0)


#define PATH_NAME_CHAR_SEPARATOR '.'
#define PATH_NAME_CHAR_DELIMITER '/'
#define PATH_NAME_CHAR_END       '\0'
#define PATH_NAME_CHAR_VALID(c) (((c>='A')&&(c<='Z'))|| \
	((c>='0')&&(c<='9'))||(c=='-')||(c=='_')||(c=='.')||(c=='/')||(c=='\0')||(c==' '))

#define FREE_ENTRY_TAG0 0xe5
#define TERM_ENTRY_TAG0 0x00
#define DOT_ENTRY_TAG0 0x2e
#define FREE_ENTRY_TAG 0x20e5
#define TERM_ENTRY_TAG 0x0000
#define DOT_ENTRY_TAG 0x202e
#define DOTDOT_ENTRY_TAG 0x2e2e

///#define ENTRY_COPY(p, x) memncpy(p, HD_dir_entry(x, 0), DIR_ENTRY_SIZE)

// Little Endian value caculation
#define LSB_GET_4BYTES(x) ((*((x)+3)) << 24) | ((*((x)+2)) << 16) | \
                            ((*((x)+1)) << 8) | ((*((x))))
#define LSB_GET_3BYTES(x) ((*((x)+2)) << 16) | \
                            ((*((x)+1)) << 8) | ((*((x))))
#define LSB_GET_2BYTES(x) ((*((x)+1)) << 8 ) | ((*((x))))
#define UNICODEtOCHAR(x)    ((*((x)+1)) << 16) | ((*((x))))

#define LSB_SET_4BYTES(p, x)    { *((p)+3)= 0x0ff&(x>>24) ;      \
                                *((p)+2) = 0x0ff&(x>>16);        \
                                *((p)+1) = 0x0ff&(x>>8);         \
                                *(p) = 0x00ff&x;  }
#define LSB_SET_3BYTES(p, x)    { *((p)+2) = 0xff&(x>>16);      \
                                *((p)+1) = 0xff&(x>>8);         \
                                *(p) = 0xff&x;  }
#define LSB_SET_2BYTES(p, x)    { *((p)+1) = 0xff&(x>>8);       \
                                *(p) = 0xff&x;  }

// FAT Volume Initialization  (p.20)
//   This is the table for FAT16 drives. NOTE that this table includes
//   entries for disk sizes larger than 512 MB even though typically
//   only the entries for disks < 512 MB in size are used.
//   The way this table is accessed is to look for the first entry
//   in the table for which the disk size is less than or equal
//   to the DiskSize field in that table entry.  For this table to
//   work properly m_usBpbRsvdSecCnt must be 1
//   must be 2, and m_usBpbRootEntCnt must be 512. Any of these values
//   being different may require the first table entries DiskSize value
//   to be changed otherwise the cluster count may be to low for FAT16.


DSKSZTOSECPERCLUS DskTableFAT16 [] = {
	{        8400,   0}, 	     // disks up to 4.1 MB, the 0 value for SecPerClusVal trips an ucNerror
	{      32680,   2},  	     // disks up to  16 MB,  1k cluster
	{    262144,   4},   	     // disks up to 128 MB,  2k cluster
	{   524288,    8},   	     // disks up to 256 MB,  4k cluster
	{ 1048576,  16},     	     // disks up to 512 MB,  8k cluster
	     	     // The entries after this point are not used unless FAT16 is forced
	{ 2097152,  32},     	     // disks up to   1 GB, 16k cluster
	{ 4194304,  64},     	     // disks up to   2 GB, 32k cluster
	{ 0xFFFFFFFF, 0}     	     // any disk greater than 2GB, 0 value for SecPerClusVal trips an ucNerror
};

//   This is the table for FAT32 drives. NOTE that this table includes
//   entries for disk sizes smaller than 512 MB even though typically
//   only the entries for disks >= 512 MB in size are used.
//   The way this table is accessed is to look for the first entry
//   in the table for which the disk size is less than or equal
//   to the DiskSize field in that table entry. For this table to
//   work properly m_usBpbRsvdSecCnt must be 32
//   must be 2. Any of these values being different may require the first
//   table entries DiskSize value to be changed otherwise the cluster count
//   may be to low for FAT32.

DSKSZTOSECPERCLUS DskTableFAT32 [] = {
	{       66600,   0},         // disks up to 32.5 MB, the 0 value for SecPerClusVal trips an ucNerror
	{     532480,   1},          // disks up to 260  MB,  .5k cluster
	{ 16777216,   8},            // disks up to   8  GB,   4k cluster
	{ 33554432, 16},             // disks up to   16 GB,   8k cluster
	{ 67108864, 32},             // disks up to   32 GB,  16k cluster
	{ 0xFFFFFFFF, 64}            // disks greater than 32GB, 32k cluster
};


// in DIR_Attr,
#define ATTR_READ_ONLY	0x01
#define ATTR_HIDDEN		0x02
#define ATTR_SYSTEM		0x04
#define ATTR_VOLUME_ID	0x08
#define ATTR_DIRECTORY	0x10
#define ATTR_ARCHIVE	0x20
#define ATTR_LONG_NAME	0x0f         //ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID
#define ATTR_LONG_NAME_MASK  0x3f    //ATTR_READ_ONLY|ATTR_HIDDEN|ATTR_SYSTEM|ATTR_VOLUME_ID|ATTR_DIRECTORY|ATTR_ARCHIVE
#define ATTR_FILES_ONLY 0x2f         // (ATTR_READ_ONLY|ATTR_HIDDEN|ATTR_SYSTEM|ATTR_ARCHIVE|ATTR_VOLUME_ID)
#define ATTR_DIR_FILES  0x3f         //(ATTR_FILES_ONLY|ATTR_DIRECTORY)
#define WRITE_CLUSTER
#define MAX_FILE_HANDLES        2
#define HDF_APPEND		0x0000
#define HDF_INSERT		0x0100
FATTYPE_T FATType;		             // FAT Type determination
//static HDFHANDLE *HDp, HDFhandle[MAX_FILE_HANDLES];  // each handle data for each file

FAT oFat;

//////////
// File Name : FAT_ReadFile1
// File Description : File Read function
// Input : file index, destination address, HSMMC_descriptor
// Output : NONE.
bool FAT_ReadFile1(s32 nIdx, u32 uDestAddr, SDHC* sCh)
{
	return (FAT_ReadFile(nIdx, (u8 *)uDestAddr, sCh) == 0) ? false : true;
}

//////////
// File Name : FAT_ReadFile2
// File Description : File Read function with file size.
// Input : file index, destination address, file size pointer, HSMMC_descriptor
// Output : NONE.
bool FAT_ReadFile2(s32 nIdx, u32 uDstAddr, u32* uFileSize, SDHC* sCh)
{
	*uFileSize = FAT_ReadFile(nIdx, (u8 *)uDstAddr, sCh);
	return (*uFileSize == 0) ? false : true;
}

//////////
// File Name : FAT_ReadFile3
// File Description : File Read function
// Input : file name, destination address, file size pointer, HSMMC_descriptor
// Output : NONE.
bool FAT_ReadFile3(const char* pFileName, u32 uDstAddr, u32* uFileSize, SDHC* sCh)
{
	int index;

	FAT_GetFileIndex(pFileName, (s32*)&index, sCh);
	*uFileSize = FAT_ReadFile(index, (u8 *)uDstAddr, sCh);
	return (*uFileSize == 0) ? false : true;
}

//////////
// File Name : FAT_ReadFile5
// File Description : File Read function
// Input : file name, block position, block count
// Output : NONE.
bool FAT_ReadFile5(const char* pFileName, u32 nBlockPos, u32 nBlocks, u32 uDestAddr, SDHC* sCh)
{
	int index;

	FAT_GetFileIndex(pFileName, (s32*)&index, sCh);
	return FAT_ReadFile4(index, nBlockPos, nBlocks, uDestAddr, sCh);
}

void FAT_GetNumOfFilesAndDirs(u32* uCount, SDHC* sCh)
{
	*uCount = oFat.m_nFileIndex;
}


///////////////////////////////
//   Array Manipulation     //
///////////////////////////////
bool FAT_CopyArray(u8* a, const u8* b, u32 n, SDHC* sCh)
{
	u32 i;

	for(i=0; i<n; i++)
	{
		*(a+i) = *(b+i);
	}
	return true;
}

void FAT_CompareArray(u8* a, const u8* b, u32 n, int* nComArray, SDHC* sCh)
{
	u32 i;

	for(i=0; i<n; i++)
	{
		if (*(a+i) < *(b+i))
		{
			*nComArray = -1;
		}
		else if (*(a+i) > *(b+i))
		{
			*nComArray = 1;
		}
	}
	// a is equal to b..
	*nComArray = 0;
}

//-----------------------------------------------------------------------
// In FAT32,
//  byte Directory Entry Structure (p.23~25)
//  DIR_Name, DIR_Attr, DIR_CrtTimeTenth, DIR_CrtTime, DIR_CrtDate,
//  DIR_LstAccDate, DIR_WrtTime, DIR_WrtDate
// In DIR_Attr,
//  FAT Long Directory Entry Structure (p.26~27)
//  Organization and Association of Short & Long Directory Entries (p.27)
//-----------------------------------------------------------------------

// Sequence of Long Directory Entries (p.27)

//-----------------------------------------------------------------------
// ChkSum()
//  Returns an unsigned byte checksum computed on an unsigned byte
//  array.  The array must be 11 bytes long and is assumed to contain
//  a name stored in the format of a MS-DOS directory entry.
// Passed:  pFcbName  Pointer to an unsigned byte array assumed to be
//                   11 bytes long.
// Returns: ucSum     An 8-bit unsigned checksum of the array pointed
//                   to by pFcbName.
//-----------------------------------------------------------------------

void FAT_ComputeChkSum (u8 *pFcbName, u8* uSum, SDHC* sCh)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -