一、嵌入式Linux的启动过程
uboot启动分为了三个阶段BL0、BL1、BL2。
系统上电后,会先启动片内iROM(芯片固化的启动程序 BL0)的程序,这部分程序主要完成初始化时钟、看门狗等外围器件,并将u-boot的头4k的内容(BL1)加载到片内RAM中运行。BL1的任务是配置好SDRAM,再将BootLoader的大部分(BL2,200k)加载到SDRAM,最后将程序跳转到BL2进行运行。BL2的任务是将Booting Device中的操作系统镜像、根文件系统加载到SDRAM中,并跳转到OS的入口处。
图中 RomBoot表示 BL0,SPL表示BL1,U-Boot表示BL2。
1、BL0(RomBoot):
RomBoot是厂商固化在SOC内部存储器的一小段程序,类似于PC机上的BIOS引导程序。SPL是由固化在芯片内部的 RomBoot 引导的。我们知道很多芯片厂商固化的ROM支持从nandflash、SDCARD等外部介质启动。所谓启动,就是从这些外部介质中搬移一段固定大小(4K/8K/16K等)的代码到内部RAM中运行。这里搬移的就是SPL。
RomBoot主要的工作内容包括:
(1)初始化部分硬件。
(2)启动模式boot mode选择。
(3)读取外部固件中的BL1(SPL)程序到片内RAM。
(4)跳转到RAM去执行这段SPL程序,把控制权交给用户程序。
(5)另外可能还有厂商的测试程序;以及为了安全性考虑,检查和加密解密外部导入的固件。
2、BL1(SPL):
- SPL(Secondary programloader)是uboot第一阶段执行的代码。主要负责搬移uboot第二阶段的代码到系统内存(System Ram,也叫片外内存DDR)中运行。
- SPL复用的是uboot里面的代码。
- SPL的主要功能就是衔接系统的硬件SRAM和u-boot之间的纽带。
怎么编译SPL呢?
SPL复用的是uboot里面的代码,那要生成我们所需要的SPL目标文件,我们又该如何下手呢?很容易想到,通过编译选项 CONFIG_SPL_XXX 便可以将SPL和uboot代码分离、复用。这里所说的编译选项便是CONFIG_SPL_BUILD,在make Kconfig的时候使能。最终编译生成的SPL二进制文件有u-boot-spl,u-boot-spl.bin以及u-boot-spl.map。
(切记SPL不能太大,不然RomBoot无法读取完整,有些你写在spl功能就无法读到内存)
3、BL2(U-BOOT):
uboot运行在DDR中,则不受空间大小限制,可以进行复杂的操作。支持包括不同文件系统、脚本执行、多种操作系统加载等等操作。其中主要的工作是从存储设备中读取kernel,解析后跳转到kernel执行。
4、Linux Kernel
linux这里包括kernel和rootfs两部分,kernel进行系统组件初始化、设备初始化,在一切准备就绪后,调用第一个用户空间程序init进行用户空间初始化。
二、分析打印信息
-- Boot from SD card --
sdio initialize done.
sd card read done.
------------------------------->bootrom-spl分割线,以上是RomBoot输出内容,从存储介质中读取spl到片内RAM中,并判断magic number。
U-Boot SPL 2016.07-00058-g6c3df97-dirty (Aug 03 2019 - 10:57:57)
Boot reason: >(Normal).
ddr4 2400 4GB init...
...
Welcome to SPL!Load U-Boot from SD ...
---------------------------------->spl-uboot分割线,以上是spl运行阶段,主要进行pll、时钟、串口等初始化;
---------------------------------->最主要的是初始化了DDR以及从存储介质中将uboot加载到DDR中。
U-Boot 2016.07 (Jul 24 2019 - 20:13:09 +0800)DeepEye1000
DRAM: 3.9 GiB
MMC: deepeye_sdhci: 0, deepeye_sdhci: 1
Using default environment
...
## Booting kernel from Legacy Image at 86000000 ...
Image Name: Linux-4.9.56
Image Type: Sandbox Linux Kernel Image (gzip compressed)
Data Size: 4921279 Bytes = 4.7 MiB
Load Address: 80000000
Entry Point: 80000000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
dtb_load_addr: 0x8F000000
Starting kernel ...
----------------->uboot-linux分割线,以上是uboot。
----------------->uboot相较于spl功能更加丰富。提供了丰富的命令,可以操作文件系统、脚本、加载不同操作系统等等。
[ 0.000000] Linux version 4.9.56 (al@al-B250-HD3) (gcc version 6.3.0 (C-SKY Tools V3.8.10-kstq-nd-r2 Glibc-2.9
[ 0.000000] C-SKY: https://github.com/c-sky/csky-linux
[ 0.000000] Phys. mem: 4032MB
...
[ 4.382887] Freeing unused kernel memory: 276k freed
[ 4.387879] This architecture does not have kernel memory protection.
[ 4.702756] EXT4-fs (mmcblk1p2): re-mounted. Opts: nodelalloc,data=journal
Starting mdev...
Starting network: OK
...----------------->linux包括kernel和rootfs,内核中初始化了外设、操作系统组件、挂载了文件系统,并调用init初始化用户空间环境。