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