📄 extfiltr.c
字号:
/****************************************************************************** * * * Project: DOC Driver for Linux 2.4 Block device driver for mDOC H3 family * * of devices under Linux kernel 2.4. * * * * Version: 1.0 * * Email questions to: oemsupport@sandisk.com * * Copyright (C) SanDisk IL Ltd. 1995 - 2007 * * SanDisk IL Ltd., 7 Atir Yeda Street, Kfar Saba 44425, Israel * * * ****************************************************************************** * * * This program 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 of the License, or any later version.* * This program 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, which is set forth in the readme.txt file. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., 51 * * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * * * This License does not grant you any right to use the trademarks, service * * marks or logos of SanDisk IL Ltd. or SanDisk Corporation. * * Subject to the foregoing, SanDisk IL Ltd., for itself and on behalf of its * * licensors, hereby reserves all intellectual property rights in the program,* * except for the rights expressly granted in this License. * * * ******************************************************************************//* * $Log$ */#include "tffsdrv.h"#ifndef TFFS_DEBUG_EXTFILTER# undef TFFS_DEBUG_DRIVER#endif/* min: 0x40000 == sect>>9 == 256 blocks/group * 1024 bytes/blocktypical: 0x800000 == sect>>15 == 8192 blocks/group * 1024 bytes/blockdefault: 0x100000 == sect>>12 == 1M */# define TFFS_EXTF_CACHE_STEP 12#define EXTF_CACHE_MASK ((1<<TFFS_EXTF_CACHE_STEP)-1)/* blocks per group must be multiple of 8, >= 256, <= 8*blocksize *//* all offsets of SB/GD are including first empty block, block bitmap doesn't */#ifdef TFFS_USE_RAM# include "tffsram.h"#else# include "blockdev.h"#endifstatic unsigned char pTmp[512];#ifdef TFFS_DEBUG_DRIVERstatic unsigned long dwSearches=0,dwSteps=0;#endifunsigned char ExtReadSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char*p);unsigned char ExtDelSector(DeviceInfo*pDevice,unsigned long dwSector,unsigned char bSectors);void AddSect(DeviceInfo*pDevice,SectInfo*pSect);SectInfo*DelSect(DeviceInfo*pDevice,SectInfo*pSect);void CacheSect(DeviceInfo*pDevice,SectInfo*pSect);void UncacheSect(DeviceInfo*pDevice,SectInfo*pSect);#define PTChanged(pSect,pData) 1void AddPT(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pBuff);void DelPT(DeviceInfo*pDevice,SectInfo*pPT);#ifdef TFFS_DEBUG_DRIVERunsigned char SBChanged(SectInfo*pSect,struct ext2_super_block*pSB){ if(le32_to_cpu(pSB->s_log_block_size) != pSect->bSect2BlockShift-1) { PrintkDebug("SBChanged: s_log_block_size different: %d -> %d",(int)pSect->bSect2BlockShift-1,(int)pSB->s_log_block_size); return 1; } if(le32_to_cpu(pSB->s_blocks_per_group) != pSect->dwBlocksPerBitmap) { PrintkDebug("SBChanged: s_blocks_per_group different: %d -> %d",(int)pSect->dwBlocksPerBitmap,(int)pSB->s_blocks_per_group); return 1; } if(pSB->s_feature_compat != pSect->dwExt3Flags) { PrintkDebug("SBChanged: s_feature_compat different: %d -> %d",(int)pSect->dwExt3Flags,(int)pSB->s_feature_compat); return 1; } PrintkDebug("SBChanged: not changed"); return 0;}#else# define SBChanged(pSect,pSB) ( ( le32_to_cpu((pSB)->s_log_block_size) != (pSect)->bSect2BlockShift-1 ) || ( le32_to_cpu((pSB)->s_blocks_per_group) != (pSect)->dwBlocksPerBitmap ) || ((pSB)->s_feature_compat!=(pSect)->dwExt3Flags))#endifvoid AddSB(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_super_block*pSB);void DelSB(DeviceInfo*pDevice,SectInfo*pPart);void AddGD(DeviceInfo*pDevice,SectInfo*pSect,struct ext2_group_desc*pGD,unsigned char bOffset);void ProcessBB(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pOld,unsigned char*pNew,unsigned char bOffset);#ifdef TFFS_DEBUG_DRIVERvoid PrintSect(SectInfo*pSect,char*p){ char*str; switch(pSect->bFlag) { case EXTF_PT: str="PT empty"; break; case EXTF_HAS_PT: str="PT"; break; case EXTF_SB: str="SB empty"; break; case EXTF_HAS_SB: str="SB"; break; case EXTF_HAS_GD: str="SB&GD"; break; case EXTF_BB: str="BB not adjusted"; break; case EXTF_HAS_BB: str="BB"; break; case 0: str="last sect"; break; default: str="BAD FLAG"; } PrintkDebug("%s: %s part %d sect %lu len %u flag %d",p,str,pSect->no,pSect->dwSector,pSect->bSectors,pSect->bFlag);}void PrintAllSect(DeviceInfo*pDevice){ SectInfo*pSect=&pDevice->sect[0]; do{ PrintSect(pSect,"LIST"); pSect=pSect->pNext; }while(pSect!=&pDevice->sect[0]);}void Printp(unsigned char*p){ int i,k; for(i=0;i<32;i++) { for(k=0;k<16;k++) printk("%2x ",*(p+((i<<4)+k))); printk("\n"); }}#else# define PrintAllSect(pDevice)# define PrintSect(pSect,p)# define Printp(p)#endifvoid ExtFilter(DeviceInfo*pDevice,unsigned char*pBuff,unsigned long dwSector,unsigned long dwSectors){ SectInfo*pSect=pDevice->pCache[dwSector>>TFFS_EXTF_CACHE_STEP]; unsigned long dwSect=dwSector; PrintkDebug("ExtFilter: dev %d sec 0x%lx + 0x%lx",pDevice->diskNo,dwSector,dwSectors); while(dwSect<dwSectors+dwSector) { unsigned char*pData; while(dwSect>=pSect->dwSector+pSect->bSectors) pSect=pSect->pNext; if(dwSect>=pSect->dwSector+pSect->bSectors || dwSect+dwSectors<=pSect->dwSector) return; if(dwSect<pSect->dwSector) dwSect=pSect->dwSector; PrintkDebug("ExtFilter: sec 0x%lx",dwSect);/* PrintkDebug("ExtFilter sec %lu + %lu: found %lu of %lu + %d",dwSector,dwSectors,dwSect,pSect->dwSector,pSect->bSectors); *//* PrintSect(pSect,"ExtFilter: found"); */ pData=pBuff+((dwSect-dwSector)<<9); switch(pSect->bFlag) { case EXTF_PT: PrintkDebug("ExtFilter: EXTF_PT"); AddPT(pDevice,pSect,pData); dwSect=pSect->pNext->dwSector; break; case EXTF_HAS_PT: PrintkDebug("ExtFilter: EXTF_HAS_PT"); if(PTChanged(pSect,pData)) { DelPT(pDevice,pSect); AddPT(pDevice,pSect,pData); } dwSect=pSect->pNext->dwSector; break; case EXTF_SB: PrintkDebug("ExtFilter: EXTF_SB"); AddSB(pDevice,pSect,(struct ext2_super_block*)pData); dwSect++; break; case EXTF_HAS_SB: PrintkDebug("ExtFilter: EXTF_HAS_SB"); if(dwSect==pSect->dwSector) /* SB changed */ { if(SBChanged(pSect,(struct ext2_super_block*)pData)) AddSB(pDevice,pSect,(struct ext2_super_block*)pData); dwSect+=2; } else { if(dwSect>=pSect->dwSector+(pSect->bSect2BlockShift==3?6:2)) /* GD added */ { AddGD(pDevice,pSect,(struct ext2_group_desc*)pData,dwSect-(pSect->dwSector+(pSect->bSect2BlockShift==3?6:2))); } dwSect++; } break; case EXTF_HAS_GD: /* ignore GD changes */ PrintkDebug("ExtFilter: EXTF_HAS_GD"); if(SBChanged(pSect,(struct ext2_super_block*)pData)) { DelSB(pDevice,pSect); AddSB(pDevice,pSect,(struct ext2_super_block*)pData); } dwSect=pSect->pNext->dwSector; break; case EXTF_BB: PrintkDebug("ExtFilter: EXTF_BB"); /* do nothing */ dwSect=pSect->pNext->dwSector; break; return; case EXTF_HAS_BB: PrintkDebug("ExtFilter: EXTF_HAS_BB"); if(ExtReadSector(pDevice,dwSect,pTmp)) ProcessBB(pDevice,pSect,pTmp,pData,dwSect-pSect->dwSector); dwSect++; break;#ifdef TFFS_DEBUG_DRIVER default: PrintkDebug("ExtFilter: wrong case %d",pSect->bFlag); dwSect++;#endif } } PrintkDebug("ExtFilter:exit");}void ExtFilterInit(DeviceInfo*pDevice){ unsigned short wCache,wCacheSize; PrintkDebug("ExtFilterInit"); /* init first and last sectors */ pDevice->sect[0].dwSector=0; pDevice->sect[0].bSectors=1; pDevice->sect[0].pParent=NULL; pDevice->sect[0].pPrev=pDevice->sect[0].pNext=&pDevice->sect[1]; pDevice->sect[0].bFlag=EXTF_PT; pDevice->sect[0].dwOffset=0; pDevice->sect[1].dwSector=0xffffffff; pDevice->sect[1].bSectors=0; pDevice->sect[1].pParent=NULL; pDevice->sect[1].pPrev=pDevice->sect[1].pNext=&pDevice->sect[0]; pDevice->sect[1].bFlag=0; pDevice->sect[1].dwOffset=0;#ifdef TFFS_DEBUG_DRIVER pDevice->sect[0].no=0; pDevice->sect[1].no=0;#endif /* init hash */ wCacheSize=(pDevice->dwSize >> TFFS_EXTF_CACHE_STEP) + 1; PrintkDebug("ExtFilterInit: cache len %u",wCacheSize); pDevice->pCache=KMalloc(sizeof(SectInfo*)*wCacheSize); if(pDevice->pCache==NULL) return; pDevice->pCache[0]=&pDevice->sect[0]; for(wCache=1;wCache<wCacheSize;wCache++) pDevice->pCache[wCache]=&pDevice->sect[1]; ExtReadSector(pDevice,0,pTmp); AddPT(pDevice,&pDevice->sect[0],pTmp); PrintAllSect(pDevice);}void ExtFilterRelease(DeviceInfo*pDevice){ PrintkDebug("ExtFilterRelease: %lu times, %lu steps, average %lu",dwSearches,dwSteps,(dwSearches!=0)?dwSteps/dwSearches:0); PrintAllSect(pDevice); DelPT(pDevice,&pDevice->sect[0]); if(pDevice->pCache!=NULL) { kfree(pDevice->pCache); pDevice->pCache=NULL; }}void AddPT(DeviceInfo*pDevice,SectInfo*pSect,unsigned char*pBuff){ SectInfo*pPT=pSect; unsigned char*pPTData,*pPartData; pPTData=KMalloc(1024); if(pPTData==NULL) return; memcpy(pPTData,pBuff,512); pPartData=pPTData+512; while(pPT!=NULL) { unsigned char bPart; SectInfo*pNextPT=NULL; PrintkDebug("AddPT %d",pPT->no); if(pPTData[510]!=0x55 || pPTData[511]!=0xaa) { PrintkDebug("AddPT %d: no signature",pPT->no); pPT->bFlag=EXTF_PT; return; } PrintkDebug("AddPT %d: signature found",pPT->no); pPT->bFlag=EXTF_HAS_PT; for(bPart=0;bPart<4;bPart++) { SectInfo*pPart; unsigned char*pData=pPTData+(446+bPart*16); if(*(pData+4)==0) { PrintkDebug("AddPT %d: empty partition %d",pPT->no,bPart); continue; } pPart=KMalloc(sizeof(SectInfo)); if(pPart==NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -