پروتکل قالب بندی (Format) درایو FAT16

این مقاله به بررسی اجمالی در مورد پروتکل سخت افزار های ذخیره سازی می پردازد. پروتکل FAT یا FAT16، قابلیت فرمت بندی حافظه های تا حداکثر دو گیگابایتی را دارد.

پروتکل FAT

در پروتکل FAT داده ها تنها دسته بندی می شوند و با خواندن ابتدای هارد دیسک، از نشانی داده ها می توانید آگاه شوید.

شروع محل درایو فرمت شده با پروتکل FAT ، دستورالعمل پرش است.

دستورالعمل پرش سه بایت به صورت 0xeb3c90 می باشد.

پس از شناسایی این سه بایت، تقریبا می توانید اطمینان یابید که وارد درایو شده اید. ۸ بایت بعدی سیستمی که درایو را فرمت کرده است را مشخص می نماید.

دو بایت بعدی: ۱۶ بیت، تعداد بایت هایی که در هر بخش (سکتور) وجود دارد.

بایت بعدی: ۸ بیت، تعداد بخش در هر خوشه (سکتور در هر کلوستر).

دو بایت بعدی: ۱۶بیت، بخش های از پیش گرفته شده (رزرو شده)

بایت بعدی: ۸ بیت، تعداد جدول های اختصاص فایل (فت ها)

دو بایت بعدی: ۱۶بیت، مجموع ورودی های هسته

دوبایت بعدی: ۱۶بیت، مجموع بخش های منطقی

بایت بعدی: ۸بیت، اطلاعات دستگاه ذخیره کننده

دو بایت بعدی: ۱۶بیت، تعداد منطقی بخش های هر فت

از نشانی 0xb تا 0x1fe مربوط به بایاس و سیستم عامل است، حجم این داده ها متغیر است.

داده 0x1fe=0x55 و 0x1ff=0xaa که چرخش (شیفت) داده برای هم گام سازی، نامیده می شود.

بخش های هر خوشه * بایت های هربخش = عددی که هنگام فرمت درایو وارد می کنید (Allocation unit size) پس یک رابطه با بیرون از درایو یافته شد.

در اینجا مشخص خواهد شد که اصل هیچ گونه از داده های دیجیتالی را، از کپی آن به هیچ وجه نمی توان تشخیص داد.

در صورتی که چند بایت دستکاری شوند، هر نوع داده دیجیتالی را می توانید کپی بگیرید، مگر در صورتی که پولک (Chip) اجازه این کار را ندهد، در این صورت، پولک در آزمایشگاههای پیشرفته باید شکافته شود و گیت های آن دستکاری شود، شاید این کار واقعا غیر ممکن باشد.

* بایت

| | بخش

( ) خوشه

( |***| |***| |***| )

بخش ها (سکتور ها) در بیشتر فرمت ها ۵۱۲ بایتی هستند. برنامه زیر، اطلاعات اولیه فایل با فرمت FAT16 را از کارت حافظه می خواند:

bool cTxos::bFileInit()
{
	if(!bSDMMCReceiveBlock(0x00000000))
	{
		strcpy(ucErrMsg,“File format 0“);

		return 0;
	}

	if(ucFileBlockData[0] != 0xeb
		|| ucFileBlockData[1] != 0x3c
		|| ucFileBlockData[2] != 0x90)//Jump instruction
	{
		strcpy(ucErrMsg,“File format J“);

		return 0;
	}

	usFileBPS = ucFileBlockData[11];
	usFileBPS |= ucFileBlockData[12] << 8;

	ucFileSPC = ucFileBlockData[13];

	usFileFRS = ucFileBlockData[14];
	usFileFRS |= ucFileBlockData[15] << 8;

	ucFileFAT = ucFileBlockData[16];

	usFileTRE = ucFileBlockData[17];
	usFileTRE |= ucFileBlockData[18] << 8;

	usFileSPF = ucFileBlockData[22];
	usFileSPF |= ucFileBlockData[23] << 8;

	if((ucFileSPC * usFileBPS) != 8192)//Block lengh
	{
		strcpy(ucErrMsg,“Block lengh is not 8192“);

		return 0;
	}

	ucFileMaxBlocksOfCals = (ucFileSPC * usFileBPS)/512;

	//root directory initialize
	if(!bOpenDir(0))
	{
		strcpy(ucErrMsg,“File format-Root dir“);

		return 0;
	}

	return 1;
}

bool cTxos::bOpenDir(unsigned short usCalusterNumber)
{
	unsigned int uiRamAddr;

	//root directory
	uiRamAddr = (usFileFRS+(usFileSPF * ucFileFAT))*usFileBPS;

	if(usCalusterNumber != 0)
		uiRamAddr += ((usCalusterNumber-2)*ucFileSPC*usFileBPS)+(usFileTRE*32);

	vDelayUS(10000);
	if(!bSDMMCReceiveBlock(uiRamAddr))
		return 0;

	for(usCalusterNumber=0; usCalusterNumber<512; usCalusterNumber++)
		ucFileDir[usCalusterNumber] = ucFileBlockData[usCalusterNumber];

	usFileEntryOffset = 0x0000; //First entry

	return 1;
}

و با برنامه زیر، فایلی با حجم نامحدود خوانده می شود؛ بعد از هر بار که ۲۵۶ خانه حافظه پرشد، دوباره از ابتدای کارت حافظه، اطلاعات خوانده می شود.

void cTxos::vReadDir()
{
	//File name 0x00
	ucFileName[0] = ucFileDir[usFileEntryOffset+0];//0x00:empty - 0xE5:deleted
	ucFileName[1] = ucFileDir[usFileEntryOffset+1];
	ucFileName[2] = ucFileDir[usFileEntryOffset+2];
	ucFileName[3] = ucFileDir[usFileEntryOffset+3];
	ucFileName[4] = ucFileDir[usFileEntryOffset+4];
	ucFileName[5] = ucFileDir[usFileEntryOffset+5];
	ucFileName[6] = ucFileDir[usFileEntryOffset+6];
	ucFileName[7] = ucFileDir[usFileEntryOffset+7];
	ucFileName[8] = '\0';

	//File type 0x08
	ucFileType[0] = ucFileDir[usFileEntryOffset+8];
	ucFileType[1] = ucFileDir[usFileEntryOffset+9];
	ucFileType[2] = ucFileDir[usFileEntryOffset+10];
	ucFileType[3] = '\0';

	//File first caluster 0x1A
	usFileOSR = ucFileDir[usFileEntryOffset+26];
	usFileOSR |= ucFileDir[usFileEntryOffset+27] << 8;

	usFileEntryOffset += 0x20; //Next entry

	//End of cache
	if(usFileEntryOffset == 0x200)
		usFileEntryOffset = 0x00; //First entry
}

bool cTxos::bOpenFile(unsigned short usCalusterNumber)
{
	unsigned short usX,
			usY,
			usFirstAddr = (usFileFRS*usFileBPS),
			usLastStart = usFirstAddr;

	vDelayUS(100);
	ucFileLastBlockOfCal = 0;
	ucFileLastCal = 0;
	usFileCalusters[0] = usCalusterNumber;
	usFileCalusters[255] = 0;
	usY = (usFileCalusters[0])*2;
	usFirstAddr = (usFileFRS*usFileBPS);
	usLastStart = usFirstAddr+(usY&0xfe00);

	if(!bSDMMCReceiveBlock(usLastStart))
		return 0;

	for(usX=0; usX<255;)
	{
		if(!((usFirstAddr+usY) >= usLastStart && (usFirstAddr+usY) < (usLastStart+512)))
		{ 
			usLastStart = usFirstAddr+(usY&0xfe00);

			if(!bSDMMCReceiveBlock(usLastStart))
				return 0;
		}
		usY = ucFileBlockData[(usY&0x01ff)]
			|(ucFileBlockData[(usY&0x01ff)+1]<<8);
		usX++;

		if(usY!=0xffff)
			usFileCalusters[usX] = usY;
		else
		{
			usFileCalusters[usX] = 0;

			break;
		}

		usY = (usFileCalusters[usX])*2;
	}

	return 1;
}

bool cTxos::bReadFile()
{ 
	vDelayUS(100);
	if(usFileCalusters[ucFileLastCal]==0)
		return 0;

	if(ucFileLastCal == 255)
		if(!bOpenFile(usFileCalusters[ucFileLastCal]))
			return 0;

	if(!bSDMMCReceiveBlock((( usFileFRS+(usFileSPF * ucFileFAT)+((usFileCalusters[ucFileLastCal]-2)*ucFileSPC) )*usFileBPS)+(usFileTRE*32)+(ucFileLastBlockOfCal*512)))
		return 0;

	if(ucFileLastBlockOfCal < ucFileMaxBlocksOfCals-1)
		ucFileLastBlockOfCal++;
	else
	{
		ucFileLastBlockOfCal = 0;
		ucFileLastCal++;
	}

	return 1;
}

void cTxos::vReadFileGoToAddr(unsigned int uiAddr)//512 bytes step - max 2MB offset from 0 in 8192 format
{
	ucFileLastCal = uiAddr/ucFileMaxBlocksOfCals;
	ucFileLastBlockOfCal = uiAddr%ucFileMaxBlocksOfCals;
}

تابع آخر، محل خواندن حافظه را جا به جا می کند، برنامه زیر نیز، یک نمونه از کاربرد توابع بالا را، برای خواندن تصاویر با فرمت BMP-16bit-RGB-565 نشان می دهد:

bool cTxos::bDrawBMPFile(unsigned short usCalNumber)
{
	unsigned short usX;
	unsigned char ucY;

	if(!bOpenFile(usCalNumber))
		return 0;

	if(!bReadFile())
		return 0;

	if(ucFileBlockData[0]==0x42 && ucFileBlockData[1]==0x4d)
	{
		usCalNumber = ucFileBlockData[10]|(ucFileBlockData[11]<<8);

		for(ucY=240; ucY>0; )
		{
			ucY--;
			for(usX=0; usX<320;usX++)
			{
				if(usCalNumber == 512)
				{
					if(!bReadFile())
						return 0;

					usCalNumber = 0;
				}
				vPrintPixel(usX,ucY,ucFileBlockData[usCalNumber]|(ucFileBlockData[usCalNumber+1]<<8));
				usCalNumber+=2;
			}
		}

		return 1;
	}
	return 0;
}

 

مقالات، پروژه ها و آموزش های بیشتر در بلاگ

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد.

5 × 4 =