0%

OrangePi-3B 移植 Linux —— 构建 U-Boot

OrangePi-3B 系列笔记:

温馨提示:

  1. OrangePi-3B 硬件版本 V1.1.1 的板子出现过有线网卡“无故”失灵的故障, 所以在进行操作前请确认开发板工作良好(修复这个问题需要更换 RK3566 芯片).
    https://www.bilibili.com/read/cv33224126
  2. 香橙派目前已经推出了硬件版本为 V2.1 的 OrangePi-3B, 有线网卡供应商更换为 RTL. 本系列文章没有针对 V2.1 的板子做过适配, 请根据实际情况操作(同时强烈谴责此种不负责任的行为, 如考虑购买此型号板子商用, 建议换个型号避坑).
  3. 本系列文章最后更新时间: 2026年08月24日, 实现了初始化 TEE 环境.

编译环境

  • 主板: OrangePi-3b_V1.1.1
  • 芯片: RK3566
  • 环境: Debian:13_x86_64(Docker)

启动流程

通俗理解

要研究 U-Boot,就不得不学习一下芯片是如何启动的。

玩过单片机的朋友都知道,单片机中基本是一个芯片内置了 CPUMEMFLASH,单片机的内置引导程序能够直接让 CPU 调用 MEMFLASH,用户只需要将程序写入 FLASH 就能开始运行。

但是类似 RK3566 这一类芯片则不同,它们更像是PC的CPU,芯片内除了 CPU 之外只有一些额外的控制器,不能给芯片本身下载程序;需要搭配外设才能运行,最主要的有 DRAMeMMC 下挂的各种存储设备;比如 OrangePi-3b 则是外挂了一个 DDR4 内存,存储则是支持 SDCardeMMCNVME 等设备,使用的使用用户程序则是存放在这些存储设备中。

和单片机相比,RK3566 运行指令存在于外扩的各种存储设备中,这些设备不是 XIP 设备,访问它们需要经过 eMMC 控制器,并且将其指令复制到 DRAM 中再运行;同时外扩的 DRAM 规格也各不相同,芯片难以在内嵌固件中初始化这些设备;现代芯片还需要支持芯片级的加密支持,这些任务组合在一起很难由片内固件和 SRAM 来完成(也有可能是兼容之前的方案故意为之,毕竟之前由于工艺和成本的原因,很难在片内集成大容量的 FLASHSRAM)。

XIP:eXecute In Place,即芯片内执行,指应用程序可以直接在 FLASH 闪存内运行,不必再把代码读到系统 DRAM 中。FLASH 内执行是指 NOR FLASH 不需要初始化,可以直接读取 FLASH 中的指令。

因此,目前主流的方案基本都是采用二段式加载方式启动 U-Boot

1. BootROM
2. Pre-Loader
3. U-Boot
4. Kernel
5. ...

这里的二段式启动指的是芯片固件 BootROM 不会直接加载 U-Boot,而是存在一个 Pre-Loader

通常 Pre-Loader 又细分为 TPL/SPL (Tiny Program Loader/Secondary Program Loader), 分别用来初始化 DRAM 和加载 U-Boot

相应的启动过程如下:

  • BootROM
    这是内嵌在芯片的固件,芯片出厂时已经固化,它在芯片上电时首先被执行;它的任务主要是寻找并执行存储设备设备中的 TPL(通常是 FLASH,但也能从 eMMC 下面的存储设备中加载,换句话说 BootROM 也能初始化 eMMC);这个阶段芯片使用片内自带 SRAM 作为内存运行,SRAM 速度极快但成本极高,容量普遍只有几百 KB;同时也反映了为什么会分为两次加载,因为此时没有初始化 DRAM, 只有几百 KB 大小的 SRAM, 没法完整加载 U-Boot 程序;
  • Pre-Loader
    Pre-LoaderBootROM 从存储设备中加载至 SRAM 执行,其中 TPL 负责初始化 DRAM,然后跳到 SPL 继续执行(过程中会跳回 BootROM),并寻找储存设备中合适的 U-Boot 并拷贝到 DRAM, 最后执行 DRAM 中的 U-Boot
  • U-Boot
    U-BootSPL 复制到内存并开始执行,它首先完成一次自身重定位,然后就是加载设备树并驱动更多的外设,最后就是加载并执行 KernelRootFS 了;另外支持 TEE 的设备在这个阶段还会完成 TEE 环境的初始化;
  • Kernel
    Kernel 可以看做是操作系统的入口了;

流程示意图如下:

BootROM --> TPL --> BootROM(Back) --> SPL--> U-Boot --> Kernel --> ...

由于 TPL/SPL 通常的表现为一个 Pre-Loader 产物/模块,所以可以简化一下流程:

BootROM --> Pre-Loader --> U-Boot --> Kernel --> ...

ARM Trusted Firmware (TF-A/ATF)

RK3566 是一颗基于 ARMv8 的芯片,它还需要支持 ARM Trusted Firmware (TF-A/ATF);启动过程按照 ATF 功能划分为:

Boot stage Exception level Description
BL1 EL3 Boot ROM firmwareNOTE:BL1 is embedded in hardware (Boot ROM + PBL commands)
BL2 EL3 Platform initialization firmware
BL31 EL3 Resident runtime firmware
BL32 EL1S [Optional] Trusted operating system. For example, OP-TEE
BL33 EL2 Normal world bootloader. For example, U-Boot, UEFI

它们直接的启动关系如图:
ATF启动关系.png

  1. Boot ROM (BL1)
    • CPU 从重置中释放出来时,硬件执行 PBL 命令,将用于平台初始化的 BL2 二进制文件复制到 SRAM,然后通过 PBI 命令跳转到 BL2 处执行。
    • 在成功执行 PBI 命令后,Boot ROM 将控制传递给 EL3BL2 映像。
  2. BL2
    • BL2 初始化 DRAM,配置 TZASC
    • BL2 在验证 BL31BL32BL33 镜像后加载到DDR内存中。
    • 完成组件镜像验证后,BL2 将执行控制权传递给名为 BL31EL3 运行时固件映像。
  3. BL31
    • EL3 处设置异常向量表。
    • 配置安全相关设置(TZPC)。
    • 为引导加载程序和操作系统提供服务,例如控制核心电源状态和使其他核心退出重置。
    • [可选]如果存在 BL32 镜像,则将执行控制权传递给可信操作系统(OP-TEE)镜像 BL32
  4. BL32
    • [可选]初始化后,BL32 将控制权返回给 BL31
  5. BL31
    • 将执行控制传递给引导加载程序 U-Boot/UEFI, BL33EL2
  6. BL33
    • 加载并启动内核和其他固件映像(如果有的话)。

ARMv7ARMv8 启动存在明显差异:
ARM启动差异.jpeg

https://docs.nxp.com/bundle/GUID-C3A436DA-E944-4F73-9811-2335DEBD04D6/page/GUID-9280C0B6-CE8D-411D-905C-F97483AAE047.html

瑞芯微的实现

瑞芯微采用的方案和上述基本一致,以下是瑞芯微的说明文档:

+--------+----------------+----------+-------------+---------+
| Boot   | Terminology #1 | Actual   | Rockchip    | Image   |
| stage  |                | program  |  Image      | Location|
| number |                | name     |   Name      | (sector)|
+--------+----------------+----------+-------------+---------+
| 1      |  Primary       | ROM code | BootRom     |         |
|        |  Program       |          |             |         |
|        |  Loader        |          |             |         |
|        |                |          |             |         |
| 2      |  Secondary     | U-Boot   |idbloader.img| 0x40    | pre-loader
|        |  Program       | TPL/SPL  |             |         |
|        |  Loader (SPL)  |          |             |         |
|        |                |          |             |         |
| 3      |  -             | U-Boot   | u-boot.itb  | 0x4000  | including u-boot and atf
|        |                |          | uboot.img   |         | only used with miniloader
|        |                |          |             |         |
|        |                | ATF/TEE  | trust.img   | 0x6000  | only used with miniloader
|        |                |          |             |         |
| 4      |  -             | kernel   | boot.img    | 0x8000  |
|        |                |          |             |         |
| 5      |  -             | rootfs   | rootfs.img  | 0x40000 |
+--------+----------------+----------+-------------+---------+

瑞芯微启动流程.jpg

瑞芯微根据 Pre-Loader(idbloader.img) 的开源与否规划了两种启动路线:

  • MiniLoader:
    瑞芯微对 TPL/SPL 方案闭源的实现,效果和分工与 TPL/SPL 类似:ddr.bin 负责初始化 DRAMminiloader 是一个类似 U-Boot 的引导程序;不同的是 miniloader 需要一个独立的分区来存储 TEE 的程序;
  • U-Boot(TPL/SPL):
    U-Boot 是一个通用引导程序,其中有 TPL/SPL 的开源实现;瑞芯微开源的 U-Boot 是基于公版 U-Boot 修改而来;

构建

OrangePi-3B 支持的正经官方 U-Boot 有三个:

  • 香橙派
    板子供应商,根据上游瑞芯微 U-Boot 的修改版,对板子有良好的适配;
  • 瑞芯微
    芯片供应商,使用 Mainline2017.x 版本改写的 U-Boot,增加了对 rk3566 芯片的深度支持。
  • Mainline
    主线 U-Boot,瑞芯微会不定时向主线合入对芯片的适配代码。支持度一般,但版本不受限制。

瑞芯微提供的 MiniLoader 不是成品镜像需要手动构建,但过程比较简单。

另外三种开源 U-Boot 构建类似,瑞芯微香橙派 提供了构建脚本,以下内容以主线 U-Boot 为主。

瑞芯微 MiniLoader(MiniLoaderAll.bin + trust.img)

瑞芯微 MiniLoader 是一个包含 TPLSPLATFTEE 的组件包,全套都是闭源的。用它们来引导 U-Boot 可以获得原厂性能。

其他的 U-Boot 编译时也会或多或少引用这个库下面的闭源二进制镜像。

克隆代码

cd ~/projects/bootloader/
git clone https://github.com/rockchip-linux/rkbin.git -b master

启动容器

docker run -ti --rm --privileged -v ~/projects/:/projects/ build-linux bash -l
  1. 关于镜像 build-linux 的内容请参考之前的笔记,其中已经安装构建所需要的软件包。

合成闭源的 Pre-Loader

Pre-Loader 也叫做 MiniLoaderAll.bin

cd /projects/bootloader/rkbin/
./tools/boot_merger ./RKBOOT/RK3566MINIALL.ini

合成闭源的 trust.img

cd /projects/bootloader/rkbin/
./tools/trust_merger ./RKTRUST/RK3568TRUST.ini

生成产物

  • rk356x_spl_loader_v1.xx.xxx.bin
    Loader 镜像, 即 MiniLoaderAll.bin,烧录到 Loaderidbloader 分区使用。
  • trust.img
    搭配 MiniLoaderAll.bin 使用的可信执行环境固件镜像, 烧录到 trust 分区使用。

香橙派 U-Boot

克隆代码

cd ~/projects/bootloader/
git clone https://github.com/rockchip-linux/rkbin.git -b master
git clone https://github.com/orangepi-xunlong/u-boot-orangepi.git -b v2017.09-rk3588 u-boot_orangepi

香橙派的 U-Boot 是基于的瑞芯微 U-Boot 改进而来, 需要引用 rkbin 的闭源镜像生成 idbloader;

启动容器

docker run -ti --rm --privileged -v ~/projects/:/projects/ build-linux bash -l
  1. 关于镜像 build-linux 的内容请参考之前的笔记,其中已经安装构建所需要的软件包。

启动编译

cd /projects/bootloader/u-boot_orangepi/
./make.sh CROSS_COMPILE=aarch64-linux-gnu- orangepi-3b-rk3566
  1. 香橙派 U-Boot 基于瑞芯微开源的 U-Boot2017.09 分支的代码,搭配的工具链版本不能太新(11.x 还能编译,切到 13.x 编译失败);

构建产物

  • u-boot_orangepi/rk356x_spl_loader_v1.xx.xxx.bin
    Loader 镜像, 即 MiniLoaderAll.bin,烧录到 Loaderidbloader 分区使用。
  • u-boot_orangepi/uboot.img
    U-Boot 镜像,烧录到 uboot 分区使用;

瑞芯微 U-Boot

克隆代码

cd ~/projects/bootloader/
git clone https://github.com/rockchip-linux/rkbin.git -b master
git clone https://github.com/rockchip-linux/u-boot.git -b next-dev u-boot_rockchip
  1. 瑞芯微 U-Boot 需要引用 rkbin 的闭源镜像生成 idbloader;

启动容器

docker run -ti --rm --privileged -v ~/projects/:/projects/ build-linux bash -l
  1. 关于镜像 build-linux 的内容请参考之前的笔记,其中已经安装构建所需要的软件包。

启动编译

cd /projects/bootloader/u-boot_rockchip/
./make.sh CROSS_COMPILE=aarch64-linux-gnu- rk3566
  1. 瑞芯微的 U-Boot 基于主线 2017.09 分支的代码,搭配的工具链版本不能太新(11.x 还能编译,切到 13.x 编译失败);

构建产物

  • u-boot_rockchip/rk356x_spl_loader_v1.xx.xxx.bin
    Loader 镜像, 即 MiniLoaderAll.bin,烧录到 Loaderidbloader 分区使用。
  • u-boot_rockchip/uboot.img
    U-Boot 镜像,烧录到 uboot 分区使用;

主线 U-Boot

2024-08-09 已经有人在主线提交 OrangePi 3b 的适配代码, 本文的内容可能会有无法对其的情况. 请以提交记录为准.
https://git.u-boot-project.org/u-boot/u-boot/-/commit/a52099b4a2ae9e8cafc79268325249bcad308012

主线 U-Boot 默认配置构建时,需要依赖 ATFOPTEE-OS。如果忽略依赖直接按照正常方式直接编译,会报如下错误:

Image 'simple-bin' is missing external blobs and is non-functional: rockchip-tpl atf-bl31

/binman/simple-bin/mkimage/rockchip-tpl (rockchip-tpl):
   An external TPL is required to initialize DRAM. Get the external TPL
   binary and build with ROCKCHIP_TPL=/path/to/ddr.bin. One possible source
   for the external TPL binary is https://github.com/rockchip-linux/rkbin.

/binman/simple-bin/fit/images/@atf-SEQ/atf-bl31 (atf-bl31):
   See the documentation for your board. You may need to build ARM Trusted
   Firmware and build with BL31=/path/to/bl31.bin

Image 'simple-bin' is missing optional external blobs but is still functional: tee-os

/binman/simple-bin/fit/images/@tee-SEQ/tee-os (tee-os):
   See the documentation for your board. You may need to build Open Portable
   Trusted Execution Environment (OP-TEE) and build with TEE=/path/to/tee.bin

Some images are invalid
make: *** [Makefile:1124: .binman_stamp] Error 103
  1. 对于 RK3566/RK3568 芯片,主线 U-Boot 附带的开源组件只包含了 SPLTPL 需要使用闭源的 Rockchip-TPL 固件;
  2. BL31ATF(ARM Trusted Firmware)目前可以使用瑞芯微闭源的 BL31 固件,也可以使用开源的 ATF
  3. BL32TEE(Trusted Execute Environment),基于 TrustZone 技术搭建的安全执行环境;目前只能使用闭源的 BL32 固件,开源的 OPTEE-OS,但目前不支持 rk3568
  4. ATF 是一组开源固件和引导加载程序,用于启动 ARM 架构设备。它负责引导设备,初始化硬件,启动 OPTEE-OS 以及其他运行时环境,如操作系统。
  5. OPTEE-OS 提供了 TEE 的操作系统和运行时环境。它是一个用于构建安全应用程序和服务的软件栈。
  6. OPTEE-OSATF 协同工作,用于实现设备的安全引导和可信执行环境。ATF 负责设备的初始化和引导,然后将控制权传递给 OPTEE-OS,从而确保 TEE 的安全性和可信性。这两个项目是嵌入式系统中安全和可信计算的关键组件。

截止2026年8月,ATF 已经对 RK35XX 系列芯片提供支持。但是 OPTEE-OS 仍然不支持。在笔者借助AI各种尝试之后,终于跑通了一条主线 U-Boot 驱动 TEE 的方法,目前看基本全网首发。

克隆代码

cd ~/projects/bootloader/
git clone https://github.com/rockchip-linux/rkbin.git -b master
git clone https://git.u-boot-project.org/u-boot/u-boot.git -b main
# ATF & OPTEE-OS
git clone https://github.com/ARM-software/arm-trusted-firmware.git -b master
git clone https://github.com/OP-TEE/optee_os.git -b master
  1. 主线 U-Boot 需要引用 rkbin 的闭源镜像生成 idbloader

启动容器

docker run -ti --rm --privileged -v ~/projects/:/projects/ build-linux bash -l
  1. 关于镜像 build-linux 的内容请参考之前的笔记,其中已经安装构建所需要的软件包。

驱动有线网卡

  1. 截止2026年8月,主线已经包含正常驱动网卡的设备树文件 arch/arm/dts/rk3566-orangepi-3b.dts
  2. 板子集成的 YT8531 的物理网卡芯片,YT8531RTL8211 可以片对片替换。

新建 U-Boot 配置文件

上一步骤增加了 arch/arm/dts/rk3568-orangepi-3b.dts 设备树文件,接下来新建一份属于 orangepi-3b 的编译配置文件 orangepi-3b-rk3566_defconfig

CONFIG_ARM=y
CONFIG_SKIP_LOWLEVEL_INIT=y
CONFIG_COUNTER_FREQUENCY=24000000
CONFIG_ARCH_ROCKCHIP=y
CONFIG_SPL_GPIO=y
CONFIG_SF_DEFAULT_SPEED=24000000
CONFIG_SF_DEFAULT_MODE=0x2000
CONFIG_DEFAULT_DEVICE_TREE="rk3566-orangepi-3b"
CONFIG_ROCKCHIP_RK3568=y
CONFIG_ROCKCHIP_SPI_IMAGE=y
CONFIG_SPL_SERIAL=y
CONFIG_TARGET_ORANGEPI_3B_RK3566=y
CONFIG_SYS_LOAD_ADDR=0xc00800
CONFIG_SF_DEFAULT_BUS=4
CONFIG_DEBUG_UART_BASE=0xFE660000
CONFIG_DEBUG_UART_CLOCK=24000000
CONFIG_SPL_SPI_FLASH_SUPPORT=y
CONFIG_SPL_SPI=y
CONFIG_PCI=y
CONFIG_DEBUG_UART=y
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_SPL_FIT_SIGNATURE=y
CONFIG_SPL_LOAD_FIT=y
CONFIG_LEGACY_IMAGE_FORMAT=y
CONFIG_DEFAULT_FDT_FILE="rockchip/rk3566-orangepi-3b.dtb"
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_SPL_MAX_SIZE=0x40000
# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
CONFIG_SPL_SPI_LOAD=y
CONFIG_SYS_SPI_U_BOOT_OFFS=0x60000
CONFIG_SPL_ATF=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_GPT=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_PCI=y
CONFIG_CMD_POWEROFF=y
CONFIG_CMD_RBROM=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_PMIC=y
CONFIG_CMD_REGULATOR=y
# CONFIG_SPL_DOS_PARTITION is not set
CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_LIVE=y
# CONFIG_OF_UPSTREAM is not set
CONFIG_OF_LIST="rk3566-orangepi-3b rk3566-orangepi-3b-v1.1 rk3566-orangepi-3b-v2.1"
CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
CONFIG_ENV_RELOC_GD_ENV_ADDR=y
CONFIG_SPL_DM_SEQ_ALIAS=y
CONFIG_SPL_SYSCON=y
CONFIG_AHCI=y
CONFIG_SCSI_AHCI=y
CONFIG_AHCI_PCI=y
CONFIG_SPL_CLK=y
CONFIG_ROCKCHIP_GPIO=y
CONFIG_SYS_I2C_ROCKCHIP=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_MISC=y
CONFIG_SUPPORT_EMMC_RPMB=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SDMA=y
CONFIG_MMC_SDHCI_ROCKCHIP=y
CONFIG_SPI_FLASH_SFDP_SUPPORT=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SPI_FLASH_XMC=y
CONFIG_DWC_ETH_QOS=y
CONFIG_DWC_ETH_QOS_ROCKCHIP=y
CONFIG_PHY_MOTORCOMM=y
CONFIG_NVME_PCI=y
CONFIG_PCIE_DW_ROCKCHIP=y
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
CONFIG_SPL_PINCTRL=y
CONFIG_DM_PMIC=y
CONFIG_DM_PMIC_FAN53555=y
CONFIG_PMIC_RK8XX=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_SPL_RAM=y
CONFIG_SCSI=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYS_NS16550_MEM32=y
CONFIG_ROCKCHIP_SFC=y
CONFIG_SYSRESET=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
CONFIG_ERRNO_STR=y
CONFIG_OPTEE_LIB=y
CONFIG_OPTEE_IMAGE=y
CONFIG_OPTEE_TZDRAM_SIZE=0x02000000

# 自定义功能
CONFIG_ARM64=y
CONFIG_BOOTSTD_FULL=y
CONFIG_BOOTMETH_ANDROID=y
CONFIG_DFU_MMC=y
CONFIG_DFU_RAM=y
CONFIG_ENV_IS_IN_MMC=y
CONFIG_LED=y
CONFIG_NVME=y
CONFIG_ENV_SOURCE_FILE=orangepi-3b-rk3566
# NET
CONFIG_NET=y
CONFIG_PHY_REALTEK=y
CONFIG_DWC_ETH_QOS=y
CONFIG_DWC_ETH_QOS_ROCKCHIP=y
# USB
CONFIG_USB=y
CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
CONFIG_USB_GADGET_VENDOR_NUM=0x18d1
CONFIG_USB_GADGET_PRODUCT_NUM=0xd00d
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_DM_USB_GADGET=y
# USB 1.1
CONFIG_USB_UHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_GENERIC=y
# USB 2.0
CONFIG_USB_DWC2=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y
# USB 3.0
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GADGET=y
CONFIG_USB_DWC3_GENERIC=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DWC3=y
# FASTBOOT
CONFIG_ANDROID_AB=y
CONFIG_ANDROID_BOOT_IMAGE=y
CONFIG_FASTBOOT=y
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
CONFIG_FASTBOOT_BUF_ADDR=0x00A00000
CONFIG_FASTBOOT_BUF_SIZE=0x0A000000
# FDT and ATAGS support for bootm
CONFIG_LMB=y
CONFIG_BOOTM_EFI=y
CONFIG_OF_LIBFDT=y
CONFIG_SUPPORT_PASSING_ATAGS=y
# 命令大全
CONFIG_CMD_2048=y
CONFIG_CMD_AB_SELECT=y
CONFIG_CMD_ABOOTIMG=y
CONFIG_CMD_ADC=y
CONFIG_CMD_ADTIMG=y
CONFIG_CMD_AES=y
CONFIG_CMD_BCB=y
CONFIG_CMD_BDINFO_EXTRA=y
CONFIG_CMD_BINOP=y
CONFIG_CMD_BOOTDEV=y
CONFIG_CMD_BOOTEFI_HELLO=y
CONFIG_CMD_BOOTEFI_HELLO_COMPILE=y
CONFIG_CMD_BOOTFLOW_FULL=y
CONFIG_CMD_BOOTM=y
CONFIG_CMD_BOOTI=y
CONFIG_CMD_BOOTMENU=y
CONFIG_CMD_BOOTMETH=y
CONFIG_CMD_CAT=y
CONFIG_CMD_DFU=y
CONFIG_CMD_EEPROM=y
CONFIG_CMD_ERASEENV=y
CONFIG_CMD_EROFS=y
CONFIG_CMD_ETHSW=y
CONFIG_CMD_EVENT=y
CONFIG_CMD_FLASH=y
CONFIG_CMD_FASTBOOT=y
CONFIG_CMD_LSBLK=y
CONFIG_CMD_PWM=y
CONFIG_CMD_MBR=y
CONFIG_CMD_INI=y
CONFIG_CMD_LED=y
CONFIG_CMD_MD5SUM=y
CONFIG_CMD_MEMINFO=y
CONFIG_CMD_MEM_SEARCH=y
CONFIG_CMD_MISC=y
CONFIG_CMD_NFS=y
CONFIG_CMD_NVME=y
CONFIG_CMD_PCAP=y
CONFIG_CMD_READ=y
CONFIG_CMD_SDRAM=y
CONFIG_CMD_SHA1SUM=y
CONFIG_CMD_SPI=y
CONFIG_CMD_STRINGS=y
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_TFTPSRV=y
CONFIG_CMD_USB=y
CONFIG_CMD_USB_MASS_STORAGE=y
CONFIG_CMD_WOL=y
CONFIG_CMD_WRITE=y
# 自定义启动命令
CONFIG_BOOTDELAY=0
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS=""
CONFIG_USE_BOOTCOMMAND=y
CONFIG_BOOTCOMMAND="bootflow scan -lb"
  1. configs/orangepi-3b-rk3566_defconfig 修改自 orangepi-3b-rk3566_defconfig 配置文件。
  2. 2024.05 主线开启了 OF_UPSTREAM 特性,大量设备树迁移到了 dts/upstream/src/arm64/ 路径下,不需要在 arch/arm/dts/Makefile 中添加设备树的编译配置了,改变为通过 CONFIG_DEFAULT_DEVICE_TREE 设置默认的设备树即可。

编译 ATF & OPTEE-OS & BL32

截止2026年8月,开源的 ATF 已经支持 rk3568,开源的 OPTEE-OS 仍不支持。但可以实现通过后处理瑞芯微闭源的 BL32 参与构建,成功驱动 TEE 环境。

编译开源 ATF

cd /projects/bootloader/arm-trusted-firmware/

# 清除缓存[可选]
make clean
make realclean

# debug 版本
make \
  CROSS_COMPILE=aarch64-linux-gnu- \
  PLAT=rk3568 \
  SPD=opteed \
  LOG_LEVEL=40 \
  DEBUG=1 \
  all

# release 版本
make \
  CROSS_COMPILE=aarch64-linux-gnu- \
  PLAT=rk3568 \
  SPD=opteed \
  all
  1. ATF 目前已经适配了 RK3568 的平台。
  2. 必须要加 SPD=opteed 参数,否则不会加载 OP-TEE 固件。
  3. DEBUG 会影响构建产物路径:build/rk3568/{debug/release}/bl31/bl31.elf

编译开源 OPTEE-OS目前无法使用,仅记录):

cd /projects/bootloader/optee_os/

# 清除缓存[可选]
rm -rf out
make clean

# debug 版本
make \
  CROSS_COMPILE32=arm-linux-gnueabi- \
  CROSS_COMPILE64=aarch64-linux-gnu- \
  PLATFORM=rockchip-rk3568 \
  CFG_ARM64_core=y \
  CFG_TEE_CORE_LOG_LEVEL=4 \
  CFG_TEE_TA_LOG_LEVEL=4 \
  CFG_TZDRAM_START=0x08400000 \
  CFG_TZDRAM_SIZE=0x00800000 \
  CFG_UART_BASE=0xFE660000 \
  DEBUG=1 \
  all

# release 版本
make \
  CROSS_COMPILE32=arm-linux-gnueabi- \
  CROSS_COMPILE64=aarch64-linux-gnu- \
  PLATFORM=rockchip-rk3588 \
  CFG_ARM64_core=y \
  all
  1. OPTEE-OS 目前仅仅适配了 rk3588 的平台,不能驱动 rk3566

处理瑞芯微 BL32 固件为 ELF 格式:

cd /projects/bootloader/rkbin/

# 转换格式
aarch64-linux-gnu-ld \
  -b binary \
  -Ttext=0x08400000 \
  -o bin/rk35/rk3568_bl32_v2.16.elf \
  bin/rk35/rk3568_bl32_v2.16.bin

# 验证
aarch64-linux-gnu-readelf -h bin/rk35/rk3568_bl32_v2.16.elf
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           AArch64
  Version:                           0x1
  Entry point address:               0x8400000
  Start of program headers:          64 (bytes into file)
  Start of section headers:          539608 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           64 (bytes)
  Number of section headers:         5
  Section header string table index: 4
  1. 这个办法是大模型找到了,不得不说大模型是真猛!

编译 U-Boot

cd /projects/bootloader/u-boot/

# 清除缓存[可选]
rm -rf build
make O=build clean
make O=build mrproper
make O=build distclean

# 应用配置
make CROSS_COMPILE=aarch64-linux-gnu- O=build orangepi-3b-rk3566_defconfig
# 图形化配置
make CROSS_COMPILE=aarch64-linux-gnu- O=build menuconfig

# 编译(使用 ATF & RK-BL32,目前推荐)
make \
  CROSS_COMPILE=aarch64-linux-gnu- \
  ROCKCHIP_TPL=../rkbin/bin/rk35/rk3566_ddr_1056MHz_v1.25.bin \
  BL31=../arm-trusted-firmware/build/rk3568/debug/bl31/bl31.elf \
  TEE=../rkbin/bin/rk35/rk3568_bl32_v2.16.elf \
  O=build -j$(nproc)

# 编译(使用 RK-BL31 & RK-BL32,目前次推荐)
make \
  CROSS_COMPILE=aarch64-linux-gnu- \
  ROCKCHIP_TPL=../rkbin/bin/rk35/rk3566_ddr_1056MHz_v1.25.bin \
  BL31=../rkbin/bin/rk35/rk3568_bl31_v1.46.elf \
  TEE=../rkbin/bin/rk35/rk3568_bl32_v2.16.elf \
  O=build -j$(nproc)

# 编译(使用 ATF & OP-TEE,实际不可用,仅记录)
make \
  CROSS_COMPILE=aarch64-linux-gnu- \
  ROCKCHIP_TPL=../rkbin/bin/rk35/rk3566_ddr_1056MHz_v1.25.bin \
  BL31=../arm-trusted-firmware/build/rk3568/debug/bl31/bl31.elf \
  TEE=../optee_os/out/arm-plat-rockchip/core/tee.elf \
  O=build -j$(nproc)
  1. 主线 U-Boot 代码可以使用最新的工具链编译。
  2. 主线 U-Boot 没有提交 RK3566 的默认配置,使用 RK3568 配置代替。
  3. 使用 makeO=build 参数重定向的编译输出产物的目录为 build
  4. ROCKCHIP_TPL 这个必须使用 rkbin 的闭源固件。
  5. BL31 可以使用瑞芯微的 BL31 闭源固件,也可以用 ATF 开源固件。
  6. TEE 目前只能使用上面处理过的瑞芯微 BL32 固件。

编译产物

  • arm-trusted-firmware/build/px30/{debug/release}/bl31/bl31.elf
    ATF 固件;
  • optee_os/out/arm-plat-rockchip/core/tee.elf & optee_os/out/arm-plat-rockchip/core/tee.bin
    OPTEE-OS 固件;
  • u-boot/build/idbloader.img
    Pre-Loader 镜像,烧录到 idbloader 分区使用;
  • u-boot/build/u-boot.img
    U-Boot 镜像,烧录到 uboot 分区使用,不加载 ATF,网卡会用不了;
  • u-boot/build/u-boot.itb
    U-Boot 镜像,烧录到 uboot 分区使用,各项功能正常;

针对 OrangePi 3B 的改动记录

https://github.com/lx0758/u-boot/commits/orangepi-3b/

烧写镜像

烧写工具

RKDevTool 是瑞芯微在 Windows 下的芯片烧写工具,和芯片内置的 MaskROM Mode 搭配实现裸机烧写。

分区表

目前只是研究 U-Boot,根据瑞芯微的 Wiki文档 - 启动模式Wiki文档 - 分区结构 说明的扇区指导,自建了一个分区表文件,借助 RKDevTool 可以进行分区表写入。

文件 parameter.txt 内容如下:

FIRMWARE_VER: 14.0
MACHINE_MODEL: OrangePi-3B
MACHINE_ID: 007
MANUFACTURER: Xunlong
MAGIC: 0x5041524B
ATAG: 0x00200800
MACHINE: orangepi_3b
CHECK_MASK: 0x80
PWR_HLD: 0,0,A,0,1
TYPE: GPT
CMDLINE:mtdparts=rk29xxnand:idbloader:8160K,uboot:4M,trust:4M,-@0x00008000(rootfs:grow)

烧写配置

# 存储 地址 名字 路径
1 EMMC 0x00000000 Loader MiniLoaderAll.bin
2 EMMC 0x00000000 Parameter parameter.txt
3 EMMC 0x00000040 idbloader idbloader.img
4 EMMC 0x00004000 uboot uboot.img/u-boot.itb
5 EMMC 0x00006000 trust
6 EMMC 0x00008000 rootfs rootfs.img
  1. 各行作用如下:
  • Loader
    用于 miniloader 方式启动区块
  • Parameter
    用于烧录分区表配置文件
  • idbloader
    用于存放前级引导 ddr/miniloaderTPL/SPL 的区块
  • uboot
    用于存放 U-Boot 的区块
  • trust
    用于存放 trust.img 的区块(仅 miniloader 方式需要)
  • rootfs
    用于存放 RootFS 的分区,包含 boot 目录
  1. 注意文件中分区的地址和尺寸指的都是扇区,每个扇区是 512B 大小,并且需要和分区表对齐
  2. 注意存储位置, 老版本的 RKDevTool 没有 存储 那一列,则需要先在 高级功能 中切换为对应的存储器;操作之前需要先下载 Loader

启动日志

DDR 5b48980fd7 typ 25/12/03-15:33.27,fwver: v1.25
...
U-Boot SPL 2026.10-rc2-00076-ge57389aee9a7 (Aug 23 2026 - 23:39:56 +0800)
Trying to boot from MMC1
## Checking hash(es) for config config-2 ... OK
## Checking hash(es) for Image atf-1 ... sha256+ OK
## Checking hash(es) for Image u-boot ... sha256+ OK
## Checking hash(es) for Image fdt-2 ... sha256+ OK
## Checking hash(es) for Image atf-2 ... sha256+ OK
## Checking hash(es) for Image atf-3 ... sha256+ OK
## Checking hash(es) for Image tee-1 ... sha256+ OK
NOTICE:  BL31: v2.15.0(debug):v2.15.0-619-g6a164dda7
NOTICE:  BL31: Built : 23:38:07, Aug 23 2026
NOTICE:  BL31: Rockchip release version: v1.0
INFO:    GICv3 without legacy support detected.
INFO:    ARM GICv3 driver initialized in EL3
INFO:    Maximum SPI INTID supported: 351
INFO:    BL31: Initializing runtime services
INFO:    BL31: cortex_a55: CPU workaround for erratum 1530923 was applied
INFO:    BL31: Initializing BL32
I/TC:
I/TC: OP-TEE version: 3.13.0-1018-g3864e29ae #hisping.lin (gcc version 10.2.1 20201103 (GNU Toolchain for the A-profile Architecture 10.2-2020.11 (arm-10.16))) #2 Tue Jul  1 02:22:06 UTC 2025 aarch64, fwver: v2.16
I/TC: OP-TEE memory size: TEEOS 0x200000 TA 0xc00000 SHM 0x200000
I/TC: Primary CPU initializing
I/TC: CRYPTO_CRYPTO_VERSION_NEW no support. Skip all algo mode check.
I/TC: Primary CPU switching to normal world boot
INFO:    BL31: Preparing for EL3 exit to normal world
INFO:    Entry point address = 0x800000
INFO:    SPSR = 0x3c9

U-Boot 2026.10-rc2-00076-ge57389aee9a7 (Aug 23 2026 - 23:39:56 +0800)

Model: Xunlong Orange Pi 3B v1.1
SoC:   RK3566
DRAM:  2 GiB
PMIC:  RK809 (on=0x10, off=0x00)
Core:  627 devices, 33 uclasses, devicetree: separate
MMC:   mmc@fe2b0000: 1, mmc@fe2c0000: 2, mmc@fe310000: 0
Reading from MMC(0)... Loading Environment from MMC... OK
In:    serial@fe660000
Out:   serial@fe660000
Err:   serial@fe660000
Model: Xunlong Orange Pi 3B v1.1
SoC:   RK3566
Net:   eth0: ethernet@fe010000
Hit any key to stop autoboot: 0
...
Scanning bootdev 'mmc@fe310000.bootdev':
  1  extlinux     ready   mmc          1  mmc@fe310000.bootdev.part /boot/extlinux/extlinux.conf
** Booting bootflow 'mmc@fe310000.bootdev.part_1' with extlinux
ORANGEPI-3B
1:      Debian
Enter choice: 1:        Debian
Retrieving file: /boot/Image.gz
Retrieving file: /boot/initramfs.img
append: earlycon console=tty1 console=ttyS2,1500000n8 consoleblank=0 loglevel=7 root=/dev/mmcblk0p1 rootfstype=ext4 rootwait rw
...
Starting kernel ...
[    0.000000] Booting Linux on physical CPU 0x0000000000 [0x412fd050]
[    0.000000] Linux version 7.1.8-orangepi-3b (user@4fdd5b745c99) (aarch64-linux-gnu-gcc (Debian 14.2.0-19) 14.2.0, GNU ld (GNU Binutils for Debian) 2.44) #20 SMP PREEMPT Mon Aug 17 22:25:51 CST 2026
[    0.000000] KASLR enabled
[    0.000000] Machine model: Xunlong Orange Pi 3B v1.1
[    0.000000] efi: UEFI not found.
[    0.000000] earlycon: uart0 at MMIO32 0x00000000fe660000 (options '1500000n8')
[    0.000000] printk: legacy bootconsole [uart0] enabled
[    0.000000] OF: reserved mem: 0x0000000008400000..0x00000000093fffff (16384 KiB) nomap non-reusable optee@8400000
[    0.000000] OF: reserved mem: 0x000000000010f000..0x000000000010f0ff (0 KiB) nomap non-reusable shmem@10f000
...
[    1.309852] optee: probing for conduit method.
[    1.310326] optee: revision 3.13 (000000003864e29a)
[    1.310820] optee: dynamic shared memory is enabled
[    1.311970] optee: initialized driver

调试

完整日志

修改 include/log.h 可以开启 Debug 日志:

diff --git a/include/log.h b/include/log.h
index 59c66eb7909..799e384b33f 100644
--- a/include/log.h
+++ b/include/log.h
@@ -188,6 +188,7 @@ int _log_buffer(enum log_category_t cat, enum log_level_t level,
 #define log_io(_fmt...)                log(LOG_CATEGORY, LOGL_DEBUG_IO, ##_fmt)
 #define log_cont(_fmt...)      log(LOGC_CONT, LOGL_CONT, ##_fmt)

+#define LOG_DEBUG
 #ifdef LOG_DEBUG
 #define _LOG_DEBUG     LOGL_FORCE_DEBUG
 #ifndef DEBUG

NFS 协议

如果需要经常调试 KernelRootFS,可以使用 U-Boot 加载并启动 NFS 中的 KernelRootFS

# 挂载 NFS 为 ROOTFS
setenv bootargs "earlycon console=ttyS2,1500000n8 root=/dev/nfs ro nfsroot=192.168.8.13:/home/liux/projects/linux/buildfs/rootfs/,vers=4 ip=dhcp rootwait"
# 通过 NFS 加载 Kernel
setenv ipaddr 192.168.8.21
nfs 0x4000000 192.168.8.13:/home/liux/projects/buildfs/rootfs/boot/Image.gz
nfs 0x2000000 192.168.8.13:/home/liux/projects/buildfs/rootfs/boot/initramfs.img
nfs 0x1000000 192.168.8.13:/home/liux/projects/buildfs/rootfs/boot/dts/rockchip/rk3566-orangepi-3b.dtb
booti 0x4000000 0x2000000 0x1000000
  1. U-Boot 的 NFS 协议只能支持 2,为了兼容给 NFS 服务器的 3 协议关了。但是 Kernel 使用 NFS 的默认协议是 3,这里强制指定为 4

使用 U-Boot 加载并启动 USB 设备中的 KernelRootFS

# 挂载 U盘 为 ROOTFS
setenv bootargs "earlycon console=ttyS2,1500000n8 root=/dev/sda1 rw rootfstype=ext4 rootwait"
# 通过 U盘 加载 Kernel
usb start
load usb 0:1 0x4000000 /boot/Image.gz
load usb 0:1 0x2000000 /boot/initramfs.img
load usb 0:1 0x1000000 /boot/dts/rockchip/rk3566-orangepi-3b.dtb
booti 0x4000000 0x2000000 0x1000000;

使用 U-Boot 加载并启动 MMC 设备中的 KernelRootFS

# 挂载 MMC 为 ROOTFS
setenv bootargs "earlycon console=ttyS2,1500000n8 root=/dev/mmcblk0p1 rw rootfstype=ext4 rootwait"
# 通过 MMC 加载 Kernel
load mmc 0:1 0x4000000 /boot/Image.gz
load mmc 0:1 0x2000000 /boot/initramfs.img
load mmc 0:1 0x1000000 /boot/dts/rockchip/rk3566-orangepi-3b.dtb
booti 0x4000000 0x2000000 0x1000000