转载地址:http://bbs.2beanet.com/vxworks-f10/vxworks-t3385.html
VxWorks的引导程序叫VxLd,由Tornado工具vxsys.com写入。它运行后会从当前磁盘的根目录下加载BOOTROM.SYS(此文件必须连续存放,因为VxLd很简单,还不认识任何文件系统),加载地址为0x8000。这个步骤通过调用BIOS INT13完成。加载完成后跳转到0x8000执行。VxWorks操作系统的第一条指令就存放于0x8000的地方(注:这是bootrom;对于vxWorks image为0x108000;或者相反)。注意在PC目标机上,VxWorks和BIOS的关系。VxWorks假定BIOS已经正确地初始化系统硬件,包括内存,PCI总线等,所以pc386,pc486等BSP就省掉了很多工作。然而VxWorks启动后,不会用到BIOS的任何功能,这和DOS不一样。因为VxWorks运行于保护模式,而BIOS功能必须从实模式下调用(也许有人可以给我们说说如何在保护模式下如何调用BIOS功能,当然这是一个高级话题)。实际在一般正常情况下,当VxWorks运行后,BIOS就彻底消失了。
romInit.s:定义了系统入口romInit函数,它是系统上电后最先执行的代码。romInit中完成禁止CPU中断,设置初始栈指针,配置DRAM控制器等少量CPU设置之后调用第一个函数romStart。进一步的硬件初始化由sysLib.c中定义的sysHwInit函数完成。在BSP开发中,romInit.s只要使RAM工作起来就行,不用进行太多的硬件初始化。
romInit.s中的硬件初始化会在sysLib.c或sysALib.c重复一遍。因为VxWorks程序只需要BootRom的参数串和启动类型代码,而不遵循依赖BootRom的硬件初始化(除了RAM初始化)。VxWorks启动时会重新初始化CPU和其他所有硬件。RAM也可在VxWorks中再初始化一遍,对程序运行不会有影响。BootRom和VxWorks的无关性是个基本原则,若不遵循这个原则,就会出现VxWorks和BootRom的关联修改。
/******************************************************************************* * * romInit - entry point for VxWorks in ROM * * romInit (startType) * int startType; /@ only used by 2nd entry point 只有热复位使用,从栈中取参数,冷复位直接指定 @/ */ /* cold start entry point in REAL MODE(16 bits)以下执行的是VxWorks系统的第一条指令。此时CPU还处于实模式,程序只能访问1M内存空间,缺省的指令为16-bit代码。需要尽快将CPU切换到保护模式 */ romInit: _romInit: cli /* LOCK INTERRUPT 禁止中断*/ jmp cold /* offset must be less than 128 */ /* warm start entry point in PROTECTED MODE(32 bits) */ .balign 16,0x90 romWarmHigh: /* ROM_WARM_HIGH(0x10) is offset */ cli /* LOCK INTERRUPT */ movl SP_ARG1(%esp),%ebx /* %ebx has the startType */ jmp warm /* warm start entry point in PROTECTED MODE(32 bits) */ .balign 16,0x90 romWarmLow: /* ROM_WARM_LOW(0x20) is offset */ cli /* LOCK INTERRUPT */ cld /* copy itself to ROM_TEXT_ADRS */ movl $ RAM_LOW_ADRS,%esi /* get src addr (RAM_LOW_ADRS) */ movl $ ROM_TEXT_ADRS,%edi /* get dst addr (ROM_TEXT_ADRS) */ movl $ ROM_SIZE,%ecx /* get nBytes to copy */ shrl $2,%ecx /* get nLongs to copy */ rep /* repeat next inst ECX time */ movsl /* copy nLongs from src to dst */ movl SP_ARG1(%esp),%ebx /* %ebx has the startType */ jmp warm /* jump to warm */ /* copyright notice appears at beginning of ROM (in TEXT segment) */ .ascii "Copyright 1984-2002 Wind River Systems, Inc." /* cold start code in REAL MODE(16 bits) */ .balign 16,0x90 cold: .byte 0x67, 0x66 /* next inst has 32bit operand */ lidt %cs:(romIdtr - romInit) /* load temporary IDT */ .byte 0x67, 0x66 /* next inst has 32bit operand */ lgdt %cs:(romGdtr - romInit) /* load temporary GDT */ /* switch to protected mode */ mov %cr0,%eax /* move CR0 to EAX */ .byte 0x66 /* next inst has 32bit operand */ or $0x00000001,%eax /* set the PE bit */ mov %eax,%cr0 /* move EAX to CR0 */ jmp romInit1 /* near jump to flush a inst queue */ romInit1: .byte 0x66 /* next inst has 32bit operand */ mov $0x0010,%eax /* set data segment 0x10 is 3rd one */ mov %ax,%ds /* set DS */ mov %ax,%es /* set ES */ mov %ax,%fs /* set FS */ mov %ax,%gs /* set GS */ mov %ax,%ss /* set SS */ .byte 0x66 /* next inst has 32bit operand */ mov $ ROM_STACK,%esp /* set lower mem stack pointer */ .byte 0x67, 0x66 /* next inst has 32bit operand */ ljmp $0x08, $ ROM_TEXT_ADRS + romInit2 - romInit /* temporary IDTR stored in code segment in ROM */ romIdtr: .word 0x0000 /* size : 0 */ .long 0x00000000 /* address: 0 */ /* temporary GDTR stored in code segment in ROM */ romGdtr: .word 0x0027 /* size : 39(8 * 5 - 1) bytes */ .long (romGdt - romInit + ROM_TEXT_ADRS) /* address: romGdt */ /* temporary GDT stored in code segment in ROM */ .balign 16,0x90 romGdt: /* 0(selector=0x0000): Null descriptor */ .word 0x0000 .word 0x0000 .byte 0x00 .byte 0x00 .byte 0x00 .byte 0x00 /* 1(selector=0x0008): Code descriptor */ .word 0xffff /* limit: xffff */ .word 0x0000 /* base : xxxx0000 */ .byte 0x00 /* base : xx00xxxx */ .byte 0x9a /* Code e/r, Present, DPL0 */ .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ .byte 0x00 /* base : 00xxxxxx */ /* 2(selector=0x0010): Data descriptor */ .word 0xffff /* limit: xffff */ .word 0x0000 /* base : xxxx0000 */ .byte 0x00 /* base : xx00xxxx */ .byte 0x92 /* Data r/w, Present, DPL0 */ .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ .byte 0x00 /* base : 00xxxxxx */ /* 3(selector=0x0018): Code descriptor, for the nesting interrupt */ .word 0xffff /* limit: xffff */ .word 0x0000 /* base : xxxx0000 */ .byte 0x00 /* base : xx00xxxx */ .byte 0x9a /* Code e/r, Present, DPL0 */ .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ .byte 0x00 /* base : 00xxxxxx */ /* 4(selector=0x0020): Code descriptor, for the nesting interrupt */ .word 0xffff /* limit: xffff */ .word 0x0000 /* base : xxxx0000 */ .byte 0x00 /* base : xx00xxxx */ .byte 0x9a /* Code e/r, Present, DPL0 */ .byte 0xcf /* limit: fxxxx, Page Gra, 32bit */ .byte 0x00 /* base : 00xxxxxx */ /* cold start code in PROTECTED MODE(32 bits) */ .balign 16,0x90 romInit2: cli /* LOCK INTERRUPT */ movl $ ROM_STACK,%esp /* set a stack pointer */ #if defined (TGT_CPU) && defined (SYMMETRIC_IO_MODE) movl $ MP_N_CPU, %eax lock incl (%eax) #endif /* defined (TGT_CPU) && defined (SYMMETRIC_IO_MODE) */ /* WindML + VesaBIOS initialization */ #ifdef INCLUDE_WINDML movl $ VESA_BIOS_DATA_PREFIX,%ebx /* move BIOS prefix addr to EBX */ movl $ VESA_BIOS_KEY_1,(%ebx) /* store "BIOS" */ addl $4,%ebx /* increment EBX */ movl $ VESA_BIOS_KEY_2,(%ebx) /* store "DATA" */ movl $ VESA_BIOS_DATA_SIZE,%ecx /* load ECX with nBytes to copy */ shrl $2,%ecx /* get nLongs to copy */ movl $0,%esi /* load ESI with source addr */ movl $ VESA_BIOS_DATA_ADDRESS,%edi /* load EDI with dest addr */ rep movsl /* copy BIOS data to VRAM */ #endif /* INCLUDE_WINDML */ /* * Don't call romA20on if booted through SFL. romA20on does ISA * I/O port accesses to turn A20 on. In case of SFL boot, ISA * I/O address space will not be initialized by properly by the * time this code gets executed. Also, A20 comes ON when booted * through SFL. */ #ifndef INCLUDE_IACSFL call FUNC(romA20on) /* enable A20 */ cmpl $0, %eax /* is A20 enabled? */ jne romInitHlt /* no: jump romInitHlt */ #endif /* INCLUDE_IACSFL */ movl $ BOOT_COLD,%ebx /* %ebx has the startType */ /* copy bootrom image to dst addr if (romInit != ROM_TEXT_ADRS) */ warm: ARCH_REGS_INIT /* initialize DR[0-7] CR0 EFLAGS */ #if (CPU == PENTIUM) || (CPU == PENTIUM2) || (CPU == PENTIUM3) || / (CPU == PENTIUM4) /* ARCH_CR4_INIT /@ initialize CR4 for P5,6,7 */ xorl %eax, %eax /* zero EAX */ movl %eax, %cr4 /* initialize CR4 */ #endif /* (CPU == PENTIUM) || (CPU == PENTIUM[234]) */ movl $romGdtr,%eax /* load the original GDT */ subl $ FUNC(romInit),%eax addl $ ROM_TEXT_ADRS,%eax pushl %eax call FUNC(romLoadGdt) movl $ STACK_ADRS, %esp /* initialise the stack pointer */ movl $ ROM_TEXT_ADRS, %esi /* get src addr(ROM_TEXT_ADRS) */ movl $ romInit, %edi /* get dst addr(romInit) */ cmpl %esi, %edi /* is src and dst same? */ je romInit4 /* yes: skip copying */ movl $ FUNC(end), %ecx /* get "end" addr */ subl %edi, %ecx /* get nBytes to copy */ shrl $2, %ecx /* get nLongs to copy */ cld /* clear the direction bit */ rep /* repeat next inst ECX time */ movsl /* copy itself to the entry point */ /* jump to romStart(absolute address, position dependent) */ romInit4: xorl %ebp, %ebp /* initialize the frame pointer */ pushl $0 /* initialise the EFLAGS */ popfl pushl %ebx /* push the startType */ movl $ FUNC(romStart),%eax /* jump to romStart */ call *%eax /* just in case, if there's a problem in romStart or romA20on */ romInitHlt: pushl %eax call FUNC(romEaxShow) /* show EAX on your display device */ hlt jmp romInitHlt