marvell的bootloader是blob+OBM+bootROM,所以还得编译OBM。
下面就对OBM进行分析。
查看OBM/Build/obm_linux.mak 文件,找到需要编译的文件。
OBJS =
obm_startup.o \
$(DDROBJS) \
$(DOWNLOADOBJS) \
$(DFCOBJS) \
$(MAINOBJS) \
$(FLASHOBJS) \
$(MISCOBJS) \
$(PLATFORMOBJS) \
$(SECUREOBJS) \
$(DMAOBJS) \
$(ONENANDOBJS) \
$(MDOCOBJS) \
$(TAVOROBJS)
可以看到首先需要的是
obm_startup.o
obm_startup.o: $(TOPDIR)/StartUp/obm_startup.S
$(AS) $(INCLUDE_DIRS) "$(TOPDIR)/StartUp/obm_startup.S" -o "$(OUTDIR)/obm_startup.o"
而它需要StartUp/obm_startup.S,所以我们查看obm_startup.S这个文件。从__main入口
__main:
@NOT SUPPORTED: ENTRY""
B
ResetHandler //初始化中断,关闭MMU,刷新列表,堆栈
B UndefinedHandler
B SwiHandler
B PrefetchHandler
B AbortHandler
NOP @ Reserved Vector
B SaveProgramState @ B IRQ Interrupt SaveProgramState
B FiqHandler @ FIQ interrupts not anabled
NOP
.align 2
.word MajorMinor, Date, Processor
NOP
@ RESET entry point
ResetHandler之后,使能所有协处理器的寄存器,从 0x5c0127F0 保存版本。
初始化DDR,使能MMU,初始化PVCR(VCO寄存器,用于PLL),然后跳到DDRInit。
查看OBM/MHLV/DDR/ddr_init.S,
ldr r2, =PLATFORMCLOCKVALUE //设置时钟,DDR读取速度
初始化DDR memory,
初始化SDRAM
bl
xlli_Dmem_initP1 @ init DDR-SDRAM (Part 1)
ldr r0, =xlli_DMEMREGS_PHYSICAL_BASE @ Dynamic Mem Controller base
orr r0, r0, #0x1
bl xlli_Rcomp @ Perform inital Rcomp calculation
ldr r0, =xlli_DMEMREGS_PHYSICAL_BASE @ Dynamic Mem Controller base
ldr r1, =0x80000000 @ DDR SDRAM base address
bl
xlli_Dmem_initP2 @ init DDR-SDRAM (Part 2)
@ Set up HCAL register with a preliminary value
@
ldr r1, =xlli_DMEMREGS_PHYSICAL_BASE @ Dynamic Memory Control Reg Base
ldr r2, =0x90001102 @ Preliminary value
str r2, [r1, #xlli_DDR_HCAL_offset] @ Write it out
.ifdef xlli_stack_pointer @ If stack pointer has been defined,
ldmfd sp!, {r0-r11, pc} @ Return to caller via the stack
.else
mov pc, lr @ Non stack return
.endif
以上跳转的,都可以查看mini_xlli_lowlev_init.S文件找到。
地址参数查看xlli_board_defs.inc文件。
回到obm_startup.S文件,继续往下看,是判定是否休眠唤醒,主要看PSR(程序状态寄存器)。假如符合情况,就拷贝DKB到0x80000000。
后面可以在 Branch to OEM Boot Main program看到下面这段代码
LDR r1, =ISRAMDateSpaceBase @ Restore platform configuration passed in by the BootROM
LDR r0, [r1]
B
OBMBootMain
LOOPFOREVER: B LOOPFOREVER
在OBM/MainProgram/obm.c查看
先看 void OBMBootMain(UINT_T PlatformSettings)
// Initialize any fuse information passed in by the BootROM
Fuses.value = PlatformSettings;
#if VERBOSE_DEBUG
Fuses.bits.Download_Disable = 0; // allows ports to be enabled
#endif
#if OBMTEST
//Fuses.bits.PlatformState = 0x5; // Default to CS2 Sibley
Fuses.bits.PlatformState = 0x4; // Default to NAND x16
Fuses.bits.BootPlatformState = 0x9;
#endif
结构体如下:
typedef union{
unsigned int value;
struct PLATFORM_FUSES bits;
}FUSE_SET, *pFUSE_SET;
struct PLATFORM_FUSES{
unsigned int DebugEn
:1;
// Bit 0 of FMRD8
unsigned int PlatformState
:4;
// Bit 1-4 of FMRD8
unsigned int Caddo_Disable
:1;
// Bit 5 of FMRD8
unsigned int JTAG_Disable
:1;
// Bit 6 of FMRD8
unsigned int Patching_Disable
:1;
// Bit 7 of FMRD8
unsigned int Patching_Revision
:4;
// Bit 8-11
of FMRD8
unsigned int UARTPort :1;
// 0 - FFUART, 1 - AltUART
unsigned int USBPort :1;
// 0 - DIFFUSB 1 - SEUSB
unsigned int CaddoDead
:1;
// 1 = Caddo did not come up.
unsigned int Resume
:1;
// 1 = resume from sleep in process
unsigned int USBWakeup
:1;
// 1 = USB wakeup from WSOTG
unsigned int PortEnabled
:1;
// 1 = Ports have been enabled
unsigned int DDRInitialized
:1;
// If the BootROM already initializes the DDR
unsigned int Download_Disable
:1;
// Bit 19 of services FMRD2 - Used to be MH-TV if 1 disable ports
unsigned int SBE
:1;
// Bit 20 of services FMRD2
unsigned int SDE
:1;
// Bit 21 of services FMRD2
unsigned int BootPlatformState
:4;
// There are the bits the BootROM booted from
unsigned int res
:6;
};
读取版本信息
Version = (UINT_T *) 0x5c0127F0;
if ( (*Version >> 16) == VERSION_2_XX)
{
LoadVersion2XXImage(Fuses, &pFlashProp[0]);
}
使能中断,初始化端口
EnableIrqInterrupts();
对BootROM检测flashes
if ((Fuses.bits.PlatformState == 0) && (Fuses.bits.BootPlatformState == 0))
按照TIM(Trusted Image Module)/
NTIM设置端口,或默认值
RetStatus.ErrorCode = InitTIMPort(&Fuses, &TIM_h);
if (RetStatus.ErrorCode == DownloadPortError)
InitDefaultPort(&Fuses);
// TIM structure for use by DKB/OBM/BootROM
typedef struct
{
pCTIM
pConsTIM;
// Constant part
pIMAGE_INFO
pImg;
// Pointer to Images
pKEY_MOD
pKey;
// Pointer to Keys
PUINT
pReserved;
// Pointer to Reserved Area
pPLAT_DS pTBTIM_DS;
// Pointer to Digital Signature
} TIM, *pTIM;
imageInfo =
FindImageInTIM(&TIM_h, OSLOADERID);
if(imageInfo == NULL)
{
imageInfo = FindImageInTIM(&TIM_h, OBMIDENTIFIER);
ImageID = imageInfo->NextImageID;
//update the imageInfo structure for the image being booted to
imageInfo = FindImageInTIM(&TIM_h, ImageID);
if(imageInfo == NULL)
{
//if we cannot find an image to boot to, error out
OBMFinalize(ImageNotFound, &pFlashProp[0]);
}
}
else
{
ImageID = OSLOADERID;
}
读取DDR EMRS(拓展寄存器,用于初始化DLL)的值
iemrs = *gDDREMRSValue;
for(i =0;i<32;i++){
itemp = iemrs;
itemp = itemp & 0x80000000;
if(itemp)
stemp[i] = 0x31;
else
stemp[i] = 0x30;
iemrs = (iemrs<<1);
}
装载映像
Retval =
CopyImageFlashToLocal(ImageID, &TIM_h, pFlashProp, NULL);
确认NTIM 或者TIM
Retval = ValidateCheckSum(TIMIDENTIFIER, &TIM_h, &pFlashProp[0]);
最后的处理:
Retval = PlatformOBMPostbootCode(&TIM_h, &pFlashProp[0]);
if (Retval != NoError)
OBMFinalize(Retval, &pFlashProp[0]);
HandleDisconnect();
ShutdownPort(FFUART_D);
ShutdownPort(ALTUART_D);
ShutdownPort(DIFF_USB_D);
ShutdownPort(U2D_USB_D);
DisableIrqInterrupts();
SaveParamsForEboot(Fuses); //保存参数
// TRANSFER CONTROL TO OS
TransferControl(imageInfo->LoadAddr, 0, imageInfo->LoadAddr);
_mod0(); //void _mod0(void) {while (1);}
1st step - Move Transfer Control to a Non-MMU translated area of the DDR
2nd Step - Turn OFF MMU, Flush TLB's
3nd Step - Copy the boot image to it's load address
回到obm_linux.mak文件中查看还需要编译DDR,Flash,Uart,USB,Boot保护等。
到此分析结束。
编译配置命令:
./configure --prefix=/home/wang/project/blob/bootloader/bin --with-board=littleton --host=arm-linux --with-linux-prefix=/home/wang/william/linux-2.6.25 --enable-xlli --enable-xllp --with-cpu-product-id=MonahansLV --with-commands=all --with-network=eth --with-nand-layout=comm_v75 --enable-xmodem --enable-nand --enable-lcd
make -f obm_linux.mak