📄 ftllite.c
字号:
/* ftllite.c - True Flash File System *//* Copyright 1984-2004 Wind River Systems, Inc. */#include "copyright_wrs.h"/* FAT-FTL Lite Software Development Kit * Copyright (C) M-Systems Ltd. 1995-1997 *//*modification history--------------------01i,12may05,jb3 Fix compile error01h,06may05,jb3 Changes for Datalight Reliance01g,06oct04,pmr turned off debugging.01f,29jul04,alr removed compilation warnings01e,29jul04,alr modified format header to ignore first 4 bytes (detection could break first 4 bytes in unit 0)01d,29jul04,alr modified format header to-do aligned writes (some MTDs don't allow mis-aligned writes)01c,29jul04,alr added sjk memory leak patch01b,29jul04,alr added (EAN) TFFS patches01a,29jul04,alr modified file header, restarted history*/#include "backgrnd.h"#include "flflash.h"#include "flbuffer.h"#include "fltl.h"#include "stdio.h"#include "logLib.h"/* better debug routines. EAN */#define DEBUG_LIGHT 1#define DEBUG_NORMAL 2#define DEBUG_INSANE 4#define DEBUG_LEVEL_LIGHT 1 /* only corruptions reported */#define DEBUG_LEVEL_NORMAL 3 /* corruptions and out of norms reported */#define DEBUG_LEVEL_INSANE 7 /* everything reported */#undef DEBUG_FTL /* turn on/off debug messages */#define DEBUG_LEVEL DEBUG_LEVEL_INSANE /* set debug level */#ifdef DEBUG_FTL/* sjk changed printf to logMsg */#define dbgMsg(num,msg,var1,var2,var3,var4,var5,var6) if(num & DEBUG_LEVEL) logMsg(msg,var1,var2,var3,var4,var5,var6);#else#define dbgMsg(num,msg,var1,var2,var3,var4,var5,var6)#endif/* Implementation constants and type definitions */#define SECTOR_OFFSET_MASK (SECTOR_SIZE - 1)typedef long int LogicalAddress; /* Byte address of media in logical unit no. order. */typedef long int VirtualAddress; /* Byte address of media as specified by Virtual Map. */typedef SectorNo LogicalSectorNo; /* A logical sector no. is given by dividing its logical address by the sector size */typedef SectorNo VirtualSectorNo; /* A virtual sector no. is such that the first page is no. 0, the 2nd is 1 etc. The virtual sector no. is given by dividing its virtual address by the sector size and adding the number of pages (result always positive). */typedef unsigned short UnitNo;#define ADDRESSES_PER_SECTOR (SECTOR_SIZE / sizeof(LogicalAddress))#define UNASSIGNED_ADDRESS 0xffffffffl#define DELETED_ADDRESS 0#define DELETED_SECTOR 0#define PAGE_SIZE_BITS (SECTOR_SIZE_BITS + (SECTOR_SIZE_BITS - 2))#define PAGE_SIZE (1L << PAGE_SIZE_BITS)/* Unit descriptor record */#define UNASSIGNED_UNIT_NO 0xffff#define MARKED_FOR_ERASE 0x7ffftypedef struct{ short noOfFreeSectors; short noOfGarbageSectors;} Unit;typedef Unit *UnitPtr;/* Structure of data on a unit */#define FREE_SECTOR 0xffffffffl#define GARBAGE_SECTOR 0#define ALLOCATED_SECTOR 0xfffffffel#define FORMAT_SECTOR 0x30#define DATA_SECTOR 0x40#define REPLACEMENT_PAGE 0x60#define BAD_SECTOR 0x70static char FORMAT_PATTERN[15] = {0x13, 3, 'C', 'I', 'S', 0x46, 57, 0, 'F', 'T', 'L', '1', '0', '0', 0};typedef struct{ char formatPattern[15]; unsigned char noOfTransferUnits; /* no. of transfer units */ LEulong wearLevelingInfo; LEushort logicalUnitNo; unsigned char log2SectorSize; unsigned char log2UnitSize; LEushort firstPhysicalEUN; /* units reserved for boot image */ LEushort noOfUnits; /* no. of formatted units */ LEulong virtualMediumSize; /* virtual size of volume */ LEulong directAddressingMemory; /* directly addressable memory */ LEushort noOfPages; /* no. of virtual pages */ unsigned char flags; unsigned char eccCode; LEulong serialNumber; LEulong altEUHoffset; LEulong BAMoffset; char reserved[12]; char embeddedCIS[4]; /* Actual length may be larger. By default, this contains FF's */} UnitHeader;/* flags assignments */#define HIDDEN_AREA_FLAG 1#define REVERSE_POLARITY_FLASH 2#define DOUBLE_BAI 4#define dummyUnit ((const UnitHeader *) 0) /* for offset calculations */#define logicalUnitNoOffset ((char *) &dummyUnit->logicalUnitNo - \ (char *) dummyUnit)#ifndef MALLOC_TFFS#define HEAP_SIZE \ ((0x100000l / PAGE_SIZE) * \ sizeof(LogicalSectorNo) + \ (0x100000l / ASSUMED_FTL_UNIT_SIZE) * \ (sizeof(Unit) + sizeof(UnitPtr))) * \ MAX_VOLUME_MBYTES + \ (ASSUMED_VM_LIMIT / SECTOR_SIZE) * \ sizeof(LogicalSectorNo)#endif#define cannotWriteOver(newContents, oldContents) \ ((newContents) & ~(oldContents))struct tTLrec{ FLBoolean badFormat; /* true if FTL format is bad */ VirtualSectorNo totalFreeSectors; /* Free sectors on volume */ SectorNo virtualSectors; /* size of virtual volume */ unsigned int unitSizeBits; /* log2 of unit size */ unsigned int erasableBlockSizeBits; /* log2 of erasable block size */ UnitNo noOfUnits; UnitNo noOfTransferUnits; UnitNo firstPhysicalEUN; int noOfPages; VirtualSectorNo directAddressingSectors;/* no. of directly addressable sectors */ VirtualAddress directAddressingMemory; /* end of directly addressable memory */ CardAddress unitOffsetMask; /* = 1 << unitSizeBits - 1 */ CardAddress bamOffset; unsigned int sectorsPerUnit; unsigned int unitHeaderSectors; /* sectors used by unit header */ Unit * physicalUnits; /* unit table by physical no. */ Unit ** logicalUnits; /* unit table by logical no. */ Unit * transferUnit; /* The active transfer unit */ LogicalSectorNo * pageTable; /* page translation table */ /* directly addressable sectors */ LogicalSectorNo replacementPageAddress; VirtualSectorNo replacementPageNo; SectorNo mappedSectorNo; const void FAR0 * mappedSector; CardAddress mappedSectorAddress; unsigned long currWearLevelingInfo;#ifdef BACKGROUND Unit * unitEraseInProgress; /* Unit currently being formatted */ FLStatus garbageCollectStatus; /* Status of garbage collection */ /* When unit transfer is in the background, and is currently in progress, all write operations done on the 'from' unit moust be mirrored on the transfer unit. If so, 'mirrorOffset' will be non-zero and will be the offset of the alternate address from the original. 'mirrorFrom' and 'mirrorTo' will be the limits of the original addresses to mirror. */ long int mirrorOffset; CardAddress mirrorFrom, mirrorTo;#endif#ifndef SINGLE_BUFFER FLBuffer * volBuffer; /* Define a sector buffer */#endif FLFlash flash;#ifndef MALLOC_TFFS char heap[HEAP_SIZE];#endif};typedef TLrec Flare;static Flare vols[DRIVES];#ifdef SINGLE_BUFFERextern FLBuffer buffer;#else#define buffer (*vol.volBuffer)/* Virtual map cache (shares memory with buffer) */#define mapCache ((LEulong *) buffer.data)#endif/* Unit header buffer (shares memory with buffer) */#define uh ((UnitHeader *) buffer.data)/* Transfer sector buffer (shares memory with buffer) */#define sectorCopy ((LEulong *) buffer.data)#define FREE_UNIT -0x400 /* Indicates a transfer unit *//*----------------------------------------------------------------------*//* p h y s i c a l B a s e *//* *//* Returns the physical address of a unit. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unit : unit pointer *//* *//* Returns: *//* physical address of unit *//*----------------------------------------------------------------------*/static CardAddress physicalBase(Flare vol, const Unit *unit){ return (CardAddress) (unit - vol.physicalUnits) << vol.unitSizeBits;}/*----------------------------------------------------------------------*//* l o g i c a l 2 P h y s i c a l *//* *//* Returns the physical address of a logical sector no. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* address : logical sector no. *//* *//* Returns: *//* CardAddress : physical address of sector *//*----------------------------------------------------------------------*/static CardAddress logical2Physical(Flare vol, LogicalSectorNo address){ return physicalBase(&vol,vol.logicalUnits[address >> (vol.unitSizeBits - SECTOR_SIZE_BITS)]) | (((CardAddress) address << SECTOR_SIZE_BITS) & vol.unitOffsetMask);}/*----------------------------------------------------------------------*//* m a p L o g i c a l *//* *//* Maps a logical sector and returns pointer to physical Flash location.*//* *//* Parameters: *//* vol : Pointer identifying drive *//* address : logical sector no. *//* *//* Returns: *//* Pointer to sector on Flash *//*----------------------------------------------------------------------*/static void FAR0 *mapLogical(Flare vol, LogicalSectorNo address){ return vol.flash.map(&vol.flash,logical2Physical(&vol,address),SECTOR_SIZE);}/*----------------------------------------------------------------------*//* a l l o c E n t r y O f f s e t *//* *//* Returns unit offset of given BAM entry *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorNo : BAM entry no. *//* *//* Returns: *//* Offset of BAM entry in unit *//*----------------------------------------------------------------------*/static int allocEntryOffset(Flare vol, int sectorNo){ return (int) (vol.bamOffset + sizeof(VirtualAddress) * sectorNo);}/*----------------------------------------------------------------------*//* m a p U n i t H e a d e r *//* *//* Map a unit header and return pointer to it. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unit : Unit to map header *//* *//* Returns: *//* Pointer to mapped unit header *//* blockAllocMap : (optional) Pointer to mapped BAM *//*----------------------------------------------------------------------*/static UnitHeader FAR0 *mapUnitHeader(Flare vol, const Unit *unit, LEulong FAR0 **blockAllocMap){ UnitHeader FAR0 *unitHeader; int length = sizeof(UnitHeader); if (blockAllocMap) length = allocEntryOffset(&vol,vol.sectorsPerUnit); unitHeader = (UnitHeader FAR0 *) vol.flash.map(&vol.flash,physicalBase(&vol,unit),length); if (blockAllocMap) *blockAllocMap = (LEulong FAR0 *) ((char FAR0 *) unitHeader + allocEntryOffset(&vol,0)); return unitHeader;}#ifndef SINGLE_BUFFER/*----------------------------------------------------------------------*//* s e t u p M a p C a c h e *//* *//* Sets up map cache sector to contents of specified Virtual Map page *//* *//* Parameters: *//* vol : Pointer identifying drive *//* pageNo : Page no. to copy to map cache *//* *//*----------------------------------------------------------------------*/static void setupMapCache(Flare vol, VirtualSectorNo pageNo){ vol.flash.read(&vol.flash,logical2Physical(&vol,vol.pageTable[pageNo]),mapCache,SECTOR_SIZE,0); if(pageNo == vol.replacementPageNo) { int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -