在做boot loader的实验, 但是要在格式化为FAT32的U盘上使用.
* 用WinHex将U盘全部字节都填成0.
* 用UltraIso中的格式化功能, 将U盘格式化成FAT32, 分配单元为4KB
* 用UltraIso提供的写入MBR功能,向U盘写入可引导的MBR, 参数为USB-HDD.
这问题就来了,MBR在0扇区,我们可以通过逆向ultraIso写入的MBR, 重写MBR + U盘格式化好之后的分区表(16 * 4字节),形成自己的MBR.
但是其他被用到的扇区, 我们不能改。否则破坏了分区信息,U盘插入后,Win7提示"此U盘未格式化,是否现在格式化"。
一次两次还行,我们可以点击关掉这个提示。做实验时间长了,还真受不了这个提示.
解决的方法有2个:
* 研究分区表信息, 做成像老毛桃那样的自启动U盘. 但是我的目标仅仅是做boot loader实验, 现在的时间和能力都不允许这么搞
* 查找不用的扇区(全0的扇区), 在我们自己的MBR执行完成后,直接跳到我们自定义的的第一个扇区(也是没有被Windows分区判断使用的扇区), 由这个扇区来加载我们做实验的后续扇区到内存. 这个方法可操作性强,可以回避那个恼人的提示.
到底能不能在做实验的U盘插入时,让Win7不弹出提示,我还没实验.
现在先写个测试程序找找到底那些扇区被用了, 被用到的扇区数量,用WinHex手工查看,数量还是比较少的。
怕看的眼花,用测试程序来找.
测试程序下载点: src_find_used_sectors.zip
效果图:
工程预览:
/// @file find_used_sectors.cpp
/// @brief 找出没有被FAT32文件系统使用扇区, 用来做boot loader实验
/// 防止U盘做实验后, 插入U盘,被Win7提示 "此U盘没有格式化, 是否现在格式化"
/// 每次插入U盘, 都被提示信息,很烦人
#include "stdafx.h"
/// 先用WinHex将U盘全部填0
/// 在U盘在UltraIos中格式化U盘, 参数: FAT32, 4KB
/// 写入MBR, 参数: USB-HDD
/// 用WinHex将U盘内容全部拷贝到文件
/// 用这个测试程序找到那些扇区被用了(有非0的字节)
/// 我们做U盘实验时, 就可以确定在哪个扇区写东西,不会让Win7弹出"U盘无效"提示
#define OBJ_FILE_TO_PARSE L"D:\\uDiskBk\\uDisk_format_ok_write_mbr_by_ultra_iso.bin"
#define SECTOR_SIZE 512
BOOL FindAndShowNoZeroContentSectorsIndex(HANDLE& hFile, LONGLONG llFileSize); ///< 查找显示有非零内容的扇区
BOOL JudgeSectorWasUsed(BYTE* pcSectorBegin, int iLenSector);
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = INVALID_HANDLE_VALUE;
LONGLONG llFileSize = 0;
do
{
if (!ns_base::IsFileExist(OBJ_FILE_TO_PARSE))
{
_tprintf(L"File not exist[%s]\r\n", OBJ_FILE_TO_PARSE);
break;
}
llFileSize = ns_base::GetFileSize(OBJ_FILE_TO_PARSE);
if (llFileSize < 0)
{
_tprintf(L"File size [0x%I64x] invalid\r\n", llFileSize);
break;
}
if (0 != (llFileSize % 512))
{
_tprintf(L"File can't mod by sector size(512 bytes\r\n");
}
if (!ns_base::OpenFileReadBinary(OBJ_FILE_TO_PARSE, hFile))
break;
if (!FindAndShowNoZeroContentSectorsIndex(hFile, llFileSize))
{
_tprintf(L"FALSE FindAndShowNoZeroContentSectorsIndex()\r\n");
}
SAFE_CLOSE_HANDLE(hFile);
} while (0);
_tprintf(L"END, press any key to quit\r\n");
#ifdef _DEBUG
getwchar();
#endif
getwchar();
return 0;
}
BOOL FindAndShowNoZeroContentSectorsIndex(HANDLE& hFile, LONGLONG llFileSize)
{
BOOL bRc = FALSE;
BYTE cBufRd[SECTOR_SIZE];
DWORD dwRdBack = 0;
long lSectorIndexCur = 0;
long lSectorWasUsed = 0;
LONGLONG llFileSizeRd = 0;
LONGLONG llPosBegin = 0;
LONGLONG llPosEnd = 0;
do
{
if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, 0, 0, FILE_BEGIN))
break;
do
{
::ZeroMemory(cBufRd, sizeof(cBufRd)); ///< !
if (!::ReadFile(hFile, &cBufRd, sizeof(cBufRd), &dwRdBack, NULL))
break;
if (dwRdBack != sizeof(cBufRd))
break;
if (JudgeSectorWasUsed(cBufRd, sizeof(cBufRd)))
{
lSectorWasUsed++;
llPosBegin = (LONGLONG)lSectorIndexCur * SECTOR_SIZE;
llPosEnd = llPosBegin + sizeof(cBufRd) - 1;
_tprintf(L"Sector[0x%.8I64x-0x%.8I64x] sector index[%ld] was used\r\n",
llPosBegin,
llPosEnd,
lSectorIndexCur);
}
llFileSizeRd += dwRdBack;
if (llFileSizeRd == llFileSize)
{
bRc = TRUE;
break;
}
lSectorIndexCur++;
} while (1);
} while (0);
if (bRc)
{
_tprintf(L"lSectorWasUsed = %ld\r\n", lSectorWasUsed);
}
return bRc;
}
BOOL JudgeSectorWasUsed(BYTE* pcSectorBegin, int iLenSector)
{
BOOL bRc = FALSE;
int iIndex = 0;
do
{
if ((NULL == pcSectorBegin)
|| (SECTOR_SIZE != iLenSector))
{
break;
}
for (iIndex = 0; iIndex < SECTOR_SIZE; iIndex++)
{
if (0 != *(pcSectorBegin + iIndex))
{
bRc = TRUE;
break;
}
}
} while (0);
return bRc;
}