2010年(49)
分类: 嵌入式
2010-09-07 11:02:59
/* system restart types */
#define BOOT_NORMAL 0x00 /* normal reboot with countdown */
#define BOOT_NO_AUTOBOOT 0x01 /* no autoboot if set */
#define BOOT_CLEAR 0x02 /* clear memory if set */
#define BOOT_QUICK_AUTOBOOT 0x04 /* fast autoboot if set */
/* for backward compatibility */
#define BOOT_WARM_AUTOBOOT BOOT_NORMAL
#define BOOT_WARM_NO_AUTOBOOT BOOT_NO_AUTOBOOT
#define BOOT_WARM_QUICK_AUTOBOOT BOOT_QUICK_AUTOBOOT
#define BOOT_COLD BOOT_CLEAR
在rominit.s开始部分,根据启动类型的不同有不同的动作。如果是冷启动那么将BOOT_COLD写入R3寄存器,否则保持R3寄存器的默认值即热启动。查找BOOT_COLD的值,没有找到,不过我估计是非0值,R3寄存器在复位时应该被清零的。
(3)romstart()
从rominit.s跳转到bootinit.c的romstart()函数时需要向romstart()函数传递一个实参即启动类型startType。根据PPC的汇编知识,PPC使用R3-R10这8个GPR来传递常规的函数实参,那么R3中的值就会作为romstart()的第一个实参。这样启动类型得以传递。
然后,在romstart()函数里会根据启动类型来确定是否清空内存。如果是冷启动,那么将清空内存,如果是热启动,那么不清空。
从romstart()函数跳转到bootconfig.c中的usrinit()函数时,把startTape作为usrinit()的实参传递过去。
Usrinit()函数用将该实参赋给全局变量sysStartType。
未使用sysStartType。
多次使用了sysStartType,但是有的使用涉及sysFlags参数,而sysFlags参数是来源于config.h中的DEFAULT_BOOT_LINE,所以在介绍了BOOT_LINE后再详细的阐释bootCmdLoop()函数。
引导参数BOOT_LINE是在config.h文件的宏定义DEFAULT_BOOT_LINE中定义的。该宏定义定义的是一个字符串,它包括了引导系统时所需要的参数。
以下代码摘自mpc859_giga11.10的config.h。首先是对DEFAULT_BOOT_LINE格式的注解:
/*Format: Launch point, file path/name, host IP, own IP, gateway IP, user name, user password */
/*dev(0,procnum)host:/file h= # e= # b= # g= # u=usr [pw=passwd] f= # tn=targetname s=script o=other */
然后是我写的网络引导和TFFS引导两种不同引导方式对应的BOOT_LINE:
#define DEFAULT_BOOT_LINE \
"motfec(0,0)cumt-hhy:vxWorks
h=192.168.0.12 e=192.168.
#define DEFAULT_BOOT_LINE \
"tffs=0,0(0,0)cumt-hhy:/tffs0/vxWorks h=192.168.0.12 e=192.168.0.123 o=motfec g=192.168.0.1 u=dh pw=dh"
在bootCmdLoop()中对DEFAULT_BOOT_LINE进行解析并使用,详见下面对bootCmdLoop()函数的分析。
如果是冷启动类型,那么打印Logo。
if (sysStartType & BOOT_CLEAR)
printBootLogo ();
usrBootLineInit (sysStartType);
调用usrBootLineInit (sysStartType)函数来获得默认引导行参数DEFAULT_BOOT_LINE。
在VxWorks操作系统中,宏BOOT_LINE_ADRS是一个指针,它指向操作系统保存引导行参数的位置。如果是冷启动,那么将config.h中定义的DEFAULT_BOOT_LINE的值拷贝到BOOT_LINE_ADRS指向的地方。
LOCAL void usrBootLineInit (int startType)
{
if (startType & BOOT_CLEAR)
{
/* this is a cold boot so get the default boot line */
if ((sysNvRamGet (BOOT_LINE_ADRS, BOOT_LINE_SIZE, 0) == ERROR) ||
(*BOOT_LINE_ADRS == EOS) || (*BOOT_LINE_ADRS == (char) -1))
{
/* either no non-volatile RAM or empty boot line */
strcpy (BOOT_LINE_ADRS, DEFAULT_BOOT_LINE);
}
}
}
bootStringToStruct (BOOT_LINE_ADRS, ¶ms);
bootStringToStruct在bootLib.h中声明,params的类型是BOOT_PARAMS,该结构类型同样在bootLib.h中声明,声明如下。
typedef struct /* BOOT_PARAMS */
{
char bootDev [BOOT_DEV_LEN]; /* boot device code */
char hostName [BOOT_HOST_LEN]; /* name of host */
char targetName [BOOT_HOST_LEN]; /* name of target */
char ead [BOOT_TARGET_ADDR_LEN]; /* ethernet internet addr */
char bad [BOOT_TARGET_ADDR_LEN]; /* backplane internet addr */
char had [BOOT_ADDR_LEN]; /* host internet addr */
char gad [BOOT_ADDR_LEN]; /* gateway internet addr */
char bootFile [BOOT_FILE_LEN]; /* name of boot file */
char startupScript [BOOT_FILE_LEN]; /* name of startup script file */
char usr [BOOT_USR_LEN]; /* user name */
char passwd [BOOT_PASSWORD_LEN]; /* password */
char other [BOOT_OTHER_LEN]; /* available for applications */
int procNum; /* processor number */
int flags; /* configuration flags */
int unitNum; /* network device unit number */
} BOOT_PARAMS;
sysFlags = params.flags;
params结构变量中的flags值应该来自于DEFAULT_BOOT_LINE中的“f”参数。
sysFlags可选的值定义在sysLib.h头文件中:
#define SYSFLG_NO_SYS_CONTROLLER 0x01
/* System debug option:
* load kernel symbol table with all symbols (not just globals)
*/
#define SYSFLG_DEBUG 0x02
#define SYSFLG_NO_AUTOBOOT 0x04 /* Don't start autoboot sequence */
#define SYSFLG_QUICK_AUTOBOOT 0x08 /* Immediate autoboot (no countdown) */
#define SYSFLG_NO_STARTUP_SCRIPT 0x10 /* Don't read startup script */
#define SYSFLG_NO_SECURITY 0x20 /* Don't ask passwd on network login */
#define SYSFLG_AUTOCONFIG 0x40 /* Use bootp or DHCP to get boot */
#define SYSFLG_TFTP 0x80 /* Use tftp to get boot image */
#define SYSFLG_PROXY 0x100 /* Use proxy arp */
#define SYSFLG_WDB 0x200 /* Use WDB agent */
#define SYSFLG_VENDOR_0 0x1000 /* vendor defined flag 0 */
#define SYSFLG_VENDOR_1 0x2000 /* vendor defined flag 1 */
#define SYSFLG_VENDOR_2 0x4000 /* vendor defined flag 2 */
#define SYSFLG_VENDOR_3 0x8000 /* vendor defined flag 3 */
是否直接引导是由传入atuoboot(timeout)的实参timeout来确定的。如果timeout是1,即等待的时间是1second基本上就是立即启动bootLoad开启引导,不给用户打断启动的机会;如果timeout是7的话,那么等待的时间是7second而用户就有机会打断启动。
if (!(sysStartType & BOOT_NO_AUTOBOOT) &&
!(sysFlags & SYSFLG_NO_AUTOBOOT))
{
int timeout = TIMEOUT;
if ((sysStartType & BOOT_QUICK_AUTOBOOT) ||
(sysFlags & SYSFLG_QUICK_AUTOBOOT))
{
timeout = 1;
}
key = autoboot (timeout); /* doesn't return if successful */
}
根据atuoboot函数的代码,如果用户在等待的过程中按下任意键,那么autoboot将return用户按下的键值。
如果atuoboot返回的值是‘@’,那么在这个循环里将会直接调用bootLoad启动引导,如果是其它的键值,那么将打印[VxWorks Boot]:并等待用户输入。
输入‘?’将会有详细的解释J
键值 |
含义 |
d |
display |
e |
exception |
f |
fill |
t |
transpose(?) (running out of letters!) |
m |
modify |
s |
system controller |
p |
print boot params |
c |
change boot params |
g |
Go |
n |
netifAdrsPrint |
N |
ETHERNET_ADR_SET |
? 、h |
help |
@、$ |
load and go with internal params |
l |
load with internal params |
v |
print version & logo |
bootLoad函数是最终的加载函数,它的函数原型如下:
LOCAL STATUS bootLoad (char * bootString, FUNCPTR *pEntry )
/* copy bootString to low mem address, if specified */
if ((bootString != NULL) && (*bootString != EOS))
strcpy (BOOT_LINE_ADRS, bootString);
从BOOT_LINE_ADRS处获取引导参数。当然引导行配置循环中用户改变的都已经保存到了BOOT_LINE_ADRS处。
/* interpret boot command */
if (usrBootLineCrack (BOOT_LINE_ADRS, ¶ms) != OK)
return (ERROR);
根据params.bootDev的值来确定引导方式。