流行启动流程
- bl1阶段是boot rom,固化在irom,这个没什么好说的
- bl2是uboot编译出来的SPL uboot,专门用于第二阶段启动的,SPL就是瘦身版本的uboot
- bl31 我们这里采用Arm Trusted Fireware(ATF)源码编译出来的bl31,这个是arm公司提供的开源代码,回头我们专门写篇文章来讲它
- bl32没有,bl33就是bootloader,这里我们是uboot
- bl33 uboot后面让它来引导linux操作系统内核
总的来说,后面我们需要3个文件,分别是:编译ATF得到BL31, uboot编译得到spl-uboot和完整uboot,然后再将这三个文件合并成一个最终文件,写入TF卡启动运行。
uboot移植的方式一般移植uboot有以下几种方式:
- 找Orange PI 3这款硬件公司其已经配置修改好的uboot代码,编译运行就行
- 找Das UBOOT官方的主线代码结合目标硬件平台自己修改配置,这个要求高一下,要求必须熟悉uboot,这种方式也更具挑战性
以第一种方式,其实硬件公司给我们提供了现场的uboot代码,https://github.com/orangepi-xunlong/OrangePiH6_uboot 。
当然这里我选择第二种方式,也就是将来无论拿过来一款新的开发板,我们都可以以此相同的步骤进行移植,第二种方式更有普遍性。
第二种方式主线移植也分两种情况来区别对待:
- 如果uboot主线版本代码已经合入Orange PI 3开发板相关代码,那就非常简单,和上面说的第一种方式移植一样,下载代码编译运行即可。
- 如果主线最新版本没有合入Orange PI 3开发板相关代码,那就需要找一款主控芯片也是全志H6的开发板作参考,基于参考板子进行配置,修改代码,编译再运行。
为什么要找主控芯片一致的开发板作为基础进行移植?主要是为了减轻工作量,因为这样主控相关代码大多不需要修改,只是对两个板子硬件上有差异的地方进行配置修改即可,比如常见像RAM或者EMMC或者外设硬件相关代码的配置修改。
我们从 Das uboot的官方代码仓:https://source.denx.de/U-Boot/u-boot/ 文件搜索开发板名称oange pi 3,我们可以看到相关的defconfig默认配置文件以及设备树文件都有了,很明显最新2023.10-rc4-00031版本已经支持该开发板,这样我们工作量就小很多,下面就是按部就班的下载源码,配置,编译,运行了。
搜索仓库
下面我们按照工具安装,下载代码,配置,编译,运行的一般步骤走起来。
安装交叉编译工具链为了编译U-Boot,您需要一个适合您的主机平台的编译器。如果您不是在目标平台上构建,则还需要 GCC 交叉编译器。
这里我们选择gcc工具链,工具链的安装搭建请参考官方文档:https://u-boot.readthedocs.io/en/latest/build/gcc.html
我的编译主机是Ubuntu22.04,是基于 Debian的。目标平台硬件主控芯片是全志H6,查看芯片手册,cpu 核心是Quad-Core ARM cortex-A53,架构是ARMV8 64.
体系结构
在基于 Debian 的系统上,交叉编译器包名为 gcc--linux-gnu。
可以使用以下命令安装 GCC 和适用于 ARMv8 架构的 GCC 交叉编译器
sudo apt-get install gcc gcc-aarch64-linux-gnu
可能需要依赖包
sudo apt-get install bc bison build-essential coccinelle \
device-tree-compiler dfu-util efitools flex gdisk graphviz imagemagick \
liblz4-tool libgnutls28-dev libguestfs-tools libncurses-dev \
libpython3-dev libsdl2-dev libssl-dev lz4 lzma lzma-alone openssl \
pkg-config python3 python3-asteval python3-coverage python3-filelock \
python3-pkg-resources python3-pycryptodome python3-pyelftools \
python3-pytest python3-pytest-xdist python3-sphinxcontrib.apidoc \
python3-sphinx-rtd-theme python3-subunit python3-testtools \
python3-virtualenv swig uuid-dev
ubuntu命令行运行以下指令,如果正常出现版本信息那就表示GCC交叉工具链安装正确了。
aarch64-linux-gnu-gcc --version
版本信息
下载代码下载步骤可以参考Das Uboot官方文档,https://u-boot.readthedocs.io/en/latest/build/source.html。
您可以通过以下方式下载源代码
git clone https://source.denx.de/u-boot/u-boot.git
或者Github 上维护着源镜像
git clone https://github.com/u-boot/u-boot
不加分支默认下载最新代码。
编译代码源码编译过程参考Uboot官方文档https://u-boot.readthedocs.io/en/latest/board/allwinner/sunxi.html。
基于全志 SoC 的开发板对于所有使用基于 Allwinner ARM 的 SoC(“sunxi”)的开发板,U-Boot 编译系统会生成单个集成镜像文件:u-boot-sunxi-with-spl.bin. 该文件可用于 SD 卡、eMMC 设备、SPI 闪存以及基于 USB-OTG 的启动方法(FEL)。
要编译出此文件:
- 对于 64 位 SoC,首先要编译出可信固件(TF-A,以前称为 ATF),您将需要其bl31.bin. 请参阅下面的更多细节。
- (可选)在 64 位 SoC 上编译出the crust management processor firmware,也就是scp.bin文件.,这个文件是可选,这里我没有用这个bin文件。
- 编译uboot镜像uboot.bin文件通用步骤:
$ export BL31=/path/to/bl31.bin # required for 64-bit SoCs
$ export SCP=/path/to/scp.bin # optional for some 64-bit SoCs
$ make <yourboardname>_defconfig #生成开发板配置
$ make #编译uboot.bin
The traditional SD card location the Allwinner BootROM loads from is 8KB (sector 16). This works fine with the old MBR partitioning scheme, which most SD cards come formatted with. However this is in the middle of a potential GPT partition table, which will become invalid in this step. Newer SoCs (starting with the H3 from late 2014) also support booting from 128KB, which is beyond even a GPT and thus a safer location.
从上面通用编译步骤看出,要编译出uboot.bin必须要用到bl31.bin文件,scp.bin文件可选,主要是要将它们一起合并到一个最终uboot.bin文件。
编译bl31.bin(ATF)使用 64 位 Soc(A64、H5、H6、H616、R329)的主板需要 bl31阶段的Arm Trusted Firmware-A固件 。这为 Armv8-A 提供了安全软件环境,并提供 PSCI 和 SMCCC 服务。全志支持已完全主流化。编译 bl31.bin:
git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
cd trusted-firmware-a
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_h6 DEBUG=1 bl31
A64 和 H5 SoC 的目标平台 ( PLAT=) 为 sun50i_a64,H6 sun50i_h6、H616 sun50i_h616 和 R329 sun50i_r329 的目标平台为 sun50i_a64。使用:
$ find plat/allwinner -name platform.mk
查找所有支持的平台。TF-A 的docs/plat/allwinner.rst包含更多信息并列出了一些编译选项。
编译完成之后会生成bl31.bin文件
$ export BL31=$(pwd)/build/sun50i_h6/debug/bl31.bin
因为我们这里没用scp.bin,所以这里就不需要生产它了。
配置编译代码之前我们要选择开发板相关配置项,上面我们查找过,最新版本uboot项目中是存在orange pi 3的默认配置文件的。
通过运行以下指令,我们可以查看,
git grep -l sun50i-h6-orangepi-3 configs
可以看到在configs目录下是存在orangepi_3_defconfig默认配置文件的,使用它即可生成配置文件.config.
make orangepi_3_defconfig
编译
- 对于 64 位板,这需要设置 BL31 环境变量BL31,找到上面生成的bl31.bin的位置(如上面 TF-A 编译示例中所示),或者在编译命令行上提供
- 同时还要制定使用的交叉编译器前缀CROSS_COMPILE=aarch64-linux-gnu-
- 因为scp.bin文件我们没用,所以要指定为/dev/null,即SCP=/dev/null,否者会提示Image 'u-boot-sunxi-with-spl' is missing external blobs and is non-functional: scp错误
make CROSS_COMPILE=aarch64-linux-gnu- BL31=/home/albert/Documents/h6/arm-trusted-firmware-master/build/sun50i_h6/debug/bl31.bin SCP=/dev/null
编译完成之后,顶层目录下会生成u-boot-sunxi-with-spl.bin文件,这个就是最终文件,里面包含ATF和SPL和uboot主体还有设备树。