WinCE7的Bootpart庫主要提供Flash資料分割函數,所以它需要Flash驅動的支援。WinCE7中Bootpart庫的源碼位置在:\WINCE700\platform\common\src\common\boot\bootpart。在我的6410開發板的eboot中就使用了Bootpart提供的一些功能函數進行分區管理。不過我看到也有很多廠商的BSP中並沒有使用微軟的Bootpart庫進行分區,而是直接使用Flash驅動函數來進行這部分工作,其實在Bootpart庫的內建函式也是調用Flash驅動函數來完成功能。
下面逐一介紹Bootpart庫函數:
1 BP_Init
BOOL BP_Init(
LPBYTE pMemory,
DWORD dwSize,
LPCTSTR lpActiveReg,
PPCI_REG_INFO pRegIn,
PPCI_REG_INFO pRegOut
);
這個函數用來初始化Bootpart庫。
pMemory指向一塊記憶體用來儲存MBR資訊,在BP_Init 函數內部將pMemory 賦值給pbMBRSector。dwSize是記憶體大小。後三個參數傳遞給FMD_Init,因為在BP_Init函數中會調用FMD_Init初始化Flash。
if (!FMD_Init (lpActiveReg, pRegIn, pRegOut))
return FALSE;
在我開發板的eboot中的OEMPlatformInit函數中調用了BP_Init函數,實際作用是用來初始化Flash和BinFS分區。
OALMSG(TRUE, (TEXT("BP_Init\r\n")));
if (!BP_Init((LPBYTE)BINFS_RAM_START, BINFS_RAM_LENGTH, NULL, NULL, NULL) )
{
OALMSG(OAL_WARN, (TEXT("WARNING: OEMPlatformInit failed to initialize Boot Media.\r\n")));
g_bBootMediaExist = FALSE;
}
else
{
g_bBootMediaExist = TRUE;
}
2 BP_OpenPartition
HANDLE BP_OpenPartition(
DWORD dwStartSector,
DWORD dwNumSectors,
DWORD dwPartType,
BOOL fActive,
DWORD dwCreationFlags
);
這個函數用來開啟或者建立分區。
dwStartSector參數是起始邏輯扇區,如果不指定扇區可以設定為NEXT_FREE_LOC。如果BP_OpenPartition函數用來開啟已經存在的的分區,這個參數會被忽略。
dwNumSectors是該分區包含的邏輯扇區數。
dwPartType是分區類型。設定為PART_BOOTSECTION表示建立一個開機磁區用來儲存引導資訊,分區中的所有block都將被標記為唯讀。設定為PART_BINFS代表BinFS分區。
fActive用來設定該分區是否是使用中的磁碟分割。
dwCreationFlags用來設定BP_OpenPartition函數的操作類型。設定為PART_CREATE_NEW表示建立新分區,設定為PART_OPEN_EXISTING表示開啟已經存在的分區,設定為PART_OPEN_ALWAYS,如果分區不存在,則建立一個新分區,如果分區已經存在,就開啟它。
在我開發板的eboot中首先調用BP_OpenPartition函數來建立BinFS分區,用來儲存系統鏡像。BinFS分區位於緊挨著MBR的下一個block,大小為image size的最大值。
hPart = BP_OpenPartition( (IMAGE_START_BLOCK+1)*PAGES_PER_BLOCK, // next block of MBR
SECTOR_TO_BLOCK_SIZE(FILE_TO_SECTOR_SIZE(dwBINFSPartLength))*PAGES_PER_BLOCK, // align to block
PART_BINFS,
TRUE,
PART_OPEN_ALWAYS);
之後又再次調用BP_OpenPartition函數將Flash中的剩餘部分建立為一個FAT32擴充分區。
// create extended partition in whatever is left
//
hPartEx = BP_OpenPartition( NEXT_FREE_LOC,
USE_REMAINING_SPACE,
PART_DOS32,
TRUE,
PART_OPEN_ALWAYS);
3 BP_ReadData
BOOL BP_ReadData(
HANDLE hPartition,
LPBYTE pbBuffer,
DWORD dwLength
);
這個函數用來從一個分區中讀取資料。hPartition是分區控制代碼,pbBuffer是用來儲存資料的緩衝區指標,dwLength是要讀取的資料長度。在BP_ReadData函數內部最終是通過Flash驅動的FMD_ReadSector來讀取分區資料的。
在我開發板的eboot中有一個ReadOSImageFromBootMedia函數用來把系統鏡像從Flash中讀取到RAM,在這個函數中就是通過BP_ReadData來讀取系統鏡像的。
if ( !BP_ReadData( hPart, (LPBYTE)(g_pTOC->id[g_dwTocEntry].dwLoadAddress), SECTOR_TO_FILE_SIZE(g_pTOC->id[g_dwTocEntry].dwTtlSectors)) )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: ReadOSImageFromBootMedia: Failed to read kernel region from partition.\r\n")));
return(FALSE);
}
4 BP_WriteData
BOOL BP_WriteData(
HANDLE hPartition,
LPBYTE pbBuffer,
DWORD dwLength
);
這個函數用來向分區中寫入資料,參數含義和BP_ReadData一樣。在我開發板eboot中有一個WriteOSImageToBootMedia函數用來將系統鏡像從RAM寫入分區。它內部就是調用BP_WriteData將鏡像資料寫入到BinFS分區的。
// Write the region to the BINFS partition.
//
if ( !BP_WriteData(hPart, (LPBYTE)dwRegionStart, dwRegionLength) )
{
EdbgOutputDebugString("ERROR: StoreImageToBootMedia: Failed to write region to BINFS partition (start=0x%x, length=0x%x).\r\n", dwRegionStart, dwRegionLength);
return(FALSE);
}
5 BP_GetPartitionInfo
PPARTENTRY BP_GetPartitionInfo(
HANDLE hPartition,
);
這個函數用來擷取分區資訊。hPartition是分區控制代碼,返回的分區資訊儲存在一個PARTENTRY結構體裡面。這個結構體的原型如下:
typedef struct _PARTENTRY {
BYTE Part_BootInd;
BYTE Part_FirstHead;
BYTE Part_FirstSector;
BYTE Part_FirstTrack;
BYTE Part_FileSystem;
BYTE Part_LastHead;
BYTE Part_LastSector;
BYTE Part_LastTrack;
DWORD Part_StartSector;
DWORD Part_TotalSectors;
} PARTENTRY;
主要是扇區起始和結尾Head、Sector、Track,以及分區中的扇區總數,起始邏輯扇區,分區類型等資訊。
6 BP_LowLevelFormat
BOOL BP_LowLevelFormat(
DWORD dwStartBlock,
DWORD dwNumBlocks,
DWORD dwFlags
);
這個函數用來對Flash做低階格式化。在我開發板的eboot列印菜單中有一個功能是:9) Format Boot Media for BinFS,用來格式化BinFS分區。實現代碼如下:
if ( !BP_LowLevelFormat( IMAGE_START_BLOCK,
wNUM_BLOCKS - IMAGE_START_BLOCK,
FORMAT_SKIP_BLOCK_CHECK) )
{
OALMSG(OAL_ERROR, (TEXT("ERROR: BootMonitor: Low-level boot media format failed.\r\n")));
continue;
}
第一個參數是要格式化的起始物理block,第二個參數是block個數,第三個參數設定為FORMAT_SKIP_BLOCK_CHECK,表示跳過讀寫壞塊。BP_LowLevelFormat函數會將從dwStartBlock開始算起第一個good block的第一個扇區作為邏輯扇區0,並將MBR資訊寫到邏輯扇區0。
7 BP_SetDataPointer
BOOL BP_SetDataPointer(
HANDLE hPartition,
DWORD dwAddress
);
這個函數用來設定指定分區的資料指標(data pointer),當下次讀寫該分區時則從該指標所儲存的邏輯位元組地址開始操作。
如:
// Set the partition file pointer to the correct offset for the kernel region.
if ( !BP_SetDataPointer(hPart, g_pTOC->id[g_dwTocEntry].dwStoreOffset) )
{
return(FALSE);
}
// Read the kernel region from the Boot Media into RAM.
if ( !BP_ReadData( hPart, (LPBYTE)(g_pTOC->id[g_dwTocEntry].dwLoadAddress), SECTOR_TO_FILE_SIZE(g_pTOC->id[g_dwTocEntry].dwTtlSectors)) )
{
return(FALSE);
}