imgtools/imglib/filesystem/source/fat32filesystem.cpp
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * CFat32FileSystem is the concrete class which is responsible for 
       
    16 * creating a FAT32 image. This class constitutes the method to 
       
    17 * create boot sector, FAT Table and data region of a FAT32 Image
       
    18 * @internalComponent
       
    19 * @released
       
    20 *
       
    21 */
       
    22 
       
    23 #include"fat32filesystem.h"
       
    24 
       
    25 /**
       
    26 Initializes the boot sector of a FAT 32 volume
       
    27 
       
    28 @internalComponent
       
    29 @released
       
    30 
       
    31 @param aPartitionSize partition size in bytes
       
    32 @param aConfigurableFatAttributes ConfigurableFatAttributes
       
    33 */
       
    34 void CFat32FileSystem::CreateBootSector(Long64 aPartitionSize,ConfigurableFatAttributes* aConfigurableFatAttributes)
       
    35 {
       
    36 	//initializes the boot sector values
       
    37 	iFAT32BootSector.SetOEMName();
       
    38 	unsigned char* OEMName =  iFAT32BootSector.OEMName();
       
    39 	iFAT32BootSector.SetJumpInstruction();
       
    40 	unsigned char* JmpBoot = iFAT32BootSector.JumpInstruction();
       
    41 	iFAT32BootSector.SetBytesPerSector(aConfigurableFatAttributes->iDriveSectorSize);
       
    42 	unsigned short BytesPerSector = (unsigned short)iFAT32BootSector.BytesPerSector();
       
    43 	iFAT32BootSector.ComputeSectorsPerCluster(aPartitionSize);
       
    44 	unsigned char SectorsPerCluster = iFAT32BootSector.SectorsPerCluster();
       
    45 	iFAT32BootSector.SetReservedSectors();
       
    46 	unsigned short ReservedSectors =  iFAT32BootSector.ReservedSectors();
       
    47 	iFAT32BootSector.SetNumberOfFats(aConfigurableFatAttributes->iDriveNoOfFATs);
       
    48 	unsigned char NumFats = iFAT32BootSector.NumberOfFats();
       
    49 	iFAT32BootSector.SetRootDirEntries();
       
    50 	unsigned short RootDirEntries = iFAT32BootSector.RootDirEntries();
       
    51 	iFAT32BootSector.ComputeTotalSectors(aPartitionSize);
       
    52 	unsigned short LowSectors = iFAT32BootSector.LowSectorsCount();
       
    53 	iFAT32BootSector.SetMedia();
       
    54 	unsigned char Media = iFAT32BootSector.Media();
       
    55 	iFAT32BootSector.ComputeFatSectors(aPartitionSize);
       
    56 	unsigned short FatSectors = iFAT32BootSector.FatSectors();
       
    57 	iFAT32BootSector.SetSectorsPerTrack();
       
    58 	unsigned short SectorPerTrack = iFAT32BootSector.SectorsPerTrack();
       
    59 	iFAT32BootSector.SetNumberOfHeads();
       
    60 	unsigned short NumberOfHeads = iFAT32BootSector.NumberOfHeads();
       
    61 	iFAT32BootSector.SetHiddenSectors();
       
    62 	unsigned int HiddenSectors = iFAT32BootSector.HiddenSectors();
       
    63 	unsigned int HighSectorsCount = iFAT32BootSector.HighSectorsCount();
       
    64 	unsigned int FatSectors32 = iFAT32BootSector.FatSectors32();
       
    65 	iFAT32BootSector.SetExtFlags();
       
    66 	unsigned short ExtFlags = iFAT32BootSector.ExtFlags();
       
    67 	iFAT32BootSector.SetFileSystemVersion();
       
    68 	unsigned short FileSystemVersion = iFAT32BootSector.FileSystemVersion();
       
    69 	iFAT32BootSector.SetRootCluster();
       
    70 	unsigned int RootCluster =  iFAT32BootSector.RootCluster();
       
    71 	iFAT32BootSector.SetFSInfo();
       
    72 	unsigned short FSInfo  = iFAT32BootSector.FSInfo();
       
    73 	iFAT32BootSector.SetBackUpBootSector();
       
    74 	unsigned short BackUpBootSector = iFAT32BootSector.BackUpBootSector();
       
    75 	iFAT32BootSector.SetFutureReserved();
       
    76 	unsigned char* FutureReserved = iFAT32BootSector.FutureReserved();
       
    77 	iFAT32BootSector.SetBootSectorDriveNumber();
       
    78 	unsigned char BootSectorDriveNumber = iFAT32BootSector.BootSectorDriveNumber();
       
    79 	iFAT32BootSector.SetReservedByte();
       
    80 	unsigned char ReservedByte = iFAT32BootSector.ReservedByte();
       
    81 	iFAT32BootSector.SetBootSignature();
       
    82 	unsigned char BootSignature = iFAT32BootSector.BootSignature();
       
    83 	iFAT32BootSector.SetVolumeId();
       
    84 	unsigned int VolumeId = iFAT32BootSector.VolumeId();
       
    85 	iFAT32BootSector.SetVolumeLab(aConfigurableFatAttributes->iDriveVolumeLabel);
       
    86 	unsigned char* VolumeLab = iFAT32BootSector.VolumeLab();
       
    87 	iFAT32BootSector.SetFileSysType();
       
    88 	unsigned char* FileSystemType = iFAT32BootSector.FileSysType();
       
    89 
       
    90 	//copying of boot sector values in to the array
       
    91 	iData = new unsigned char[BytesPerSector];
       
    92 	unsigned int pos = 0;
       
    93 	memcpy(&iData[pos],JmpBoot,3);
       
    94 	pos += 3;
       
    95 	memcpy(&iData[pos],OEMName,8);
       
    96 	pos += 8;
       
    97 	memcpy(&iData[pos],&BytesPerSector,2);
       
    98 	pos += 2;
       
    99 	memcpy(&iData[pos],&SectorsPerCluster,1);
       
   100 	pos += 1;
       
   101 	memcpy(&iData[pos],&ReservedSectors,2);
       
   102 	pos += 2;
       
   103 	memcpy(&iData[pos],&NumFats,1);
       
   104 	pos += 1;
       
   105 	memcpy(&iData[pos],&RootDirEntries,2);
       
   106 	pos += 2;
       
   107 	memcpy(&iData[pos],&LowSectors,2);
       
   108 	pos += 2;
       
   109 	memcpy(&iData[pos],&Media,1);
       
   110 	pos += 1;
       
   111 	memcpy(&iData[pos],&FatSectors,2);
       
   112 	pos += 2;
       
   113 	memcpy(&iData[pos],&SectorPerTrack,2);
       
   114 	pos += 2;
       
   115 	memcpy(&iData[pos],&NumberOfHeads,2);
       
   116 	pos += 2;
       
   117 	memcpy(&iData[pos],&HiddenSectors,4);
       
   118 	pos += 4;
       
   119 	memcpy(&iData[pos],&HighSectorsCount,4);
       
   120 	pos += 4;
       
   121 	memcpy(&iData[pos],&FatSectors32,4);
       
   122 	pos += 4;
       
   123 	memcpy(&iData[pos],&ExtFlags,2);
       
   124 	pos += 2;
       
   125 	memcpy(&iData[pos],&FileSystemVersion,2);
       
   126 	pos += 2;
       
   127 	memcpy(&iData[pos],&RootCluster,4);
       
   128 	pos += 4;
       
   129 	memcpy(&iData[pos],&FSInfo,2);
       
   130 	pos += 2;
       
   131 	memcpy(&iData[pos],&BackUpBootSector,2);
       
   132 	pos += 2;
       
   133 	memcpy(&iData[pos],FutureReserved,12);
       
   134 	pos += 12;
       
   135 	memcpy(&iData[pos],&BootSectorDriveNumber,1);
       
   136 	pos += 1;
       
   137 	memcpy(&iData[pos],&ReservedByte,1);
       
   138 	pos += 1;
       
   139 	memcpy(&iData[pos],&BootSignature,1);
       
   140 	pos += 1;
       
   141 	memcpy(&iData[pos],&VolumeId,4);
       
   142 	pos += 4;
       
   143 	memcpy(&iData[pos],VolumeLab,11);
       
   144 	pos += 11;
       
   145 	memcpy(&iData[pos],FileSystemType,8);
       
   146 	pos += 8;
       
   147 	while(pos < BytesPerSector)
       
   148 	{
       
   149 		iData[pos] = 0x00;
       
   150 		pos++;
       
   151 	}
       
   152 	// Set sector [510] as 0xAA and [511] as 0x55 to mark the end of boot sector
       
   153 	iData[KSizeOfFatBootSector-2] = 0x55;
       
   154 	iData[KSizeOfFatBootSector-1] = 0xAA;
       
   155 	// It is perfectly ok for the last two bytes of the boot sector to also 
       
   156 	// have the signature 0xAA55.
       
   157 	iData[BytesPerSector-2] = 0x55;
       
   158 	iData[BytesPerSector-1] = 0xAA;
       
   159 	ComputeClusterSizeInBytes();
       
   160 	ComputeRootDirSectors();
       
   161 	ComputeBytesPerSector();
       
   162 	MessageHandler::ReportMessage (INFORMATION,BOOTSECTORCREATEMSG, "FAT32");
       
   163 }
       
   164 
       
   165 /**
       
   166 Writes the boot sector of a FAT 32 volume
       
   167 
       
   168 @internalComponent
       
   169 @released
       
   170 
       
   171 @param aOutPutStream handle for the image file
       
   172 */
       
   173 void CFat32FileSystem::WriteBootSector(ofstream& aOutPutStream)
       
   174 {
       
   175 	MessageHandler::ReportMessage (INFORMATION,BOOTSECTORWRITEMSG, "FAT32");
       
   176 	aOutPutStream.write(reinterpret_cast<char*>(&iData[0]),iFAT32BootSector.BytesPerSector());
       
   177 	aOutPutStream.flush();
       
   178 }
       
   179 
       
   180 /**
       
   181 Creates and writes the FAT Table sector of a FAT 32 volume
       
   182 
       
   183 @internalComponent
       
   184 @released
       
   185 
       
   186 @param aClustersPerEntryMap iDatastructure containing the mapping of clusters allocated to the file.
       
   187 @param aOutPutStream handle for the image file
       
   188 */
       
   189 void CFat32FileSystem::CreateFatTable(ofstream& aOutPutStream)
       
   190 {
       
   191 	//data is written from cluster 2
       
   192 	unsigned int clusterCounter = 2;
       
   193 	unsigned int FATSizeInBytes = (iFAT32BootSector.FatSectors32()) * (iFAT32BootSector.BytesPerSector());
       
   194 	// Each FAT32 entries occupies 4 bytes, hence divided by 4
       
   195 	unsigned int totalFatEntries = FATSizeInBytes / 4;
       
   196 	//contains the address of FAT Table 	
       
   197 	unsigned int *FatTable = new unsigned int[totalFatEntries];
       
   198 
       
   199 	/**Say cluster 5 starts at 5 and occupies clusters 7 and 9. The FAT table should have the 
       
   200 	value 7 at	cluster location 5, the value 9 at cluster 7 and 'eof' value at cluster 9.
       
   201 	Below algorithm serves this algorithm
       
   202 	*/
       
   203 	int previousCluster;
       
   204 	FatTable[0] = KFat32FirstEntry;
       
   205 	FatTable[1] =  EOF32;
       
   206 	Iterator itr = iClustersPerEntry->begin();
       
   207 	while(itr !=  iClustersPerEntry->end())
       
   208 	{
       
   209 		previousCluster = itr->second;
       
   210 		if(iClustersPerEntry->count(itr->first) > 1)
       
   211 		{
       
   212 			for(unsigned int i = 1; i < iClustersPerEntry->count(itr->first); i++)
       
   213 			{
       
   214 				FatTable[previousCluster] = (++itr)->second;
       
   215 				previousCluster = itr->second;
       
   216 				++clusterCounter;
       
   217 			}
       
   218 		}
       
   219 		FatTable[previousCluster] = EOF32;
       
   220 		itr++;
       
   221 		++clusterCounter;
       
   222 	}
       
   223 	// Each FAT32 entries occupies 4 bytes, hence multiply by 4
       
   224 	std::string aFatString(reinterpret_cast<char*>(FatTable),clusterCounter*4);
       
   225 	delete[] FatTable;
       
   226 	if(clusterCounter < totalFatEntries)
       
   227 	{
       
   228 		// Each FAT32 entries occupies 4 bytes, hence multiply by 4
       
   229 		aFatString.append((totalFatEntries - clusterCounter)*4, 0);
       
   230 	}
       
   231 	MessageHandler::ReportMessage (INFORMATION,FATTABLEWRITEMSG,
       
   232 								   "FAT32");
       
   233 	//Write FAT table multiple times depending on the value of No of FATS set.
       
   234 	unsigned int noOfFats = iFAT32BootSector.NumberOfFats();
       
   235 	for(unsigned int i=0; i<noOfFats; i++)
       
   236 	{
       
   237 		aOutPutStream.write(aFatString.c_str(),aFatString.length());
       
   238 	}
       
   239 	aFatString.erase();
       
   240 	aOutPutStream.flush();
       
   241 }
       
   242 
       
   243 /**
       
   244 FSINfo iData structure specific to FAT32
       
   245 
       
   246 @internalComponent
       
   247 @released
       
   248 
       
   249 @param aOutPutStream handle for the image file
       
   250 */
       
   251 void CFat32FileSystem::CreateFSinfoSector(ofstream& aOutPutStream)
       
   252 {
       
   253 	int counter = 0;
       
   254 	unsigned int bytesPerSector = iFAT32BootSector.BytesPerSector();
       
   255 	FSinfoData = new unsigned char[bytesPerSector];
       
   256 	iFSInfo.SetFSInfo();
       
   257 	memcpy(&FSinfoData[counter], &iFSInfo.FSI_LeadSign,4);
       
   258 	counter += 4;
       
   259 	memcpy(&FSinfoData[counter], &iFSInfo.FSI_Reserved,480);
       
   260 	counter += 480;
       
   261 	memcpy(&FSinfoData[counter], &iFSInfo.FSI_StrucSig,4);
       
   262 	counter += 4;
       
   263 	memcpy(&FSinfoData[counter], &iFSInfo.FSI_Free_Count,4);
       
   264 	counter += 4;
       
   265 	memcpy(&FSinfoData[counter], &iFSInfo.FSI_Nxt_Free,4);
       
   266 	counter += 4;
       
   267 	memcpy(&FSinfoData[counter], &iFSInfo.FSI_Reserved2,12);
       
   268 	counter += 12;
       
   269 	memcpy(&FSinfoData[counter], &iFSInfo.FSI_TrailSig,4);
       
   270 	counter += 4;
       
   271 	counter += (bytesPerSector-KSizeOfFatBootSector);
       
   272 	aOutPutStream.write(reinterpret_cast<char*>(&FSinfoData[0]),counter);
       
   273 	aOutPutStream.flush();	
       
   274 }
       
   275 
       
   276 /**
       
   277  Initializes the left over reserved sectors of FAT32 image other than boot sector and FSinfo iData sector(sector 0 and 1)
       
   278 
       
   279  @internalComponent
       
   280  @released
       
   281 
       
   282  @param aOutPutStream handle to file stream		
       
   283 */
       
   284 void CFat32FileSystem::RestReservedSectors(ofstream& aOutPutStream)
       
   285 {
       
   286 	unsigned int bytesPerSector = iFAT32BootSector.BytesPerSector();
       
   287 	unsigned char* nullsector = new unsigned char[bytesPerSector];
       
   288 	for(unsigned int counter = 0; counter < bytesPerSector ; counter++)
       
   289 	{
       
   290 		nullsector[counter] = 0;
       
   291 	}
       
   292 	nullsector[KSizeOfFatBootSector-2] = 0x55;
       
   293 	nullsector[KSizeOfFatBootSector-1] = 0xAA;
       
   294 	for(unsigned int sectorcount = 2; sectorcount < (unsigned int)(iFAT32BootSector.ReservedSectors()) - 1; sectorcount++)
       
   295 	{
       
   296 		// Sector no 6 and 7 contains the duplicate copy of boot sector and FSInfo sector in a FAT32 Image
       
   297 		if(sectorcount == KBootBackupSector)
       
   298 		{
       
   299 			aOutPutStream.write(reinterpret_cast<char*>(&iData[0]),bytesPerSector);		
       
   300 			aOutPutStream.flush();
       
   301 		}
       
   302 		if(sectorcount == KFatBackupSector)
       
   303 		{
       
   304 			aOutPutStream.write(reinterpret_cast<char*>(&FSinfoData[0]),bytesPerSector);		
       
   305 			aOutPutStream.flush();
       
   306 		}
       
   307 		else
       
   308 		{
       
   309 			aOutPutStream.write(reinterpret_cast<char*>(&nullsector[0]),bytesPerSector);		
       
   310 			aOutPutStream.flush();
       
   311 		}
       
   312 	}
       
   313 	delete[] nullsector;
       
   314 	nullsector = NULL;
       
   315 }
       
   316 
       
   317 /**
       
   318 compute the cluster size in bytes,iClusterSize
       
   319 
       
   320 @internalComponent
       
   321 @released
       
   322 */
       
   323 void CFat32FileSystem::ComputeClusterSizeInBytes()
       
   324 {
       
   325 	iClusterSize = iFAT32BootSector.SectorsPerCluster()*iFAT32BootSector.BytesPerSector();
       
   326 }
       
   327 
       
   328 /**
       
   329 Compute the count of sectors occupied by the root directory,iRootDirSectors.
       
   330 
       
   331 @internalComponent
       
   332 @released
       
   333 */
       
   334 void CFat32FileSystem::ComputeRootDirSectors()
       
   335 {
       
   336 	iRootDirSectors = (iFAT32BootSector.RootDirEntries() * (KDefaultRootDirEntrySize) + 
       
   337 		              (iFAT32BootSector.BytesPerSector() - 1)) / iFAT32BootSector.BytesPerSector();
       
   338 }
       
   339 
       
   340 /*
       
   341 Initialize the Bytes per Sector variable value.
       
   342 
       
   343 @internalComponent
       
   344 @released
       
   345 */
       
   346 void CFat32FileSystem::ComputeBytesPerSector()
       
   347 {
       
   348 	iBytesPerSector = iFAT32BootSector.BytesPerSector();
       
   349 }
       
   350 
       
   351 /*
       
   352 Sets the total number of clusters in iData segment of the FAT volume
       
   353 
       
   354 
       
   355 @internalComponent
       
   356 @released
       
   357 
       
   358 @aPartitionSize partition size in bytes
       
   359 */
       
   360 void CFat32FileSystem::ComputeTotalClusters(Long64 aPartitionSize)
       
   361 {
       
   362 	unsigned int totalDataSectors = iFAT32BootSector.TotalSectors(aPartitionSize) - 
       
   363 									((iFAT32BootSector.NumberOfFats() * 
       
   364 									iFAT32BootSector.FatSectors32()) + 
       
   365 									iRootDirSectors+iFAT32BootSector.ReservedSectors());
       
   366 
       
   367  	iTotalClusters = totalDataSectors / iFAT32BootSector.SectorsPerCluster();
       
   368 	if(iTotalClusters < KMinimumFat32Clusters)
       
   369 	{
       
   370 		throw ErrorHandler(BOOTSECTORERROR,"Low Partition Size",__FILE__, __LINE__);
       
   371 	}
       
   372 	else if(iTotalClusters > KMaximumFat32Clusters)
       
   373 	{
       
   374 		throw ErrorHandler(BOOTSECTORERROR,"high Partition Size",__FILE__, __LINE__);
       
   375 	}
       
   376 }
       
   377 /**
       
   378 This methods encapsulates the function call to write a complete FAT32 Image
       
   379 
       
   380 @internalComponent
       
   381 @released
       
   382 
       
   383 @param aPartitionSize partition size in bytes
       
   384 @param aNodeList Directory structure 
       
   385 @param aOutPutStream output stream for writing file image
       
   386 @param aImageFileName image file name 
       
   387 @param aLogFileName log file name 
       
   388 @param aConfigurableFatAttributes ConfigurableFatAttributes
       
   389 */
       
   390 
       
   391 void CFat32FileSystem::Execute(Long64 aPartitionSize,EntryList aNodeList,
       
   392 							   ofstream& aOutPutStream,ConfigurableFatAttributes* aConfigurableFatAttributes)
       
   393 {
       
   394 	CDirRegion* dirRegionPtr = NULL;
       
   395 	try
       
   396 	{
       
   397 		CreateBootSector(aPartitionSize,aConfigurableFatAttributes);
       
   398 		ComputeTotalClusters(aPartitionSize);
       
   399 		WriteBootSector(aOutPutStream);
       
   400 		dirRegionPtr = new CDirRegion(aNodeList,this);
       
   401 		dirRegionPtr->Execute();
       
   402 		iClustersPerEntry = dirRegionPtr->GetClustersPerEntryMap();
       
   403 		CreateFSinfoSector(aOutPutStream);
       
   404 		RestReservedSectors(aOutPutStream);
       
   405 		CreateFatTable(aOutPutStream);
       
   406 		dirRegionPtr->WriteClustersIntoFile(aOutPutStream);
       
   407 		delete dirRegionPtr;
       
   408 		dirRegionPtr = NULL;
       
   409 	}
       
   410 	catch(ErrorHandler &aError)
       
   411 	{
       
   412 		delete dirRegionPtr;
       
   413 		dirRegionPtr = NULL;
       
   414 		throw ErrorHandler(aError.iMessageIndex,(char*)aError.iSubMessage.c_str(),(char*)aError.iFileName.c_str(),aError.iLineNumber);
       
   415 	}
       
   416 	/**
       
   417 	Irrespective of successful or unsuccessful data drive image generation ROFSBUILD
       
   418 	may try to generate images for successive ".oby" file input.
       
   419 	During this course unhandled exceptions may cause leaving some memory on heap 
       
   420 	unused. so the unhandled exceptions handling is used to free the memory allocated 
       
   421 	on heap. 
       
   422 	*/
       
   423 	catch(...)
       
   424 	{
       
   425 		delete dirRegionPtr;
       
   426 		dirRegionPtr = NULL;
       
   427 		throw ErrorHandler(UNKNOWNERROR, __FILE__, __LINE__);
       
   428 	}
       
   429 }
       
   430 
       
   431 /**
       
   432 Destructor of class CFat32FileSystem
       
   433 
       
   434 @internalComponent
       
   435 @released
       
   436 */
       
   437 CFat32FileSystem::~CFat32FileSystem()
       
   438 {
       
   439 	delete[] FSinfoData;
       
   440 };