/*
**********************************************************************
* Micrium, Inc.
* 949 Crestview Circle
* Weston, FL 33327-1848
*
* uC/FS
*
* (c) Copyright 2001 - 2003, Micrium, Inc.
* All rights reserved.
*
***********************************************************************
----------------------------------------------------------------------
File : fat_misc.c
Purpose : File system's FAT File System Layer misc routines
----------------------------------------------------------------------
Known problems or limitations with current version
----------------------------------------------------------------------
None.
---------------------------END-OF-HEADER------------------------------
*/
/*********************************************************************
*
* #include Section
*
**********************************************************************
*/
#include "fs_conf.h"
#include "fs_port.h"
#include "fs_dev.h"
#include "fs_api.h"
#include "fs_fsl.h"
#include "fs_int.h"
#include "fs_os.h"
#include "fs_lbl.h"
#include "fs_fat.h"
#include "fs_clib.h"
/*********************************************************************
*
* #define constants
*
**********************************************************************
*/
#ifndef FS_FAT_NOFAT32
#define FS_FAT_NOFAT32 0
#endif /* FS_FAT_NOFAT32 */
#ifndef FS_DIR_MAXOPEN
#define FS_DIR_MAXOPEN 0
#endif /* FS_DIR_MAXOPEN */
#define FS_MEMBLOCK_NUM (FS_MAXOPEN+FS_DIR_MAXOPEN)*2
/*********************************************************************
*
* Local data types
*
**********************************************************************
*/
typedef struct {
int status;
char memory[FS_FAT_SEC_SIZE];
} _FS_FAT_block_type;
/*********************************************************************
*
* Local Variables
*
**********************************************************************
*/
static _FS_FAT_block_type _FS_memblock[FS_MEMBLOCK_NUM];
/*********************************************************************
*
* Local functions section
*
**********************************************************************
*/
/*********************************************************************
*
* _FS_ReadBPB
*
Description:
FS internal function. Read Bios-Parameter-Block from a device and
copy the relevant data to FS__FAT_aBPBUnit.
Parameters:
Idx - Index of device in the device information table
referred by FS__pDevInfo.
Unit - Unit number.
Return value:
==0 - BPB successfully read.
<0 - An error has occured.
*/
static int _FS_ReadBPB(int Idx, FS_u32 Unit) {
int err;
unsigned char *buffer;
buffer = (unsigned char*)FS__fat_malloc(FS_FAT_SEC_SIZE);
if (!buffer) {
return -1;
}
err = FS__lb_read(FS__pDevInfo[Idx].devdriver, Unit, 0, (void*)buffer);
if (err < 0) {
FS__fat_free(buffer);
return -1;
}
/* Assign FS__FAT_aBPBUnit */
FS__FAT_aBPBUnit[Idx][Unit].BytesPerSec = buffer[11] + 256 * buffer[12]; /* _512_,1024,2048,4096 */
FS__FAT_aBPBUnit[Idx][Unit].SecPerClus = buffer[13]; /* sec in allocation unit */
FS__FAT_aBPBUnit[Idx][Unit].RsvdSecCnt = buffer[14] + 256 * buffer[15]; /* 1 for FAT12 & FAT16 */
FS__FAT_aBPBUnit[Idx][Unit].NumFATs = buffer[16]; /* 2 */
FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt = buffer[17] + 256 * buffer[18]; /* number of root dir entries */
FS__FAT_aBPBUnit[Idx][Unit].TotSec16 = buffer[19] + 256 * buffer[20]; /* RSVD + FAT + ROOT + FATA (<64k) */
FS__FAT_aBPBUnit[Idx][Unit].FATSz16 = buffer[22] + 256 * buffer[23]; /* number of FAT sectors */
FS__FAT_aBPBUnit[Idx][Unit].TotSec32 = buffer[32] + 0x100UL * buffer[33] /* RSVD + FAT + ROOT + FATA (>=64k) */
+ 0x10000UL * buffer[34]
+ 0x1000000UL * buffer[35];
if (FS__FAT_aBPBUnit[Idx][Unit].FATSz16 == 0) {
FS__FAT_aBPBUnit[Idx][Unit].FATSz32 = buffer[36] + 0x100UL * buffer[37] /* number of FAT sectors */
+ 0x10000UL * buffer[38]
+ 0x1000000UL * buffer[39];
FS__FAT_aBPBUnit[Idx][Unit].ExtFlags = buffer[40] + 256 * buffer[41]; /* mirroring info */
FS__FAT_aBPBUnit[Idx][Unit].RootClus = buffer[44] + 0x100UL * buffer[45] /* root dir clus for FAT32 */
+ 0x10000UL * buffer[46]
+ 0x1000000UL * buffer[47];
FS__FAT_aBPBUnit[Idx][Unit].FSInfo = buffer[48] + 256 * buffer[49]; /* position of FSInfo structure */
}
else {
FS__FAT_aBPBUnit[Idx][Unit].FATSz32 = 0;
FS__FAT_aBPBUnit[Idx][Unit].ExtFlags = 0;
FS__FAT_aBPBUnit[Idx][Unit].RootClus = 0;
FS__FAT_aBPBUnit[Idx][Unit].FSInfo = 0;
}
FS__FAT_aBPBUnit[Idx][Unit].Signature = buffer[FS_FAT_SEC_SIZE-2]
+ 256 * buffer[FS_FAT_SEC_SIZE-1];
FS__fat_free(buffer);
return err;
}
/*********************************************************************
*
* _FS__fat_FindFreeCluster
*
Description:
FS internal function. Find the next free entry in the FAT.
Parameters:
Idx - Index of device in the device information table
referred by FS__pDevInfo.
Unit - Unit number.
pFATSector - Returns the sector number of the free entry.
pLastSector - Returns the sector number of the sector in pBuffer.
pFATOffset - Returns the offset of the free FAT entry within the
sector pFATSector.
LastClust - Cluster, which will be used to link the new allocated
cluster to. Here it is used at hint for where to start
in the FAT.
pBuffer - Pointer to a sector buffer.
FSysType - ==1 => FAT12
==0 => FAT16
==2 => FAT32
FATSize - Size of one FAT ind sectors.
BytesPerSec - Number of bytes in each sector.
Return value:
>=0 - Number of the free cluster.
<0 - An error has occured.
*/
static FS_i32 _FS__fat_FindFreeCluster(int Idx, FS_u32 Unit, FS_i32 *pFATSector,
FS_i32 *pLastSector, FS_i32 *pFATOffset,
FS_i32 LastClust, unsigned char *pBuffer,
int FSysType, FS_u32 FATSize, FS_i32 BytesPerSec) {
FS_u32 totclst;
FS_u32 rootdirsize;
FS_i32 curclst;
FS_i32 fatindex;
int err;
int scan;
unsigned char fatentry;
unsigned char a;
unsigned char b;
#if (FS_FAT_NOFAT32==0)
unsigned char c;
unsigned char d;
#endif
if (LastClust > 0) {
curclst = LastClust + 1; /* Start scan after the previous allocated sector */
}
else {
curclst = 0; /* Start scan at the beginning of the media */
}
scan = 0;
*pFATSector = 0;
*pLastSector = -1;
fatentry = 0xff;
/* Calculate total number of data clusters on the media */
totclst = (FS_u32)FS__FAT_aBPBUnit[Idx][Unit].TotSec16;
if (totclst == 0) {
totclst = FS__FAT_aBPBUnit[Idx][Unit].TotSec32;
}
rootdirsize = ((FS_u32)((FS_u32)FS__FAT_aBPBUnit[Idx][Unit].RootEntCnt) * FS_FAT_DENTRY_SIZE) / BytesPerSec;
totcls