Esempio n. 1
0
// =======================================================
void CExt2Part::readSuperBlock() 
{
  BEGIN;

  CExt2Super sb;
  int nRes;

  // init
  memset(&m_info, 0, sizeof(CInfoExt2Header));

  // 0. go to the beginning of the super block
  nRes = fseek(m_fDeviceFile, 1024, SEEK_SET);
  if (nRes == -1)
    goto error_readSuperBlock;
  
  // 1. read and print important informations
  nRes = fread(&sb, sizeof(sb), 1, m_fDeviceFile);
  if (nRes != 1)
    goto error_readSuperBlock;

  // check partition has an ext2 file system
  if (sb.s_magic != Le16ToCpu(EXT2_SUPER_MAGIC))
    goto error_readSuperBlock;

  // read and print important informations	
  m_info.dwBlockSize = (EXT2_MIN_BLOCK_SIZE << Le32ToCpu(sb.s_log_block_size)); //sb.s_blocksize; //EXT2_BLOCK_SIZE(m_fs->super);
  showDebug(1, "blksize=%lu\n", m_info.dwBlockSize);
  m_info.dwFirstBlock = Le32ToCpu(sb.s_first_data_block);
  showDebug(1, "first=%lu\n", m_info.dwFirstBlock);
  m_info.dwTotalBlocksCount = Le32ToCpu(sb.s_blocks_count);
  showDebug(1, "total blocks=%lu\n", m_info.dwTotalBlocksCount);
  m_info.dwBlocksPerGroup = Le32ToCpu(sb.s_blocks_per_group);
  showDebug(1, "BlocksPerGroup=%lu\n", m_info.dwBlocksPerGroup);

  m_info.dwGroupsCount = (m_info.dwTotalBlocksCount - m_info.dwFirstBlock + m_info.dwBlocksPerGroup - 1) / Le32ToCpu(sb.s_blocks_per_group);
  showDebug(1, "groups=%lu\n", m_info.dwGroupsCount);
  m_info.dwLogicalBlocksPerExt2Block =  m_info.dwBlockSize / LOGICAL_EXT2_BLKSIZE;
  showDebug(1, "m_info.dwLogicalBlocksPerExt2Block=%lu\n",m_info.dwLogicalBlocksPerExt2Block);
  showDebug(1, "logperblok=%lu\n", m_info.dwLogicalBlocksPerExt2Block);
  
  m_info.dwDescPerBlock = m_info.dwBlockSize / sizeof(CExt2GroupDesc);
  m_info.dwDescBlocks = (m_info.dwGroupsCount + m_info.dwDescPerBlock - 1) / m_info.dwDescPerBlock;
  //debugWin("m_info.dwDescBlocks=%lu",(DWORD)m_info.dwDescBlocks);

  // virtual blocks used in the abstract CFSBase
  m_header.qwBlocksCount = m_info.dwTotalBlocksCount * m_info.dwLogicalBlocksPerExt2Block;
  m_header.qwBlockSize = LOGICAL_EXT2_BLKSIZE;
  m_header.qwBitmapSize = ((m_header.qwBlocksCount+7) / 8)+16;
  m_header.qwUsedBlocks = (m_info.dwTotalBlocksCount - Le32ToCpu(sb.s_free_blocks_count)) * m_info.dwLogicalBlocksPerExt2Block; 

  //debugWin("freeblks=%lu", sb.s_free_blocks_count);
  strncpy(m_header.szLabel, sb.s_volume_name, 64);

  // features
  m_info.dwFeatureCompat = Le32ToCpu(sb.s_feature_compat);
  m_info.dwFeatureIncompat = Le32ToCpu(sb.s_feature_incompat);
  m_info.dwFeatureRoCompat = Le32ToCpu(sb.s_feature_ro_compat);

  // misc infos
  m_info.dwRevLevel = Le32ToCpu(sb.s_rev_level);	// Revision level 
  memcpy(m_info.cUuid, sb.s_uuid, 16); // 128-bit uuid for volume

  //success_readSuperBlock:
  setSuperBlockInfos(true, true, m_header.qwUsedBlocks*m_header.qwBlockSize, ((QWORD)Le32ToCpu(sb.s_free_blocks_count)) * ((QWORD)m_info.dwBlockSize));
  showDebug(1, "end success\n");  
  RETURN;

 error_readSuperBlock:
  g_interface -> ErrorReadingSuperblock(errno);
  THROW(ERR_WRONG_FS);
}
// Load partition information from storage device.
bool PartitionLoad(FS_CONTEXT* FsContext, uint8_t DriverId)
{
	uint32_t		RootDirSectors;
	uint32_t		BootSecNum = 0;
	uint32_t		FatSize;
	uint32_t		TotalSectors;
	uint8_t		IndexPtb;
	uint8_t		SectorSizeMul;
	uint32_t		temp2;
	uint8_t		ExtBootEntry = 0;
	uint16_t		BPBRsvSectCnt;
	uint8_t        LogicDriverId = 1;
	uint8_t			LoopFlag = 0;

#ifdef FUNC_USB_EN
	if(FsContext->gFsInfo.DevID == DEV_ID_USB)
	{
		SectorSizeMul = (HostStorGetBlockSize() / SECTOR_SIZE);
	}
	else
#endif
	{
		SectorSizeMul = 1;
	}
//	FS_DBG("SectorSizeMul: %d\n", (uint16_t)SectorSizeMul);

	while(1)
	{
		LoopFlag = 0;
		//read MBR
		//if(!ReadBlock(BootSecNum, (uint8_t*)(FsContext->FAT_BUFFER), 1))
		if(RES_OK != disk_read(FsContext->gFsInfo.DevID, (uint8_t*)(FsContext->FAT_BUFFER), BootSecNum, 1))
		{
			FS_DBG("ReadBlock() error!\n");
			return FALSE;
		}
		FsContext->gFsInfo.CurrFATSecNum = BootSecNum;
	#ifndef CANCEL_COMMON_SIGNATURE_JUDGMENT
		if(*(uint16_t*)((FsContext->FAT_BUFFER) + SIGNATURE_OFFSET) != COMMON_SIGNATURE)		//if 0x55aa
		{
			return FALSE;
		}
	#endif
		for(IndexPtb = 0; IndexPtb < 4; IndexPtb++)
		{
			PARTITION* pPart = &((PARTITION*)((FsContext->FAT_BUFFER) + PARTITION_OFFSET))[IndexPtb];

			if((pPart->PartitionType == 0x05)			//Extended partition
					&& ((ExtBootEntry == 0) || (IndexPtb >= ExtBootEntry)))
			{
				BootSecNum += Le32ToCpu(pPart->FirstSectorNum);
				ExtBootEntry = IndexPtb + 1;
	//			FS_DBG("Extended partition bootSecNum:%ld\n", (uint32_t)BootSecNum);
				LoopFlag = 1;
				break;
			}

			//check the partition type and get the boot sector num
			if(pPart->PartitionType == 0x04
					|| pPart->PartitionType == 0x06
					|| pPart->PartitionType == 0x0B
					|| pPart->PartitionType == 0x0C
					|| pPart->PartitionType == 0x01
					|| pPart->PartitionType == 0x0E)
			{
				if(DriverId <= 1 || LogicDriverId == DriverId)
				{
					BootSecNum += Le32ToCpu(pPart->FirstSectorNum);
					break;
				}
				LogicDriverId++;
			}
		}
		if(LoopFlag)
		{
			continue;
		}

		if((IndexPtb == 4) && ((ExtBootEntry > 0) && (ExtBootEntry < 4)))
		{
			//if extended parttion failed,try again.
			BootSecNum = 0;
			continue;//增加对第一分区为无效扩展分区设备的支持
		}
		break;
	}

	if((DriverId > 1) && (LogicDriverId != DriverId))
	{
		return FALSE;
	}

	//read DBR
	//if(!ReadBlock((BootSecNum * SectorSizeMul), (uint8_t*)(FsContext->FAT_BUFFER), 1))
	if(RES_OK != disk_read(FsContext->gFsInfo.DevID, (uint8_t*)(FsContext->FAT_BUFFER), (BootSecNum * SectorSizeMul), 1))
	{
		return FALSE;
	}
	FsContext->gFsInfo.CurrFATSecNum = (BootSecNum * SectorSizeMul);
#ifndef CANCEL_COMMON_SIGNATURE_JUDGMENT
	if(*(uint16_t*)((FsContext->FAT_BUFFER)  + SIGNATURE_OFFSET) != COMMON_SIGNATURE)		//if 0x55aa
	{
		return FALSE;
	}
#endif
#define pzero_sector ((BOOT_SECTOR*)((FsContext->FAT_BUFFER)))

	//updata device information
	FsContext->gFsInfo.ClusterSize = pzero_sector->BPB_SecPerClus;

	//get first sector of FAT
	BPBRsvSectCnt = Le16ToCpu(pzero_sector->BPB_RsvdSecCnt);
	FsContext->gFsInfo.FatStart = BPBRsvSectCnt + BootSecNum;

	//get sectors of boot dir
	if(pzero_sector->BPB_RootEntCnt != 0)
	{
		RootDirSectors = (Le16ToCpu(pzero_sector->BPB_RootEntCnt) * 32 + SECTOR_SIZE - 1) / SECTOR_SIZE;
	}
	else
	{
		RootDirSectors = 0;
	}

	//get FAT size
	if(pzero_sector->BPB_FATSz16 != 0)
	{
		FatSize = Le16ToCpu(pzero_sector->BPB_FATSz16);
	}
	else
	{
		FatSize = Le32ToCpu(pzero_sector->BPB_FATSz32);
	}

	//get total cluster
	if(pzero_sector->BPB_TotSec16 != 0)
	{
		TotalSectors = Le16ToCpu(pzero_sector->BPB_TotSec16);
	}
	else
	{
		TotalSectors = Le32ToCpu(pzero_sector->BPB_TotSec32);
	}

	temp2 = (TotalSectors - (BPBRsvSectCnt + FatSize * pzero_sector->BPB_NumFATs + RootDirSectors)) / FsContext->gFsInfo.ClusterSize;
//	FS_DBG("temp2:%ld\n", (uint32_t)temp2);

	if(temp2 < 4085)
	{
		FS_DBG("FAT12\n");
		FsContext->gFsInfo.IsCpatFS = FALSE;				//FAT12
		return TRUE;
	}
	else if(temp2 < 65525)
	{
		FS_DBG("FAT16\n");
		FsContext->gFsInfo.FAT32 = 0;						//FAT16
		FsContext->gFsInfo.IsCpatFS = TRUE;
	}
	else
	{
		//FAT32设备BPB_RootEntCnt/BPB_TotSec16/BPB_FATSz16数值必须为零
		if(memcmp((uint8_t*)((FsContext->FAT_BUFFER) + 0x36), "FAT16\0\0\0", 8) == 0)
		{
			//客户有一个U盘(USB启动盘),根据计算得出的簇数目应该为FAT32,实际为FAT16系统,为支持这一类设备,需要做此处理
			FS_DBG("FAT16\n");
			FsContext->gFsInfo.FAT32 = 0;
		}
		else
		{
			FS_DBG("FAT32\n");
			FsContext->gFsInfo.FAT32 = 1;						//FAT32
		}
		FsContext->gFsInfo.IsCpatFS = TRUE;
	}

	FsContext->gFsInfo.DataStart = FsContext->gFsInfo.FatStart + (FatSize * pzero_sector->BPB_NumFATs) + RootDirSectors;		//the first sector of data
	// get max cluster number in this drive.
	//FsContext->gFsInfo.MaxCluster = ((TotalSectors - FsContext->gFsInfo.DataStart) / FsContext->gFsInfo.ClusterSize) + 2;
	FsContext->gFsInfo.MaxCluster = temp2 + 2;

	//get the data start and boot dir start
	if(FsContext->gFsInfo.FAT32)
	{
		FsContext->gFsInfo.RootStart = FsContext->gFsInfo.DataStart + (Le32ToCpu(pzero_sector->BPB_RootClus) - 2) * FsContext->gFsInfo.ClusterSize;
	}
	else
	{
		FsContext->gFsInfo.RootStart = FsContext->gFsInfo.FatStart + FatSize * pzero_sector->BPB_NumFATs;						//FAT16 the first sector of root dir
	}

	FsContext->gFsInfo.ClusterSize *= SectorSizeMul;
//	RootDirSectors *= SectorSizeMul;
	FsContext->gFsInfo.FatStart *= SectorSizeMul;
	FsContext->gFsInfo.DataStart *= SectorSizeMul;
	FsContext->gFsInfo.MaxSector = (BootSecNum + TotalSectors) * SectorSizeMul;
	FsContext->gFsInfo.RootStart *= SectorSizeMul;


//	FS_DBG("*************UDisk virtual params******************\n");
//	FS_DBG("ClusterSize:%ld\n", (uint32_t)FsContext->gFsInfo.ClusterSize);
//	FS_DBG("RootDirSectors:%ld\n", (uint32_t)RootDirSectors);
//	FS_DBG("FatStart:%ld\n", (uint32_t)FsContext->gFsInfo.FatStart);
//	FS_DBG("RootStart:%ld\n", (uint32_t)FsContext->gFsInfo.RootStart);
//	FS_DBG("DataStart:%ld\n", (uint32_t)FsContext->gFsInfo.DataStart);
//	FS_DBG("MaxCluster:%ld\n", (uint32_t)FsContext->gFsInfo.MaxCluster);
//	FS_DBG("*****************************************************\n\n");

	return TRUE;
}