TEE-TA学习轨迹第五篇:ARM 64 双pflash + 标准FIP+Linux内核+TEE驱动在完整安全启动详细实操步骤

双pflash + 标准FIP 完整安全启动详细实操步骤

一、整体硬件模拟设计&原理说明

1.1 真实硬件上电流程

ARM开发板上电复位后,CPU固定从片内ROM(BL1固化在NOR Flash 0地址)执行第一条指令:
  1. BL1:最小硬件初始化、安全RAM初始化、校验并加载FIP固件包内的BL2;
  2. BL2:外设初始化、安全固件完整性校验,依次加载BL31、OP-TEE(BL32)、U-Boot(BL33);
  3. BL31(EL3安全监控):初始化PSCI电源管理、SMC异常转发,拉起OP-TEE安全世界后,将CPU切换到Non-secure EL1非安全态交给U-Boot;
  4. U-Boot引导Linux内核+根文件系统,普通业务运行在非安全世界。

1.2 QEMU硬件模拟设计(为什么用两块64MB pflash)

  • pflash0(地址0x00000000):存放bl1.bin,设置为只读,模拟出厂固化的片上启动ROM,防止固件被误擦写篡改;
  • pflash1(地址0x04000000):存放fip.bin标准固件包,BL1会固定从该地址解析FIP头部,加载后续所有阶段固件;
  • 必须填充至64MB原因:QEMU virt平台硬件规范约束,单块NOR Flash固定容量为64MB(67108864字节),原始编译出的bin只有几十KB,小于硬件规定大小会直接报区域大小不匹配错误,truncate仅在文件尾部补0,不修改原有固件数据。

1.3 完整启动链路

BL1(EL3) → BL2(S-EL1) → BL31(EL3) → BL32(OP-TEE S-EL1) → BL33(U-Boot NS-EL1) → Linux(NS-EL1)

第一阶段:源码编译四大核心固件

前置环境准备

# 1. 安装AArch64交叉编译工具链 
sudo apt install aarch64-linux-gnu-gcc aarch64-linux-gnu-binutils make git 
# 2. 全局环境变量(全程保持不变,保证编译平台一致) 
export CROSS_COMPILE=aarch64-linux-gnu- 
export PLAT=qemu export DEBUG=1

工具用途解释:

  1. CROSS_COMPILE:ATF、OP-TEE、U-Boot均为裸机代码,无操作系统库依赖,必须使用ARM64交叉编译器,不能使用x86宿主机编译器;
  2. PLAT=qemu:指定硬件平台为QEMU virt,自动适配该平台内存布局、GIC中断、Flash基地址、外设寄存器;
  3. DEBUG=1:开启详细日志输出,后续FIP校验失败、镜像加载崩溃时可以快速定位问题。

步骤1:编译ATF(产出BL1、BL2、BL31 + 打包工具fiptool)

1.1 进入ATF源码目录,清理旧编译产物

cd arm-trusted-firmware make clean
原因:避免旧版本目标文件、链接脚本残留,防止镜像地址错乱、编译产物不匹配。

1.2 编译三大引导固件

make PLAT=qemu ARCH=aarch64 CROSS_COMPILE=aarch64-none-elf- DEBUG=1
编译产物路径:build/qemu/debug/
文件名
作用
烧录位置
bl1.bin
上电第一阶段固化引导
pflash0(第一块Flash)
bl2.bin
安全态第二阶段引导
打包进FIP
bl31.bin
EL3安全监控核心,SMC/PSCI实现
打包进FIP

1.3 编译fiptool打包工具

make -C tools/fiptool
必须用本套ATF编译fiptool的原因
FIP固件包自带魔数+UUID头部校验,只有同版本ATF编译出的fiptool打包的镜像,才能被当前BL1正常解析;跨版本工具打包会直接触发FIP header check failed校验失败,BL1无法进入下一阶段。

步骤2:编译OP-TEE(BL32安全操作系统 tee.bin)

apt install -y gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf 
export CROSS_COMPILE=arm-linux-gnueabihf- 
export CROSS_COMPILE64=aarch64-linux-gnu- 
make PLATFORM=vexpress-qemu_armv8a \ 
ARCH=arm \ 
CFG_ARM64_core=y \ 
CROSS_COMPILE64=aarch64-none-elf- \ 
-j32

编译产物

tee-pager_v2.bin

原理&原因

OP-TEE运行在S-EL1安全世界,作为可信操作系统处理加密、密钥、安全存储等敏感业务;Linux所有安全调用都会通过SMC指令转发到EL3 BL31,再路由到OP-TEE,必须打包进FIP由ATF统一加载初始化。

步骤3:编译U-Boot(BL33非安全引导 u-boot.bin)

make clean 
# 重新加载配置 
make qemu_arm64_defconfig 
# 用新工具链编译 
make CROSS_COMPILE=aarch64-none-elf- -j32

关键注意点:必须使用裸二进制u-boot.bin

  1. 不能使用u-boot-dtb.bin、不能用mkimage加过头部的镜像;
  2. 原因:FIP容器仅支持原生裸bin格式,带U-Boot镜像头会导致长度、校验字段异常,ATF加载镜像会失败。

作用

U-Boot运行在NS-EL1非安全世界,负责初始化外设、加载Linux内核、传递启动参数,是安全世界和普通操作系统的中间引导层。

步骤4:归集打包所需的4个镜像

将以下4个文件拷贝到同一个工作目录./firmware/:
  1. bl2.bin(ATF编译产物)
  2. bl31.bin(ATF编译产物)
  3. tee-pager_v2.bin(OP-TEE编译产物)
  4. u-boot.bin(U-Boot编译产物)

第二阶段:fiptool打包标准FIP固件包

步骤1:执行FIP打包命令

# 切换到固件目录,使用同版本fiptool打包


../arm-trusted-firmware/tools/fiptool/fiptool create \
    --tb-fw bl2.bin \
    --scp-fw bl31.bin \
    --tos-fw tee-pager_v2.bin \
    --nt-fw u-boot.bin \
    fip.bin

参数逐行解释

  1. --tb-fw bl2.bin:可信启动固件,安全启动第二阶段镜像;
  2. --scp-fw bl31.bin:EL3安全监控固件,电源管理、SMC指令转发核心;
  3. --tos-fw tee.bin:可信操作系统镜像,即OP-TEE安全系统;
  4. --nt-fw u-boot.bin:非可信固件,非安全世界引导程序;
  5. 输出fip.bin:带校验头部的固件容器,BL1可以通过内部镜像索引表,按地址、长度、校验值逐个加载固件。

步骤2:校验FIP镜像合法性(必做前置检查)

../arm-trusted-firmware/tools/fiptool/fiptool info fip.bin

正常结果

终端打印出 TB_FW、SCP_FW、TOS_FW、NT_FW 四段镜像的加载地址、镜像长度、CRC校验信息。

校验必要性

提前规避FIP格式错误,如果校验失败,BL1上电会直接卡在FIP header check failed,无法启动后续固件,提前校验节省调试时间。

第三阶段:pflash镜像扩容至64MB(适配QEMU硬件规范)

步骤1:处理BL1镜像(第一块只读Flash)

cp bl1.bin bl1_64m.bin
truncate -s 64M bl1_64m.bin

  • cp:备份原始镜像,防止源文件被意外修改;
  • truncate -s 64M:保留原有固件数据,在文件末尾填充0字节,将文件总大小扩充为64MB,匹配QEMU pflash硬件容量约束。

步骤2:处理FIP固件包(第二块Flash)

cp fip.bin fip_64m.bin 
truncate -s 64M fip_64m.bin

步骤3:校验镜像大小

ls -lh bl1_64m.bin
fip_64m.bin

预期:两个文件大小均为64M。
异常:大小不是64M,QEMU启动直接抛出ROM区域大小不匹配错误。
制作uramdisk.imgbootdisk.img,在制作好busybox基础制作
./u-boot/tools/mkimage -A arm64 -O linux -T ramdisk -C gzip -n "aarch64_rootfs" -d ramdisk.cpio.gz uramdisk.img

制作制作
bootdisk.img
dd if=/dev/zero of=bootdisk.img bs=1M count=64
mkfs.ext4 bootdisk.img
mkdir -p tmp_mount
sudo mount bootdisk.img tmp_mount/
sudo cp Image qemu_virt_optee.dtb uramdisk.img tmp_mount/
sudo umount tmp_mount

第四阶段:启动成功进入uboot日志

qemu-system-aarch64 -M virt,secure=on,gic-version=2 -cpu cortex-a57 -smp 2 -m 1024 -nographic -drive if=pflash,format=raw,file=bl1_64m.bin,readonly=on -drive if=pflash,format=raw,file=fip_64m.bin -device loader,file=Image,addr=0x52000000 -device loader,file=qemu_virt_optee.dtb,addr=0x55000000 -device loader,file=uramdisk.img,addr=0x56000000 -device virtio-blk-device,drive=hd0 -drive if=none,file=bootdisk.img,id=hd0,format=raw -serial mon:stdio -serial tcp:localhost:54320,server,nowait

设置打印输出方便调试
=> setenv bootargs "console=ttyAMA0,115200 earlycon=pl011,0x09000000 root=/dev/ram init=/linuxrc rw"
=> booti 0x52000000 0x56000000 0x55000000

设备树修改:

/dts-v1/;

/ {
	interrupt-parent = <0x8005>;
	model = "linux,dummy-virt";
	#size-cells = <0x02>;
	#address-cells = <0x02>;
	compatible = "linux,dummy-virt";

    /* 新增:firmware 节点 + optee 子节点 */
	firmware {
		optee {
			compatible = "linaro,optee-tz";
			method = "smc";
		};
	};

	psci {
		migrate = <0xc4000005>;
		cpu_on = <0xc4000003>;
		cpu_off = <0x84000002>;
		cpu_suspend = <0xc4000001>;
		method = "smc"; //"hvc"你的设备树指定 PSCI 使用 hvc 调用方式(Hypervisor 调用),
                                 //但当前系统运行在 EL1 特权级、没有 Hypervisor 层,HVC 指令属于未定义指令,直接触发异常;
                                //调用栈完全印证了这一点:psci_probe → 执行 HVC 指令 → 未定义指令异常 → 内核 panic。
		compatible = "arm,psci-1.0\0arm,psci-0.2\0arm,psci";
	};

	

无法挂载文件系统,修改设备树
flash@0 {
        bank-width = <0x04>;
        reg = <0x00 0x4000000 0x00 0x4000000>;
        compatible = "cfi-flash";
	};

崩溃日志分析,是没有找到根文件系统
[    2.633114] ALSA device list:
[    2.633732]   No soundcards found.
[    2.644052] uart-pl011 9000000.pl011: no DMA platform data
[    2.654346] /dev/root: Can't open blockdev
[    2.655059] VFS: Cannot open root device "ram" or unknown-block(1,0): error -6
[    2.655320] Please append a correct "root=" boot option; here are the available partitions:
[    2.656158] fe00           65536 vda
[    2.656424]  driver: virtio_blk
[    2.656802] 1f00           65536 mtdblock0
[    2.656866]  (driver?)
[    2.657988] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)
[    2.658848] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.0.12 #2
[    2.659309] Hardware name: linux,dummy-virt (DT)
[    2.660070] Call trace:
[    2.660451]  dump_backtrace+0xdc/0xe8
[    2.661054]  show_stack+0x18/0x50
[    2.661329]  dump_stack_lvl+0x68/0x84
[    2.661574]  dump_stack+0x18/0x34
[    2.661774]  panic+0x16c/0x32c
[    2.661950]  mount_block_root+0x15c/0x210
[    2.662157]  mount_root+0x1e0/0x21c
[    2.662347]  prepare_namespace+0x130/0x170
[    2.662542]  kernel_init_freeable+0x24c/0x290
[    2.662742]  kernel_init+0x24/0x130
[    2.662936]  ret_from_fork+0x10/0x20
[    2.663910] SMP: stopping secondary CPUs
[    2.664989] Kernel Offset: 0x485f02e00000 from 0xffff800008000000
[    2.665237] PHYS_OFFSET: 0xffff94e6c0000000
[    2.665501] CPU features: 0x4400,080cb020,00001086
[    2.666151] Memory Limit: none
[    2.667381] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0) ]---

增加root=参数没有解决,配置内核,继续增加支持RAM DISK
General setup -> Initial RAM filesystem and RAM disk (initramfs/initrd) support
继续提示无法加载,在宿主机上处理 uramdisk.img,去掉 U-Boot 头部,生成内核可直接识别的纯 gzip 压缩镜像。
跳过前64字节的uImage头,输出纯压缩的根文件系统
dd if=uramdisk.img of=rootfs_raw.gz bs=64 skip=1
1. 先卸载之前可能挂载的镜像(如果有)
sudo umount bootdisk.img 2>/dev/null
2. 重新格式化磁盘,保证干净
mkfs.ext4 -F bootdisk.img
mkdir -p rootfs_mnt
sudo mount bootdisk.img rootfs_mnt
mkdir -p tmp_extract
zcat rootfs_raw.gz | cpio -idmv -D tmp_extract
3. 把 rootfs 子目录里的所有内容移到磁盘根目录
sudo mv tmp_extract/rootfs/* rootfs_mnt/
sudo mv tmp_extract/rootfs/.* rootfs_mnt/ 2>/dev/null
5. 补全系统运行必须的空目录
sudo mkdir -p rootfs_mnt/{dev,proc,sys,tmp,run}
6. 卸载并同步数据
sudo umount rootfs_mnt

进入uboot之后启动命令
setenv bootargs "console=ttyAMA0,115200 earlycon=pl011,0x09000000 root=/dev/vda rw init=/linuxrc"
booti 0x52000000 - 0x55000000
进入qemu 的 Linux系统的控制台
源码下载地址: https://pan.quark.cn/s/a4b39357ea24 谷歌公司设计了一款无费用且具备开源特性的网络浏览器,名为Chrome,因其卓越的速度、稳定性和安全性而广受赞誉。该浏览器运用了前沿的Web渲染引擎Blink以及JavaScript引擎V8,旨在保障网页载入与脚本运行的卓越效能。为应对无网络环境下的Chrome安装需求,特别准备了离线安装包。此压缩文件内含32位与64位两种规格的Chrome浏览器离线安装方案,具体文件名分别为"chromedev_x64-v68.0.3423.2.exe"与"chromedev_x86-v68.0.3423.2.exe"。在文件命名中,"x64"标识64位版本,适用于64位操作系统平台,而"x86"则对应32位版本,适配32位操作系统。文件名中的"v68.0.3423.2"代表Chrome的一个特定版本号,各版本可能涵盖安全补丁、性能改进或新增功能。与32位Chrome相比,64位版本具备如下长处:能够处理更多内存容量,从而提升多任务作业能力;针对现代硬件的优化使其运行更为迅猛;64位版本更具备高级别的安全防护,能更周全地抵御恶意软件的侵袭。尽管如此,32位版本对于仍在使用32位操作系统的用户,或是在系统资源需求不高的场景下,依然适用。在部署Chrome浏览器时,用户需依据其个人计算机的操作系统平台,挑选匹配的版本进行安装。通过击相应的.exe文件,安装流程将自动启动,一般包含接受使用许可、确定安装路径及构建桌面快捷方式等环节。若在安装阶段遭遇难题,可参照提示信息或联系技术支援获取协助,同时该压缩文件发布者亦表明欢迎用户以留言形式反映问题。Chrome浏览器的主要特质涵盖:直观的用户界面设计...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值