FAT-Protokoll (Laufwerksformat)

Electronics and Programming tutorials and projects

FAT-Protokoll (Laufwerksformat)

fat16 protocol FAT 协议

Dieser Artikel bietet einen Überblick über Speicherhardwareprotokolle. Mit dem FAT16- oder FAT-Protokoll können Speicher bis zu zwei Gigabyte formatiert werden.

FAT-Protokoll

Im FAT-Protokoll werden Daten nur kategorisiert, und durch Lesen des Anfangs der Festplatte können Sie die Adresse der Daten ermitteln.

Der Startort eines Laufwerks, das mit dem FAT-Protokoll formatiert ist, ist ein „Sprungbefehl“.

Der Sprungbefehl lautet 0xeb3c90.

Nachdem Sie diese drei Bytes identifiziert haben, können Sie fast sicher sein, dass Sie das Laufwerk eingegeben haben. Die nächsten 8 Bytes geben das System an, das das Laufwerk formatiert hat.

Die nächsten beiden Bytes: 16 Bit, die Anzahl der Bytes in jedem Sektor.

Nächstes Byte: 8 Bit, die Anzahl der Sektoren pro Cluster (Sektoren pro Cluster).

Nächste zwei Bytes: 16 Bit, vorab abgerufene (reservierte) Segmente

Nächstes Byte: 8 Bit, die Anzahl der Dateizuordnungstabellen (Fats)

Die nächsten zwei Bytes: 16 Bit, die gesamten Kernel-(Root-)Einträge

Nächstes Byte: 16 Bit, die Summe der logischen Teile

Nächstes Byte: 8 Bit, Informationen zum Speichergerät

Die nächsten beiden Bytes: 16 Bit, die logische Anzahl der Segmente pro Fett

Von der Adresse 0xb bis 0x1fe hängt es von der Vorspannung und dem Betriebssystem ab, die Menge dieser Daten ist variabel.

Daten 0x1fe=0x55 und 0x1ff=0xaa, was zur Synchronisation als Datenrotation (Verschiebung) bezeichnet wird.

Abschnitte jedes Clusters * Bytes jedes Abschnitts = die Zahl, die Sie beim Formatieren des Laufwerks eingeben (Größe der Zuordnungseinheit), sodass eine Beziehung zur Außenseite des Laufwerks gefunden wurde.

Dabei wird deutlich, dass das Original jeglicher digitaler Daten in keiner Weise von ihrer Kopie zu unterscheiden ist.

Sie können jede Art von digitalen Daten kopieren, es sei denn, der Chip erlaubt dies nicht. Um diese Art von geschützten Daten zu kopieren, muss der Chip in fortgeschrittenen Labors gespalten und seine Tore manipuliert werden, was nahezu unmöglich ist.

  • Byte

| | der Sektor

( ) Cluster

( || || |*| )

Sektoren sind in den meisten Formaten 512 Byte groß. Das folgende Programm liest die Grundinformationen der Datei im FAT16- oder FAT-Format von der Speicherkarte:

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;
}

Und mit dem folgenden Programm wird eine Datei mit unbegrenzter Größe gelesen; Nach jedem Füllen der 256 Speicherzellen werden die Daten erneut vom Anfang der Speicherkarte gelesen.

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] = '';

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

	//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;
}

Die letzte Funktion verschiebt die Leseposition/den Speicherort. Das folgende Programm zeigt auch ein Beispiel für die Verwendung der oben genannten Funktionen zum Lesen von Bildern im BMP-16bit-RGB-565-Format:

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;
}

***““Elektronik-, Programmier- und Arduino-Projekte, einschließlich Quellcodes, Schaltpläne und PCB-Pläne für Ingenieure, Studenten und Bastler““***

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

vier × vier =