一.实现multbin
1.首先修改config.bib
比如:
#elif defined IMGMULTIBIN
; NAME START ADDR SIZE TYPE
; ----------------------------------------------------------------
NK 80220000 007DE000 RAMIMAGE
SHELL 809FE000 00100000 RAMIMAGE
APPS 80AFE000 00100000 RAMIMAGE
CHAIN 80BFE000 00002000 RESERVED ; XIP chain info
RAM 80C00000 01000000 RAM
pdwXIPLoc 00000000 80BFE000 FIXUPVAR ; XIP pTOC
AUTOSIZE=ON ;自动调整RAM 起始地址到 最近的 XIP region的末尾
ROM_AUTOSIZE=ON ;每个分隔的XIP regin 的大小自动调整
DLLADDR_AUTOSIZE=ON ;自动调整 dll地址空间大小根据 multiple XIP regions.
XIPSCHAIN=80bfe000 ; 指定CHAIN region 在内存段的地址.
Note This address is applicable for the example provided in the previous step of this procedure.
If you use a customized address for the CHAIN region or a different BSP, you will have to
update this variable to match your settings
pdwXIPLoc 必须定义START ADDR =00000000 SIZE=CHAIN的START ADDR
CHAIN 用来保存多个bin的chain info,CHAIN的位置和你bootloader代码有关,(cepc一般放在 NK region 后面)
所有的RAMIMAGE 必须在物理,虚拟地址上都连续
经验上每个bin 加32K (msdn:As a good practice, add the sizes of all files for a given region,
and then add an extra 32K as a buffer. Adding this extra amount provides room for the files to
reduce and expand as they change between each successive build)
2.修改platform.bib,把不同的部分放入到不动的region中 (其他bib也可以修改的)
比如
if IMGMULTIBIN
shell.exe $(_FLATRELEASEDIR)\shell.exe SHELL SH
filesys.exe $(_FLATRELEASEDIR)\filesys.exe SHELL SH
#else
shell.exe $(_FLATRELEASEDIR)\shell.exe NK SH
filesys.exe $(_FLATRELEASEDIR)\filesys.exe NK SH
#endif
表示把文件系统, shell放到 SHELL regin (shell.bin)
3.设置: 环境变量IMGMULTIBIN =1
4.在cfw.c中的OEMInit中的最后加上对InitRomChain的调用,来连接各个bin,最后连接到OEMRomChain 上!!!
void InitRomChain(void)
{
static ROMChain_t s_pNextRom[MAX_ROM] = {0};
DWORD dwRomCount = 0;
DWORD dwChainCount = 0;
DWORD *pdwCurXIP;
DWORD dwNumXIPs;
PXIPCHAIN_ENTRY pChainEntry = NULL;
if(pdwXIPLoc == NOT_FIXEDUP)
{
return; //pdwXIPLoc 必须是 FIXUPVAR ,否则表示没有chain或者设置不对
}
// set the top bit to mark it as a virtual address
pdwCurXIP = (DWORD*)(((DWORD)pdwXIPLoc) | 0x80000000);
// first DWORD is number of XIPs
dwNumXIPs = (*pdwCurXIP);
if(dwNumXIPs > MAX_ROM)
{
lpWriteDebugStringFunc(TEXT("ERROR: Number of XIPs exceeds MAX\n"));
return;
}
pChainEntry = (PXIPCHAIN_ENTRY)(pdwCurXIP + 1); //其实就是指向CHAIN 中chain info的相关信息
while(dwChainCount < dwNumXIPs)
{
if ((pChainEntry->usFlags & ROMXIP_OK_TO_LOAD) && // flags indicates valid XIP
*(LPDWORD)(((DWORD)(pChainEntry->pvAddr)) + ROM_SIGNATURE_OFFSET) == ROM_SIGNATURE)
{
s_pNextRom[dwRomCount].pTOC = *(ROMHDR **)( ((DWORD)(pChainEntry->pvAddr)) + ROM_SIGNATURE_OFFSET + 4 );
s_pNextRom[dwRomCount].pNext = NULL;
if (dwRomCount != 0)
{
s_pNextRom[dwRomCount-1].pNext = &s_pNextRom[dwRomCount];
}
else
{
OEMRomChain = s_pNextRom;
}
dwRomCount++;
}
else
{
lpWriteDebugStringFunc( _T("Invalid XIP found\n") );
}
++pChainEntry;
dwChainCount++;
}
}
//在romldr.h中 定义了上面的相关的
typedef struct _XIPCHAIN_ENTRY {
LPVOID pvAddr; // address of the XIP
DWORD dwLength; // the size of the XIP
DWORD dwMaxLength; // the biggest it can grow to
USHORT usOrder; // where to put into ROMChain_t
USHORT usFlags; // flags/status of XIP
DWORD dwVersion; // version info
CHAR szName[XIP_NAMELEN]; // Name of XIP, typically the bin file''s name, w/o .bin
DWORD dwAlgoFlags; // algorithm to use for signature verification
DWORD dwKeyLen; // length of key in byPublicKey
BYTE byPublicKey[596]; // public key data
} XIPCHAIN_ENTRY, *PXIPCHAIN_ENTRY;
#define ROMXIP_OK_TO_LOAD 0x0001
#define ROMXIP_IS_SIGNED 0x0002
#define ROM_SIGNATURE_OFFSET 64 //0x40
#define ROM_SIGNATURE 0x43454345 //cece 4byte =>ROMHDR 在0x44偏移处,
//每个bin 都有个pToc指向ROMHDR开头的地址,看下面的bin 文件结构,在0x44offset处地址里面放的是ROMHDR地址,开始是-1,由romimage.exe来设置的
//有点糊涂了 再分析下bin文件的结构
struct BinFile{
BYTE signature[7]; // = { ''''B'''', ''''0'''', ''''0'''', ''''0'''', ''''F'''', ''''F'''', ''''\a'''' }
DWORD ImageStart
DWORD ImageLength
Record ImageRecords[RecordNum]
};
struct Record{
DWORD address;
DWORD length;
DWORD chksum;
};
在文件的最开端,会放置一个BinFile结构,imageStart和ImageLength分别对应镜像展开后在内存中存放的首地址和长度。
该结构中的RecordNum为不确定的,通常在最后一个记录之后增加一个address和Chksum都为0的纪录表示结束,
而这个表示结束的结构中的Length则标示其实际入口点。
可以用viewbin -r 去看下nk.bin:
Image Start = 0x8C200000, length = 0x00E158C8
Start address = 0x8C201000
Checking record #22 for potential TOC (ROMOFFSET = 0xFF446658)
Checking record #177 for potential TOC (ROMOFFSET = 0x00000000)
Found pTOC = 0x8d013950
ROMOFFSET = 0x00000000
ROMHDR ----------------------------------------
DLL First : 0x01E401E7
DLL Last : 0x02000000
Physical First : 0x8C200000
Physical Last : 0x8D0158C8
RAM Start : 0x8E600000
RAM Free : 0x8E629000
RAM End : 0x8FF00000
Kernel flags : 0x00000002
Prof Symbol Offset : 0x00000000
Num Copy Entries : 1
Copy Entries Offset : 0x8CC7AE8C
Num Modules : 166
Num Files : 95
Kernel Debugger : No
CPU : 0x01c2 (Thumb)
Extensions : 0x8C20266C
ROMHDR Extensions -----------------------------
PID[0] = 0x00000000
PID[1] = 0x00000000
PID[2] = 0x00000000
PID[3] = 0x00000000
PID[4] = 0x00000000
PID[5] = 0x00000000
PID[6] = 0x00000000
PID[7] = 0x00000000
PID[8] = 0x00000000
PID[9] = 0x00000000
Next: 00000000
COPY Sections ---------------------------------
Src: 0x8CD18DA8 Dest: 0x8E606000 CLen: 0x228 DLen: 0x22B4C
MODULES ---------------------------------------
11/20/2006 03:20:28 268800 nk.exe
11/20/2006 03:25:22 550400 coredll.dll
11/20/2006 03:25:22 205824 filesys.exe
11/20/2006 03:25:22 723968 gwes.exe
11/20/2006 03:09:08 25600 device.exe
.......................
.......................
FILES ----------------------------------------
11/20/2006 03:10:42 C_R_ 2897 12461 ceconfig.h (ROM 0x8C55E4AC)
11/20/2006 03:25:18 _HRS 0 694654 wince.nls (ROM 0x8CE36984)
5/09/2007 14:06:14 CHRS 3427 20574 initobj.dat (ROM 0x8C730280)
.......................
.......................
done.
分布结构:
Image :
Offset -----------
0x00 | ImageStart
|
|
0x40 | Rom Signature { 0x43454345 }
0x44 | Pointer to the ROMHDR for this Region
|
|
0x???? | ROMHDR{ <-pToc所指
| };
|
Chain file
struct _XIPCHAIN_ENTRY {
LPVOID pvAddr; // address of the XIP
DWORD dwLength; // the size of the XIP
DWORD dwMaxLength; // the biggest it can grow to
USHORT usOrder; // where to put into ROMChain_t
USHORT usFlags; // flags/status of XIP
DWORD dwVersion; // version info
CHAR szName[XIP_NAMELEN]; // Name of XIP, typically the bin file''''s name, w/o .bin
DWORD dwAlgoFlags; // algorithm to use for signature verification
DWORD dwKeyLen; // length of key in byPublicKey
BYTE byPublicKey[596]; // public key data
};
Offset --------------------------
0x00 | DWORD Count;
0x04 | XIPCHAIN_ENTRY[1]{
| };
| XIPCHAIN_ENTRY[2]{
| };
| ...
二.关于OEMMultiBINNotify ,他是被blcommon 来调用,来让我们获得一个或多个 BIN regions的信息的
比如
用结构
typedef struct _MultiBINInfo_
{
DWORD dwNumRegions;
RegionInfo Region[BL_MAX_BIN_REGIONS];
} MultiBINInfo, *PMultiBINInfo;
定义一个MultiBINInfo g_BINRegionInfo;全局变量在OEMMultiBINNotify中获得每个bin regins的信息
ReginInfo结构:
typedef struct _RegionInfo_
{
DWORD dwRegionStart;
DWORD dwRegionLength;
} RegionInfo, *PRegionInfo;
g_BINRegionInfo 被WriteRegionsToBootMedia 写regions到flash用到,
我用的是nandflash,
WriteRegionsToBootMedia中这段
// Look in the kernel region''s extension area for a multi-BIN extension descriptor.
// This region, if found, details the number, start, and size of each BIN region.
//
//for (nCount = 0, dwNumExts = 0 ; (nCount < g_BINRegionInfo.dwNumRegions) && !pChainInfo ; nCount++)
for (nCount = 0, dwNumExts = 0 ; (nCount < g_BINRegionInfo.dwNumRegions); nCount++)
{
// Does this region contain nk.exe and an extension pointer?
//
pExt = (EXTENSION *)GetKernelExtPointer(g_BINRegionInfo.Region[nCount].dwRegionStart,
g_BINRegionInfo.Region[nCount].dwRegionLength );
if ( pExt != NULL)
{
// If there is an extension pointer region, walk it until the end.
//
while (pExt)
{
DWORD dwBaseAddr = g_BINRegionInfo.Region[nCount].dwRegionStart;
pExt = (EXTENSION *)OEMMapMemAddr(dwBaseAddr, (DWORD)pExt);
EdbgOutputDebugString("INFO: OEMLaunch: Found chain extenstion: ''%s'' @ 0x%x\r\n", pExt->name, dwBaseAddr);
if ((pExt->type == 0) && !strcmp(pExt->name, "chain information"))
{
pChainInfo = (PXIPCHAIN_SUMMARY) OEMMapMemAddr(dwBaseAddr, (DWORD)pExt->pdata);
dwNumExts = (pExt->length / sizeof(XIPCHAIN_SUMMARY));
EdbgOutputDebugString("INFO: OEMLaunch: Found ''chain information'' (pChainInfo=0x%x Extensions=0x%x).\r\n", (DWORD)pChainInfo, dwNumExts);
break;
}
pExt = (EXTENSION *)pExt->pNextExt;
}
}
else {
// Search for Chain region. Chain region doesn''t have the ROMSIGNATURE set
DWORD dwRegionStart = g_BINRegionInfo.Region[nCount].dwRegionStart;
DWORD dwSig = *(LPDWORD) OEMMapMemAddr(dwRegionStart, dwRegionStart + ROM_SIGNATURE_OFFSET);
if ( dwSig != ROM_SIGNATURE) {
// It is the chain
dwChainStart = dwRegionStart;
dwChainLength = g_BINRegionInfo.Region[nCount].dwRegionLength;
EdbgOutputDebugString("Found the Chain region: StartAddress: 0x%X; Length: 0x%X\n", dwChainStart, dwChainLength);
}
}
}
// nk.exe and an extension pointer 这个是什么意思,就是说nk.exe 包含一个扩展point是派什么用处的,那位知道告诉我
感觉是一个是bootlaod时的概念,一个是运行是的概念
bootlaoder时 :通过OEMMultiBINNotify 获得的信息来进行下载等应用
运行时,是根据config.bib中CHAIN的关于regions的信息,通过InitRomChain 来把他串起来,
三.toc block ,是和nand boot有关的东西
typedef struct _TOC {
DWORD dwSignature;
// How to boot the images in this TOC.
// This could be moved into the image descriptor if desired,
// but I prefer to conserve space.
BOOT_CFG BootCfg;
// Array of Image Descriptors.
IMAGE_DESCRIPTOR id[MAX_TOC_DESCRIPTORS];
// UCHAR Pad[12]; // align on SECTOR_SIZE
CHAININFO chainInfo;
} TOC, *PTOC; // 512 bytes
typedef struct _IMAGE_DESCRIPTOR {
// File version info
DWORD dwVersion; // e.g: build number
DWORD dwSignature; // e.g: "EBOT", "CFSH", etc
UCHAR ucString[IMAGE_STRING_LEN]; // e.g: "PocketPC_2002"
DWORD dwImageType; // IMAGE_TYPE_ flags
DWORD dwTtlSectors; // TTL image size in sectors.
// We store size in sectors instead of bytes
// to simplify sector reads in Nboot.
DWORD dwLoadAddress; // Virtual address to load image (ImageStart)
DWORD dwJumpAddress; // Virtual address to jump (StartAddress/LaunchAddr)
// This array equates to a sector-based MXIP MultiBINInfo in blcommon.
// Unused entries are zeroed.
// You could chain image descriptors if needed.
SG_SECTOR sgList[MAX_SG_SECTORS];
// BinFS support to load nk region only
//struct
//{
ULONG dwStoreOffset; // byte offset - not needed - remove!
//ULONG RunAddress; // nk dwRegionStart address
//ULONG Length; // nk dwRegionLength in bytes
//ULONG LaunchAddress; // nk dwLaunchAddr
//} NKRegion;
} IMAGE_DESCRIPTOR, *PIMAGE_DESCRIPTOR;
这些信息被写入block 1,
为nboot启动 nk,或 eboot提供信息的