android启动---lk入口文件crt0.s解析
android啟動---lk入口文件crt0.s解析
// .section 偽操作, 用戶可以通過.section 偽操作來自定義一個段,每一個段以段名為開始, //以下一個段名或者文件結尾為結束,這里段名是.text.boot。 .section ".text.boot" //通過.global把_start聲明為一個對鏈接器可見的全局標識 .globl _start //匯編程序缺省入口是 start 標號,也可在連接腳本文件中用 ENTRY 標志指明其它入口點。 _start: //下面有8種異常情況可以使正常指令順序中止執行,分別為復位、未定義指令、軟件中斷、//指令預取中止、數據中止、預留、中斷請求、快速中斷請求,其中reset在本函數中定義,//其他的在exceptions.s中定義,下面分析reset。b resetb arm_undefinedb arm_syscallb arm_prefetch_abortb arm_data_abortb arm_reservedb arm_irqb arm_fiqreset: //lk/makefile定義ENABLE_TRUSTZONE := 0沒有使能TRUSTZONE(信任區)。 #ifdef ENABLE_TRUSTZONE/*Add reference to TZ symbol so linker includes it in final image */ldr r7, =_binary_tzbsp_tzbsp_bin_start #endif/* do some cpu setup */ #if ARM_WITH_CP15/* Read SCTLR */ /* Mrc(Move to ARM Register from Coprocessor)指令是將協處理器寄存器的數據傳送到ARM處理器寄存器中。P15表示協處理器15(CP15);0表示協處理器操作碼opcode1,對于CP15來說這里為0;r0是目的寄存器,是ARM處理器的寄存器;c1和c0為源寄存器,協處理器的寄存器CRn和CRm,CRn寄存器包含第1個 操作數,CRm協處理器中附加的源操作數寄存器或目標寄存器;最后一個0表示協處理器操作碼opcode2,如果不需要設置附加信息,將Crm設置為c0。 */ //CP15執行操作0(opcode1)和0(opcode2),操作數是c1和c0,其操作結果傳送到r0 mrc p15, 0, r0, c1, c0, 0/* XXX this is currently for arm926, revist with armv6 cores *//* new thumb behavior, low exception vectors, i/d cache disable, mmu disabled */ //BIC位清除指令,禁用ICache、選擇低端異常中斷向量(Normal exception vectors selected) //0x00000000-0x0000001C、保持 ARMv5 以上版本的正常功能。bic r0, r0, #(1<<15| 1<<13 | 1<<12) //禁用禁止MMU或者PU、禁用一級整體緩存(unified cache,不分代碼和數據,都存在一起)/數據緩存(L1 unified/data cache disabled)bic r0, r0, #(1<<2 | 1<<0)/* disable alignment faults *///禁止地址對齊檢查bic r0, r0, #(1<<1) /* Enable CP15 barriers by default */ //使能 26 位地址異常檢查,在lk/platform/msm8953/rules.mk定義了ARM_CORE_V8 #ifdef ARM_CORE_V8orr r0, r0, #(1<<5) #endif /* Write SCTLR *///將上面設置后的ro的值寫入到P15的寄存器c1(控制寄存器1)中mcr p15, 0, r0, c1, c0, 0 #ifdef ENABLE_TRUSTZONE/*nkazi: not needed ? Setting VBAR to location of new vector table : 0x80000 */ //c12用來設置異常向量基地址,這里把要修改的異常向量基地址保存到r0中。ldr r0, =0x00080000mcr p15, 0, r0, c12, c0, 0 #endif #endif/*WITH_CPU_EARLY_INIT在lk/platform/msm8953/rules.mk賦值為0,ENABLE_TRUSTZONE也是0,這段沒有調用,暫不關注*/ #if WITH_CPU_EARLY_INIT/* call platform/arch/etc specific init code */ #ifndef ENABLE_TRUSTZONE/* Not needed when TrustZone is the first bootloader that runs.*/bl __cpu_early_init #endif/* declare return address as global to avoid using stack */ .globl _cpu_early_init_complete_cpu_early_init_complete:#endif/*ENABLE_NANDWRITE沒有定義,WITH_CPU_WARM_BOOT在lk/platform/msm8953/rules.mk賦值為0,,這段沒有調用,暫不關注*/ #if (!ENABLE_NANDWRITE) #if WITH_CPU_WARM_BOOTldr r0, warm_boot_tagcmp r0, #1/* if set, warm boot */ldreq pc, =BASE_ADDRmov r0, #1str r0, warm_boot_tag #endif #endif/* see if we need to relocate */ /*在ARM處理器架構中,PC寄存器通常是指向當前指令后的第三條指令地址,即在ARM指令是+8,這里是把PC寄存器指向的指令地址賦值給r0,因為ARM32一條指令4字節,所以r0的值為.Laddr的內存地址。 */mov r0, pc //計算出_start的內存地址,即本段代碼的加載位置,保存在r0sub r0, r0, #(.Laddr - _start) .Laddr:ldr r1, =_start //加載復位地址到r1 /*比較_start與復位地址是否一致,即本段代碼是否加載到復位地址。如相等不需要進行代碼重定位,調用Lstack_setup設置stack,否則需要繼續進行代碼重定位。*/cmp r0, r1beq .Lstack_setup/* we need to relocate ourselves to the proper spot */ldr r2, =__data_end .Lrelocate_loop:// 進行循環拷貝,將代碼段拷貝到復位地址處 // ldr把數據從內存加載到寄存器,r3 = *(r0);r0=r0+4;ldr r3, [r0], #4 //str把數據從寄存器保存到內存中,*r1 = r3;r1=r1+4;str r3, [r1], #4cmp r1, r2 // 判斷拷貝是否完成bne .Lrelocate_loop/* we're relocated, jump to the right address */ldr r0, =.Lstack_setupbx r0 //重定位完成,此處使用絕對跳轉,跳轉到正確的地址。//檢測熱啟動的全局變量 .ltorg #if WITH_CPU_WARM_BOOT warm_boot_tag:.word 0 //分配一個32bit的內存,并初始化為0 #endif.Lstack_setup:/* set up the stack for irq, fiq, abort, undefined, system/user, and lastly supervisor mode */mrs r0, cpsr //將程序狀態寄存器cpsr內容傳送到通用寄存器r0bic r0, r0, #0x1f//清除M[4:0],這幾位決定處理器的運行模式,比如user、FIQ等。 /* 加載內存地址,堆棧向低地址增長 */ldr r2, =abort_stack_top //將abort_stack_top的地址賦給r2orr r1, r0, #0x12 // irqmsr cpsr_c, r1 // 設置irq模式 //將全局符號irq_save_spot的地址賦給r13ldr r13, =irq_save_spot /* save a pointer to a temporary dumping spot used during irq delivery *//* 堆棧指針r13(SP):每一種異常模式都有其自己獨立的r13,它通常指向異常模式所專用的堆棧,也就是說五種異常模式、非異常模式(用戶模式和系統模式),都有各自獨立的堆棧,用不同的堆棧指針來索引。這樣當ARM進入異常模式的時候,程序就可以把一般通用寄存器壓入堆棧,返回時再出棧,保證了各種模式下程序的狀態的完整性 */ orr r1, r0, #0x11 // fiqmsr cpsr_c, r1mov sp, r2 //設置fiq模式的堆棧orr r1, r0, #0x17 // abortmsr cpsr_c, r1mov sp, r2orr r1, r0, #0x1b // undefinedmsr cpsr_c, r1mov sp, r2orr r1, r0, #0x1f // systemmsr cpsr_c, r1mov sp, r2orr r1, r0, #0x13 // supervisormsr cpsr_c, r1mov sp, r2/* copy the initialized data segment out of rom if necessary */ //__data_start_rom,__data_start,__data_end的定義都在system-onesegment.ld中ldr r0, =__data_start_romldr r1, =__data_startldr r2, =__data_endcmp r0, r1 /*比較__data_start_rom和__data_start的內存地址是否相等,如果相等則跳轉到.L__do_bss處,如果不等(也就是沒有靜態數據),則執行.L__copy_loop:*/beq .L__do_bss//靜態數據初始化 .L__copy_loop:cmp r1, r2ldrlt r3, [r0], #4strlt r3, [r1], #4blt .L__copy_loop//完成數據段的拷貝//bss數據段初始化為0 .L__do_bss:/* clear out the bss */ldr r0, =__bss_startldr r1, =_endmov r2, #0// 完成bss段的清零 .L__bss_loop:cmp r0, r1strlt r2, [r0], #4blt .L__bss_loop#ifdef ARM_CPU_CORTEX_A8DSB //數據屏障ISB //指令屏障 #endifbl kmain //調用lk的main函數b . //死循環.ltorg.bss .align 2/* the abort stack is for unrecoverable errors.* also note the initial working stack is set to here.* when the threading system starts up it'll switch to a new * dynamically allocated stack, so we don't need it for very long*/ abort_stack:.skip 4096 //異常堆棧的大小4096字節 abort_stack_top:參考鏈接
LK源碼解析 1 crt0.s
https://blog.csdn.net/xichangbao/article/details/51484138
?
ARM架構參考手冊
https://developer.arm.com/documentation/ddi0487/ga
?
ARM協處理器(CP15)指令介紹
https://blog.csdn.net/u012357001/article/details/88989827
?
ARM協處理器CP15寄存器詳解
https://blog.csdn.net/a815064247/article/details/75238312
?
little-kernel分析.md
https://github.com/hardenedlinux/embedded-iot_profile/blob/master/docs/arm64/dragonboard410c/little-kernel%E5%88%86%E6%9E%90.md
?
高通(Qualcomm)LK源碼深度分析
https://blog.csdn.net/sdkdlwk/article/details/78291496?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control
總結
以上是生活随笔為你收集整理的android启动---lk入口文件crt0.s解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android lk DEFINES定义
- 下一篇: 一个好用的开源在线时序图/波形图(Tim