FAT 协议 (驱动器格式)

Electronics and Programming tutorials and projects

FAT 协议 (驱动器格式)

fat16 protocol FAT 协议

本文概述了存储硬件协议。 FAT16 或 FAT 协议 最多可以 格式 化 2 GB 的存储器。

FAT 协议

在 FAT 协议 中,数据只是进行了分类,通过读取硬盘的开头就可以知道数据的地址。

使用 FAT 协议格式化的驱动器的起始位置是“跳转指令”。

跳转指令为0xeb3c90。

识别出这三个字节后,你几乎可以确定你已经进入了驱动器。 接下来的 8 个字节指定格式化驱动器的系统。

接下来的两个字节:16位,每个扇区的字节数。

下一个字节:8位,每簇的扇区数(sectors per cluster)。

接下来的两个字节:16 位,预取(保留)段

下一个字节:8位,文件分配表(fats)的数量

接下来的两个字节:16 位,内核(根)条目总数

下一个字节:16位,逻辑部分之和

下一个字节:8位,存储设备信息

接下来的两个字节:16 位,每个 fat 的逻辑段数

从地址0xb到0x1fe与偏差和操作系统有关,该数据量是可变的。

数据0x1fe=0x55和0x1ff=0xaa,称为数据旋转(移位)以进行同步。

每个簇的节数*每个节的字节数=格式化驱动器时输入的数字(分配单元大小),因此发现与驱动器外部的关系。

这里很清楚,任何数字数据的原始版本都不能以任何方式区分其副本。

你可以复制任何类型的数字数据,除非芯片不允许这样做,所以要复制这些受保护的数据,必须在先进的实验室中分割芯片并操纵其门,这几乎是不可能的。

* 字节 / byte

| | 该部门 / sector

( ) 簇 / cluster

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

大 多 数 格 式 中 的 扇 区 为 512 字 节。 下 面 的 程 序 从 存 储 卡 中 读 取 FAT16 或 FAT 格 式 文 件 的 基 本 信 息:

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

在 下 面 的 程 序 中,读 取 一 个 无 限 大 小 的 文 件; 每 次 填 满 256 个 存 储 单 元 后,都 会 重 新 从存 储 卡 的 开 头 读 取 数 据。

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

最 后 一 个 函 数 移 动 内 存 读 取 位 置 / 位 置,下 面 的 程 序 也 展 示 了 使 用 上 述 函 数 读 取 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;
}

***“”电子、编程和 Arduino 项目,包括为工程师、学生和业余爱好者提供的源代码、原理图和 PCB 计划“”***

 

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

3 + 19 =