目录
- [1 实验目的及环境](#1 实验目的及环境)
-
- [1.1 实验目的](#1.1 实验目的)
- [1.2 实验环境](#1.2 实验环境)
-
- [1.2.1 拉取代码](#1.2.1 拉取代码)
- 1.2.2搭建交叉编译环境
- [2 相关镜像编译](#2 相关镜像编译)
-
- [2.1 TF-A镜像编译](#2.1 TF-A镜像编译)
- [2.2 U-Boot镜像编译](#2.2 U-Boot镜像编译)
- [2.3 Linux Kernel镜像编译](#2.3 Linux Kernel镜像编译)
- [2.4 构建跟文件系统](#2.4 构建跟文件系统)
- [3 启动linux内核](#3 启动linux内核)
-
- [3.1 启动脚本构建](#3.1 启动脚本构建)
- [3.2 启动Linux内核](#3.2 启动Linux内核)
1 实验目的及环境
1.1 实验目的
通过FVP加载TF-A,用uboot作为TF-A的BL33,然后使用uboot加载linux内核。
1.2 实验环境
1.2.1 拉取代码
需要拉去的代码为:Linux源码、TF-A源码、Uboot源码。
1.2.2搭建交叉编译环境
(1)安装依赖
sudo apt-get update
sudo apt-get install -y \
gcc-aarch64-linux-gnu make git flex bison bc \
libssl-dev device-tree-compiler dwarves \
libncurses-dev python3
(2)设置环境变量
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
2 相关镜像编译
2.1 TF-A镜像编译
(1)获取源码
git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git
cd trusted-firmware-a
(2)编译镜像
编译生成BL1、BL2、BL31并生成FIP包,指定Uboot作为BL33。
make PLAT=fvp DEBUG=1 RESET_TO_BL31=1 \
BL33=/abs/path/to/u-boot.bin \
all fip
注:这里的RESET_TO_BL31=1指的是直接从BL31启动,因为我们是在fvp环境中启动,BL1、BL2这些和具体硬件平台相关的代码并不需要,同时能够加快启动速度。
2.2 U-Boot镜像编译
(1)获取源码
git clone https://source.denx.de/u-boot/u-boot.git
cd u-boot
(2)配置FVP为默认板子
make CROSS_COMPILE=aarch64-linux-gnu- vexpress_fvp_defconfig
(3)编译
make CROSS_COMPILE=aarch64-linux-gnu-
注:这部分的内容还有一些需要修改,具体参照3.3小节。
2.3 Linux Kernel镜像编译
(1)获取源码
git clone --depth=1 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
(2)配置
make defconfig
(3)增加FVP虚拟接口的支持
cat > fvp.fragment <<'EOF'
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_MMIO=y
CONFIG_VIRTIO_BLK=y
CONFIG_VIRTIO_NET=y
CONFIG_EXT4_FS=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_INITRD=y
EOF
(4)将fvp.fragment文件中的内容合并到.config
./scripts/kconfig/merge_config.sh .config fvp.fragment
(5)编译
make Image dtbs modules
注:arch/arm64/boot/Image 、arch/arm64/boot/dts/arm/fvp-base-revc.dtb
2.4 构建跟文件系统
(1)获取源码
git clone https://busybox.net/git/busybox.git
cd busybox
(2)配置&静态编译
make defconfig
sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
make -j$(nproc)
make CONFIG_PREFIX=/tmp/initramfs install
(3)准备目录
mkdir -p /tmp/initramfs/{dev,proc,sys}
(4)设备节点
sudo mknod -m 600 /tmp/initramfs/dev/console c 5 1
sudo mknod -m 666 /tmp/initramfs/dev/null c 1 3
(5)最小可用/init
cat > /tmp/initramfs/init <<'EOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs devtmpfs /dev 2>/dev/null || true
echo "Hello from initramfs"
exec /bin/sh
EOF
chmod +x /tmp/initramfs/init
(6)打包
cd /tmp/initramfs
find . -print0 | cpio --null -ov --format=newc | gzip -9 > /tmp/rootfs.cpio.gz
3 启动linux内核
3.1 启动脚本构建
通过脚本启动fvp,加载TF-A并启动Linux,具体脚本如下:
#!/bin/bash
set -e
FVP_BIN=/home/pengfei/Base_RevC_AEMvA_pkg/models/Linux64_GCC-9.3/FVP_Base_RevC-2xAEMvA
TF_A_BUILD=/home/pengfei/code/tf-a/build/fvp/debug
LINUX_BUILD=/home/pengfei/code/linux/arch/arm64/boot
INITRAMFS=/tmp
$FVP_BIN \
-C pctl.startup=0.0.0.0 \
-C bp.secure_memory=0 \
-C bp.ve_sysregs.exit_on_shutdown=1 \
-C cluster0.NUM_CORES=4 -C cluster1.NUM_CORES=4 \
-C bp.secureflashloader.fname=$TF_A_BUILD/bl1.bin \
-C bp.flashloader0.fname=$TF_A_BUILD/fip.bin \
--data cluster0.cpu0=$LINUX_BUILD/Image@0x80080000 \
--data cluster0.cpu0=$LINUX_BUILD/dts/arm/fvp-base-revc.dtb@0x84000000 \
--data cluster0.cpu0=/tmp/rootfs.cpio.gz@0x86000000
3.2 启动Linux内核
这里需要注意一下,如果用fvp的启动起来的uboot,不能粘贴复制,比较麻烦,所以我们直接修改uboot的源码,具体的修改位置为:
u-boot/include/configs/vexpress_aemv8.h
#define CFG_EXTRA_ENV_SETTINGS \
"kernel_addr_r=" __stringify(VEXPRESS_KERNEL_ADDR) "\0" \
"ramdisk_addr_r=" __stringify(VEXPRESS_RAMDISK_ADDR) "\0" \
"pxefile_addr_r=" __stringify(VEXPRESS_PXEFILE_ADDR) "\0" \
"fdt_addr_r=" __stringify(VEXPRESS_FDT_ADDR) "\0" \
"scriptaddr=" __stringify(VEXPRESS_SCRIPT_ADDR) "\0" \
EXTRA_ENV_NAMES \
BOOTENV \
"kernel_addr_r=0x80080000\0" \
"fdt_addr_r=0x84000000\0" \
"ramdisk_addr_r=0x86000000\0" \
/* ---- our overrides ---- */ \
"boot_targets=\0" \
"bootargs=console=ttyAMA0 earlycon=pl011,0x1c090000 rdinit=/init\0" \
"ramdisk_size=0x0011F256\0" \
"bootcmd=booti ${kernel_addr_r} ${ramdisk_addr_r}:${ramdisk_size} ${fdt_addr_r}\0"
注:ramdisk_size这个是你构建的跟文件系统的大小的十六进制。另外每次修改uboot的文件都需要重新编译uboot,同时还需要重新编译TF-A。