헥사 에디터로 부트로더 복사하는게 영.. 수동이라.. 자동으로 가상 파일에 복사하는 프로그램을 만들었다.

첫 섹터에 파티션 정보를 읽어서 해당 FAT을 찾고 거기에 기존 BPB를 건너뛰고 부트코드만 복사하는 코드이다. 생각 같아선 디스크 관리 에서 이미지를 마운트 시켜서 드라이브로 바로 입력하고 싶었으나, Windows 7 에서 볼륨이 있는 부트섹터 접근을 막았다고 하나.. 어쨌듯 하는 방법을 몰라서 그냥 파일을 읽어서 쓰는 방법으로 작성했다.


// 2013. 08. 02
// mangg@manggong.org
// 
// 
// 가상이미지 파일에 부트로더 복사.
// 할일 없어서 이거나 주물럭 주물럭.

#include "stdafx.h"
#include <Windows.h>

#define PARTITION_POS	0x1BE

#pragma pack(push, 1)
typedef struct _PARTITION                                                                          
{                                                                                                  
	BYTE ACTIVE;	// 부팅 가능 플래그 (0x80 : 부팅 가능, 0x00 : 부팅 불가)
	BYTE CHS_BEGIN[3];
	BYTE TYPE;		// 파티션 타입 ( 0x07:NTFS, 0x05:Extended Partition, 0x0B:FAT32, 0x0E:FAT16, 0x0F:Extended Partition, exp INT 13h
					//				0x1B: Hidden FAT32, 0x42:Secure FileSystem, 0x82:Linux Swap partition, 0x83:Linux native file systems)
	BYTE CHS_END[3];
	INT32 LBA_START;
	INT32 LENGTH;
} PARTITION, *PPARTITION;

typedef struct _FAT
{
	BYTE CODE[3];
	CHAR SYSTEMID[8];
	WORD SECTOR_SIZE;
	BYTE SECTOR_CLUSTER;
	WORD RESERVED_SECTOR;
	BYTE FAT_NUM;
	WORD ROOT_DIRECTORY_ENTRY_CNT;
	WORD TOTAL_SECTOR16;
	BYTE MEDIATYPE;
	WORD SECTOR_FAT16;
	WORD SECTOR_TRACK;
	WORD SECTOR_HEAD;
	DWORD HIDDEN_SECTOR;
	DWORD TOTAL_SECTOR32;
	DWORD SECTOR_FAT32;
	WORD EXT_FLAGS;
	WORD VER;
	DWORD ROOT_DIRECTORY_CLUSTER;
	WORD INFO;
	WORD BACKUP_BOOT_SECTOR;
	BYTE RESERVED_ID[12];
	BYTE PHYSICALDISK_TYPE;
	BYTE RESERVED;
	BYTE SIGNATURE;
	DWORD VOLUMEID;
	BYTE VOLUME_LABLE[11];
	BYTE FILESYSTEM_TYPE[8];
} FAT32, *PFAT32;


#pragma pack(pop)

bool LoadBootloader(BYTE *pDiskInfo,TCHAR *BootloaderFile);
bool CopyBootloader(HANDLE hFile, __int64 sector, BYTE *pDiskInfo,TCHAR *BootloaderFile);
bool GetFAT(HANDLE hFile,  __int64 sector, BYTE *pDiskInfo, PFAT32 FAT_INFO);
bool GetActivePartition(HANDLE hFile, BYTE *pDiskInfo, PPARTITION PartitionInfo);
bool DISK_WRITE(HANDLE hFile, __int64 sector, BYTE *pData, int sectorSize);
bool DISK_WRITE_PARTICLE(HANDLE hFile, __int64 sector, DWORD offset, BYTE *pData, int writeSize);
bool DISK_READ(HANDLE hFile, __int64 sector, BYTE *pData, int sectorSize);

void Print_PhysicalList()
{
	TCHAR physical[65536];
	TCHAR logical[65536];

    QueryDosDevice(NULL, physical, sizeof(physical));
	printf("Physical Drive Number : \n");

    for (char *pos = physical; *pos; pos+=strlen(pos)+1) 
	{
        QueryDosDevice(pos, logical, sizeof(logical));

		if( strstr(pos, "Physical") != NULL )
		{
			printf("%s : %s\n", pos, logical);
		}
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE hFile;
	TCHAR szDrive[MAX_PATH];
	DWORD	FAT_SECTOR = 0;
	BYTE	*pDiskInfo;
	PARTITION PartitionInfo;
	FAT32 FAT_INFO;

	if( argc < 3 )
	{
		printf("Usage : bootcopy bootloader VirtualFile\n\n");
		//Print_PhysicalList();
		return -1;
	}

	_stprintf(szDrive, _T("%s"), argv[2]);

	hFile = ::CreateFile(
						szDrive, 
						GENERIC_READ | GENERIC_WRITE, 
						FILE_SHARE_READ | FILE_SHARE_WRITE, 
						NULL, 
						OPEN_EXISTING, 
						0, 
						NULL);

	if( hFile == INVALID_HANDLE_VALUE )
	{
		printf("Don't read drive\n");
		return -1;
	}


	pDiskInfo = (BYTE*)malloc(0x200);
	if(pDiskInfo == NULL )
	{
		CloseHandle(hFile);
		printf("Don't Allocate Memory\n");
		return -1;
	}

	DWORD junk;
	BOOL bResult;


	char bs[255];
	memset(bs,0,255);

	/////////////////////////////////////////
	// READ PARTITION INFO

	if( GetActivePartition(hFile, pDiskInfo, &PartitionInfo) == false )
	{
		CloseHandle(hFile);
		free(pDiskInfo);
		printf("Don't Read Partition Info\n");
		return -1;
	}

	/////////////////////////////////////////
	// READ FAT32 INFO
	if( GetFAT(hFile, PartitionInfo.LBA_START, pDiskInfo, &FAT_INFO) == false )
	{
		CloseHandle(hFile);
		free(pDiskInfo);
		printf("Don't Read FAT Info\n");
		return -1;
	}

	/////////////////////////////////////////
	// COPY BOOTLOADER
	if( CopyBootloader(hFile, PartitionInfo.LBA_START, pDiskInfo, argv[1]) == false )
	{
		CloseHandle(hFile);
		free(pDiskInfo);
		printf("Don't Copy Bootloader\n");
		return -1;
	}

	printf("Copy Success...\n");

	free(pDiskInfo);
	CloseHandle(hFile);

	return 0;
}

bool DISK_READ(HANDLE hFile, __int64 sector, BYTE *pData, int sectorSize)
{
	DWORD read = 0;

	LARGE_INTEGER li;

	li.QuadPart = (0x200 * sector) & ~(0x200-1);

	if (::SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
	{
		::GetLastError();
		return false;
	}

	if (!::ReadFile(hFile, pData, sectorSize, &read, NULL))
		return false;

	return true;
}

bool DISK_WRITE(HANDLE hFile, __int64 sector, BYTE *pData, int sectorSize)
{
	DWORD written = 0;

	LARGE_INTEGER li;

	li.QuadPart = (0x200 * sector) & ~(0x200-1);

	if (::SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
	{
		::GetLastError();
		return false;
	}

	if (!::WriteFile(hFile, pData, sectorSize, &written, NULL))
		return false;

	return true;
}

bool DISK_WRITE_PARTICLE(HANDLE hFile, __int64 sector, DWORD offset, BYTE *pData, int writeSize)
{
	DWORD written = 0;

	LARGE_INTEGER li;

	li.QuadPart = (0x200 * sector) & ~(0x200-1);
	li.LowPart += offset;

	if (::SetFilePointer(hFile, li.LowPart, &li.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
	{
		printf("SetFilePointer error : %d\n",::GetLastError());
		return false;
	}

	if (!::WriteFile(hFile, pData, writeSize, &written, NULL))
	{
		return false;
	}

	return true;
}

bool GetFAT(HANDLE hFile,  __int64 sector, BYTE *pDiskInfo, PFAT32 FAT_INFO)
{
	DWORD read = 0;

	if(DISK_READ(hFile, sector, pDiskInfo, 0x200) == false )
	{
		return false;
	}

	memcpy(FAT_INFO, pDiskInfo, sizeof(FAT32));

	return true;
}

bool GetActivePartition(HANDLE hFile, BYTE *pDiskInfo, PPARTITION PartitionInfo)
{
	PPARTITION PartitionTemp = NULL;

	if( DISK_READ(hFile, 0, pDiskInfo, 0x200) == false )
		return false;

	for(int i = 0; i < 4; i++ )
	{
		PartitionTemp = (PPARTITION) (pDiskInfo + PARTITION_POS + (sizeof(PARTITION) * i));

		if(PartitionTemp->ACTIVE == 0x80 )
		{
			memcpy(PartitionInfo, PartitionTemp, sizeof(PARTITION));
			return true;
		}
	}

	return false;
}

bool CopyBootloader(HANDLE hFile, __int64 sector, BYTE *pDiskInfo,TCHAR *BootloaderFile)
{
	if( LoadBootloader(pDiskInfo, BootloaderFile) == false)
		return false;

	if( DISK_WRITE_PARTICLE(hFile, sector, 0, pDiskInfo, 3) == false )
	{
		printf("ERROR : Copy \"BOOT JMP CODE\" to DISK\n");
		return false;
	}

	pDiskInfo += 0x5A;
	if( DISK_WRITE_PARTICLE(hFile, sector, 0x5A, pDiskInfo, 0x200-0x5A) == false)
	{
		printf("ERROR : Copy \"BOOT CODE\" to DISK\n");
		return false;
	}

	return true;
}

bool LoadBootloader(BYTE *pDiskInfo,TCHAR *BootloaderFile)
{
	HANDLE hBOOTFile;
	DWORD dwReadn;

	hBOOTFile = ::CreateFile(
						BootloaderFile, 
						GENERIC_READ | GENERIC_WRITE, 
						FILE_SHARE_READ | FILE_SHARE_WRITE, 
						NULL, 
						OPEN_EXISTING, 
						0, 
						NULL);

	if( hBOOTFile == INVALID_HANDLE_VALUE )
	{
		printf("Don't open bootloader\n");
		return false;
	}

	if(!::ReadFile(hBOOTFile, pDiskInfo, 0x200, &dwReadn, NULL))
	{
		printf("Don't read bootloader\n");

		CloseHandle(hBOOTFile);
		return false;
	}
	if(dwReadn != 0x200)
	{
		printf("Is not match bootloader size\n");
		CloseHandle(hBOOTFile);
		return false;
	}

	CloseHandle(hBOOTFile);
	return true;
}

개발 환경

Windows 7
Visual Studio 2010

잘되면 내탓, 잘 못되면 조상탓.

 

'프로그래밍 > OS 만들기' 카테고리의 다른 글

OS 만들기 #12 - PE 파일 포맷  (0) 2013.09.10
OS 만들기 #11 - 리얼모드 & 보호모드  (0) 2013.08.14
OS 만들기 #9 - 부트로더  (0) 2013.08.14
OS 만들기 #8 - 부트로더  (0) 2013.08.14
OS 만들기 #7 - FAT32  (1) 2013.08.14

+ Recent posts