Android系統啟動過程-uBoot+Kernel+Android
轉載自:http://www.cnblogs.com/pngcui/p/4665106.html
摘要:本文是參考大量網上資源在結合自己檢視原始碼總結出來的,讓自己同時也讓大家加深對Android系統啟動過程有一個更加深入的瞭解!再次強調,本文的大多數功勞應歸功於那些原創者們,同時一些必要的參考連結我會一一附上。
注:由於本人採用Exynos4412開發板學習,所以本文大部分資料都是基於此處理器的
簡介:對於整個Android系統的啟動總的來說分為三個階段:
BootLoader引導即uBoot.bin
linux核心啟動即zImage
Android系統啟動即ramdisk.img與system.img
以上四個檔案都是經過自己編譯後生成的且通過燒寫測試,接下來開始說這三大部分的啟動過程。
目錄:一、BootLoader的啟動
1.彙編部分
2.c部分
二、Kernel的啟動
1.zImage解壓縮
2.kernel的彙編啟動階段
3.kernel的c啟動階段
三、Android的啟動
1.init程序
2.init啟動的各種服務
3.android啟動圖示
第一部分:BootLoader的啟動流程
uBoot的第一條指令從cpu/arm920t/start.S檔案開始
1. 設定CPU進入SVC模式(系統管理模式),cpsr[4:0]=0xd3。
1 #include <common.h> 2 #include <config.h> 3 4 /* 5 ************************************************************************* 6 * 7 * Jump vector table as in table 3.1 in [1] 8 * 9 *************************************************************************10 */ 11 12 13 .globl _start 14 _start: b start_code 15 ldr pc, _undefined_instruction 16 ldr pc, _software_interrupt 17 ldr pc, _prefetch_abort 18 ldr pc, _data_abort 19 ldr pc, _not_used 20 ldr pc, _irq 21 ldr pc, _fiq 22 23 _undefined_instruction: .word undefined_instruction 24 _software_interrupt: .word software_interrupt 25 _prefetch_abort: .word prefetch_abort 26 _data_abort: .word data_abort 27 _not_used: .word not_used 28 _irq: .word irq 29 _fiq: .word fiq 30 31 .balignl 16,0xdeadbeef
接著進入Start_code中:設定CPU進入SVC模式。
1 /* 2 * the actual start code 3 */ 4 5 start_code: 6 /* 7 * set the cpu to SVC32 mode 8 */ 9 mrs r0, cpsr 10 bic r0, r0, #0x1f 11 orr r0, r0, #0xd3 12 msr cpsr, r0 13 14 bl coloured_LED_init 15 bl red_LED_on
2.關看門狗,WTCON=0x0,並設定暫存器地址。
1 /* turn off the watchdog */ 2 3 # if defined(CONFIG_S3C2400) 4 # define pWTCON 0x15300000 5 # define INTMSK 0x14400008 /* Interupt-Controller base addresses */ 6 # define CLKDIVN 0x14800014 /* clock divisor register */ 7 #else 8 # define pWTCON 0x53000000 9 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ 10 # define INTSUBMSK 0x4A00001C 11 # define CLKDIVN 0x4C000014 /* clock divisor register */ 12 # endif 13 14 ldr r0, =pWTCON 15 mov r1, #0x0 16 str r1, [r0]
3.關中斷,INTMSK=0xFFFFFFFF, INTSUBMSK=0x3FF。
1 /* 2 * mask all IRQs by setting all bits in the INTMR - default 3 */ 4 mov r1, #0xffffffff 5 ldr r0, =INTMSK 6 str r1, [r0] 7 # if defined(CONFIG_S3C2410) 8 ldr r1, =0x3ff 9 ldr r0, =INTSUBMSK 10 str r1, [r0] 11 # endif
4.時鐘設定CLKDIVN=0x3 , FCLK:HCLK:PCLK = 1:2:4
1 /* FCLK:HCLK:PCLK = 1:2:4 */ 2 /* default FCLK is 120 MHz ! */ 3 ldr r0, =CLKDIVN 4 mov r1, #3 5 str r1, [r0] 6 #endif /* CONFIG_S3C24X0 */
5.詢問是否進行CPU初始化
1 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 2 bl cpu_init_crit 3 #endif
6.relocate函式
1 #ifndef CONFIG_SKIP_RELOCATE_UBOOT 2 relocate: /* relocate U-Boot to RAM */ 3 adr r0, _start /* r0 <- current position of code */ 4 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 5 cmp r0, r1 /* don't reloc during debug */ 6 beq stack_setup 7 8 ldr r2, _armboot_start 9 ldr r3, _bss_start 10 sub r2, r3, r2 /* r2 <- size of armboot */ 11 add r2, r0, r2 /* r2 <- source end address */ 12 13 copy_loop: 14 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 15 stmia r1!, {r3-r10} /* copy to target address [r1] */ 16 cmp r0, r2 /* until source end addreee [r2] */ 17 ble copy_loop 18 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
7.初始化堆疊
1 /* Set up the stack */ 2 stack_setup: 3 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 4 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 5 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 6 #ifdef CONFIG_USE_IRQ 7 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 8 #endif 9 sub sp, r0, #12 /* leave 3 words for abort-stack */ 10 11 clear_bss: 12 ldr r0, _bss_start /* find start of bss segment */ 13 ldr r1, _bss_end /* stop here */ 14 mov r2, #0x00000000 /* clear */ 15 16 clbss_l:str r2, [r0] /* clear loop... */ 17 add r0, r0, #4 18 cmp r0, r1 19 ble clbss_l
8.CPU的初始化,即cpu_init_crit函式,完成以後回到主函式
1 #ifndef CONFIG_SKIP_LOWLEVEL_INIT 2 cpu_init_crit: 3 /* 4 * flush v4 I/D caches 5 */ 6 mov r0, #0 7 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 8 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 9 10 /* 11 * disable MMU stuff and caches 12 */ 13 mrc p15, 0, r0, c1, c0, 0 14 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 15 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 16 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 17 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 18 mcr p15, 0, r0, c1, c0, 0 19 20 /* 21 * before relocating, we have to setup RAM timing 22 * because memory timing is board-dependend, you will 23 * find a lowlevel_init.S in your board directory. 24 */ 25 mov ip, lr 26 27 bl lowlevel_init 28 29 mov lr, ip 30 mov pc, lr 31 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
9.從這裡跳轉到第二階段C程式碼中去
1 ldr pc, _start_armboot 2 3 _start_armboot: .word start_armboot
C部分從檔案/lib_arm/board.c的start_armboot()函式開始
1.定義一個struct global_data結構體指標gd,struct global_data結構體物件gd_data,
定義一個struct bd_info結構體物件bd_data,定義一個指向函式的二級指標init_fnc_ptr,定義的全域性結構體物件都是放在堆疊中的,gd是放在暫存器中的。
2. gd=&gd_data,gd->bd = &bd_data,並且全部空間清0。
3.init_fnc_ptr = init_sequence(一個初始化函式指標陣列)。將會在接下來的for迴圈中提取出每一個函式來依次執行完。
4.配置可用的flash空間,並且打印出相關資訊,flash_init()和display_flash_config()。
5.mem_malloc_init()函式,分配堆空間.
6.env_relocate該函式的作用是將0x33ef0000開始16K的環境引數拷貝到堆空間中去。
7.gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr")通過這中方式獲得環境變數列表中的ipaddr引數(開發板ip),獲得環境變數中的MAC地址,設定到gd->bd->bi_enetaddr[reg]中。
8.devices_init函式,建立了devlist,但是隻有一個串列埠設備註冊在內。
9.console_init_r函式:控制檯完全初始化,此後可以使用函式serial_getc和serial_putc或者putc和getc來輸出log。
10.使能中斷,如果有網絡卡裝置,設定網絡卡MAC和IP地址。
11.main_loop ();定義於common/main.c。到此所有的初始化工作已經完成,main_loop在標準輸入裝置中接受命令,然後分析,查詢和執行。
12.在上面的main_loop函式中,通常在開發完成的階段都會設定一個bootcmd的環境變數,然後將延時bootdelay設定成0,這樣當u-boot跑到這裡的時候就不會因為使用者按下了任意鍵就進入了命令列模式,
可以直接執行bootcmd的命令來直接載入kernel的Image然後移交控制權。如果進入了命令列模式,我們也可以手動輸入命令來啟動系統,輸入的命令也是基本和bootcmd一樣
1 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) 2 s = getenv ("bootdelay"); 3 bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; 4 5 debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay);
這個地方時設定bootdelay的地方,即在引導kernel時等待使用者命令,進入命令列模式,進行分割槽,格式化等操作。
13.uBoot 引導核心啟動的最後一步是:通過一個函式指標 thekernel()帶三個引數跳轉到核心( zImage )入口點開始執行,此時, u-boot 的任務已經完成,控制權完全交給核心( zImage )。
在 uBoot 的檔案lib_arm\bootm.c中定義了 thekernel, 並在 do_bootm_linux 的最後執行 thekernel。
定義thekernel函式指標,獲取bootargs引數給commandline指標。
theKernel (0, machid, bd->bi_boot_params);第一個引數必須為0,第二個引數為機器型別ID,第三個引數為傳遞給核心引數的起始地址0x30000100
1 int do_bootm_linux(相關推薦
Android系統啟動過程-uBoot+Kernel+Android
轉載自:http://www.cnblogs.com/pngcui/p/4665106.html 摘要:本文是參考大量網上資源在結合自己檢視原始碼總結出來的,讓自己同時也讓大家加深對Android系統啟動過程有一個更加深入的瞭解!再次強調,本文的大多數功勞應
Android系統啟動過程
android 框架的示意圖: Linux核心啟動之後就到Android Init程序,進而啟動Android相關的服務和應用 啟動的過程如下圖所示: 一 Init程序的啟動 init程序,它是一個由核心啟動的使
Android系統啟動過程學習
使用 android 手機已經長時間了,同時,從大學學習 android 開發開始,也進行過多款 android app 專案的開發,但是對 android 內部的啟動過程,即當我們從按下電源鍵開機開始, android 系統內部是如何執行的,由於android
Android系統啟動過程分析
Android系統啟動過程分析 一、Android平臺架構 首先貼一張Android系統架構圖方便理解整個Android架構,這可以讓我們從整體上對整個啟動流程有個大概認知。 可以看出整個架構由5部分構成,從下到上分別為: 1. Linux核心層 Android 的核心繫統服務基於Linux 核心,在此基
Linux啟動流程-bootloader至kernel的過程--android系統啟動流程
1 Bootloader 對於一般的ARM處理器,CPU上電或復位執行第一條指令所在地址,即第一段程式Bootloader的開始地址,Bootloader一般存於Nor-flash(XIP),支援晶片內執行。 Bootloader的功能可總結為:1)初始化CPU時鐘,記憶體
Android 的 ramdisk.img、system.img、userdata.img 作用說明,以及UBoot 系統啟動過程
一個分割槽影像檔案,它會在kernel 啟動的時候,以只讀的方式被 mount , 這個檔案中只是包含了 /init 以及一些配置檔案,這個ramdisk 被用來呼叫init,以及把真正的root file system mount 起來。 #其實ramdisk.img的內容就是/out/target/pro
Android系統啟動流程(一)解析init進程啟動過程
option 寫入 android change failed miss 通知 target sna 前言 作為“Android框架層”這個大系列中的第一個系列,我們首先要了解的是Android系統啟動流程,在這個流程中會涉及到很多重要的知識點,這個系列我們就來一一講解它們
Android系統啟動流程(一)解析init程序啟動過程
前言 作為“Android框架層”這個大系列中的第一個系列,我們首先要了解的是Android系統啟動流程,在這個流程中會涉及到很多重要的知識點,這個系列我們就來一一講解它們,這一篇我們就來學習init程序。 1.init簡介 init程序是An
android原始碼4.4.2----系統啟動過程分析
public class SystemServer { private static final String TAG = "SystemServer"; public static final int FACTORY_TEST_OFF = 0; public static final int F
Android系統啟動流程(二)解析Zygote程序啟動過程
前言 上一篇文章我們分析了init程序的啟動過程,啟動過程中主要做了三件事,其中一件就是建立了Zygote程序,那麼Zygote程序是什麼,它做了哪些事呢?這篇文章會給你這些問題的答案。 1.Zygote簡介 在Android系統中,DVM(D
Android系統啟動流程——解析init程序啟動過程
最近主要是在看android關機充電流程,對android啟動有些迷惑,結合網上部落格專家的文章,加一些自己的理解。 1.init簡介 init程序是Android系統中使用者空間的第一個程序,作為第一個程序,它被賦予了很多極其重要的工作職責,比如建立zygote(孵化器
Android原始碼學習之八—系統啟動過程
Android原始碼數量龐大,雖然對它的學習從未停止,但是整理成這樣的文字,實在是費時費力的一件事情,不過好在前文已經對其基本機制加以分析,相信以此為基礎,其他的內容學習起來就沒那麼困難了。 今天是20
Android系統啟動流程(四)Launcher啟動過程與系統啟動流程
相關文章 Android系統架構與系統原始碼目錄 Android系統啟動流程(一)解析init程序啟動過程 Android系統啟動流程(二)解析Zygote程序啟動過程 Android系統啟動流程(三)解析SyetemServer程序啟動過程 前言
Android系統啟動流程(三)解析SyetemServer程序啟動過程
相關文章 Android系統架構與系統原始碼目錄 Android系統啟動流程(一)解析init程序啟動過程 Android系統啟動流程(二)解析Zygote程序啟動過程 前言 上一篇我們學習了Zygote程序,並且知道Zygote程序啟動了SyetemServ
Android編譯過程總結及android中各種img檔案的作用以及系統啟動過程
編譯環境:ubuntu 10.04(或者更高)(windows平臺目前不被支援) 本文以編譯android2.3為例,64位作業系統 1、編譯環境的準備 (1)確保安裝有ubuntu系統或者虛擬機器 (2)安裝JDK1.6(對於Android2.3以上程式碼) $ sud
為什麽要有uboot?帶你全面分析嵌入式linux系統啟動過程中uboot的作用
統一 一次 fail 進入 是我 臺式機 平板 配置 webp 1.為什麽要有uboot 1.1、計算機系統的主要部件 (1)計算機系統就是以CPU為核心來運行的系統。典型的計算機系統有:PC機(臺式機+筆記本)、嵌入式設備(手機、平板電腦、遊戲機)、單片機(家用電器像
Android系統啟動流程
包名 more dev ted androi cap 執行 ons 開始 當系統引導程序啟動Linux內核,內核會記載各種數據結構,和驅動程序,加載完畢之後,Android系統開始啟動並加載第一個用戶級別的進程:init(system/core/init/Init.c)
為什麼要有uboot?帶你全面分析嵌入式linux系統啟動過程中uboot的作用
為什麼要有uboot?帶你全面分析嵌入式linux系統啟動過程中uboot的作用 2017-08-24 18:19作業系統 1.為什麼要有uboot 1.1、計算機系統的主要部件 (1)計算機系統就是以CPU為核心來執行的系統。典型的計算機系統有:PC機(桌上型電腦+筆記
Android系統啟動-Init篇
基於Android 6.0的原始碼剖析, 分析Android啟動過程程序號為1的init程序的工作內容 /system/core/init/ - init.cpp - init_parser.cpp - signal_handler.cpp 一、概述 init
Android系統啟動流程——init程序
配置檔案:system/rootdir/init.rc init程序是一個由核心啟動的使用者級程序。核心自行啟動之後(已經被載入記憶體,開始執行並已初始化所有裝置驅動程式和資料結構等),通過啟動一個使用者級程式init的方式完成引導過程。Init始終是第一個程序,可