linux内核启动 Android系统启动过程详解
android启动流程

android启动流程Android启动流程:Android是一款广泛使用的移动操作系统,其启动流程是一个相对复杂的过程,涉及到多个模块的加载和启动。
下面将详细介绍Android的启动流程。
1、开机自检(Boot)当手机开机时,首先进行开机自检。
在这个阶段,系统会检测硬件设备的状态,包括电池是否齐全、屏幕是否正常等。
如果硬件设备通过了自检,系统将会开始启动。
2、引导加载程序(Bootloader)开机自检完成后,系统会加载引导加载程序(Bootloader)。
引导加载程序是硬件平台的一部分,其主要作用是启动操作系统。
在加载引导加载程序的过程中,系统会自动检测手机的存储器设备,确定存储设备中是否有可用的引导文件。
3、Linux内核加载一旦引导加载程序找到可用的引导文件,系统将会加载Linux内核。
Linux内核是Android系统的核心组件,负责管理内存、文件系统、驱动程序等。
4、文件系统加载一旦Linux内核加载完成,系统将会加载文件系统。
Android系统使用的是基于Linux的文件系统,在这个过程中,系统会加载并初始化各个文件系统,包括根文件系统、系统文件系统、数据文件系统等。
5、初始化进程(Init)一旦文件系统加载完成,系统将会启动初始化进程(Init)。
初始化进程是Android系统的第一个进程,其作用是启动系统的各个进程和服务。
6、启动用户空间(System Server)在初始化进程启动后,系统会启动用户空间,加载系统的用户界面等组件。
7、启动应用程序一旦用户空间加载完成,系统将会启动应用程序。
应用程序是Android系统的核心功能,包括系统应用程序和用户安装的应用程序。
系统应用程序包括电话、短信、浏览器等,而用户安装的应用程序则是用户根据自己的需求下载和安装的。
8、应用程序启动完成一旦应用程序启动完成,系统将进入正常运行状态,用户可以通过界面操作手机。
总结:Android系统的启动流程是一个复杂而严密的过程,经过开机自检、引导加载程序、Linux内核加载、文件系统加载、初始化进程、启动用户空间、启动应用程序等多个步骤,最终实现用户界面的显示和应用程序的运行。
在你的Android手机上运行Linux

在你的Android⼿机上运⾏Linux[2020.03.06] 今⽇再观,真不愧乃2018年的古董⽂章。
以前提供的链接现在已经通通失效,JuiceSSH终究不再更新,Termux拥有了更⾼的可玩度,也有了许多其他的替代⽅案。
因此将此⽂稍作修缮,或不再有其他额外改动了。
之前试过许多⽅法(也就⼏种),像什么Complete Linux Installer,Debian noroot,利⽤已有的Linux构造Bootstrap之类,要么就是复杂得要命(调了两天没有调出来),要么就是鸡肋,直到发现了⼀款叫做Linux Deploy的软件。
这款软件是需要root才能运⾏的,没有root的童鞋可以转向那些Termux的教程了。
只是Termux没有Linux Deploy性能好,可定制程度稍低罢了。
看来这款软件的先置需求还是不多的,随随便便就能处理好是不是?好吧,现在步⼊正题,开始安装Linux Deploy(欢迎花样作死)。
1.安装Linux Deploy虽然有些应⽤商店⾥有Linux Deploy,⽹上也可以下得到,但是版本估计都很旧,所以推荐到Google Play商店⾥下载(没有链接提供哈)。
就像安装微信⼀样安装好它就⾏了。
然后打开......是这个样⼦的:你看,上⾯都教你怎么安装了!(笑)2.配置Linux Deploy如果你想要安装多个系统,建议更改⼀下配置⽂件的名称。
(哎呀,强迫症⼜犯了,你们忽略我吧)先点击左上的“恒等于号”点击配置⽂件点⼀下那⽀笔既然这次我们要安装的是Ubuntu,那就写上Ubuntu好了......更改好后点击确定如果不想你的Linux运⾏时CPU休眠导致卡成龟,最好让其保持唤醒返回,点击设置勾选“保持CPU唤醒”,顺便把“锁定Wi-Fi"也勾上吧,嘿嘿!3.设置安装选项在设置安装选项之前,需要看看⼿机的CPU架构和/data分区剩余空间回到主页⾯,点击右上⽅的三个点点击状态然后就会滚出来很多⾏字⽐如,我的⼿机CPU是armv8l的,/data分区还剩15.9GB,这些信息都要记住,后⾯要⽤到(不记住好像也没什么事)现在可以正式开始设置安装选项了,点击右下⽅的⼀个⿁畜的按钮容器类型不⽤管,直接从发⾏版开始由于这回我们要安装Ubuntu,那就选Ubuntu好了(废话)接下来就是架构了,根据我们之前在状态⾥看到的CPU架构选择合适的架构⼀般有armv8字样的CPU是64位的,选择arm64或aarch64(看哪个有选哪个,这⾥是arm64,那就选arm64),其他的选armhf即可(除⾮你的⼿机⽼到炸裂,就只能选armel了,不过太⽼的⼿机是装不上Linux Deploy的),如果有些神机是i386或者x86_64(amd64)的,直接照着选就可以了(表⽰膜拜)⽐如我的⼿机是armv8l,就选arm64好了⾄于发⾏版版本嘛,你⾃⼰选好了。
全志平台linux启动流程分析全志平台linux启动流程分析

全志平台linux启动流程分析全志平台linux启动流程分析一、BROM阶段机器上电之后会执行固化在BROM里面的一段引导程序,这个程序会依次遍历所有支持的启动介质,直到找到第一个支持的。
目前支持的启动介质是sd/mmc卡、nand和spinor。
当程序初始化启动介质成功后,就从固定位置读入Bootloader的Boot0到SRAM,然后跳到SRAM执行。
下面展示了BROM的执行流程二、Bootloader阶段Bootloader是全志平台上从小系统一直沿用下来的内核加载器,在这里的主要职责是加载U-Boot到DRAM。
Bootloader分为两个部分,分别是Boot0和Boot1。
Boot0:初始化DRAM,加载Boot1到DRAM;Boot1:调频,加载U-Boot到DRAM;为什么Bootloader要划分成Boot0和Boot1两个部分?因为在Bootloader阶段,使用的SRAM大小是32KB,除去C运行环境需要的栈空间,可用的空间在24KB左右,这点不足以载入整个Bootloader。
因此,需要将Bootloader划分成两个部分,尽可能将繁重的任务放在Boot1执行,这个情况类似于Linux系统中断执行环境的上半部和下半部。
1. boot0执行过程2. boot1的执行过程Boot1会进行一次系统调频,将CPU的频率调到用户在sys_config1.fex target段配置的boot_clock。
如何在Boot1让机器进入升级模式?(1)按住power键,再按任意键3下;(2)接上串口启动,进入Boot1后在键盘输入2;如何替换Bootloader分区的内容?接上串口启动,进入Boot1后在键盘输入1,USB会挂载Bootloader分区到PC上,卷标是“Volume”,替换掉相关的文件之后重启机器即可生效。
Boot1会检测低电关机,以及插入火牛开机的情况进入关机程序。
后者需要在sys_config1.fex里配置。
deepin使用笔记——在Linux上运行安卓(Android)app

deepin使⽤笔记——在Linux上运⾏安卓(Android)app 昨晚⼩折腾了⼀下,在 deepin 上装上了安卓版的抖⾳。
桌⾯上的抖⾳图标运⾏抖⾳很简单,这是通过 xDroid 实现的。
xDroid 由北京麟卓信息科技有限公司()开发,是⼀款专门在 Linux 中运⾏ Android 应⽤的软件,其未来的⽬标是让百万量级 Android 应⽤在主流PC平台(含国产)上以⾼效运⾏,⼤⼤拓展 Linux 的⽣态环境。
与现有的各种 Android 模拟器不同,xDroid 没有使⽤虚拟机,⽽是使 Android 应⽤以 Linux 原⽣程序的形式运⾏,性能媲美标准的 Linux 程序。
只要主流 Linux ⽀持的硬件,即可安装部署 xDroid ,甚⾄可以在虚拟机中的 Linux 上运⾏。
xDroid ⾃带的应⽤商店 xAppCenter 提供了⽬前经过兼容性测试的各种 Android 应⽤,更为便利。
有了 xDroid,就可以充分利⽤已有的 Android 开发环境、开发⼈员、开发⼯具、开发资源,来拓展 Linux 的⽣态环境。
————————————————版权声明:本⽂为CSDN博主「wd123326」的原创⽂章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原⽂出处链接及本声明。
原⽂链接:https:///wd123326/article/details/80860371说起来挺复杂,其实可以简单理解为:xDroid 不是⼀个通常意义上的安卓模拟器,它不是虚拟机,⽽是⼀个中间层,通过它,安卓app可以像是原⽣应⽤⼀样运⾏在linux 系统上。
接下来是 xDroid 的安装使⽤教程(以本⼈的经验为准,并不保证100%有效)。
第⼀步,当然是下载 xDroid,百度⼀下,很容易就能找到。
下载好以后,是⼀个名为【xDroidInstall-x86_64-v2.7000-20190621155253.tar.gz】的压缩包,直接解压,得倒名为【xDroidInstall-x86_64】的⽂件夹。
androidstartup原理

androidstartup原理Android是由Google开发的一套开放源代码的操作系统,主要用于移动设备和嵌入式系统。
它被广泛应用于智能手机、平板电脑、智能电视等移动设备中。
Android系统的启动过程是一个复杂的过程,涉及到很多不同的模块和组件。
下面将详细介绍Android系统的启动原理。
Android系统的启动过程主要包括五个阶段:引导加载程序、Linux内核初始化、系统服务初始化、应用程序启动和进程初始化。
首先是引导加载程序阶段。
当设备开机时,引导加载程序会被加载并执行。
引导加载程序主要负责初始化硬件设备,并加载第二阶段的引导加载程序。
在这个阶段,设备会进行一些硬件自检和初始化操作,确保设备能够正常运行。
接着是Linux内核初始化阶段。
在这个阶段,Linux内核会被加载并执行。
Linux内核是Android系统的核心部分,它负责管理系统的各种硬件资源和提供系统服务,同时也是Android系统与硬件之间的桥梁。
在这个阶段,Linux内核会初始化一些重要的子系统,如内存管理、文件系统、网络协议栈等。
然后是系统服务初始化阶段。
在这个阶段,系统服务会被加载并启动。
系统服务是Android系统中的一些核心组件,它们负责提供各种系统功能和服务,如Activity管理、通知管理、电源管理、输入管理等。
在这个阶段,系统服务会被初始化,并通过Binder机制提供接口供应用程序调用。
接下来是应用程序启动阶段。
在这个阶段,一些重要的应用程序会被加载并启动。
Android系统中有一些应用程序是系统级别的,它们在系统启动过程中会被优先加载和启动,如Launcher、Settings等。
在这个阶段,应用程序会被启动,并进入到运行状态。
最后是进程初始化阶段。
在这个阶段,Android系统会创建并初始化一些重要的进程。
Android系统采用了一种轻量级的进程模型,每个应用程序对应一个独立的进程,各个进程之间通过IPC机制进行通信。
linux下配置android开发环境(图解)

linux下配置android开发环境(Fedora)1、将配置环境所需要的:jdk、android-sdk、eclipse安装包拷贝到/home目录下,并为为文件增加可修改可执行权限2、安装JDK3、配置JDK环境变量(1)进入profile文件(2)按i编辑,如下:(3)、按ESC,再按:wq 保存退出4、安装android sdk5、安装eclipse6、运行eclipse7、安装Eclipse的ADT 插件(开发android应用)(1)离线安装:启动Eclipse,选择Help > Install New Software,在出现的对话框里,点击Add按钮,在对话框的name一栏输入“ADT”(可随意),点击Archive...,选择已下载的ADT插件(ADT-0.9.7.zip)压缩文件。
(2)在线安装:点击Archive,地址栏中输入:https:///android/eclipse(如有问题,去掉s,用http)8、安装完ADT后,会有如下提示:(1)选择“Apply Changes Now”,会自动联网下载安装android SDK(2)选择“Restart Now”,重新启动eclipse,需手动安装android sdkwindow->preferences,左边点击android,右边SDK Location中选择Android SDK所在位置。
安装模拟器平台:window->Android manager 在线下载不同版本的Android模拟器如果有已存在的android sdk,可以直接指定:9、虚拟手机创建(1)Windows→A VD Manager→new 新建虚拟手机name:随意;Target:选择平台,即android模拟器SD card:用于存储文件,Skin:屏幕。
Build-in:不同屏幕有不同分辨率屏幕分辨率HVGA:320×480 QVGA:240x320 WQVGA400:240X400WQVAG432:240X432(2)点击右侧“start”启动,效果图:我最开始配置Android环境时,用的是旧版本的Red Hat Linux (Red Hat 9) 。
Android 开机启动流程

Android的开机流程1. 系统引导bootloader1) 源码:bootable/bootloader/*2) 说明:加电后,CPU将先执行bootloader程序,此处有三种选择a) 开机按Camera+Power启动到fastboot,即命令或SD卡烧写模式,不加载内核及文件系统,此处可以进行工厂模式的烧写b) 开机按Home+Power启动到recovery模式,加载recovery.img,recovery.img包含内核,基本的文件系统,用于工程模式的烧写c) 开机按Power,正常启动系统,加载boot.img,boot.img包含内核,基本文件系统,用于正常启动手机(以下只分析正常启动的情况)2. 内核kernel1) 源码:kernel/*2) 说明:kernel由bootloader加载3. 文件系统及应用init1) 源码:system/core/init/*2) 配置文件:system/rootdir/init.rc,3) 说明:init是一个由内核启动的用户级进程,它按照init.rc中的设置执行:启动服务(这里的服务指linux底层服务,如adbd提供adb支持,vold提供SD卡挂载等),执行命令和按其中的配置语句执行相应功能4. 重要的后台程序zygote1) 源码:frameworks/base/cmds/app_main.cpp等2) 说明:zygote是一个在init.rc中被指定启动的服务,该服务对应的命令是/system/bin/app_processa) 建立Java Runtime,建立虚拟机b) 建立Socket接收ActivityManangerService的请求,用于Fork应用程序c) 启动System Server5. 系统服务system server1) 源码:frameworks/base/services/java/com/android/server/SystemServer.java2) 说明:被zygote启动,通过System Manager管理android的服务(这里的服务指frameworks/base/services下的服务,如卫星定位服务,剪切板服务等)6. 桌面launcher1) 源码:ActivityManagerService.java为入口,packages/apps/launcher*实现2) 说明:系统启动成功后SystemServer使用xxx.systemReady()通知各个服务,系统已经就绪,桌面程序Home就是在ActivityManagerService.systemReady()通知的过程中建立的,最终调用()启launcher7. 解锁1) 源码:frameworks/policies/base/phone/com/android/internal/policy/impl/*lock*2) 说明:系统启动成功后SystemServer调用wm.systemReady()通知WindowManagerService,进而调用PhoneWindowManager,最终通过LockPatternKeyguardView显示解锁界面,跟踪代码可以看到解锁界面并不是一个Activity,这是只是向特定层上绘图,其代码了存放在特殊的位置8. 开机自启动的第三方应用程序1) 源码:frameworks/base/services/java/com/android/server/am/ActivityManagerService.java2) 说明:系统启动成功后SystemServer调用ActivityManagerNative.getDefault().systemReady()通知ActivityManager启动成功,ActivityManager会通过置变量mBooting,通知它的另一线程,该线程会发送广播android.intent.action.BOOT_COMPLETED以告知已注册的第三方程序在开机时自动启动。
高通Andriod开机流程与镜像说明

⾼通Andriod开机流程与镜像说明Android镜像说明Android设备刷机时都需要ROM包,ROM包下⾯有很多的.img和其他的相关镜像⽂件,其中这⾥⾯包含了Android很多的分区,Android镜像⽂件是通过源码编译⽣成的,下⾯是ROM包各个镜像的作⽤:镜像⽂件说明boot.img boot分区,包括内核⽂件和虚拟内存盘Ramdisk,负责设备开机,可在recovery模式进⾏擦除,重新安装带有boot分区的新系统system.img system分区,包含Android系统的⽤户界⾯以及设置上的⼀些预装系统应⽤recovery.img recovery分区,替代启动分区,执⾏恢复和维护系统的⼀些操作userdata.img data分区,⽤于保存⽤户的数据,例如联系⼈,短信,设置偏好和应⽤程序存放的地⽅cache.img cache分区,⽤于放置系统频繁访问的数据和应⽤程序组件的分区persist.img persist分区包含了设备的传感器和信号部分的驱动程序,例如wifi,蓝⽛连接都有关系splash.img开机画⾯⽂件NON-HLOS.bin modem image负责处理通讯协议相关的基带镜像prog_emmc_firehose_8953_ddr.mbn QFIL软件烧录系统的时候,需要⽤到此⽂件,应该是关于EMMC、DDR的配置参数相关的sbl1.mbn硬件的初始化,并且保存加载其他模块信息的顺序tz.mbn trustzone是ARM TrustZone® 技术是系统范围的安全⽅法,基于安全需求和引导模式配置XPU,NAND MPU,它和其他模块代码运⾏在相互隔离的区域,主要实现底层很多安全性特性emmc_appsboot.mbn bootloader⽂件,进⼊fastboot模式相关⽂件rpm.mbn电源管理器,是⾼通MSM平台另外加的⼀块芯⽚,虽然与AP芯⽚打包在⼀起,但其是⼀个独⽴的ARM Core。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
linux内核启动+Android系统启动过程详解第一部分:汇编部分Linux启动之linux-rk3288-tchip/kernel/arch/arm/boot/compressed/ head.S分析这段代码是linux boot后执行的第一个程序,完成的主要工作是解压内核,然后跳转到相关执行地址。
这部分代码在做驱动开发时不需要改动,但分析其执行流程对是理解android 的第一步开头有一段宏定义这是gnu arm汇编的宏定义。
关于GUN 的汇编和其他编译器,在指令语法上有很大差别,具体可查询相关GUN汇编语法了解另外此段代码必须不能包括重定位部分。
因为这时一开始必须要立即运行的。
所谓重定位,比如当编译时某个文件用到外部符号是用动态链接库的方式,那么该文件生成的目标文件将包含重定位信息,在加载时需要重定位该符号,否则执行时将因找不到地址而出错#ifdef DEBUG//开始是调试用,主要是一些打印输出函数,不用关心#if defined(CONFIG_DEBUG_ICEDCC)……具体代码略#endif宏定义结束之后定义了一个段,.section ".start", #alloc, #execinstr这个段的段名是 .start,#alloc表示Section contains allocated data, #execinstr表示Sectioncontains executable instructions.生成最终映像时,这段代码会放在最开头.alignstart:.type start,#function /*.type指定start这个符号是函数类型*/.rept 8mov r0, r0 //将此命令重复8次,相当于nop,这里是为中断向量保存空间.endrb 1f.word 0x016f2818 @ Magic numbers to help the loader.word start @ absolute load/run zImage//此处保存了内核加载和运行的地址,实质上也是本函数的运行地址address.word _edata @ 内核结束地址//注意这些地址在顶层vmlixu.lds(具体在/kernel文件夹里)里进行了定义,是链接的地址,加载内核后可能会进行重定位1: mov r7, r1 @ 保存architecture ID,这里是从bootload传递进来的mov r8, r2 @ 保存参数列表atags指针r1和r2中分别存放着由bootloader传递过来的architectureID和指向标记列表的指针。
这里将这两个参数先保存。
#ifndef __ARM_ARCH_2__/** Booting from Angel - need to enter SVC mode and disable* FIQs/IRQs (numeric definitions from angel arm.h source).* We only do this if we were in user mode on entry.*/读取cpsr并判断是否处理器处于supervisor模式——从bootload进入kernel,系统已经处于SVC32模式;而利用angel进入则处于user模式,还需要额外两条指令。
之后是再次确认中断关闭,并完成cpsr写入Angel 是ARM的调试协议,一般用的是MULTI-ICE。
ANGLE 需要在板子上有驻留程序,然后通过串口就可以调试了。
用过的AXD或trace调试环境的话,对此应该比较熟悉。
not_angel: //若不是通过angel调试进入内核mrs r2, cpsr @ turn off interrupts toorr r2, r2, #0xc0 @ prevent angel from runningmsr cpsr_c, r2 //这里将cpsr中I、F位分别置“1”,关闭IRQ和FIQ#elseteqp pc, #0x0c000003 @ turn offinterrupts常用TEQP PC,#(新模式编号)来改变模式#endif另外链接器会把一些处理器相关的代码链接到这个位置,也就是arch/arm/boot/compressed/head-xxx.S文件中的代码。
在高通平台下,这个文件是head-msm.S连接脚是compress/vmlinux.lds,其中部分内容大致如下,在连接时,连接器根据每个文件中的段名将相同的段合在一起,比如将head.S和head-msm.S的.start段合在一起SECTIONS{. = TEXT_START;_text = .;.text : {_start = .;*(.start)*(.text)*(.text.*)*(.fixup)*(.gnu.warning)*(.rodata)*(.rodata.*)*(.glue_7)*(.glue_7t)*(.piggydata). = ALIGN(4);}_etext = .;}下面即进入.text段.textadr r0, LC0 //当前运行时LC0符号所在地址位置,注意,这里用的是adr指令,这个指令会根据目前PC的值,计算符号相对于PC的位置,是个相对地址。
之所以这样做,是因为下面指令用到了绝对地址加载ldmia指令,必须要调整确定目前LC0的真实位置,这个位置也就是用adr 来计算ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp}subs r0, r0, r1 @ //这里获得当前LCD0实际地址与链接地址差值//r1即是LC0的连接地址,也即由vmlinux.lds定位的地址//差值存入r0中。
beq not_relocated //如果相等不需要重定位,因为已经在正确的//地址运行了。
重定位的原因是,MMU单元未使能,不能进行地址映射,必须要手工重定位。
下面举个简单例子说明:如果连接地址是0xc0000000,那么LC0的连接地址假如连接为0xc0000010,那么LC0相对于连接起始地址的差为0x10,当此段代码是从0xc0000000运行的话,那么执行adrr0,LC0的值实际上按下面公式计算:R0=PC+0x10,由于PC=连接处的值,可知,此时是在ram 中运行,同理如果是在不是在连接处运行,则假设是在0x00000000处运行,则R0=0x00000000+0x10,可知,此时不是在ram的连接处运行。
上面这几行代码用于判断代码是否已经重定位到内存中,LC0这个符号在head.S中定义如下,实质上相当于c语言的全局数据结构,结构的每个域存储的是一个指针。
指针本身的值代表不同的代码段,已经在顶层连接脚本vmlinux.lds里进行了赋值,比如_start是内核开始的地址.type LC0, #objectLC0: .word LC0 @ r1//这个要加载到r1中的LC0是链接时LC0的地址.word __bss_start @ r2.word _end @ r3.word zreladdr @ r4.word _start @ r5.word _got_start @ r6.word _got_end @ ip.word user_stack+4096@ sp通过当前运行时LC0的地址与链接器所链接的地址进行比较判断。
若相等则是运行在链接的地址上。
如果不是运行在链接的地址上,则下面的代码必须修改相关地址,进行重新运行/** r5 - zImage base address* r6 - GOT start* ip - GOT end*///修正实际运行的位置,否则跳转指令就找不到相关代码add r5, r5, r0 //修改内核映像基地址add r6, r6, r0add ip, ip, r0 //修改got表的起始和结束位置#ifndef CONFIG_ZBOOT_ROM/*若没有定义CONFIG_ZBOOT_ROM,此时运行的是完全位置无关代码位置无关代码,也就是不能有绝对地址寻址。
所以为了保持相对地址正确,需要将bss段以及堆栈的地址都进行调整* r2 - BSS start* r3 - BSS end* sp - stack pointer*/add r2, r2, r0add r3, r3, r0add sp, sp, r0//全局符号表的地址也需要更改,否则,对全局变量引用将会出错1: ldr r1, [r6, #0] @ relocate entries in the GOTadd r1, r1, r0 @ table. This fixes up thestr r1, [r6], #4 @ C references.cmp r6, ipblo 1b#else //若定义了CONFIG_ZBOOT_ROM,只对got表中在bss段以外的符号进行重定位1: ldr r1, [r6, #0] @ relocate entries in the GOTcmp r1, r2 @ entry < bss_start ||cmphs r3, r1 @ _end < entryaddlo r1, r1, r0 @ table. This fixes up thestr r1, [r6], #4 @ C references.cmp r6, ipblo 1b#endif如果运行当前运行地址和链接地址相等,则不需进行重定位。
直接清除bss段not_relocated: mov r0, #01: str r0, [r2], #4 @ clear bssstr r0, [r2], #4str r0, [r2], #4str r0, [r2], #4cmp r2, r3blo 1b之后跳转到cache_on处bl cache_oncache_on定义.align 5cache_on: mov r3, #8 @ cache_on functionb call_cache_fn把r3的值设为8。
这是一个偏移量,也就是索引proc_types中的操作函数。
然后跳转到call_cache_fn。
这个函数的定义如下:call_cache_fn:adr r12, proc_types //把proc_types的相对地址加载到r12中#ifdef CONFIG_CPU_CP15mrc p15, 0, r6, c0, c0 @ get processor ID #elseldr r6, =CONFIG_PROCESSOR_ID#endif1: ldr r1, [r12, #0] @ get valueldr r2, [r12, #4] @ get maskeor r1, r1, r6 @ (real ^ match)tst r1, r2 @是否和CPU ID 匹配?addeq pc, r12, r3 @用刚才的偏移量,查找//到cache操作函数,找到后就执行相关操作,比如执行b __armv7_mmu_cache_on//add r12, r12, #4*5 //如果不相等,则偏移到下个proc_types结构处b 1baddeq pc, r12, r3 @ call cache functionproc_type的定义如下,实质上还是一张数据结构表.type proc_types,#objectproc_types:.word 0x41560600 @ ARM6/610.word 0xffffffe0b __arm6_mmu_cache_off @ works, but slowb __arm6_mmu_cache_offmov pc, lr@ b __arm6_mmu_cache_on@ untested@ b __arm6_mmu_cache_off@ b __armv3_mmu_cache_flush.word 0x00000000 @ old ARM ID.word 0x0000f000mov pc, lrmov pc, lrmov pc, lr.word 0x41007000 @ ARM7/710.word 0xfff8fe00b __arm7_mmu_cache_offb __arm7_mmu_cache_offmov pc, lr.word 0x41807200 @ ARM720T (writethrough).word 0xffffff00b __armv4_mmu_cache_onb __armv4_mmu_cache_offmov pc, lr.word 0x41007400 @ ARM74x.word 0xff00ff00b __armv3_mpu_cache_onb __armv3_mpu_cache_offb __armv3_mpu_cache_flush.word 0x41009400 @ ARM94x.word 0xff00ff00b __armv4_mpu_cache_onb __armv4_mpu_cache_offb __armv4_mpu_cache_flush.word 0x00007000 @ ARM7 IDs.word 0x0000f000mov pc, lrmov pc, lrmov pc, lr@ Everything from here on will be the new ID system..word 0x4401a100 @ sa110 / sa1100.word 0xffffffe0b __armv4_mmu_cache_onb __armv4_mmu_cache_offb __armv4_mmu_cache_flush.word 0x6901b110 @ sa1110.word 0xfffffff0b __armv4_mmu_cache_onb __armv4_mmu_cache_offb __armv4_mmu_cache_flush@ These match on the architecture ID.word 0x00020000 @.word 0x000f0000 //b __armv4_mmu_cache_onb __armv4_mmu_cache_on //指令的地址b __armv4_mmu_cache_offb __armv4_mmu_cache_flush.word 0x00050000 @ ARMv5TE.word 0x000f0000b __armv4_mmu_cache_onb __armv4_mmu_cache_offb __armv4_mmu_cache_flush.word 0x00060000 @ ARMv5TEJ.word 0x000f0000b __armv4_mmu_cache_onb __armv4_mmu_cache_offb __armv4_mmu_cache_flush.word 0x0007b000 @ ARMv6.word 0x0007f000b __armv4_mmu_cache_onb __armv4_mmu_cache_offb __armv6_mmu_cache_flush.word 0 @ unrecognised type.word 0mov pc, lrmov pc, lrmov pc, lr.size proc_types, . - proc_types找到执行的cache函数后,就用上面的addeq pc, r12, r3直接跳转,例如执行下面这个处理器结构的cache函数__armv7_mmu_cache_on:mov r12, lr //注意,这里需要手工保存返回地址!!这样做的原因是下面的bl指令会覆盖掉原来的lr,为保证程序正确返回,需要保存原来lr的值bl __setup_mmumov r0, #0mcr p15, 0, r0, c7, c10, 4 @ drain write buffermcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBsmrc p15, 0, r0, c1, c0, 0 @ read control regorr r0, r0, #0x5000 @ I-cache enable, RR cache replacementorr r0, r0, #0x0030bl __common_mmu_cache_onmov r0, #0mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBsmov pc, r12 //返回到cache_on这个函数首先执行__setup_mmu,然后清空write buffer、I/Dcache、TLB.接着打开i-cache,设置为Round-robin replacement。