android启动---lk入口文件crt0.s解析
发布日期:2021-06-30 21:46:49
浏览次数:2
分类:技术文章
本文共 5876 字,大约阅读时间需要 19 分钟。
android启动---lk入口文件crt0.s解析
// .section 伪操作, 用户可以通过.section 伪操作来自定义一个段,每一个段以段名为开始, //以下一个段名或者文件结尾为结束,这里段名是.text.boot。.section ".text.boot"//通过.global把_start声明为一个对链接器可见的全局标识.globl _start//汇编程序缺省入口是 start 标号,也可在连接脚本文件中用 ENTRY 标志指明其它入口点。_start://下面有8种异常情况可以使正常指令顺序中止执行,分别为复位、未定义指令、软件中断、//指令预取中止、数据中止、预留、中断请求、快速中断请求,其中reset在本函数中定义,//其他的在exceptions.s中定义,下面分析reset。 b reset b arm_undefined b arm_syscall b arm_prefetch_abort b arm_data_abort b arm_reserved b arm_irq b 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_V8 orr 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, =0x00080000 mcr 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_BOOT ldr r0, warm_boot_tag cmp r0, #1 /* if set, warm boot */ ldreq pc, =BASE_ADDR mov r0, #1 str 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的内存地址,即本段代码的加载位置,保存在r0 sub r0, r0, #(.Laddr - _start).Laddr: ldr r1, =_start //加载复位地址到r1/*比较_start与复位地址是否一致,即本段代码是否加载到复位地址。如相等不需要进行代码重定位,调用Lstack_setup设置stack,否则需要继续进行代码重定位。*/ cmp r0, r1 beq .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], #4 cmp r1, r2 // 判断拷贝是否完成 bne .Lrelocate_loop /* we're relocated, jump to the right address */ ldr r0, =.Lstack_setup bx r0 //重定位完成,此处使用绝对跳转,跳转到正确的地址。//检测热启动的全局变量.ltorg#if WITH_CPU_WARM_BOOTwarm_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内容传送到通用寄存器r0 bic r0, r0, #0x1f//清除M[4:0],这几位决定处理器的运行模式,比如user、FIQ等。/* 加载内存地址,堆栈向低地址增长 */ ldr r2, =abort_stack_top //将abort_stack_top的地址赋给r2 orr r1, r0, #0x12 // irq msr cpsr_c, r1 // 设置irq模式//将全局符号irq_save_spot的地址赋给r13 ldr r13, =irq_save_spot /* save a pointer to a temporary dumping spot used during irq delivery *//*堆栈指针r13(SP):每一种异常模式都有其自己独立的r13,它通常指向异常模式所专用的堆栈,也就是说五种异常模式、非异常模式(用户模式和系统模式),都有各自独立的堆栈,用不同的堆栈指针来索引。这样当ARM进入异常模式的时候,程序就可以把一般通用寄存器压入堆栈,返回时再出栈,保证了各种模式下程序的状态的完整性*/ orr r1, r0, #0x11 // fiq msr cpsr_c, r1 mov sp, r2 //设置fiq模式的堆栈 orr r1, r0, #0x17 // abort msr cpsr_c, r1 mov sp, r2 orr r1, r0, #0x1b // undefined msr cpsr_c, r1 mov sp, r2 orr r1, r0, #0x1f // system msr cpsr_c, r1 mov sp, r2 orr r1, r0, #0x13 // supervisor msr cpsr_c, r1 mov 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_rom ldr r1, =__data_start ldr r2, =__data_end cmp r0, r1/*比较__data_start_rom和__data_start的内存地址是否相等,如果相等则跳转到.L__do_bss处,如果不等(也就是没有静态数据),则执行.L__copy_loop:*/ beq .L__do_bss//静态数据初始化.L__copy_loop: cmp r1, r2 ldrlt r3, [r0], #4 strlt r3, [r1], #4 blt .L__copy_loop//完成数据段的拷贝//bss数据段初始化为0 .L__do_bss: /* clear out the bss */ ldr r0, =__bss_start ldr r1, =_end mov r2, #0// 完成bss段的清零.L__bss_loop: cmp r0, r1 strlt r2, [r0], #4 blt .L__bss_loop#ifdef ARM_CPU_CORTEX_A8 DSB //数据屏障 ISB //指令屏障#endif bl 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
ARM架构参考手册
ARM协处理器(CP15)指令介绍
ARM协处理器CP15寄存器详解
https://blog.csdn.net/a815064247/article/details/75238312
little-kernel分析.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
转载地址:https://loongembedded.blog.csdn.net/article/details/113803471 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
路过按个爪印,很不错,赞一个!
[***.219.124.196]2024年04月09日 07时30分28秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
用户权限设计-基于RBAC模型
2021-07-03
微服务springcloud2系列篇-网关GATEWAY跨域问题
2021-07-03
软件质量的8个特性
2021-07-03
应届渣渣前端的艰难求职之路
2021-07-03
2021年不可错过的17种JS优化技巧(一)
2021-07-03
月薪15~20k的前端面试问什么?
2021-07-03
在 Vue 中用 Axios 异步请求API
2021-07-03
MySQL进阶查询(SELECT 语句高级用法)
2019-04-30
Mysql 之主从复制
2019-04-30
【工具使用】新版CSDN-markdown编辑器使用指南
2019-04-30
【NLP学习笔记】中文分词(Word Segmentation,WS)
2019-04-30
【超越白皮书7】你需要知道关于ETH2.0的几个事实
2019-04-30
对于时间复杂度的通俗理解
2019-04-30
如何输入多组数据并输出每组数据的和?
2019-04-30
行阶梯型矩阵
2019-04-30
图像处理学习笔记
2019-04-30
MATLAB函数备忘(定期更新)
2019-04-30
13行MATLAB代码实现网络爬虫 爬取NASA画廊星图
2019-04-30
MATLAB指定路径保存图片方法
2019-04-30
Python一键获取微信推送封面图
2019-04-30