romStart函数在文件target/config/all/bootInit.c中定义,用于bootrom的第二阶段初始化。首先把text和data段从ROM拷贝到RAM中,然后初始化部分RAM,进行解压。下面参考源码进行详细分析。
void romStart
(
FAST int startType /* start type */
)
{
#if ((CPU_FAMILY==SPARC) || (CPU_FAMILY==MIPS) || (CPU_FAMILY==I80X86) || \
(CPU_FAMILY==PPC) || (CPU_FAMILY==ARM))
volatile /* to force absolute adressing */
#endif /* (CPU_FAMILY==SPARC) */
FUNCPTR absEntry; /* to avoid PC Relative Jump Subroutine */
#if (CPU_FAMILY==ARM) && (!defined(ROM_RESIDENT)) && !defined(BOOTCODE_IN_RAM)
VOIDFUNCPTR ramfillLongs = fillLongs; /* force call to RAM */
#define fillLongs(a,b,c) ramfillLongs(a,b,c)
#endif /* (CPU_FAMILY==ARM) */
#if (CPU_FAMILY==MC680X0) && !defined(ROM_RESIDENT) && !defined(BOOTCODE_IN_RAM)
volatile VOIDFUNCPTR romcopyLongs = ©Longs; /* force call to ROM */
#define copyLongs romcopyLongs
#endif /* (CPU_FAMILY==MC680X0) */
/*
* Copy from ROM to RAM, minus the compressed image
* if compressed boot ROM which relies on binArray
* appearing last in DATA segment.
*/
#ifdef ROM_RESIDENT
/* If ROM resident code, then copy only data segment
* from ROM to RAM, initialize memory and jump
* to usrInit.
*/
#if (CPU_FAMILY == SPARC)
copyLongs ((UINT *)(etext + 8), (UINT *) RESIDENT_DATA,
#else
copyLongs ((UINT *)etext, (UINT *) RESIDENT_DATA,
#endif
((UINT) wrs_kernel_data_end - (UINT) RESIDENT_DATA) / sizeof (long));
#else /* ROM_RESIDENT */
#ifdef UNCOMPRESS
#if (CPU_FAMILY == MIPS)
/*
* copy text to uncached locations to avoid problems with
* copy back caches
*/
((FUNCPTR)ROM_OFFSET(copyLongs)) (ROM_TEXT_ADRS, (UINT)K0_TO_K1(romInit),
ROM_COPY_SIZE / sizeof (long));
#else /* CPU_FAMILY == MIPS */
((FUNCPTR)ROM_OFFSET(copyLongs)) (ROM_TEXT_ADRS, (UINT)romInit,
ROM_COPY_SIZE / sizeof (long));
#endif /* CPU_FAMILY == MIPS */
#else /* UNCOMPRESS */
#if (CPU_FAMILY == MIPS)
/*
* copy text to uncached locations to avoid problems with
* copy back caches
* copy the entire data segment because there is no way to ensure that
* binArray is the last thing in the data segment because of GP relative
* addressing
*/
((FUNCPTR)ROM_OFFSET(copyLongs)) (ROM_TEXT_ADRS, (UINT)K0_TO_K1(romInit),
((UINT)wrs_kernel_data_end - (UINT)romInit) / sizeof (long));
#else /* CPU_FAMILY == MIPS */
((FUNCPTR)ROM_OFFSET(copyLongs)) (ROM_TEXT_ADRS, (UINT)romInit,
((UINT)binArrayStart - (UINT)romInit)/ sizeof (long));
((FUNCPTR)ROM_OFFSET(copyLongs))
((UINT *)((UINT)ROM_TEXT_ADRS + ((UINT)BINARRAYEND_ROUNDOFF -
(UINT)romInit)), (UINT *)BINARRAYEND_ROUNDOFF,
((UINT)wrs_kernel_data_end - (UINT)binArrayEnd) / sizeof (long));
#if (CPU==XSCALE)
/* validate coherence, can not assume uncached area... */
((FUNCPTR)ROM_OFFSET(checkLongs))
(ROM_TEXT_ADRS, (UINT)romInit,
((UINT)binArrayStart - (UINT)romInit) / sizeof (long));
((FUNCPTR)ROM_OFFSET(checkLongs))
((UINT *)((UINT)ROM_TEXT_ADRS + ((UINT)BINARRAYEND_ROUNDOFF -
(UINT)romInit)), (UINT *)BINARRAYEND_ROUNDOFF,
((UINT)wrs_kernel_data_end - (UINT)binArrayEnd) / sizeof (long));
#endif
#endif /* CPU_FAMILY == MIPS */
#endif /* UNCOMPRESS */
#endif /* ROM_RESIDENT */
#if (CPU_FAMILY != MIPS) && (!defined (BOOTCODE_IN_RAM))
/* clear all memory if cold booting */
if (startType & BOOT_CLEAR)
{
#ifdef ROM_RESIDENT
/* Clear memory not loaded with text & data.
*
* We are careful about initializing all memory (except
* STACK_SAVE bytes) due to parity error generation (on
* some hardware) at a later stage. This is usually
* caused by read accesses without initialization.
*/
fillLongs ((UINT *)SYS_MEM_BOTTOM,
((UINT) RESIDENT_DATA - STACK_SAVE - (UINT)SYS_MEM_BOTTOM)
/ sizeof(long), 0);
fillLongs (((UINT *) wrs_kernel_data_end),
((UINT)SYS_MEM_TOP - ((UINT) wrs_kernel_data_end)) / sizeof(long), 0);
#else /* ROM_RESIDENT */
fillLongs ((UINT *)(SYS_MEM_BOTTOM),
((UINT)romInit - STACK_SAVE - (UINT)SYS_MEM_BOTTOM) /
sizeof(long), 0);
#if defined (UNCOMPRESS)
fillLongs ((UINT *)((UINT)romInit + ROM_COPY_SIZE),
((UINT)SYS_MEM_TOP - ((UINT)romInit + ROM_COPY_SIZE))
/ sizeof(long), 0);
#else
fillLongs ((UINT *)wrs_kernel_data_end,
((UINT)SYS_MEM_TOP - (UINT)wrs_kernel_data_end) / sizeof (long), 0);
#endif /* UNCOMPRESS */
#endif /* ROM_RESIDENT */
/*
* Ensure the boot line is null. This is necessary for those
* targets whose boot line is excluded from cleaning.
*/
*(BOOT_LINE_ADRS) = EOS;
}
#endif /* (CPU_FAMILY != MIPS) && (!defined (BOOTCODE_IN_RAM)) */
/* jump to VxWorks entry point (after uncompressing) */
#if defined (UNCOMPRESS) || defined (ROM_RESIDENT)
#if (CPU_FAMILY == I960)
absEntry = (FUNCPTR)sysInitAlt; /* reinit proc tbl */
#else
absEntry = (FUNCPTR)usrInit; /* on to bootConfig */
#endif /* CPU_FAMILY == I960 */
#else
{
#if (CPU_FAMILY == MIPS)
volatile FUNCPTR absUncompress = (FUNCPTR) UNCMP_RTN;
if ((absUncompress) ((UCHAR *)ROM_OFFSET(binArrayStart),
(UCHAR *)K0_TO_K1(RAM_DST_ADRS),
(int)((UINT)binArrayEnd - (UINT)binArrayStart)) != OK)
#elif (CPU_FAMILY == I80X86) || (CPU_FAMILY == ARM)
volatile FUNCPTR absUncompress = (FUNCPTR) UNCMP_RTN;
if ((absUncompress) ((UCHAR *)ROM_OFFSET(binArrayStart),
(UCHAR *)RAM_DST_ADRS, binArrayEnd - binArrayStart) != OK)
#else
if (UNCMP_RTN ((UCHAR *)ROM_OFFSET(binArrayStart),
(UCHAR *)RAM_DST_ADRS, binArrayEnd - binArrayStart) != OK)
#endif /* (CPU_FAMILY == MIPS) */
return; /* if we return then ROM's will halt */
absEntry = (FUNCPTR)RAM_DST_ADRS; /* compressedEntry () */
}
#endif /* defined UNCOMPRESS || defined ROM_RESIDENT */
#if ((CPU_FAMILY == ARM) && ARM_THUMB)
absEntry = (FUNCPTR)((UINT32)absEntry | 1); /* force Thumb state */
#endif /* CPU_FAMILY == ARM */
(absEntry) (startType);
}
#if (CPU_FAMILY==ARM) && (!defined(ROM_RESIDENT))
#undef fillLongs
#endif /* (CPU_FAMILY==ARM) */
#if (CPU_FAMILY==MC680X0) && !defined(ROM_RESIDENT) && !defined(BOOTCODE_IN_RAM)
#undef copyLongs /* undo effects from above define */
#endif /* CPU_FAMILY==MC680X0 */
其中以VxWorks_rom未压缩版的内核镜像为对象进行分析,则函数rom_Start如下:
void romStart
(
FAST int startType/*参数传递使用寄存器*/
)
{
volatile FUNCPTR absEntry;
VOIDFUNCPTR ramfillLongs = fillLongs;
#define fillLongs(a,b,c) ramfillLongs(a,b,c)
/*重定位copyLongs函数到ROM中*/
/*其中ROM_OFFSET定义如下:*/
/* #define ROM_OFFSET(adr) (((UINT)adr - (UINT)romInit) + ROM_TEXT_ADRS)*/
((FUNCPTR)ROM_OFFSET(copyLongs))(ROM_TEXT_ADRS,(UINT)romInit,ROM_COPY_SIZE/sizeof(long));//拷贝ROM代码到RAM中
if(startType & BOOT_CLEAR)
{
fillLongs((UINT*)(SYS_MEM_BOTTOM),((UINT)romInit-STACK_SAVE-(UINT)SYS_MEM_BOTTOM)/sizeof(long),0);//填充SYS_MEM_BOTTOM~栈之间的内存空间为0
fillLongs((UINT*)((UINT)romInit+ROM_COPY_SIZE),((UINT)SYS_MEM_TOP-((UINT)romInit+ROM_COPY_SIZE))/sizeof(long),0);//填充SYS_MEMTOP到romInit+ROM_COPY_SIZE处的内容为0
*(BOOT_LINE_ADRS) = EOS;
}
absEntry = (FUNCPTR)usrInit;//on to bootConfig
(absEntry)(startType);//跳转到usrInit
}
/*其中的copyLongs也在bootInit.c中定义*/
LOCAL void copyLongs (source, destination, nlongs)
FAST UINT *source; /* pointer to source buffer */
FAST UINT *destination; /* pointer to destination buffer */
UINT nlongs; /* number of longs to copy */
{
FAST UINT *dstend = destination + nlongs;
FAST UINT nchunks;
/* Hop by chunks of longs, for speed. */
for (nchunks = nlongs / 8; nchunks; --nchunks)
{
destination[0] = source[0];
destination[1] = source[1];
destination[2] = source[2];
destination[3] = source[3];
destination[4] = source[4];
destination[5] = source[5];
destination[6] = source[6];
destination[7] = source[7];
destination += 8, source += 8;
}
/* Do the remainder one long at a time. */
while (destination < dstend)
*destination++ = *source++;
}
/*fillLongs函数也在bootInit.c中定义*/
#ifndef BOOTCODE_IN_RAM
/*******************************************************************************
*
* fillLongs - fill a buffer with a value a long at a time
*
* This routine fills the first <nlongs> longs of the buffer with <val>.
*/
LOCAL void fillLongs (buf, nlongs, val)
FAST UINT *buf; /* pointer to buffer */
UINT nlongs; /* number of longs to fill */
FAST UINT val; /* char with which to fill buffer */
{
FAST UINT *bufend = buf + nlongs;
FAST UINT nchunks;
/* Hop by chunks of longs, for speed. */
for (nchunks = nlongs / 8; nchunks; --nchunks)
{
buf[0] = val;
buf[1] = val;
buf[2] = val;
buf[3] = val;
buf[4] = val;
buf[5] = val;
buf[6] = val;
buf[7] = val;
buf += 8;
}
/* Do the remainder one long at a time. */
while (buf < bufend)
*buf++ = val;
}
#endif /* BOOTCODE_IN_RAM */
下图是VxWorks下romStart的执行过程示意图。