#include <stdio.h>
#include <stdlib.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
struct mac_tab
{
	const unsigned long len;
	const unsigned long vel[];
};


const char bios_head_X250[32]=
{
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0xA5,0xF0,0x0F,0x03,0x00,0x04,0x03,0x06,0x02,0x10,0x15,0x20,0x01,0x21,0x00
};
const char bios_head_X260[32]=
{
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x5A,0xA5,0xF0,0x0F,0x03,0x00,0x04,0x00,0x08,0x02,0x10,0x42,0x30,0x03,0x31,0x00
};

struct mac_tab x250_mac=
{
	0,
	{0}
};
struct mac_tab x260_mac=
{
	2,
	{0x1000,0x2000}
};
/*
bios type:

 0: need change
 1: X250
 2: X260
 

*/
char bios_type=0; 
char buff[0xffffff];
struct mac_tab *chage_mac_tab;
char outputdir[256];
char inputdir[256];
char chack_str(const char *a,char *b,int len)
{
	int c;
	for(c=0;c<len;c++)
	{
		if(a[c]!=b[c])
		{
			return 1;
		}
	}
	return 0;
}


void change_bios_type()
{
	FILE *unlock_bios = NULL;

	
	do
	{
		printf("选择BIOS机型：（输入编号）\n 1-> X250 \n 2-> X260 \n");
		scanf("%d",&bios_type);	
		
		if(bios_type==1)
		{
			unlock_bios=fopen("./X250.bbb","rb");
			chage_mac_tab=&x250_mac;
		}
		if(bios_type==2)
		{
			unlock_bios=fopen("./X260.bbb","rb");
			chage_mac_tab=&x260_mac;
		}
		if(unlock_bios==NULL)
		{
			printf("ERROR_NOTFUND_THE_S_FILE\n");
			bios_type=0; 
		}		
	}while(bios_type==0);

	fread(buff,0xffffff,1,unlock_bios);	
	fclose(unlock_bios);
	
/*	
	
	

*/	
}


char tryunlock(char *dir)
{
	int a=0;
	unsigned long mac_t=0;
	if(dir==NULL)//手动输入模式 
	{
		printf(" 直接输入BIOS路径:\n 或输入命令:\n change    改变BIOS类型。\n exit      退出程序 \n");
		for(a=0;a<256;a++)//清空输入缓存 
		{
			inputdir[a]=0;
		}
		scanf("%s",inputdir);//读取输入 
		if(chack_str("change",inputdir,6)==0)//读取特殊字符串 
		{
			change_bios_type();             //改变bios类型 
			return 1;
		}
		if(chack_str("exit",inputdir,4)==0)
		{
			return 0;
		}
	}else
	{
		a=0;
		while(dir[a]!='\0')//拖入文件模式 
		{
			inputdir[a]=dir[a];
			a++;
		}
	}

	if(bios_type==0)  //还没设置bios类型 
	{
		change_bios_type();//改变bios类型 
		
	}
	
	printf("Input flie  %s\n",inputdir);
	
	FILE *bios=NULL;         //将要破解的bios 
	FILE *output_bios=NULL;	//输出的bios 
	bios=fopen(inputdir,"rb");
	char id[32];
	
	if(bios==NULL)//打开将要破解的bios失败 可能是路径错误 
	{
		printf("ERROR. can't Open file ..\n");
		return 0; 
	}else
	{
		fread(id,32,1,bios);//读取将要破解的bios的前32个字节 鉴定是不是bios文件 
		if(chack_str(buff,id,32))
		{
			printf("ERROR. Not Bios File\n");
			return 0;
		}else
		{
			//printf("try it..\n");
			if(fseek(bios,0xf00,SEEK_SET))//读取将要破解的Bios的ID 
			{
				printf("ERROR. -0\n");
				return 0;
			}else
			{
				fread(id,32,1,bios);
				for(a=0;a<32;a++)//将ID写入已破解bios 
				{
					buff[0xf00+a]=id[a];
				}
			}		
			//更改MAC地址 
			if(fseek(bios,0x1000,SEEK_SET))//读取将要破解的Bios的MAC
			{
				printf("ERROR. -0\n");
				return 0;
			}else
			{
				for(a=0;a<32;a++)//复用id数组 
				{
					id[a]=0;
				}
				fread(id,6,1,bios);
				//写入到已破解bios,有好几个地址 
				for(mac_t=0;mac_t<chage_mac_tab->len;mac_t++)
				{
					for(a=0;a<6;a++)
					{
						buff[chage_mac_tab->vel[mac_t]+a]=id[a];
					}
				}

			}
				
			for(a=0;a<256;a++)
			{
				outputdir[a]=0;
			}
			printf("MAC: %02X%02X%02X%02X%02X%02X \n",id[0],id[1],id[2],id[3],id[4],id[5]);
			sprintf(outputdir,"%s%s",inputdir,"_unlock.bin");
			printf("Output flie %s",outputdir);
			output_bios=fopen(outputdir,"wb");
			if(output_bios==NULL)
			{
				printf("ERROR. can't Output file ..\n");
			}else
			{
				fwrite(buff,0xffffff,1,output_bios);
				fclose(output_bios);
			}
			
			printf("\n\n");					
					
				
				
			

			
		}
		
	}
	
	fclose(bios);
	
	return 1;
	/*
	int a;
	FILE *bios=NULL;
	FILE *output_bios=NULL;
	bios=fopen(dir,"rb");
	if(bios==NULL)
	{
		printf("ERROR. can't Open file ..\n");
	}else
	{
		fread(id,32,1,bios);
		if(chack_str(bios_head,id,32))
		{
			printf("ERROR. Not Bios File\n");
		}else
		{
			//printf("try it..\n");
			if(fseek(bios,0xf00,SEEK_SET))
			{
				printf("ERROR. -0\n");
			}else
			{
				fread(id,32,1,bios);
				for(a=0;a<32;a++)
				{
					buff[0xf00+a]=id[a];
				}
				for(a=0;a<256;a++)
				{
					outputdir[a]=0;
				}
				printf("id: %s \n",id);
				sprintf(outputdir,"%s%s",dir,"_unlock.bin");
				printf("Output flie %s",outputdir);
				output_bios=fopen(outputdir,"wb");
				if(output_bios==NULL)
				{
					printf("ERROR. can't Output file ..\n");
				}else
				{
					fwrite(buff,0xffffff,1,output_bios);
					fclose(output_bios);
				}
				
				printf("\n\n");
			}
		}
		
	}
	
	fclose(bios);
	*/
}
	
int main(int argc, char *argv[])
{

	printf("ThinkPad Bios unlock..v0.1\n\n\n");
	if(argc==1)
	{
		printf("联想ThinkPad Bios超级密码解锁程序。支持X250，X260（测试）\n\n使用方法：\n");
		printf("1 使用编程器将原机Bios读出\n");
		printf("2 将读出的内容以二进制格式bin保存\n");
		printf("3 将bin文件拖进本程序，程序会自动生成解锁Bios，（支持批量拖入,某些路径需要以管理员身份运行本软件）\n");  
		printf("4 将生成的解锁bios刷入，然后开机，按F1进入Bios，将超级密码改成空密码，按F10保存\n");
		printf("5 完成！ 注意，部分Bios芯片写入之前要先清空，否则无法校验通过。\n\n\n");
		printf("编写日期 2021-12-12 00:46 联系 吴文峰 邮箱 kevin@lmve.net \n\n");
		printf("项目地址 https://git.lmve.net/kevin/thinkpad_unlock_bios \n博客地址 https://wnfed.com \n\n！！！请勿商用！！！\n\n");	
	}
		
	while(argc>1)
	{
	
		argc--;
		tryunlock(argv[argc]);
	}
	printf("\n");
	printf("\n");
	
	char while_flag=0;
	do
	{
		while_flag=tryunlock(NULL);
	}while(while_flag);
	
	//printf("have %d file\n",argc-1);
	//printf(argv[1]);
	//system("pause");
	return 0;
}
