wince6.0啓動

以S3C6410爲例子,S3C6410的內部SRAM地址爲0x0C00 0000 ~ 0x0C00 1FFF,DRAM的Base地址爲0x50000000 ,S3C6410支持NAND,SD啓動,S3C6410裏面有固化的ROM,
當系統上電的時候,將執行固化ROM中的代碼,然後檢查硬件的GPIO配置,如果配置成NAND 啓動,則把NAND的前8K讀入內部的SRAM(stepping Stone)中,然後跳轉到
Stepping Stone的開頭,執行Bootloader1 (也就是下文的stepldr), stepldr負責把eboot從NAND中搬到DRAM中,然後執行eboot( boot loader 2),eboot通過網絡下載
NK.bin或者從NAND中把內核搬到DRAM中,然後執行WINCE內核.所以整個啓動過程分爲三階段,stepldr -->eboot --> wince kernel .
下面詳細地分析各個階段.
一 bootloader 1  stepldr
  從stepldr的startup.s開始.startup.s主要是初始化硬件,中斷,配置好C運行的環境,然後跳轉到main函數中,執行C代碼.
   startuo.s 的流程是 :
       startup --> Enable I cache -->關閉watchdog ,Interrupt dosable -> 時鐘初始化 --> 初始化DRAM控制器 --> 初始化IRQ,SVC stack -->
      判斷是否睡眠 ---N--> Clear DRAM -->main
                  --Y-> 跳到NK的開頭 (也就是DRAM + 0x100000的地方)
                               

   main.c :
      UART初始化 --> nand 初始化 -> 從NAND中把eboot搬到DRAM中 -->跳轉到 eboot的開頭
       
  我們看代碼有2個全局變量。
   ROMHDR * volatile const pTOC = (ROMHDR *)-1; 這個在ROMImage裏面會賦值。
   static BOOL g_bLargeBlock = FALSE; // For Large Block Check
   這兩個全局變量的位置爲:500F0000 根據stepldr.bib
  

二 bootloader 2  eboot
  startup.s
   startup -->  Enable I cache -->關閉watchdog ,Interrupt dosable -> 時鐘初始化 --> Disable VIC --> enable 中斷 -->CLEAR DRAM(從1M到128M地址的DRAM,因爲低1M地址
   空間目前放的是eboot ) --> 初始化MMU Table (根據g_oalAddressTable,把DRAM的Base地址0x50000000映射到0x80000000,此後地址都用虛擬地址) --> 初始化IRQ,SVC stack -->
    -->main 
 
   
  main.c
    main --> BootloaderMain
  
  BootloaderMain的流程:
  KernelRelocate -->OEMDebugInit(初始化串口,這樣就可以打印信息了) -->OEMPlatformInit -->OEMPreDownload -->DownloadImage-->OEMLaunch (切換到ce內核了)
  OEMPlatformInit :
    InitializeDisplay --> 初始化中斷 -->NAND Flash驅動 初始化 --> MainMenu (一些選項,比如設置IP) -->ethernet 驅動初始化
  
  OEMPreDownload : get IP , initialize TFTP
  DownloadImage :
   先用OEMReadData讀7位頭,然後根據這7位判斷是bin 還是 nb0 等
   假如是bin , 調用 DownloadBin

  
 

三 wince OS
  wince os 的啓動我們也可以換分爲2個階段,第一個階段,初始化OAL,一直到FirstSchedule開始調度,第二階段,開始對文件系統,註冊表,driver的
  初始化和加載。
(1)初始化 OAL
 
1.startup.s
  
    初始化一些硬件外設 --> KernelStart

2.KernelStart
   在PRIVATE\WINCEOS\COREOS\NK\LDR\ARM\armstart.s中
   根據OALAddress Table初始化頁表 , 打開MMU和初始化Cache和中斷向量
   初始化stack
   調用ArmInit
    mov     r12, r0
    ldr     r0, =KData
    mov     pc, r12                          ; jump to entry of kernel.dll
3 ArmInit
   在PRIVATE\WINCEOS\COREOS\NK\LDR\ARM\arminit.c中
   LPVOID ARMInit (struct KDataStruct *pKData)
{
    /* Initialize kernel globals */
    KernelRelocate (pTOC);

    /* The only argument passed to the entry point of kernel.dll is the address */
    /* of KData, we need to put everything we need to pass to in in KData. */
    pKData->dwTOCAddr     = (DWORD) pTOC;
    pKData->dwOEMInitGlobalsAddr = (DWORD) OEMInitGlobals;

    SetOsAxsDataBlockPointer(pKData);

    return FindKernelEntry (pTOC);
}
 主要是內核重定位 .返回kernel.dll的入口位置.
  在上面的KernelStart函數中,mov pc, r12指令跳轉到kernel.dll的入口位置.
 

4 FindKernelEntry找到NKStartup
   在PRIVATE\WINCEOS\COREOS\NK\KERNEL\ARM\mdarm.c中
   調用 ARMSetup (PRIVATE\WINCEOS\COREOS\NK\KERNEL\ARM\mdarm.c)to perform addition setup for CPU (vector table, 1st-level PT mappings, etc)
   調用OEMInitDebugSerial 以及    OEMInit
   
5   OEMInit
   在\PLATFORM\SMDK6410\SRC\OAL\OALLIB\init.c中

      OALCacheGlobalsInit();
      .....
    OALArgsInit((BSP_ARGS *)IMAGE_SHARE_ARGS_UA_START);// Check and Initialize the BSP Args area
     .....
      if (!OALIntrInit())// Initialize Interrupts
    {
        OALMSG(OAL_ERROR, (L"[OAL:ERR] OEMInit() : failed to initialize interrupts\n"));
    }
    .......
    OALTimerInit(RESCHED_PERIOD, (OEM_COUNT_1MS ), 0);// Initialize System Clock
    .......
    KITLIoctl(IOCTL_KITL_STARTUP, NULL, 0, NULL, 0, NULL);  // Initialize the KITL connection if required
  
  

6、KernelSstart函數:
    這裏的KernelStart函數與前面的KernelStart函數的屬於兩個完全不同的函數,NKStartup函數中調用的KernelStart 函數爲
    $(_PRIVATEROOT)\WINCEOS\COREOS\NK\KERNEL\ARM\armtrap.s文件中的KernelStart 函數,
    主要完成調用內核初始化函數KernelInit,並跳轉到操作系統的第一個啓動的任務。
LEAF_ENTRY KernelStart
    ldr r4, =KData ; (r4) = ptr to KDataStruct
    ldr r0, =APIRet
    str r0, [r4, #pAPIReturn] ; set API return address
    mov r1, #SVC_MODE
    msr cpsr_c, r1 ; switch to Supervisor Mode w/IRQs enabled
    CALL KernelInit ; initialize scheduler, etc.
    mov r0, #0 ; no current thread
    mov r1, #ID_RESCHEDULE
    b FirstSchedule
ENTRY_END

7、KernelInit函數:
    Windows CE 6.0的內核初始化函數同其他版本的內核初始化函數基本相近,主要完成在啓動第一個線程前對內核進行初始化,主要包括API函數集初始化、堆的初始化、初始化內存池、進程初始化、線程初始化和文件映射初始化等操作。
void KernelInit (void)
{
#ifdef DEBUG
    g_pNKGlobal->pfnWriteDebugString (TEXT("Windows CE KernelInit\r\n"));
#endif
    APICallInit ();// setup API set
    HeapInit ();// setup kernel heap
    InitMemoryPool ();// setup physical memory
    PROCInit ();// initialize process
    VMInit (g_pprcNK);// setup VM for kernel
    THRDInit ();// initialize threadsv
    MapfileInit ();
#ifdef DEBUG
    g_pNKGlobal->pfnWriteDebugString (TEXT("Scheduling the first thread.\r\n"));
#endif
}

8、FirstSchedule:
    FirstSchedule函數爲Windows CE操作系統啓動過程中最後無條件跳轉的一個函數,windows CE進行第一個調度,實際爲一個空閒線程,因爲windows CE系統還沒有完成啓動,只有當windows CE完全啓動並進入穩定狀態,然後啓動文件系統filesys.dll,設備管理device.dll,窗體圖像子系統gews.dll和shell程序 explore.exe。

 

(2)系統的其它部分初始化

2.1    FirstSchedule --〉SystemStartupFunc
2.2    而在SystemStartupFunc中,會創立一個內核線程
   CreateKernelThread (RunApps,0,THREAD_RT_PRIORITY_NORMAL,0)
   這樣就執行線程的函數RunApps
2.3    在RunApps中,NKLoadLibraryEx (L"filesys.dll", MAKELONG (LOAD_LIBRARY_IN_KERNEL, LLIB_NO_PAGING), NULL);
     進行filesys.dll的加載,
2.4     然後啓動一個線程,執行filesys.dll的 WinMain
2.5      等待filesys.dll 的event SYSTEM/FSReady
2.6      收到後: 
            InitMUILanguages();// Initialize MUI-Resource loader (requires registry)
       
            InitSystemSettings (); // Read system settings from registry
   
我們再來看看 FILESYS.DLL 。它相當於Windows CE以前版本中的FILESYS.EXE,負責初始化文件系統、對象存儲、註冊表、CEDB數據庫、設備通知以及其它一些工作。

1  Filesys.dll 檢測是冷啓動還是熱啓動
  如果是冷啓動,對象存儲內存將被初始化並映射給Filesys.dll.對於熱啓動,不用初始化而直接映射給Filesys.dll
2 Filesys.dll 從ROM中加載 OEM的 Certification DLL .

3 對於熱啓動,如果系統必須冷啓動, Filesys.dll調用OAL函數pNotifyForceCleanboot.

4 對於冷啓動, Filesys.dll 初始化RTC,通過調用OEMIoControl函數,控制號爲IOCTL_HAL_INIT_RTC I/O.
5 Filesys.dll 按照順序初始化下列APIs:
   Database APIs
   File system APIs
   Point-to-point message queue APIs
   Event log APIs
   Registry APIs
對於冷啓動, Filesys.dll初始化註冊表數據.數據初始化過程取決於是hive註冊表還是RAM註冊表.
如果在註冊表裏指定了缺省的用戶Profile, Filesys.dll加載缺省用戶的profile並初始化 HKEY_CURRENT_USER下的數據.

6 如果Device.dll 沒有啓動並且HKEY_LOCAL_MACHINE\System\StorageManager 指向一個可以加載的DLL, Filesys.dll加載存儲管理器.
  如果存儲管理器加載了, Filesys.dll創建一個線程來初始化它.

7 Filesys.dll 初始化NLS數據(national language support).
8 對於一個乾淨的啓動,Filesys.dll查閱Initobj.dat文件,然後從ROM中拷貝這些文件到根文件系統.
  比如Initobj.dat內容爲:
  root:-Directory("Program Files")
  root:-Directory("My Documents")
  Directory("\Windows"):-Directory("Desktop")
  Directory("\Windows"):-Directory("Programs")
  Directory("\Windows"):-Directory("Recent")
  Directory("\Windows\Desktop"):-File("Media Player.lnk", "\Windows\ceplayer.lnk")
  Directory("\Windows\Programs"):-File("Media Player.lnk", "\Windows\ceplayer.lnk")
  Directory("\Windows\Desktop"):-File("Messenger.lnk", "\Windows\msmsgs.lnk")
  Directory("\Windows\Programs"):-File("Messenger.lnk", "\Windows\msmsgs.lnk")
  它的意思是:
   先用root命令在根目錄\下面建立2個文件夾,分別叫Program Files和My Documents.
   然後在\Windows下面建立3個文件夾Desktop,Program,Recent
   最後把Media Player的鏈接ceplayer.lnk,msmsgs.lnk拷貝到\windows\Desktop,Programs目錄下,命名爲Media Player.lnk,Messenger.lnk. 

9 如果需要的話,Filesys.dll初始化時區並設置夏令時 (daylight saving time ,DST).
10 對於冷啓動, Filesys.dll爲用數據庫引擎設置區域,對於EDB數據庫,通過調用CeChangeDatabaseLCID (EDB)而對於CEDB數據庫調用CeChangeDatabaseLCID (CEDB).
   此外,對於冷啓動,Filesys.dll從Initdb.ini文件中加載數據來填充對象存儲數據庫.
  

11 Filesys.dll告訴kernel:Filesys.dll已經好了. Filesys.dll然後等待kernel通知去啓動OS的其他部分.

12 Filesys.dll根據HKEY_LOCAL_MACHINE\System\Events註冊表創建命名的事件. 這些事件被擁有他們的進程設置.

13 Filesys.dll 啓動HKEY_LOCAL_MACHINE\Init所列的應用
如果Device.dll在HKEY_LOCAL_MACHINE\Init中,而它又已經被啓動,Filesys.dll會去打開SYSTEM/BOOTPHASE2事件,並會向Device.dll發信號。
該動作使得Device.dll會去重讀註冊表,並完成最後階段的驅動初始化。任何驅動都可以去等待該同樣的事件,這樣驅動就可以去再讀一次註冊表。

在正常的啓動過程中,Filesys.dll建立了一些文件並把他們存儲在user storage中. 這些文件將佔用 1.8 MB的可用的user storage.

下列文件在啓動過程中被創建:

System.hv    \Documents and Settings\system.hv          345 KB   系統註冊表hive文件
User.hv       \Documents and Settings\default\user.hv   345 KB    缺省用戶的用戶註冊表hive文件

對於filesys.dll啓動過程,參見 http://msdn.microsoft.com/en-us/library/aa912276.aspx

再來看Device.dll,它被加載後,將讀取 HKLM\Drivers\BuildIn下面的信息,然後一個一個驅動被加載,加載後相應地在 HKLM\Drivers\Active下面創立相應的鍵.

發佈了26 篇原創文章 · 獲贊 19 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章