Android启动流程

本文详细描述了从RomCode启动到Android系统启动的完整流程,涉及CPU初始化、模式判断、SecureBoot验证、eMMC和SPL加载、ATF与LK引导、kernel启动以及多个模块的初始化和功能开启,如AudioDSP和WCN。
摘要由CSDN通过智能技术生成

目录

一、romcode启动

一、CPU与Chip初始化阶段

二、模式判断阶段

三、Security(安全) 启动阶段

二、emmc启动

一、emmc初始化

二、emmc boot

三、SPL 备份功能

四、Secure Boot

三、SPL启动

四、ATF启动

五、LK启动

六、kernel启动

一、Kernel 启动依赖的模

二、 Kernel 引导的模块

三、kernel模块加载

七、Android 启动

一、init第一阶段FirstStageMain

二、nit 第二阶段 SecondStageMain

八、WCN 启动

一、上电校准

二、业务开启

九、Audio DSP 启动

十、系统分区

一、romcode启动

CPU与Chip初始化阶段

在这一阶段中,RomCode 初始化所需的模块,包括 UART、Keypad、eFuse(非易失性存储器件)、CE(安全模块)、TrustZone(安全执行环境)、Timer和 Pin。

二、模式判断阶段

RomCode 会根据外部信号如 PTEST_FUNC_MODE 进入 Ptest 模式,再根据按键判断是否进入 SD Boot 等模式。如果是 Key[0][1],则从 SD Card 读取 bootloader,否则进入 Download 模式。

在 Download 模式下,进一步判断 USB Download 是否使能。

USB Download 使能,则进行 USB 下载。

USB Download 未使能,则监控 UART0 和 UART1。如有一个 UART 口接收到 3 个 0x7E 数据包则使用该 UART 口进行下载,如果 80ms 内没有 UART 收到 3 个 0x7E数据包就会下载超时,超时后会回到正常启动模式。

在正常启动模式下,RomCode 会根据 Strapping Pins 判断是 eMMC、SD 或是 UFS 启动。

eMMC 平台:RomCode 会从 eMMC 卡的 Boot0 分区中读取 70KB 的 bootloader 到 Share Memory 中。如果读取失败则尝试从 Boot1 分区重新读取 bootloader。

SD 平台:RomCode 读取 SD 卡 0x10000 开始位置 70KB 的 bootloader 到 Share Memory。如果读取失败则重新读取一次。

UFS 平台:RomCode 读取 UFS BootA 分区 70KB bootloader 到 Share Memory。如果读取失败则尝试从 BootB 分区重新读取 70KB bootloader。

注:当eMMC上电后,SOC可以通过简单的协议来读取eMMC存储设备中的数据。通常情况下,SOC的ROM代码会在上电后将eMMC BOOT分区的内容加载到SOC内部的SRAM中执行。

三、Security(安全) 启动阶段

Secure Boot 使能,则对 Read 和 Download 数据进行 HASH 和 RSA 校验,校验成功则跳转到对应模式的起始地址运行。Secure Boot 未使能,则直接跳转对应模式的起始地址运行。

、emmc启动

在 eMMC 启动时,RomCode 需要通过 eMMC 控制器读取 eMMC 卡 Boot 分区的前 70KB 数据到 IRAM(soc内部ram)后才开始运行。

一、emmc初始化

打开 eMMC AHB clock,配置 eMMC 使用的 Pin,设置 base clock 为 26MHz;设置 SD clock 为小于或等于 380kHz;设置 eMMC 控制器为默认的 SDR12 模式;设置 bus width 为 1bit 模式。

  • emmc初始化过程
  • 发送 CMD0 使 eMMC 进入 idle (空闲)状态.
  • 发送 CMD1 确认 eMMC 是否已经 ready,并且判断是否是高容量(大于或等于 2GB)eMMC。
  • 发送 CMD2 读 CID。
  • 发送 CMD3 设置 relative address(相对地址)。
  • 发送 CMD9 读取 CSD(卡的容量、最大读取/写入速度、支持的命令集)。
  • 发送 CMD7 选中 eMMC。
  • 设置 block size 为 512Byte。

二、emmc boot

设置 base clock 为 26MHz,初始化时 380kHz,300kHz,200kHz,100kHz 轮询,传输数据时设置eMMC clock 为 6.5MHz。

设置使用分区为 Boot0 或 Boot1,并发送 CMD18 从分区中读取 SPL,做哈希校验。Boot0 和 Boot1 内容相同,如果 Boot0 校验失败,则使用 Boot1。

三、SPL 备份功能

eMMC Boot 先从 Partition0 分区中读取 SPL进行校验,如果校验成功,则进入 Secure Boot 流程,如果校验失败,则开始读取 Partition1 分区中的 SPL。

四、Secure Boot

Secure Boot是一种安全机制,用于确保系统启动过程中加载的软件镜像是经过验证且未被篡改的。使用加密算法去检验image文件是否被篡改。

三、SPL启动

SPL启动需要运行 Spl.bin,它存放于 eMMC 物理分区 Boot1 和 Boot2 中。执行过程如下:

RomCode 通过 Flash 控制器接口,从 Flash 读取 Spl.bin 到 IRAM 上。

对 Spl.bin 进行验证,验证完成后程序跳转到 Spl.bin 运行。

一旦BOOT分区的内容被加载,SPL(Secondary Program Loader)即开始执行。SPL负责初始化必要的硬件环境,为加载后续的引导加载程序(如U-Boot)做准备。其次,SPL还可能负责识别和驱动一些基本的硬件设备,比如内存(DDR)、串口等,以便能够进行基本的数据读写操作和调试输出。在某些情况下,SPL还可以进行一些安全性检查,例如校验数据的完整性或解密加密的启动数据。

四、ATF启动

SPL执行完 DDR 等硬件的初始化动作后,从 SML分区加载 ATF(ARM可信固件)、TOS(安全启动组件) 和 LK image 文件,然后跳转到ATF 入口代码开始在 DDR 上运行 ATF。

说明:ATF 启动过程中,如需支持 TOS,则会启动 TOS。TOS 启动完成后,再返回到 ATF 运行。如果无需支持 TOS,则 ATF 启动的最后阶段会跳转到 LK 入口代码启动 LK。

五、LK启动

lk.bin 由 sml-sign.bin 和 u-boot-spl-16k-sign.bin 加载,并且在 sml-sign.bin 执行完后跳转运行。

启动流程内部架:

Board Init

arm_reset:主要完成 bss 清除、栈设置等底层初始化,由汇编来完成,之后跳转到 lk_main 函数(C 语言)。

lk_main:完成线程初始化(thread_init_early);cache、mmu 初始化;使能(arch_early_init)早期驱动(如 serial、trace 等);创建 heap、bootstrap2 线程,为后面运行构建完整的 C 代码运行环境。

bootstrap2:完成 chipram参数获取(platform_init);外围设备(如 regulator、Flash、keypad等)初始化(target_init);Log 系统初始化,并进入 App_init。

App Init

当前内部仅注册一个 Appsprdboot

do<Select Mode>

选择启动模式并执行:

Calibration模式:这个模式主要用于系统校准,比如电池电量的校准或触摸屏的校准。通常这不是一个常规用户会频繁使用的模式,但对于设备维护和调试来说可能很重要。

Recovery模式:当用户按下特定组合键(通常是音量加键+电源键)时,系统会进入恢复模式,即recovery模式。在这种模式下,用户可以进行系统恢复操作,如清除数据/恢复出厂设置、从SD卡安装更新、应用备份和还原等。这相当于Android系统的一个维护模式,允许用户在系统出现问题时进行修复操作。

Fastboot模式:也称为快速启动模式,当用户按下另一组特定组合键(如音量减键+电源键)或者通过adb指令时,系统会进入此模式。在这个模式下,可以进行刷机操作,即通过电脑端软件将新的系统镜像文件安装到设备的EMMC存储中。它常用于刷新设备固件或在更深层次上对设备进行修改。

多核启动:

LK project/<board>.mk 中配置 WITH_SMP:=1 开启多核启动。

多核启动流程说明:

arch_init()中 core0 为多核创建 secondarybootstrap2 线程,用于线程切换和下电使用。

遍历 boot funcs,根据 boot funcs 返回结果进入对应模式。如果进入的模式为 normal_mode(),则进行多核操作。

调用 secondary_cpu_poweron()给多核上电,多核上电后会执行到 secondarybootstrap2 线程中等待core0 创建完成实际任务。

 core0 调用 secondary_task_create()创建每个核要执行的线程,最后将 thread_created_lock 置位。

如果多核在 secondarybootstrap2 线程中判断出 thread_created_lock 被置位,则进行线程切换执行对应的任务,开始正式的多核并行处理。

core0 执行 boot_load 线程从 Flash 中加载 boot.img 和 vendor_boot.img 到内存中;core1 执行 lcd_init线程进行 LCD 的初始化。

core0 执行完 boot_load 线程后会切换到 secure_verify 线程,在该线程中进行验签等操作;core1 同步执行 kernel_dtb_parse 线程来进行 Kernel 和 dtb 的处理,core1 执行完此线程后会下电。而 core0 执行线程完成后会等待 core1 下电,调用 start_linux()跳转到 Kernel 运行。

单核启动:

读取 misc 分区里的 A/B control 信息,如果信息不存在,则创建其信息。

从 logo 分区加载图片 image 进行开机 logo 显示。

从 boot_a 或 boot_b 分区读取 boot.img 的 Android header,根据 vendor_boot 和 boot image 中的 header信息,加载 ramdisk 到 DDR(memory layout 指定位置)。

根据 vendor_boot 和 boot image 中的 header 信息加载 dtb 到 DDR

从 dtbo 分区读取 dtbo 与 dtb 进行合并。

根据 vendor_boot 和 boot image 中的 header 信息,加载 initbootimage 中的 ramdisk 到 DDR。

跳转到 Kernel 入口。

六、kernel启动

一、Kernel 启动依赖的模

Kernel 启动依赖的模块有 ATF 与 LK。

在 ATF 中会完成对 CPU 及 GIC 的上电与硬件初始化工作。

在 LK 中会完成 Kernel 的引导工作和 cmdline/bootconfig 传递参数等功能。LK 会读取 Kernel 启动所必须的 boot.img 和 dtbo.img 文件,并解压到指定位置,跳转到指定地址运行 Kernel 代码。

二、 Kernel 引导的模块

Kernel 引导的模块为 Android 模块。

在 Kernel 启动的最后阶段,系统执行 ramdisk(RAM) 里 first stage init 程序,该程序位于 ramdisk 中,主要完成 fstab 的加载工作。之后改变 root 到 system,加载位于 system分区内的 second stage init 程序,该程序为Android init 进程,用于加载 Android service。

注:fstab是文件系统表(File System Table)的缩写。/etc/fstab是一个重要的系统配置文件,它存放了系统中各个存储设备和分区的静态信息,包括它们的挂载点、文件系统类型、挂载选项等。当Linux系统启动时,初始化进程(init进程)会根据/etc/inittab文件中的指示,读取/etc/fstab中的信息并自动执行文件系统的挂载操作。fstab中的每个条目都定义了一个文件系统及其相关的参数,包含:文件系统或分区的文件名、文件系统的挂载点、文件系统的文件格式等,通过这个文件,系统管理员可以控制哪些文件系统在启动时被挂载,以及它们的挂载行为。这样可以避免每次开机后手动挂载所需的分区,提高了效率和便利性。

三、kernel模块加载

内核映像加载:引导加载程序将内核映像(通常是zImage或Image)加载到内存中,并设置好相关的环境变量和参数,以便内核在启动时使用。

内核初始化:内核开始执行,并进行自身的初始化工作。这包括设置CPU、内存、外设等硬件设备的初始化,以及初始化内核内部的数据结构和功能模块。

启动设备驱动:内核会启动各种设备驱动程序,使得硬件设备能够正常工作。

挂载根文件系统:内核会挂载根文件系统(通常是ext4或其他文件系统),这是Android系统中所有其他文件系统的起点。

启动init进程:一旦根文件系统被挂载,内核会启动init进程。init进程是Android系统中的第一个进程,其PID(进程ID)为1。init进程负责进一步的系统初始化工作,包括启动各种系统服务和守护进程。

注:kernel版本不同加载机制也不同,在 Kernel5.4 和 Kernel5.15 上 ko 化的要求也有所不同,从 Kernel5.4 开始 64 位必须 ko 化,而Kernel5.15 使用的是 Google 的 image,image 没有的模块必须 ko 化。

七、Android 启动

Kernel 启动完成后,进入 Android init 启动阶段,入口在 system/core/init/main.cpp 中。Android init 启动流程中依据业务流程会多次通过 execv 来调用 system/bin/init 可执行文件,依据每次传递参数的不同整个Android init 进程启动可分为如下几个阶段:

FirstStageMain

SetupSelinux

SecondStageMain

一、init第一阶段FirstStageMain

在上述流程中,super 分区的挂载从 init 第一阶段 FirstStageMain (system/core/init/)函数开始。在 FirstStageMain 函数中,主要是进行 dev、sys、proc 等 tmpfs (临时文件系统)文件系统的挂载,并创建一些关键路径和文件,完成后再运行DoFirstStageMount 函数。

FirstStageMain 执行最后会通过 execv 重新调用可执行文件 init(参selinux_setup)来触发SetupSelinux。SetupSelinux主要是通过加载 Selinux policy 来确保 linux访问的安全性。

注:tmpfs(临时文件系统)是 Linux 内核中的一种虚拟内存文件系统,它可以用来创建临时的、非持久性的文件和目录。

execv用于替换当前的init进程映像,以执行新的system/bin/init可执行文件。execv是一个系统调用,用于在当前进程中运行一个新的程序。它将完全替换当前进程的映像、数据和堆栈等信息,用新的程序替代旧的程序继续执行。

二、nit 第二阶段 SecondStageMain

SetupSelinux通过 execv 调用可执行文件 init(参数 second_stage)来触发 init 第二阶段SecondStageMain。

PropertyInit:读取分区目录下的.prop 类型文件(例如 system/build.prop)初始化 property 属性值。

InstallSignalFdHandler:初始化 signal 句柄,用于监听 init 启动的子进程的状态变更,避免出现Zombie progress。

LoadBootScripts:解析各个分区/etc/init 目录下的“.rc”类型文件,将解析内容存入对应的数据结构(比如解析的 Service 类型语句信息会存放到 Service 链表中)供后续使用。

上述 init 启动的 service 中,对于 FrameWork 层及应用层来说最重要的进程就是 Zygote。

init 进程通过解析 init.zygote32.rc(32 位)或者 init.zygote64.rc(system/core/rootdir 64 位)配置文件来启动 Zygote 进程。Zygote 进程启动过程中会进行虚拟机的创建(startVm)以及 native 函数的注册(startReg),之后会调用ZygoteInit 完成预加载(preload)并启动 SystemServer 进程(startSystemServer负责启动和管理各种系统服务),创建 java 层的各个系统Services。

注:创建(startVm),这是为了初始化Dalvik虚拟机(运行Android应用程序的虚拟机),它是Android系统中Java应用程序的运行环境。注册(startReg),这是为了将一些C/C++函数注册到Java环境中,使得Java代码可以调用这些函数。preload预加载是指预先加载一些常用的类和资源,以便在应用程序启动时能够快速加载。

八、WCN 启动

WCN 主要包括 Wi-Fi、蓝牙、FM、GNSS 四个功能模块。

一、上电校准

系统上电初始化后 BSP Driver 进行加载,随之 GNSS/CP2 上电,获取 GNSS CP2 Firmware 路径。最后将其加载到内存中并进行校准,校准完成后 GNSS/CP2 下电。

二、业务开启

系统上电后加载蓝牙和 FM 驱动,初始化 GNSS HAL 模块。此时,可以通过 UI 界面控制各项业务(Wi-Fi 业务、蓝牙业务、FM 业务、GNSS 业务)。如果此时 Wi-Fi/蓝牙/FM 业务都未开启,那么打开任何一个业务都会重新下载 Firmware bin CP2 并启动 CP2。同样开机定位功能也会启动GNSS Firmware 的加载。Firmware bin 文件支持单分区和 AB 分区,并自动识别,主要通过文件路径后面是否加后缀或加_A 或_B 来区分业务开启流程。

九、Audio DSP 启动

如果项目存在 Audio DSP,那么它由 LK 进行加载。当 LK loader_nvm搬运分区数据时,加载 Flash 上的 Audio DSP 代码到 DDR 上的指定位置。

十、系统分区

  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值