imgtools/imglib/filesystem/source/fat16filesystem.cpp
changeset 2 39c28ec933dd
child 6 787612182dd0
equal deleted inserted replaced
1:820b22e13ff1 2:39c28ec933dd
       
     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 * CFat16FileSystem is the concrete class which is responsible for 
       
    16 * creating a FAT16 image. This class constitutes the method to 
       
    17 * create boot sector, FAT Table and data region of a FAT16 Image
       
    18 * @internalComponent
       
    19 * @released
       
    20 *
       
    21 */
       
    22 
       
    23 #include"fat16filesystem.h"
       
    24 #include <cstring>
       
    25 
       
    26 /**
       
    27 Initializes the boot sector of a FAT 16 volume
       
    28 
       
    29 @internalComponent
       
    30 @released
       
    31 
       
    32 @param aPartitionSize partition size in bytes
       
    33 @param aConfigurableFatAttributes ConfigurableFatAttributes
       
    34 */
       
    35 void CFat16FileSystem::CreateBootSector(Long64 aPartitionSize,ConfigurableFatAttributes* aConfigurableFatAttributes)
       
    36 {
       
    37  	iFAT16BootSector.SetOEMName();
       
    38 	unsigned char* OEMName = iFAT16BootSector.OEMName();
       
    39 	iFAT16BootSector.SetJumpInstruction();
       
    40 	unsigned char* JmpBoot = iFAT16BootSector.JumpInstruction();
       
    41 	iFAT16BootSector.SetBytesPerSector(aConfigurableFatAttributes->iDriveSectorSize);
       
    42 	unsigned short BytesPerSector = (unsigned short)iFAT16BootSector.BytesPerSector();
       
    43 	iFAT16BootSector.ComputeSectorsPerCluster(aPartitionSize);
       
    44 	unsigned char SectorsPerCluster = iFAT16BootSector.SectorsPerCluster();
       
    45 	iFAT16BootSector.SetReservedSectors();
       
    46 	unsigned short ReservedSectors = iFAT16BootSector.ReservedSectors();
       
    47 	iFAT16BootSector.SetNumberOfFats(aConfigurableFatAttributes->iDriveNoOfFATs);
       
    48 	unsigned char NumFats = iFAT16BootSector.NumberOfFats();
       
    49 	iFAT16BootSector.SetRootDirEntries();
       
    50 	unsigned short RootDirEntries = iFAT16BootSector.RootDirEntries();
       
    51 	iFAT16BootSector.ComputeTotalSectors(aPartitionSize);
       
    52 	unsigned short LowSectors = iFAT16BootSector.LowSectorsCount();
       
    53 	iFAT16BootSector.SetMedia();
       
    54 	unsigned char Media = iFAT16BootSector.Media();
       
    55 	iFAT16BootSector.ComputeFatSectors(aPartitionSize);
       
    56 	unsigned short FatSectors = iFAT16BootSector.FatSectors();
       
    57 	iFAT16BootSector.SetSectorsPerTrack();
       
    58 	unsigned short SectorPerTrack = iFAT16BootSector.SectorsPerTrack();
       
    59 	iFAT16BootSector.SetNumberOfHeads();
       
    60 	unsigned short NumberOfHeads = iFAT16BootSector.NumberOfHeads();
       
    61 	iFAT16BootSector.SetHiddenSectors();
       
    62 	unsigned int HiddenSectors = iFAT16BootSector.HiddenSectors();
       
    63 	unsigned int HighSectorsCount = iFAT16BootSector.HighSectorsCount();
       
    64 	iFAT16BootSector.SetBootSectorDriveNumber();
       
    65 	unsigned char BootSectorDriveNumber = iFAT16BootSector.BootSectorDriveNumber();
       
    66 	iFAT16BootSector.SetReservedByte();
       
    67 	unsigned char ReservedByte = iFAT16BootSector.ReservedByte();
       
    68 	iFAT16BootSector.SetBootSignature();
       
    69 	unsigned char BootSignature = iFAT16BootSector.BootSignature();
       
    70 	iFAT16BootSector.SetVolumeId();
       
    71 	unsigned int VolumeId = iFAT16BootSector.VolumeId();
       
    72 	iFAT16BootSector.SetVolumeLab(aConfigurableFatAttributes->iDriveVolumeLabel);
       
    73 	unsigned char* VolumeLab = iFAT16BootSector.VolumeLab();
       
    74 	iFAT16BootSector.SetFileSysType();
       
    75 	unsigned char* FileSysType = iFAT16BootSector.FileSysType();
       
    76 	//copying of boot sector values in to the array
       
    77 	iData = new unsigned char[BytesPerSector];
       
    78 	unsigned int pos = 0;
       
    79 	memmove(&iData[pos],JmpBoot,3);
       
    80 	pos += 3;
       
    81 	memmove(&iData[pos],OEMName,8);
       
    82 	pos += 8;
       
    83 	memmove(&iData[pos],&BytesPerSector,2);
       
    84 	pos += 2;
       
    85 	memmove(&iData[pos],&SectorsPerCluster,1);
       
    86 	pos += 1;
       
    87 	memmove(&iData[pos],&ReservedSectors,2);
       
    88 	pos += 2;
       
    89 	memmove(&iData[pos],&NumFats,1);
       
    90 	pos += 1;
       
    91 	memmove(&iData[pos],&RootDirEntries,2);
       
    92 	pos += 2;
       
    93 	memmove(&iData[pos],&LowSectors,2);
       
    94 	pos += 2;
       
    95 	memmove(&iData[pos],&Media,1);
       
    96 	pos += 1;
       
    97 	memmove(&iData[pos],&FatSectors,2);
       
    98 	pos += 2;
       
    99 	memmove(&iData[pos],&SectorPerTrack,2);
       
   100 	pos += 2;
       
   101 	memmove(&iData[pos],&NumberOfHeads,2);
       
   102 	pos += 2;
       
   103 	memmove(&iData[pos],&HiddenSectors,4);
       
   104 	pos += 4;
       
   105 	memmove(&iData[pos],&HighSectorsCount,4);
       
   106 	pos += 4;
       
   107 	memmove(&iData[pos],&BootSectorDriveNumber,1);		
       
   108 	pos += 1;
       
   109 	memmove(&iData[pos],&ReservedByte,1);
       
   110 	pos += 1;
       
   111 	memmove(&iData[pos],&BootSignature,1);
       
   112 	pos += 1;
       
   113 	memmove(&iData[pos],&VolumeId,4);
       
   114 	pos += 4;
       
   115 	memmove(&iData[pos],VolumeLab,11);
       
   116 	pos += 11;
       
   117 	memmove(&iData[pos],FileSysType,8);
       
   118 	pos += 8;
       
   119 	while(pos < BytesPerSector)
       
   120 	{
       
   121 		iData[pos] = 0;
       
   122 		pos++;
       
   123 	}
       
   124 	// Set sector [510] as 0xAA and [511] as 0x55 to mark the end of boot sector
       
   125 	iData[KSizeOfFatBootSector-2] = 0x55;
       
   126 	iData[KSizeOfFatBootSector-1] = 0xAA;
       
   127 	// It is perfectly ok for the last two bytes of the boot sector to also 
       
   128 	// have the signature 0xAA55.
       
   129 	iData[BytesPerSector-2] = 0x55;
       
   130 	iData[BytesPerSector-1] = 0xAA;
       
   131 
       
   132 
       
   133 	ComputeClusterSizeInBytes();
       
   134 	ComputeRootDirSectors();
       
   135 	ComputeBytesPerSector();
       
   136 	MessageHandler::ReportMessage (INFORMATION,BOOTSECTORCREATEMSG, const_cast<char *>("FAT16"));
       
   137 }
       
   138 
       
   139 /**
       
   140 Writes the boot sector of a FAT 16 volume
       
   141 @param aOutPutStream handle to file stream	
       
   142 
       
   143 @internalComponent
       
   144 @released
       
   145 */
       
   146 void CFat16FileSystem::WriteBootSector(ofstream& aOutPutStream)
       
   147 {
       
   148 	MessageHandler::ReportMessage (INFORMATION,BOOTSECTORWRITEMSG,const_cast<char *>("FAT16"));
       
   149 	aOutPutStream.write(reinterpret_cast<char*>(&iData[0]),iFAT16BootSector.BytesPerSector());
       
   150 	aOutPutStream.flush();
       
   151 }
       
   152 /**
       
   153 Creates the FAT Table
       
   154 
       
   155 @internalComponent
       
   156 @released
       
   157 
       
   158 @param ofstream
       
   159 */
       
   160 void CFat16FileSystem::CreateFatTable(ofstream& aOutPutStream)
       
   161 {
       
   162 	int FATSizeInBytes = (iFAT16BootSector.FatSectors()) * (iFAT16BootSector.BytesPerSector());
       
   163 	// Each FAT16 entries occupies 2 bytes, hence divided by 2
       
   164 	unsigned int totalFatEntries = FATSizeInBytes / 2;
       
   165 	unsigned short *FatTable = new unsigned short[totalFatEntries];
       
   166 	unsigned short int clusterCounter = 1;
       
   167 	int previousCluster;
       
   168 	FatTable[0] = KFat16FirstEntry;
       
   169 	/**Say cluster 5 starts at 5 and occupies clusters 7 and 9. The FAT table should have the 
       
   170 	value 7 at	cluster location 5, the value 9 at cluster 7 and 'eof' value at cluster 9.
       
   171 	Below algorithm serves this algorithm
       
   172 	*/
       
   173 	Iterator itr = iClustersPerEntry->begin();
       
   174 	while(itr != iClustersPerEntry->end())
       
   175 	{
       
   176 		previousCluster = itr->second;
       
   177 		if(iClustersPerEntry->count(itr->first) > 1)
       
   178 		{
       
   179 			for(unsigned int i = 1; i < iClustersPerEntry->count(itr->first); i++)
       
   180 			{
       
   181 				FatTable[previousCluster] = (unsigned short)(++itr)->second;
       
   182 				previousCluster = itr->second;
       
   183 				++clusterCounter;
       
   184 			}
       
   185 		}
       
   186 		FatTable[previousCluster] = EOF16;
       
   187 		itr++;
       
   188 		++clusterCounter;
       
   189 	}
       
   190 	// Each FAT16 entries occupies 2 bytes, hence multiply by 2
       
   191 	std::string aFatString(reinterpret_cast<char*>(FatTable),clusterCounter*2);
       
   192 	delete[] FatTable;
       
   193 	if(clusterCounter < totalFatEntries)
       
   194 	{
       
   195 		// Each FAT16 entries occupies 2 bytes, hence multiply by 2
       
   196 		aFatString.append((totalFatEntries - clusterCounter)*2, 0);
       
   197 	}
       
   198 
       
   199 	MessageHandler::ReportMessage (INFORMATION,FATTABLEWRITEMSG,const_cast<char *>("FAT16"));
       
   200 
       
   201 	// Write FAT table multiple times depending upon the No of FATS set.
       
   202 	unsigned int noOfFats = iFAT16BootSector.NumberOfFats();
       
   203 	for(unsigned int i=0; i<noOfFats; i++)
       
   204 	{
       
   205 		aOutPutStream.write(aFatString.c_str(),aFatString.length());
       
   206 	}
       
   207 	
       
   208 	aFatString.erase();
       
   209 	aOutPutStream.flush();
       
   210 }
       
   211 
       
   212 /**
       
   213 set the cluster size in bytes,iClusterSize
       
   214 
       
   215 @internalComponent
       
   216 @released
       
   217 */
       
   218 void CFat16FileSystem::ComputeClusterSizeInBytes()
       
   219 {
       
   220 	iClusterSize = (iFAT16BootSector.SectorsPerCluster()) * (iFAT16BootSector.BytesPerSector());
       
   221 }
       
   222 
       
   223 /**
       
   224 set the count of sectors occupied by the root directory,iRootDirSectors.
       
   225 
       
   226 @internalComponent
       
   227 @released
       
   228 */
       
   229 void CFat16FileSystem::ComputeRootDirSectors()
       
   230 {
       
   231 	iRootDirSectors = (iFAT16BootSector.RootDirEntries() * (KDefaultRootDirEntrySize) + 
       
   232 					  (iFAT16BootSector.BytesPerSector() - 1)) / iFAT16BootSector.BytesPerSector();
       
   233 }	
       
   234 
       
   235 /**
       
   236 Initialize the Bytes per Sector variable value.
       
   237 
       
   238 @internalComponent
       
   239 @released
       
   240 */
       
   241 void CFat16FileSystem::ComputeBytesPerSector()
       
   242 {
       
   243 	iBytesPerSector = iFAT16BootSector.BytesPerSector();
       
   244 }
       
   245 
       
   246 
       
   247 /**
       
   248 Compute the total number of clusters in Data segment of the FAT volume
       
   249 
       
   250 @internalComponent
       
   251 @released
       
   252 */
       
   253 void CFat16FileSystem::ComputeTotalClusters(Long64 aPartitionSize)
       
   254 {
       
   255 	unsigned long int iTotalDataSectors = iFAT16BootSector.TotalSectors(aPartitionSize) - 
       
   256 										  ((iFAT16BootSector.NumberOfFats() * iFAT16BootSector.FatSectors()) + 
       
   257 										  iRootDirSectors + iFAT16BootSector.ReservedSectors());
       
   258 	iTotalClusters = iTotalDataSectors / iFAT16BootSector.SectorsPerCluster();
       
   259 	if(iTotalClusters < KMinimumFat16Clusters)
       
   260 	{
       
   261 		throw ErrorHandler(BOOTSECTORERROR,
       
   262 			const_cast<char *>("Low Partition Size"),
       
   263 			const_cast<char *>(__FILE__),__LINE__);
       
   264 	}
       
   265 	if(iTotalClusters > KMaximumFat16Clusters)
       
   266 	{
       
   267 		throw ErrorHandler(BOOTSECTORERROR,
       
   268 			const_cast<char *>("High Partition Size"),
       
   269 			const_cast<char *>(__FILE__),__LINE__);
       
   270 	}
       
   271 	
       
   272 }
       
   273 
       
   274 /**
       
   275 This methods encapsulates the function call to write a complete FAT16 Image
       
   276 
       
   277 @internalComponent
       
   278 @released
       
   279 
       
   280 @param aPartitionSize partition size in bytes
       
   281 @param aNodeList Directory structure 
       
   282 @param aOutPutStream output stream for writing file image
       
   283 @param aImageFileName image file name 
       
   284 @param aLogFileName log file name 
       
   285 @param aConfigurableFatAttributes ConfigurableFatAttributes
       
   286 */
       
   287 
       
   288 void CFat16FileSystem::Execute(Long64 aPartitionSize,EntryList aNodeList,ofstream& aOutPutStream,
       
   289 							   ConfigurableFatAttributes* aConfigurableFatAttributes)
       
   290 {
       
   291 	CDirRegion* dirRegionPtr = NULL;
       
   292 	try
       
   293 	{
       
   294 		CreateBootSector(aPartitionSize,aConfigurableFatAttributes);
       
   295 		ComputeTotalClusters(aPartitionSize);
       
   296 		WriteBootSector(aOutPutStream);
       
   297 		dirRegionPtr = new CDirRegion(aNodeList,this);
       
   298 		dirRegionPtr->Execute();
       
   299 		iClustersPerEntry = dirRegionPtr->GetClustersPerEntryMap();
       
   300 		CreateFatTable(aOutPutStream);
       
   301 		dirRegionPtr ->WriteClustersIntoFile(aOutPutStream);
       
   302 		delete dirRegionPtr ;
       
   303 	}
       
   304 	catch(ErrorHandler &aError)
       
   305 	{
       
   306 		delete dirRegionPtr;
       
   307 		//Re throw the same error message
       
   308 		throw ErrorHandler(aError.iMessageIndex,(char*)aError.iSubMessage.c_str(),(char*)aError.iFileName.c_str(),aError.iLineNumber);
       
   309 	}
       
   310 	/**
       
   311 	Irrespective of successful or unsuccessful data drive image generation ROFSBUILD
       
   312 	may try to generate images for successive ".oby" file input.
       
   313 	During this course unhandled exceptions may cause leaving some memory on heap 
       
   314 	unused. so the unhandled exceptions handling is used to free the memory allocated 
       
   315 	on heap. 
       
   316 	*/
       
   317 	catch(...)
       
   318 	{
       
   319 		delete dirRegionPtr;
       
   320 		throw ErrorHandler(UNKNOWNERROR, const_cast<char *>(__FILE__), __LINE__);
       
   321 	}
       
   322 }