- 启动过程图解
armv8平台单板启动大体上可以分为两类:1. 没有ATF(ARM Trusted Firmware)情况下的启动;2. 有ATF情况下的启动。
没有ATF的启动过程比较简单,没什么说的。

有ATF的情况下,启动过程比较复杂,根据BL2运行级别,又可以分为两种情况:1. BL2运行于EL3异常级别;2. BL2运行于EL1异常级别。


- 各部分作用
bootrom:每一个芯片都会有一个片内ROM,在出厂时厂家在其中固化好了一段代码,不可更改。
bootrom完成了哪些任务?
初始化最小运行系统,包括时钟初始化、片内SRAM初始化以及一些芯片级外设的初始化。
加载spl或者EL2到片内SRAM。
spl或者EL2被下载到片内SRAM后,CPU控制权移交给spl或EL2,ROM-Code任务结束。
spl:Secondary programloader, 因为芯片厂商固化的ROM支持从nandflash, SDCARD等外部介质启动,所以RomBoot会根据硬件电路的启动模式选择读取对应介质一小段数据到片内内存。RomBoot读取多少才算合适呢?每个用户的需求不一样,大小也不能确定。很多芯片厂商干脆就只读4K/8K/16K等很小一段数据。这段数据你可以存放芯片初始化,读取介质数据到内存的工作是完全没有问题的。就这样在我们的软件界就产生了一个SPL概念,RomBoot读取这一小段代码就叫spl。
SPL(Secondary programloader)是uboot第一阶段执行的代码。主要负责搬移uboot第二阶段的代码到系统内存(System Ram,也叫片外内存)中运行。
spl需要负责片外内存的初始化,还要从存储设备如norflash,emmc加载uboot镜像,因此,还要负责这些外设的初始化。
BL1、BL2、BL31、BL32、BL33:ATF的源代码共分为BL1、BL2、BL31、BL32、BL33部分,其中BL1、BL2、BL31部分属于固定的固件,BL32和BL33分别用于加载TEE和REE侧的镜像。
BL1对应的就是bootrom里面固化的代码。
BL2对应的就是SPL。
BL1是信任链的根所在,一般是固化在芯片内部的一段代码,叫做bootrom,具有最高的执行权限EL3,在 CPU 出厂时就被写死了。
BL2既可以运行在EL3特权级别的,也可以运行在EL1级别。BL2在flash中的一段可信安全启动代码,它的可信建立在BL1对它的验证,主要完成一些平台相关的初始化,比如对ddr的初始化等,然后负责加载BL31、BL32、BL33镜像。
BL31作为EL3最后的安全堡垒,它不像BL1和BL2是一次性运行的,会常驻内存。它通过SMC指令为Non-Secure持续提供设计安全的服务,在Secure World和Non-Secure World之间进行切换。它的主要任务是找到BL32,验签,并运行BL32。常见的PSCI(Power State Coordination Interface)功能是在ATF的BL31上实现。
BL32是Trust OS, 一般在BL32会运行Trust OS + 安全app,它是一个可信安全的OS运行在EL1并在EL0启动可信任APP(如指纹信息,支付应用的密码等),并在Trust OS运行完成后通过SMC指令返回BL31,BL31切换到Non-Seucre World继续执行BL33。
BL33就是Normal Wrold了,运行的都是非安全固件,也就是我们常见的UEFI firmware或者u-boot,也可能是直接启动Linux kernel。启动BL1,BL2,BL31,BL32则是一个完整的ATF信任链建立流程(ARM Trusted Firmware)。
-
spl和uboot启动流程
设置异常向量表;
进入特权模式;
关闭看门狗;
关闭中断;
使I/D cache失效,关闭MMU。(此时是在片内内存上运行,外部内存还没使用,关闭cache和MMU,避免发生不可预料的错误)
RAM初始化;
uboot代码加载;
设置堆栈,清除BSS段。(局部变量不设置初始值的时候,其初始值是不确定的,需要清0)
跳转到uboot第二阶段运行。
Uboot第二阶段完成soc初始化,并把自己从RAM低端地址拷贝到RAM高端地址,把低端地址留给操作系统。(可选)
uboot完成地址重定向,在RAM高端地址继续运行。
uboot把OS从Flash中加载到RAM的低地址空间段。
uboot调整到os, 在RAM的低地址空间段执行OS。 -
uboot传参给kernel
uboot事先将准备好的传参(字符串,就是bootargs)放在内存的一个地址处(就是bi_boot_params),然后uboot就启动了内核(uboot在启动内核时真正是通过寄存器r0 r1 r2来直接传递参数的,其中有一个寄存器中就是bi_boot_params)。内核启动后从寄存器r2中读取bi_boot_params就知道了uboot给我传递的参数到底在内存的哪里。然后自己去内存的那个地方去找bootargs。


565

被折叠的 条评论
为什么被折叠?



