📄 hdd_file.c
字号:
/*=================================================================
hdd_fs.c: Some FileSystem Info Function for HDD
2002-04-28 10:00AM Created by Verdure
2002-06-12 08:42AM Modified by cyue
Copyright(c)2000-2002 by Worldplus Technology (ShenZhen) Co., Ltd.
ALL RIGHTS RESERVED
=================================================================*/
#include "config.h"
#include "set.h"
#include "global.h"
#include "hdd_if.h"
#include "user_init.h"
#ifdef SUPPORT_HDD_ACCESS
#define D printf("INFO: __%d__(%s:%s)\n",__LINE__,__FILE__,__FUNCTION__);
#define SUPPORT_FAT2 //MIKEY 2003.09.18 write FAT2
//#define SUPPORT_BACKUP_FAT //MIKEY 2003.09.18 copy FAT1 to FAT2
#define DBG_HDD_FS //MIKEY_DEBUG
#ifndef DBG_HDD_FS
#undef printf
#define printf(f, a...) {}
#endif
UINT32 keep_lba=-1;
//==============================================================
//
//==============================================================
// Global for FAT FS
extern UINT8 pwb[];
//UINT8 *Info_buff=pwb+0;
#define NAVBUFSTART (0xa03c0000) // 0xa03c0000 40k
UINT8 *Info_buff=(UINT8 *)(NAVBUFSTART+0);
UINT8 HD_EXIST;
HDD_INFO HDD_Info;
BPB_INFO BPB;
UINT32 Data_Start_Clus;
UINT32 File_FDB_Lba;
UINT32 Start_LBA;
UINT32 Data_Curr_Clus;
UINT32 Data_Next_Clus;
int FS_Get_BPBPara(UINT8*);
PARTITION_INFO* HDD_AddPE(HDD_INFO* HDD_Info,UINT32 MBR,PARTITION_ENTRY* pe)
{
PARTITION_INFO *pi=0;
#ifdef PI_USE_MATRIX
int j;
for(j=0;j<MAX_PART_INFO;j++)
if(!HDD_Info->part[j].type) break;
pi=&HDD_Info->part[j];
#else
PARTITION_INFO *hddpi;
pi=(PARTITION_INFO*)malloc(sizeof(PARTITION_INFO));
#endif
pi->type=pe->type;
pi->next=NULL;
pi->startlba=MBR+(pe->secfrommbr_hi<<16|pe->secfrommbr_lo);
Start_LBA=pi->startlba;
// printf("\n startlba:%x\n",Start_LBA);//jichuan
pi->seccnt=pe->seccnt_hi<<16|pe->seccnt_lo;
pi->act=pe->act;
#ifndef PI_USE_MATRIX
if(HDD_Info->partition_list==NULL)
HDD_Info->partition_list=pi;
else {
for(hddpi=HDD_Info->partition_list;hddpi->next!=NULL;hddpi=hddpi->next);
hddpi->next=pi;
}
#endif
return pi;
}
int HDD_MakeInfo(HDD_INFO *HDD_Info,UINT8* buff)
{
PARTITION_ENTRY *pe;
UINT32 i;
UINT32 MBR=0,secfrommbr,seccnt;
#ifdef PI_USE_MATRIX
for(i=0;i<MAX_PART_INFO;i++)
HDD_Info->part[i].type=0;
#else
HDD_Info->partition_list=NULL;
#endif
HDD_ReadSec(buff,MBR,1);
//print_sector(buff);
for(i=0;i<4;i++) { //Parse Primary partitions
pe=(PARTITION_ENTRY*)(buff+ 0x1be +i*16);
secfrommbr=pe->secfrommbr_hi<<16|pe->secfrommbr_lo;
seccnt=pe->seccnt_hi<<16|pe->seccnt_lo;
printf("\n--secfrommbr=%lx--\n",secfrommbr);
if (!pe->type)
continue;
if ((pe->type==0x0f)||(pe->type==0x05)) {
// Extended Partition!!
UINT32 MBREXT=MBR+secfrommbr;
do {
HDD_ReadSec(buff,MBREXT,1);
printf("\n Parse EXT %lu... ",MBREXT);
if (*(UINT16*)(buff+510)!=0xaa55) {
printf("\n Fail EXT Partition!!");
break;
}
pe=(PARTITION_ENTRY*)(buff + 0x1be);
secfrommbr=pe->secfrommbr_hi<<16|pe->secfrommbr_lo;
seccnt=pe->seccnt_hi<<16|pe->seccnt_lo;
if (pe->type) {
#ifdef MIKEY
HDD_AddPE(HDD_Info,MBREXT,pe);
#else
printf("MIKEY: skip add EXT partition type[%x]\n",pe->type);
break;
#endif
}
else
break;
pe=(PARTITION_ENTRY*)(buff+ 0x1be +16);
if(!pe->type) {
printf("\nLast MBR!!");
MBREXT=HDD_Info->seccnt - seccnt;
}
else {
MBREXT=MBREXT+secfrommbr+seccnt;
}
}while((pe->type==0x0f)||(pe->type==0x05));
}
else {
HDD_AddPE(HDD_Info,MBR,pe);
printf("\n primary=%d \n",i);
}
}
return 0;
}
void HDD_Dump_Info(HDD_INFO* HDD_Info)
{
PARTITION_INFO *pi;
int i;
printf("\n\nHDD: C=%lu H=%lu S=%lu",HDD_Info->cyl,HDD_Info->head,HDD_Info->sec);
printf("\nHDD total Sectors = %lu, %lu MB ",HDD_Info->seccnt,HDD_Info->seccnt/2000);
printf("\nPAR A TYPE START LBA COUNT");
#ifdef PI_USE_MATRIX
for(i=0;i<MAX_PART_INFO;i++) {
pi= &HDD_Info->part[i];
if(pi->type)
printf("\n%2d %02x %02x %10lu %10lu\n",i,pi->act,pi->type,pi->startlba,pi->seccnt);
}
#else
for(i=0,pi=HDD_Info->partition_list;pi!=NULL;i++,pi=pi->next) {
printf("\n%2d %02x %02x %10lu %10lu",i,pi->act,pi->type,pi->startlba,pi->seccnt);
}
#endif
}
static int FS_check_SecPerClus(unsigned SecPerClus)
{
unsigned char log;
for(log = 0; log < 8; log++) {
if(SecPerClus & 1) {
SecPerClus >>= 1;
return (SecPerClus != 0) ? -1 : log;
}
SecPerClus >>= 1;
}
return -1;
}
int FS_check_BootSec(UINT8* buf)
{
UINT16 temp;
//check Jump Code + NOP
if(buf[0] == 0xE9)
/* OK */;
else if(buf[0] == 0xEB && buf[2] == 0x90)
/* OK */;
else {
printf("Missing JMP/NOP\n");
return 1;
}
//check Sectors Per Cluster
temp = buf[13];
if(FS_check_SecPerClus(temp) < 0) {
printf("Sectors per cluster (%u) is not a power of 2\n",temp);
return 1;
}
//check the Number of FATs
temp = buf[16];
if(temp != 1 && temp != 2) {
printf("Invalid number of FATs (%u)\n",temp);
return 1;
}
//check Sectors Per Track
temp = read_le16(buf + 24);
if(temp == 0 || temp > 63) {
printf("Invalid number of sectors (%u)\n",temp);
return 1;
}
//check Number of Heads
temp = read_le16(buf + 26);
if(temp == 0 || temp > 255) {
printf("Invalid number of heads (%u)\n",temp);
return 1;
}
return FS_Get_BPBPara(buf);
}
int FS_Get_BPBPara(UINT8* buf)
{
BPB.BytesPerSec=(buf[12]<<8)|buf[11];
switch(BPB.BytesPerSec) {
case 512: BPB.BytesPerSecPwr=9; break;
case 2048: BPB.BytesPerSecPwr=11; break;
case 256: BPB.BytesPerSecPwr=8; break;
}
printf("\n## BytesPerSec:%d ",BPB.BytesPerSec);
BPB.SecPerClus=buf[13];
switch(BPB.SecPerClus) {
case 128: BPB.SecPerClusPwr=7; break; //64K allocation unit
case 64: BPB.SecPerClusPwr=6; break; //32K allocation unit
case 32: BPB.SecPerClusPwr=5; break; //16K allocation unit
case 16: BPB.SecPerClusPwr=4; break; // 8K allocation unit
case 8: BPB.SecPerClusPwr=3; break; // 4K allocation unit
case 4: BPB.SecPerClusPwr=2; break; // 2K allocation unit
}
printf("\n## SecPerClus:%d ",BPB.SecPerClus);
printf("\n## SecPerClusPwr:%d ",BPB.SecPerClusPwr);
BPB.ReserSecCnt=read_le16(buf + 14);
BPB.NumFATs=buf[16];
// BPB.MediaDescriptor=buf[21];
// BPB.SecPerTrack=read_le16(buf + 24);
// BPB.NumHeads=read_le16(buf + 26);
// BPB.HiddenSecCnt=read_le32(buf + 28);
// BPB.TolSec32=read_le32(buf + 32);
BPB.FATSize32=read_le32(buf + 36);
printf("\n## FATSize32:%d ",BPB.FATSize32);
BPB.CurrDirClus=BPB.RootClus=read_le32(buf + 44);
BPB.FAT1_Start=Start_LBA+BPB.ReserSecCnt;
printf("\n## BPB.FAT1_Start:%d ",BPB.FAT1_Start);
if (BPB.NumFATs==1)
BPB.FAT2_Start=0;
if (BPB.NumFATs==2)
BPB.FAT2_Start=BPB.FAT1_Start+BPB.FATSize32;
BPB.Data_Area_Start=((BPB.RootClus-2)*BPB.SecPerClus) + BPB.FAT1_Start+BPB.FATSize32*BPB.NumFATs;
printf("\n## BPB.Data_Area_Start:%d \n",BPB.Data_Area_Start);
return 0;
}
UINT32 Last_FAT_Lba=0x0FFFFFFF; // cyue: Try to make a cache 2002-06-11 11:14PM
UINT8 *FS_ReadInfoSec(UINT32 lba,int seccnt)
{
if(Last_FAT_Lba!=lba) {
HDD_ReadSec(Info_buff,lba,seccnt);
}
return Info_buff;
}
void FS_flush_cache()
{
keep_lba=-1;
}
UINT32 FS_Get_NextClus(UINT32 clus) //MIKEY 2003.09.02 for speed up
{
UINT32 lba;
UINT32 nOffset;
// static UINT32 keep_lba=-1;
static UINT32 keep_count=0;
// extern UINT8 pwb[];
// UINT8 *buff512=pwb+512;
UINT8 *buff512=(UINT8 *)(NAVBUFSTART+512);
keep_lba=-1; //MIKEY disable cache
nOffset=clus&0x7F;//%128;
lba=(clus>>7)+BPB.FAT1_Start;
if(keep_lba!=lba) { //MIKEY_CACHE
keep_lba=lba;
HDD_ReadSec(buff512, lba, 1);
}
else {
keep_count++;
if((keep_count % 100)==99)
printf("INFO: FS_Get_NextClus keep_count(%ld)\n",keep_count);
}
Data_Next_Clus=read_le32(buff512+(nOffset<<2))&0x0fffffff;
return Data_Next_Clus;
}
//==============================================================
//
//==============================================================
//extern BYTE CardReadSector();
extern BYTE FSReadSector();
extern BYTE CardWriteSector();
extern void *memcpy();
extern unsigned strlen();
/* Check whether HD present */
UINT8 HDD_DEV_Existence(void)
{
return 0;
}
int HDD_ReadSec(UINT8 *buff, UINT32 lba, int seccnt)
{
int i;
int ret=0;
for(i=0;i<5;i++) { // retry?
// if((ret=CardReadSector(lba, seccnt, buff))==0)
if((ret=FSReadSector(lba, seccnt, buff))==0)
break; //OK
printf("ERROR: HDD_ReadSec retry(%d)\n",i+1);
}
return ret;
}
int HDD_WriteSec(UINT8 *buff, UINT32 lba, int seccnt)
{
int i;
int ret=0;
for(i=0;i<5;i++) { // retry?
if((ret=CardWriteSector(lba, seccnt, buff))==0)
break; //OK
printf("ERROR: HDD_WriteSec retry(%d)\n",i+1);
}
return ret;
}
UINT32 FS_LBA2Clus(UINT32 lba)
{
UINT32 clus;
clus = (lba - BPB.Data_Area_Start)/BPB.SecPerClus + 2;
return clus;
}
UINT32 FS_LBAinClus(UINT32 lba)
{
UINT32 curClus, nextClus;
int i;
curClus = FS_LBA2Clus(lba);
for (i=0; i<BPB.SecPerClus; i++) {
nextClus = FS_LBA2Clus(lba+i+1);
if (curClus != nextClus)
break;
}
return i;
}
//==============================================================
//
//==============================================================
#ifdef SUPPORT_BACKUP_FAT
void HDD_Backup_FAT(void)
{
UINT32 i;
if(BPB.NumFATs<2)
return;
for(i=0; i<BPB.FATSize32; i++) {
HDD_ReadSec (Info_buff, BPB.FAT1_Start+i, 1);
HDD_WriteSec(Info_buff, BPB.FAT2_Start+i, 1);
}
}
#endif //SUPPORT_BACKUP_FAT
int HDD_list_clus(FILE_INFO *fp)
{
UINT32 st,next;
// UINT32 lba_count=LBA_COUNT(fp->fsize),sec_count=BPB.SecPerClus;
int i=0;
st=fp->start_clus;
next=0;
//printf("MIKEY: lba_count(%d)/(%d)=(%d)\n",lba_count,sec_count,(lba_count+sec_count-1)/sec_count);
while(1) {
printf("$$ clus(%4d):[%x]\n",i,st);
if(st>=0x0FFFFFF8) {//End?
break;
}
next=FS_Get_NextClus(st);
st=next;
i++;
}
return 0;
}
//==============================================================
//
//==============================================================
UINT8 FS_Emu_stricmp(UINT8* s1, UINT8* s2)
{
UINT16 i;
//MIKEY_BUG
// for(i=0;(i<11)&&(*s1)&&(*s2);i++,s1++,s2++) {
for(i=0;i<11;i++) {
if(((s1[i])&~0x20)!=((s2[i])&~0x20))
return 1;
}
return 0;
}
UINT8 HDD_Mount(void)
{
UINT8 i;
if ((HD_EXIST = HDD_DEV_Existence()))
return 0;
HDD_MakeInfo(&HDD_Info,Info_buff);
for(i=0;HDD_Info.part[i].type;i++) { /*浪代–
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -