news 2026/8/17 21:58:47

一篇搞懂RK3568从启动到OS全过程:存储角度

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
一篇搞懂RK3568从启动到OS全过程:存储角度

1 RK3568框图


本文从程序在不同存储其中的运行跳转,来理解RK3568启动的全过程。

  1. 访问地址
    • 框图:https://www.rock-chips.com/uploads/pdf/2022.8.26/191/RK3568%20Brief%20Datasheet.pdf
    • TRM Part1:https://opensource.rock-chips.com/images/2/26/Rockchip_RK3568_TRM_Part1_V1.3-20220930P.PDF
  2. 上电boot流程
    • BootROM映射到物理地址0xFFFF0000,CPU从0xFFFF0000读取第一条指令并执行
    • 可执行程序角度:BootROM -> TPL(ddr.bin,DDR初始化) -> SPL(spl.bin,加载后续镜像) -> Trust(ARM Trust Firmware + OP-TEE,安全) -> U-Boot(加载内核) -> Kernel(运行内核)
    • 存储角度:BootROM -> SRAM(TPL) -> SRAM(SPL) + DDR(SPL) -> DDR(Trust) -> DDR(U-Boot)
  3. 镜像
    • 本质:二进制文件的一种组织形式
    • 作用:CPU从存储设备中读取镜像文件,获取二进制可执行程序入口,跳转执行
    • 种类:TPL,SPL,UBoot,Trust,Kernel
  4. 目录
    • 2 boot流程:帮助理解boot的启动流程
    • 3 RK3568物理地址空间设计:帮助理解CPU如何从BootROM读取指令并执行;帮助理解CPU如何访问SRAM;帮助理解CPU如何访问DDR内存
    • 4 存储分区:帮助理解镜像数据在存储设备中的分布
    • 5 BootROM:帮助立即存储在MaskROM存储设备中的程序的执行流程
    • 6 SRAM:帮助理解运行在SRAM中的TPL和SPL(如果支持重定位,SPL会把代码搬移到DDR中执行)的执行流程
    • 7 DDR:帮助理解运行在DDR内存中的UBoot的执行流程

2 boot流程

  1. RK3568开源方案:BootROM -> TPL -> SPL -> Trust -> UBoot -> Kernel
  2. RK3568闭源方案:MaskROM -> ddr.bin -> miniloader.bin -> Trust -> UBoot -> Kernel
  3. boot执行流程
    • CPU从0xFFFF0000获取第一条指令,并执行BootROM代码
    • 依次检查SPI Nor Flash,SPI NAND Flash,NAND Flash,eMMC Flash,SD卡,USB OTAG
    • 从存储器中读取ID BLOCK,并进行检查和校验
    • 加载DDR(TPL)初始化代码到SRAM中并执行
    • 加载SPL代码到DDR中并执行
    • 加载UBoot到DDR中并执行
    • 加载Kernel,跳转到Kernel执行

3 RK3568物理地址空间设计

  1. 物理地址分布
    • DDR内存区域
    • 外设寄存器
    • SRAM区域
    • BooROM区域
  2. boot地址映射
    • remap[1:0]=2’b00
      • BootRom(20KB) : 0xFFFF0000
      • PMU_SRAM(8KB) : 0xFDCD0000
      • SYSTEM_SRAM (64KB) : 0xFDCC0000
    • remap[1:0]=2’b11
      • BootRom(20KB) : 不可访问
      • PMU_SRAM(8KB) :0xFFFF0000
      • PMU_SRAM(8KB) :0xFDCD0000
      • SYSTEM_SRAM (64KB) :0xFDCC0000
    • remap[1:0]=2’b10
      • BootRom(20KB) :不可访问
      • SYSTEM_SRAM (64KB) :0xFFFF0000
      • PMU_SRAM(8KB) :0xFDCD0000
      • SYSTEM_SRAM (64KB) :0xFDCC0000
  3. 外设空间映射:TRM Part1的Addresss Mapping章节
  4. PCIe:超过4G空间的地址
    • PCIe内存空间: 这是“数据窗口”,CPU 读写这个窗口,就是在读写 PCIe 设备. CPU 直接访问 PCIe 设备上的 BAR 空间(如显卡的显存)
      - PCIe2x1_S: 0x300000000
      - PCIe3x1_S: 0x340000000
      - PCIe3x2_S: 0x380000000
    • -PCIe配置空间: 这是“控制面板”,用来配置控制器本身和发现/配置 PCIe 设备. CPU 访问 PCIe 控制器自身的配置寄存器,或通过控制器间接访问 PCIe 设备的配置空间
      - PCIe2x1_DBI: 0x3C0000000
      - PCIe3x1_DBI: 0x3C0400000
      - PCIe3x2_DBI: 0x3C0800000

4 存储分区

  1. 默认分区映射表:https://opensource.rock-chips.com/wiki_Partitions
  2. 注意事项
    • 一级引导是MiniLoader,则loader2可存放uboot.img,trust分区可存放trust.img
    • 一级引导是不支持安全可信固件的SPL,则loader2分区可存放u-boot.bin,无可用trust分区
    • 一级引导式支持安全可信固件的SPL(搭载ATF或OPTEE),则loader2分区用于存放u-boot.itb(内含u-boot.bin与可信固件二进制文件),无可用trust分区
  3. RK使用GPT分区表:https://github.com/rockchip-linux/u-boot/blob/android/doc/README.gpt

4.1 不同存储介质的ID BLOCK偏移

  1. eMMC芯片
    - 首先需要了解eMMC芯片的结构
    - 从boot扇区加载, 也就是从0扇区加载
    - 扇区 64 = 0x40(同 SD,eMMC 的 user data area)
  2. SD卡
    - 前置空间需要放置MBR
    - 扇区 64 = 0x40(32KB 偏移)
  3. SPI Nor Flash
    - 起始扇区 0(0x0 偏移), SPI 无"扇区"概念,按字节/页读
    - rkspi 每 4KB 只用前 2KB 做 spread(镜像翻倍)
    - rknand 按 pagesize/skippages 做 spread
  4. SPI NAND Flash
    - 存在坏块管理, 从逻辑0扇区加载, 可设置备份分区
    - 起始页 0(0x0 偏移,但有跳页要求): NAND page(pagesize,如2KB/4KB)
  5. NAND Flash
    - 起始页 0(同 SPI NAND,跳页)

4.2 不同介质的本质区别

  1. SD/eMMC 用扇区 64(0x40)
    • SD/eMMC 的前 64 个扇区(32KB)是 MBR/GPT 分区表区域,BootROM 跳过分区表,从扇区 64 开始读 ID Block
    • doc/README.rockchip:296 明确:“rksd.c produces an image consisting of 32KB of empty space, a header and u-boot-spl-dtb.bin”——这 32KB 空白就是留给分区表的
    • SD/eMMC 是块设备,有分区表(MBR/GPT),BootROM 必须跳过分区表才能放引导代码,所以固定从扇区 64 开始
  2. SPI Nor / NAND 从起始(0x0)读
    • SPI/NAND 没有分区表的概念,BootROM 直接从介质最起始处读 ID Block
    • doc/README.rockchip:323:“The image should be written to the start of SPI flash.”
    • SPI Nor 是线性字节设备,没有分区表,从 0 开始即可
  3. NAND 的"位置"还要考虑坏块和跳页
    • NAND 有坏块,BootROM 读取时会跳过坏块
    • NAND 的 page 结构要求 spread
    • SPI NAND / 并行 NAND 是页设备,没有分区表,从 page 0 开始,但要处理坏块和页对齐

4.3 镜像打包相关代码

  1. 关键文件
    • 不同介质的封装差异:uboot/tools/rksd.c、rkspi.c、rknand.c
    • 扇区偏移文档:uboo/doc/README.rockchip
    • 镜像打包逻辑:uboot/make.sh 的打包逻辑

5 BootROM

  1. BootROM执行流程
    • BootROM被映射到物理地址0xFFFF0000
    • CPU从0xFFFF0000读取指令并执行
    • CPU从存储设备中读取ID BLOCK并校验
    • 校验成功,加载TPL
  2. 前置分析
    • BootROM不可修改,由于它首先要加载ID BLOCK,而其支持的存储设备有很多:SPI Nor Flash,SPI NAND Flash,NAND Flash,eMMC Flash,SD卡,所以它只能从固定位置访问ID BLOCK
    • 对于不同的存储器,我们要掌握这个固定位置的设计,这是确保系统能正常启动的第一步
    • ID BLOCK是校验镜像合法性的第一步,ID BLOCK的组成也是镜像启动的关键一步
    • 校验成功后,开始加载TPL。BootROM如何知道从存储器的什么位置加载TPL?在ID BLOCK的位置不变的情况下,扩展性的最好的设计就是通过在镜像头部记录不同镜像的offset,依此来定位镜像的位置。所以镜像的头部信息非常重要

5.1 BootROM加载TPL/SPL

  1. 处理流程
    • 从可用的存储其中读取ID BLOCK
    • 校验ID BLOCK通过, 则加载DDR初始化代码到SRAM中执行

5.2 ID BLOCK

  1. 本质: 给tpl/spl加头部信息
    • 通过mkimage工具给tpl+spl加一个头部信息
    • 这个头部信息中包含了魔数, tpl哈希值, spl哈希值, tpl入口地址, spl入口地址等信息
    • make.sh
      • mkimage -T rksd -d tpl:spl: idblock.bin / idbloader.img
  2. 如何管理存储的块信息: uboot/tools/rkcommon.h
enum { RK_BLK_SIZE = 512, RK_SIZE_ALIGN = 2048, RK_INIT_OFFSET = 4, RK_MAX_BOOT_SIZE = 512 << 10, RK_SPL_HDR_START = RK_INIT_OFFSET * RK_BLK_SIZE, RK_SPL_HDR_SIZE = 4, };
  1. 不同芯片版本对应的ID BLOCK不同: uboot/tools/rkcommon.c
struct spl_info { const char *imagename; const char *spl_hdr; const uint32_t spl_size; const bool spl_rc4; const uint32_t header_ver; }; static struct spl_info spl_infos[] = { { "rk3066", "RK30", 0x8000, true, RK_HEADER_V1 }, ... { "rk1808", "RK18", 0x200000 - 0x2000, false, RK_HEADER_V1 }, ... { "rk3568", "RK35", 0x10000 - 0x1000, false, RK_HEADER_V2 }, { "rk3576", "RK35", 0x80000 - 0x1000, false, RK_HEADER_V2 }, { "rk3588", "RK35", 0x100000 - 0x1000, false, RK_HEADER_V2 }, };
  1. 不同版本使用的头部数据
struct header0_info_v2 { uint32_t magic; // 偏移0x00: RK_MAGIC_V2 = 0x534E4B52 ("RKSN") uint8_t reserved[4]; // 偏移0x04 uint32_t size_and_nimage; // 偏移0x08: [31:16]镜像数; [15:0]hash字段偏移(4B单位) uint32_t boot_flag; // 偏移0x0C: [3:0]hash类型(0=none,1=sha256,2=sha512) uint8_t reserved1[104]; // 偏移0x10 struct image_entry images[4]; // 偏移0x78: 最多4个镜像(TPL+SPL) uint8_t reserved2[1064]; uint8_t hash[512]; // header 自身的 SHA256 }; struct image_entry { // rkcommon.c:45-52 uint32_t size_and_off; // [31:16]镜像大小(扇区数); [15:0]镜像扇区偏移 uint32_t address; // 加载地址, 默认 0xFFFFFFFF uint32_t flag; uint32_t counter; // 镜像序号(1,2,...) uint8_t reserved[8]; uint8_t hash[64]; // 该镜像的 hash };
  1. ID BLOCK二进制布局
存储介质扇区 64 (0x40) 起: ┌─────────────────────────────────────────────────────┐ 0x000 │ header0 (4KB = 4扇区) │ │ header0_info_v2 结构 + 填充 + hash[512] │ ← BootROM 先读这里 │ images[0]: TPL — size_and_off=[大小|偏移4] │ │ images[1]: SPL — size_and_off=[大小|偏移4+TPL大小] │ ← BootROM 据此找 SPL ├─────────────────────────────────────────────────────┤ 0x800 (扇区4) │ "RK35" (4字节 spl_name) + TPL 代码 (init_file) │ ← TPL 数据, 2KB对齐 ├─────────────────────────────────────────────────────┤ 0x800 + TPL_size │ SPL 代码 (boot_file) │ ← SPL 数据, 2KB对齐 └─────────────────────────────────────────────────────┘

6 SRAM:TPL + SPL

6.1 TPL内存布局: DDR相关, 根据SoC特化

  1. 配置
    • u-boot-next-dev\arch\arm\mach-rockchip\Kconfig
      • RK3568
        • TPL_LDSCRIPT: default “arch/arm/mach-rockchip/u-boot-tpl-v8.lds”
        • TPL_TEXT_BASE:default 0xfdcc1000 - remap[1:0]=2’b00: BootRom = 0xFFFF0000, SYS_SRAM = 0xFDCC0000
          • SRAM是64KB, 从0x1000开始, 说明TPL要小于60KB
        • TPL_MAX_SIZE:default 61440
        • ROCKCHIP_IRAM_START_ADDR: 0xfdcc0000
  2. 链接脚本
    • u-boot-next-dev\arch\arm\mach-rockchip\u-boot-tpl-v8.lds
    • TPL_TEXT_BASE: text -> rodata -> data -> u_boot_list -> image_copy_end -> bss
    • 条件判断
      • CONFIG_TPL_MAX_SIZE
      • CONFIG_TPL_BSS_MAX_SIZE
      • CONFIG_TPL_MAX_FOOTPRINT
  3. CONFIG_TPL_TINY_FRAMEWORK: 极简TPL框架内存布局
0xfdcc0000 ┌─────────────────────────────┐ IRAM 基地址 │ BROM 保留区 (0xfdcc0000~0xfdcc1000)│ 含 BROM 启动源ID @ 0xfdcc0010 0xfdcc1000 ├─────────────────────────────┤ TPL_TEXT_BASE (TPL 加载/运行地址) │ .text (代码段, start.o 在最前) │ │ .rodata (只读数据) │ │ .data (已初始化数据) │ ← TPL_MAX_SIZE=60KB 上限 │ .u_boot_list (链表) │ │ .image_copy_end / .end │ 0xfdcc1000 │ .bss (NOLOAD, 运行时清零) │ ← TPL 的 BSS 紧跟在代码后(同一段SRAM) +60KB └─────────────────────────────┘ 0xfdcc1000 + 0xF000 = 0xfdcd0000 │ (SRAM 剩余空间留给 BROM 回调) │

6.2 SPL内存布局

  1. 配置
    • include/configs/rk3568_common.h
      • #define CONFIG_SPL_TEXT_BASE 0x00000000 // 行15:代码段链接地址(DDR起始)
      • #define CONFIG_SPL_MAX_SIZE 0x00040000 // 行16:256KB
      • #define CONFIG_SPL_BSS_START_ADDR 0x03fe0000 // 行17:BSS在DDR的0x03fe0000
      • #define CONFIG_SPL_BSS_MAX_SIZE 0x00010000 // 行18:64KB
      • #define CONFIG_SPL_STACK 0x03fe0000 // 行19:栈在0x03fe0000(与BSS同址)
      • #define CONFIG_SPL_LOAD_FIT_ADDRESS 0x10000000 // 行23:FIT临时加载点
  2. 链接脚本
    • u-boot-next-dev\arch\arm\cpu\armv8\u-boot-spl.lds(ARM64通用SPL脚本)
    • text -> rodata -> data -> u_boot_list -> image_copy_end -> end ->
      • CONFIG_SPL_SKIP_RELOCATE(无重定位): _image_binary_end -> bss
      • 重定位:rel_dyn_start -> rela.dyn -> .rel_dyn_end -> _image_binary_end -> bss
  3. 内存布局
DDR 0x00000000 ┌─────────────────────────────┐ .sram 区域 (ORIGIN=SPL_TEXT_BASE=0, LEN=256KB) │ .text (代码, start.o 最前) │ ← SPL 被加载到这里运行 │ .rodata │ │ .data │ │ .u_boot_list │ │ .rela.dyn (重定位信息) │ 0x00040000 ├─────────────────────────────┤ SPL_MAX_SIZE 上限 (256KB) │ ... DDR 可用空间 ... │ │ (FIT 镜像临时加载到 0x10000000) │ │ ... │ 0x03fe0000 ├─────────────────────────────┤ .sdram 区域 (ORIGIN=SPL_BSS_START_ADDR, LEN=64KB) │ SPL 栈 (CONFIG_SPL_STACK) │ ← 栈顶 0x03fe0000,向下生长 │ ↓ gd 结构 (栈顶预留) │ board_init_f_alloc_reserve 在此预留 gd │ ↓ │ │ .bss (NOLOAD, 64KB) │ ← BSS 段,crt0_64.S:144 清零 0x03ff0000 ├─────────────────────────────┤ BSS_MAX_SIZE 上限 │ ... DDR 可用空间 ... │

7 DDR内存:SPL + UBoot + Kernel

  1. 内存物理地址空间
    • 32位CPU
      • 0x00000000 - 0xEFFFFFFF:3.75G内存
      • 0xF0000000 - 0xFFFFFFFF:外设寄存器
    • 64位CPU
      • 0x00000000 - 0xEFFFFFFF:3.75G内存
      • 0xF0000000 - 0xFFFFFFFF:外设寄存器
      • 超过4G的位置依然可以随意访问,也就是说DDR可以扩展到8G,16G,设置更多
      • 对于ARM64来说,支持48位的扩展地址

7.1 DDR内存地址布局:uboot/include/configs/rk3568_common.h

  1. SPL
    • CONFIG_SPL_TEXT_BASE:0x00000000
    • CONFIG_SPL_MAX_SIZE:0x40000,限制256KB。对应 MiniLoaderAll.bin 的代码容量上限
    • CONFIG_SPL_STACK:0x03fe0000,SPL 运行栈地址
    • CONFIG_SPL_BSS_START_ADDR:0x03fe0000,SPL BSS 段起始地址
    • CONFIG_SPL_BSS_MAX_SIZE:0x10000,64KB。SPL 全局变量(BSS 段)最大空间
    • CONFIG_SPL_LOAD_FIT_ADDRESS:0x10000000,SPL 加载 FIT 镜像 (u-boot.itb) 的内存目标地址
  2. UBoot
    • CONFIG_SYS_TEXT_BASE:U-Boot 主程序运行基地址。正常启动U-Boot 加载至 0x00a00000 运行;USB烧录调试模式,重定位到 0x00000000。
    • CONFIG_SYS_INIT_SP_ADDR:U-Boot 启动初期栈指针地址
    • CONFIG_SYS_LOAD_ADDR:默认下载地址,loadb/loadx 等命令默认把文件读到这个内存地址
    • CONFIG_SYS_SDRAM_BASE:0。DDR内存基地址为0
    • SDRAM_MAX_SIZE:0xf0000000。可用DDR上限,上方保留给外设寄存器
  3. Kernel
#define ENV_MEM_LAYOUT_SETTINGS \ "scriptaddr=0x00c00000\0" \ "pxefile_addr_r=0x00e00000\0" \ "fdt_addr_r=0x08300000\0" \ "kernel_addr_r=0x00280000\0" \ "kernel_addr_c=0x04080000\0" \ "ramdisk_addr_r=0x0a200000\0"

7.2 DDR内存地址布局:来源于uboot手册

【DDR内存地址布局】 ATF Start Addr:0x00000000 Size:1M Usage:ARM Trusted Firmware Secure:Yes SHM Start Addr:0x00100000 Size:1M Usage:SHM, Pstore Secure:No OP-TEE Start Addr:0x08400000 Size:2M~30M Usage:参考TEE开发手册 Secure:Yes FDT Start Addr:fdt_addr_r Size:- Usage:kernel dtb Secure:No KERNEL Start Addr:kernel_addr_r Size:- Usage:kernel镜像 Secure:No RAMDISK Start Addr:ramdisk_addr_r Size:- Usage:ramdisk镜像 Secure:No …… Start Addr:- Size:- Usage:- Secure:- FASTBOOT Start Addr:- Size:- Usage:Fastboot buffer Secure:No …… Start Addr:- Size:- Usage:- Secure:- SP Start Addr:- Size:- Usage:stack Secure:No FDT Start Addr:- Size:sizeof(dtb) Usage:U-Boot dtb Secure:No GD Start Addr:- Size:sizeof(gd) Usage:- Secure:No Board Start Addr:- Size:sizeof(bd_t) Usage:- Secure:No MALLOC Start Addr:- Size:CONFIG_SYS_MALLOC_LEN Usage:系统的堆空间 Secure:No U-Boot Start Addr:- Size:sizeof(mon) Usage:u-boot镜像 Secure:No Video FB Start Addr:- Size:fb size(32M) Usage:显示帧缓存 Secure:No TLB Table Start Addr:RAM_TOP-64K Size:32K Usage:MMU页表 Secure:No 【PS】 64位平台: ATF是ARMv8必需的, OP-TEE是可选的; 32位平台, 只有OP-TEE kernel fdt/kernel/ramdisk是U-Boot需要加载的固件地址, 由ENV_MEM_LAYOUT_SETTINGS定义 Fastboot功能需要的buffer地址和大小在deconfig中定义 OP-TEE 占据的空间需要根据实际需求而定

7.3 SPL加载UBoot

  1. SPL加载FIT镜像: uboot.itb
    • 配置: CONFIG_ROCKCHIP_FIT_IMAGE_PACK
    • FIT 本质是 FDT(设备树格式)blob,magic = FDT_MAGIC(0xd00dfeed)
    • FIT 由 make_fit_atf.sh 生成 u-boot.its,再 mkimage -f u-boot.its -E uboot.itb(-E 外部数据)打包。结构(arch/arm/mach-rockchip/fit_nodes.sh)
  2. FIT打包
FIT 包含的关键信息(属性定义在 include/image.h:923-953): - load(FIT_LOAD_PROP):镜像加载地址 - entry(FIT_ENTRY_PROP):镜像入口地址(uboot 节点无此属性) - os(FIT_OS_PROP):OS 类型——"arm-trusted-firmware"/"U-Boot"/"op-tee",SPL 据此决定跳转方式 - data/data-position/data-offset/data-size:镜像数据(-E 外部数据) - hash:每段 SHA256,SPL 校验完整性 - firmware/loadables/fdt:配置节点指定加载顺序
  1. 从启动到FI镜像加载
SPL 入口 start.S:21 _start → reset → save_boot_params(setjmp 保存 BROM 上下文)→ 设 EL3 → master_cpu: bl _main(start.S:237)→ crt0_64.S:68 _main: - crt0_64.S:75-76:ldr x0, =(CONFIG_SPL_STACK=0x03fe0000) 设栈; - crt0_64.S:82-86:board_init_f_alloc_reserve/board_init_f_init_reserve(栈顶预留 gd); - crt0_64.S:89:bl board_init_f(spl.c:204)—— spl_early_init、RAM init、console; - crt0_64.S:125-138:spl_relocate_stack_gd(RK3568 返回0,不重定位栈); - crt0_64.S:144-149:清 BSS(0x03fe0000~0x03ff0000); - crt0_64.S:152-154:b board_init_r(common/spl/spl.c:507)。 board_init_r(spl.c:507-650)SPL 主循环: - spl.c:560-561:entry_point_bl32=-1; entry_point_bl33=CONFIG_SYS_TEXT_BASE(默认值); - spl.c:573:board_boot_order → spl_boot_device(返回 BOOT_DEVICE_MMC1); - spl.c:575:boot_from_devices → spl_mmc_load_image(spl_mmc.c:282)。
  1. 加载FIT流程
① 检测 FIT(spl_mmc.c:57-105 mmc_load_image_raw_sector): header = (struct image_header *)(CONFIG_SYS_TEXT_BASE - sizeof(struct image_header)); blk_dread(..., sector, 1, header); // 读1扇区头部 if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && image_get_magic(header) == FDT_MAGIC) // line 76-82 ★ spl_load_simple_fit(spl_image, &load, sector, header); // line 91 → FIT 路径 ② 加载 FIT blob 到内存(spl_fit.c:929 spl_load_simple_fit → spl_fit.c:702 spl_internal_load_simple_fit): - spl_fit_load_blob(spl_fit.c:489-538):把整个 FIT DTB 放在 CONFIG_SYS_TEXT_BASE - size 之前(≈0x009fxxxx),base_offset 供外部>
  • 镜像加载地址
  • ┌───────────────┬───────────┬──────────────────────────────┬─────────────────────────┬────────────────────────────────────────────────────┐ │ 镜像 │ FIT 节点 │ 加载地址 │ 地址来源 │ 文件:行号 │ ├───────────────┼───────────┼──────────────────────────────┼─────────────────────────┼────────────────────────────────────────────────────┤ │ U-Boot │ uboot │ 0x00a00000 │ CONFIG_SYS_TEXT_BASE │ rk3568_common.h:32; fit_args.sh:120; spl_fit.c:888 │ ├───────────────┼───────────┼──────────────────────────────┼─────────────────────────┼────────────────────────────────────────────────────┤ │ ATF bl31 段1 │ atf-1 │ bl31.elf 段1 p_paddr │ decode_bl31.py:31 │ fit_nodes.sh:129; spl_fit.c:837 │ ├───────────────┼───────────┼──────────────────────────────┼─────────────────────────┼────────────────────────────────────────────────────┤ │ ATF bl31 段2+ │ atf-2.. │ 各段 p_paddr │ 同上 │ fit_nodes.sh:166 │ ├───────────────┼───────────┼──────────────────────────────┼─────────────────────────┼────────────────────────────────────────────────────┤ │ OP-TEE │ optee │ 0x08400000 │ DRAM_BASE(0)+0x08400000 │ fit_args.sh:44; spl_fit.c:914 │ ├───────────────┼───────────┼──────────────────────────────┼─────────────────────────┼────────────────────────────────────────────────────┤ │ U-Boot dtb │ fdt │ 紧跟 firmware 之后 │ spl_fit_append_fdt │ spl_fit.c:417 │ ├───────────────┼───────────┼──────────────────────────────┼─────────────────────────┼────────────────────────────────────────────────────┤ │ FIT 临时 DTB │ 整个 blob │ 0x009fxxxx(TEXT_BASE 之前) │ spl_fit_load_blob │ spl_fit.c:525 │ └───────────────┴───────────┴──────────────────────────────┴─────────────────────────┴────────────────────────────────────────────────────┘
    1. 镜像调用
    spl_fit.c:888:spl_image->entry_point_bl33 = image_info.load_addr = 0x00a00000。 跳转分发(spl.c:590-604) switch (spl_image.os) { case IH_OS_ARM_TRUSTED_FIRMWARE: // line 596 printf("Jumping to %s(0x%08lx) via ARM Trusted Firmware(0x%08lx)\n", ..., (ulong)spl_image.entry_point_bl33, (ulong)spl_image.entry_point); spl_invoke_atf(&spl_image); // line 602 ★ break; } 跳转前的准备工作 ① 从 FDT /fit-images 查找最终入口(spl_atf.c:171-220 spl_invoke_atf): ② 清理(spl_atf.c:212 spl_cleanup_before_jump,定义在 spl.c:725-757): ③ 构造 bl31_params 并跳转(spl_atf.c:123-133 bl31_entry): 跳转后:ATF(bl31) 在 EL3 初始化安全世界 → 启动 OP-TEE@EL1 Secure → ERET 到 U-Boot@EL2 Non-secure(0x00a00000)。 为什么 SPL 不直接跳 U-Boot 而要先跳 ATF 1. EL 切换必须经 ERET:SPL 在 EL3 Secure,U-Boot 要在 EL2 Non-secure,从 EL3 降到 EL2 同时切安全态只能靠 ERET(目标 EL 由 SPSR_EL3/ELR_EL3 决定),SPL 直接跳做不到; 2. 常驻 EL3 服务:kernel 运行后需要 PSCI(多核上下电)、SMC 路由(访问 OP-TEE/加密/OTP),没有 bl31 常驻 EL3,kernel 发 SMC 无人响应; 3. Secure/Normal 世界分离:OP-TEE 需先在 EL1 Secure 启动,ATF 负责调度 BL31→BL32→BL33。

    7.4 UBoot加载Kernel

    1. Kernel镜像格式
      • Android boot.img: uboot/include/android_image.h
        • uboot/common/image-android.c
        • 镜像布局:header(1页) | kernel(n) | ramdisk(m) | second(o) | [dtb]
      • ARM64 Image header
        • Documentation/arm64/booting.txt in the Linux kernel
        • uboot/cmd/booti.c:20-31
      • RK私有镜像
        • bootrkp.c
        • 8 字节 header(tag=TAG_KERNEL + size)+ data + CRC32
      • FIT镜像
        • FDT 格式,内含 kernel/ramdisk/fdt 子节点,fit_get_blob(fit.c:139-215)从 boot/recovery 分区读取
    2. 镜像处理路径
    ┌──────────────┬────────────────┬────────────────────┬────────────────────────┬──────────────────────────────────────────────────┐ │ 路径 │ 命令 │ Kernel 来源 │ 镜像格式 │ 文件:行号 │ ├──────────────┼────────────────┼────────────────────┼────────────────────────┼──────────────────────────────────────────────────┤ │ bootrkp │ bootrkp │ kernel 分区 │ RK 私有 rockchip_image │ cmd/bootrkp.c:215-300 │ ├──────────────┼────────────────┼────────────────────┼────────────────────────┼──────────────────────────────────────────────────┤ │ boot_android │ boot_android │ boot/recovery 分区 │ Android boot.img │ cmd/boot_android.c:21; android_bootloader.c:1217 │ ├──────────────┼────────────────┼────────────────────┼────────────────────────┼──────────────────────────────────────────────────┤ │ boot_fit │ boot_fit │ boot/recovery 分区 │ FIT │ cmd/bootfit.c:59; fit.c:422 │ ├──────────────┼────────────────┼────────────────────┼────────────────────────┼──────────────────────────────────────────────────┤ │ distro │ distro_bootcmd │ 任意设备 │ extlinux.conf/boot.scr │ config_distro_bootcmd.h:383 │ └──────────────┴────────────────┴────────────────────┴────────────────────────┴──────────────────────────────────────────────────┘
    1. 进入uboot, 倒计时无按键则执行bootcmd:按顺序执行
    #define RKIMG_BOOTCOMMAND \ "boot_android ${devtype} ${devnum};" \ "boot_fit;" \ "bootrkp;" \ "run distro_bootcmd;"
    1. 加载位置
    #define ENV_MEM_LAYOUT_SETTINGS \ "scriptaddr=0x00c00000\0" \ "pxefile_addr_r=0x00e00000\0" \ "fdt_addr_r=0x08300000\0" \ "kernel_addr_r=0x00280000\0" \ "kernel_addr_c=0x04080000\0" \ "ramdisk_addr_r=0x0a200000\0"
    版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
    网站建设 2026/8/17 21:52:32

    MemRouter架构解析:基于向量检索的对话智能体长期记忆实现

    1. 项目概述&#xff1a;当对话智能体需要记住“很久以前的事”在构建一个真正能与人进行长期、连贯对话的智能体时&#xff0c;我们总会遇到一个核心瓶颈&#xff1a;记忆。想象一下&#xff0c;你和一位朋友聊天&#xff0c;他能记住你们三个月前讨论过的旅行计划、上周你提到…

    作者头像 李华
    网站建设 2026/8/17 21:51:36

    触感仪表盘:汽车座舱交互从视觉依赖到多感官融合的技术演进

    1. 项目缘起&#xff1a;从“视觉轰炸”到“触觉引导”的驾驶交互变革最近几年&#xff0c;汽车座舱的屏幕是越做越大&#xff0c;从双联屏到贯穿式三联屏&#xff0c;再到副驾娱乐屏&#xff0c;信息显示是越来越丰富。但不知道你有没有和我一样的感受&#xff1a;开车时&…

    作者头像 李华
    网站建设 2026/8/17 21:50:41

    palera1n越狱工具实战指南:从checkm8漏洞原理到Rootless一键越狱

    palera1n越狱工具实战指南&#xff1a;从checkm8漏洞原理到Rootless一键越狱 【免费下载链接】palera1n Jailbreak for A8 through A11, T2 devices, on iOS/iPadOS/tvOS 15.0, bridgeOS 5.0 and higher. 项目地址: https://gitcode.com/GitHub_Trending/pa/palera1n pa…

    作者头像 李华
    网站建设 2026/8/17 21:48:46

    自考英语一造句短语-东方仙盟

    describe (描述) 造句&#xff1a;She described her happy childhood to me. 翻译&#xff1a;她向我描述了她快乐的童年。interrupt (打断&#xff0c;打扰) 造句&#xff1a;Please do not interrupt others when they are speaking. 翻译&#xff1a;别人说话的时候请不要打…

    作者头像 李华