x86上vxworks启动分析

转载地址: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


sysALib.s:这是VxWorks中另外一个汇编代码文件,实现了RAM中VxWorks的入口函数sysInit。该函数代码位于VxWorks程序映像的开始,保证实现BootRom到VxWorks的成功跳转。重复实现romInit的部分功能,如禁止中断和初始化栈等,然后跳转到usrInit。
sysLib.c:该文件是BSP的主要源代码文件,不像上两个系统初始化文件,sysLib.c没有明显执行流程,而为上层代码提供硬件相关的服务接口。主要函数有:
sysHwInit:目标机核心硬件初始化,如片选、中断、系统时钟等;
sysHwInit2:目标机附加硬件初始化,如辅助时钟等;
sysPhysMemTop:取物理RAM内存最大地址;
sysMemTop:取VxWorks可用内存的最大地址,允许用户在物理RAM顶保留空间;
sysToMonitor:用于系统热复位。
VxWorks启动顺序:从宏观来看,一般是先加载BootRom;BootRom再加载VxWorks应用,并跳转到VxWorks的入口sysInit执行;VxWorks有可能根据启动脚本文件加载应用模块。整个启动过程完成后,系统进入多任务环境运行。
从文件的角度来看启动过程,按启动顺序列出相关文件如下:
BootRom
romInit.s:实现系统初始化入口romInit,完成最基本的CPU初始化,如禁止中断和片选初始化等,为后续启动作好准备。完成后跳转到romStart执行。
bootInit.c:实现系统第一个C函数入口romStart。主要完成程序映像中各段到RAM中的复制,各种程序映像在此分支,完成后调用usrInit函数。
bootConfig.c:实现usrInit函数,完成进入多任务环境前所有的初始化工作,完成后进入多任务环境,usrRoot为第一个系统任务,创建tBoot任务,tBoot任务完成VxWorks映像的加载。
VxWorks
sysALib.s:实现VxWorks的专用入口sysInit。假设CPU基础硬件初始化完成,简单初始化CPU后跳转到usrInit。
prjConfig.c:实现usrInit函数,完成进入多任务环境前所有的初始化工作。
usrKernel.c:实现usrKernelInit函数,使系统进入多任务环境。
prjConfig.c:实现usrRoot任务函数,完成操作系统一些上层初始化后,调用usrAppInit,完成应用代码必要的初始化,应用代码可能会在这里创建多个任务。
ROM启动VxWorks
romInit.s:实现系统初始化入口romInit,完成最基本的CPU初始化,如禁止中断和片选初始化等,为后续启动作好准备。完成后跳转到romStart执行。
romStart.c:c:实现系统第一个C函数入口romStart。主要完成程序映像中各段到RAM中的复制,各种程序映像在此分支,完成后跳转sysInit()执行。
后续步骤同前面的VxWorks顺序。

 

 

 

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值