----------------------------------------------------------------------------------------------------------------------------
开发板 :NanoPC-T6
开发板
eMMC
:256GB
LPDDR4
:16GB
显示屏 :15.6
英寸HDMI
接口显示屏
u-boot
:2017.09
linux
:6.1
----------------------------------------------------------------------------------------------------------------------------
本节将会介绍linux
内核以及uboot
的编译过程,该编译教程来来自友善之家官方。
一、下载工具和固件
1.1 下载工具
root@zhengyang:/work/sambashare/rk3588/friendly# git clone https://github.com/friendlyarm/sd-fuse_rk3588.git --single-branch -b kernel-6.1.y
root@zhengyang:/work/sambashare/rk3588/friendly# git clone https://521github.com/friendlyarm/sd-fuse_rk3588.git --single-branch -b kernel-6.1.y
root@zhengyang:/work/sambashare/rk3588/friendly# cd sd-fuse_rk3588/
如果第一个下载比较慢,可以尝试使用第二个命令,切换镜像源。后面涉及到的github
源码下载,均可切换为521github
。
1.2 下载固件
系统镜像,这里我们以debian-bullseye-desktop-arm64
为例,下载地址:https://download.friendlyelec.com/NanoPC-T6
。
将debian-bullseye-desktop-arm64-images.tgz
(位于"\03_分区镜像文件"目录下,以实际下载的文件为准)拷贝到/work/sambashare/rk3588/friendly/sd-fuse_rk3588
目录下;
root@zhengyang:/work/sambashare/rk3588/sd-fuse_rk3588# ll debian*
-rwxrw-rw- 1 root root 1590466719 Dec 3 01:49 debian-bullseye-desktop-arm64-images.tgz*
-rwxrw-rw- 1 root root 75 Nov 18 19:05 debian-bullseye-desktop-arm64-images.tgz.hash.md5*
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# tar -xvzf debian-bullseye-desktop-arm64-images.tgz
解压得到debian-bullseye-desktop-arm64
文件夹;
root@zhengyang:/work/sambashare/rk3588/sd-fuse_rk3588# ll debian-bullseye-desktop-arm64
-rw-r--r-- 1 root root 8072140 May 28 2023 boot.img
-rw-r--r-- 1 root root 1424 May 28 2023 dtbo.img
-rw-r--r-- 1 root root 307200 Sep 8 23:33 idbloader.img
-rw-r--r-- 1 root root 64 Nov 17 10:03 info.conf
-rw-r--r-- 1 root root 35551252 Nov 16 16:17 kernel.img
-rw-r--r-- 1 root root 471488 Sep 8 23:33 MiniLoaderAll.bin
-rw-r--r-- 1 root root 49152 May 28 2023 misc.img
-rw-r--r-- 1 root root 470 Nov 17 10:03 parameter.txt
-rw-r--r-- 1 root root 6227456 Nov 16 16:17 resource.img
-rw-r--r-- 1 root root 3992675220 Nov 17 10:03 rootfs.img
-rw-r--r-- 1 root root 4194304 Sep 8 23:33 uboot.img
-rw-r--r-- 1 root root 159868 Nov 17 10:03 userdata.img
二、编译内核
2.1 下载内核源码
下载内核源代码:
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# git clone https://github.com/friendlyarm/kernel-rockchip --depth 1 -b nanopi6-v6.1.y kernel-rk3588
保存到当前路径kernel-rk3588
文件夹中。
2.2 修改build-kernel.sh
脚本
在编译内核之前我们需要修改build-kernel.sh
脚本;
根据自己安装的交叉编译环境,这里我需要替换如下代码为:
CROSS_COMPILE=aarch64-linux-gnu- 修改为 CROSS_COMPILE=arm-linux-
并且将如下代码移除:
export PATH=/opt/FriendlyARM/toolchain/11.3-aarch64/bin/:$PATH
if [ ! -d /opt/FriendlyARM/toolchain/11.3-aarch64 ]; then
echo "please install aarch64-gcc-11.3 first, using these commands: "
echo " git clone https://github.com/friendlyarm/prebuilts.git -b master --depth 1"
echo " cd prebuilts/gcc-x64"
echo " sudo tar xvf toolchain-11.3-aarch64.tar.xz -C /"
exit 1
fi
我安装的交叉编译环境位于/usr/local/arm/12.2.1
,并且我已经将其配置为全局环境变量了。
此外我们还需要修改./tools/update_kernel_bin_to_img.sh
,配置;
CROSS_COMPILE=arm-linux-
2.3 编译内核
执行编译内核命令,编译完成后会自动更新debian-bullseye-desktop-arm64
目录下的相关镜像文件,包括文件系统中的内核模块 (rootfs.img
会被解包并重新打包,即更新/lib/modules
下的驱动模块);
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# KERNEL_SRC=$PWD/kernel-rk3588 ./build-kernel.sh debian-bullseye-desktop-arm64
using official logo.
using official kernel logo.
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
YACC scripts/kconfig/zconf.tab.c
LEX scripts/kconfig/zconf.lex.c
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
#
# configuration written to .config
#
WRAP arch/arm64/include/generated/uapi/asm/errno.h
WRAP arch/arm64/include/generated/uapi/asm/ioctl.h
......
其中:
KERNEL_SRC
配置为内核源码所在路径;$1
配置为目标OS
系统debian-bullseye-desktop-arm64
;
编译完成后会在./out
路径下生成若干文件:
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ll out/
drwxr-xr-x 7 root root 4096 Dec 4 22:43 cryptodev-linux/
drwxr-xr-x 4 root root 4096 Dec 4 22:43 nft-fullcone/
drwxr-xr-x 3 root root 4096 Dec 4 22:42 output_rk3588_kmodules/
drwxr-xr-x 3 root root 4096 Dec 4 22:43 r8125/
drwxr-xr-x 22 root root 4096 Dec 4 22:47 rootfs_new/
drwxr-xr-x 8 root root 4096 Dec 4 22:46 rtl8812au/
drwxr-xr-x 9 root root 4096 Dec 4 22:44 rtl8821CU/
drwxr-xr-x 8 root root 4096 Dec 4 22:45 rtl8822bu/
drwxr-xr-x 8 root root 4096 Dec 4 22:45 rtl8822cs/
drwxr-xr-x 4 root root 16384 Dec 4 22:43 rtw88/
其中:
cryptodev-linux
、rtl8812au
、rtl8821CU
、rtl8822bu
、rtl8822cs
、rtw88
:cryptodev
以及usb wifi
驱动源码;output_rk3588_kmodules
:为内核驱动模块;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ls out/output_rk3588_kmodules/lib/modules/6.1.25/
cryptodev.ko modules.builtin.bin modules.softdep rtl8821CU.ko rtw_8723du.ko rtw_8822bs.ko rtw_sdio.ko
kernel modules.builtin.modinfo modules.symbols rtl8822bu.ko rtw_8821ce.ko rtw_8822ce.ko rtw_usb.ko
modules.alias modules.dep modules.symbols.bin rtl8822cs.ko rtw_8821c.ko rtw_8822c.ko
modules.alias.bin modules.dep.bin nft_fullcone.ko rtw_8723de.ko rtw_8821cs.ko rtw_8822cs.ko
modules.builtin modules.devname r8125.ko rtw_8723d.ko rtw_8822be.ko rtw_core.ko
modules.builtin.alias.bin modules.order rtl8812au.ko rtw_8723ds.ko rtw_8822b.ko rtw_pci.ko
rootfs_new
:新的根文件系统的源码;
此外debian-bullseye-desktop-arm64
目录下的内核镜像和根文件系统被更新了;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ll debian-bullseye-desktop-arm64
总用量 3962492
drwxr-xr-x 2 root root 4096 Dec 4 22:48 ./
drwxr-xr-x 11 root root 4096 Dec 4 22:42 ../
-rw-r--r-- 1 root root 8072140 May 28 2023 boot.img
-rw-r--r-- 1 root root 1424 May 28 2023 dtbo.img
-rw-r--r-- 1 root root 307200 Sep 8 23:33 idbloader.img
-rw-r--r-- 1 root root 64 Nov 17 10:03 info.conf
-rw-r--r-- 1 root root 37910548 Dec 4 22:46 kernel.img # 更新了
-rw-r--r-- 1 root root 471488 Sep 8 23:33 MiniLoaderAll.bin
-rw-r--r-- 1 root root 49152 May 28 2023 misc.img
-rw-r--r-- 1 root root 470 Dec 4 22:48 parameter.txt # 更新了
-rw-r--r-- 1 root root 5785600 Dec 4 22:46 resource.img # 更新了
-rw-r--r-- 1 root root 4000600956 Dec 4 22:48 rootfs.img # 更新了
-rw-r--r-- 1 root root 4194304 Sep 8 23:33 uboot.img
-rw-r--r-- 1 root root 159868 Nov 17 10:03 userdata.img
2.4 build-kernel.sh
分析
如果感兴趣可以分析一下./build-kernel.sh
的主要工作流程。
2.4.1 配置内核
首先配置内核:
cd ${KERNEL_SRC}
[ -d .git ] && git clean -dxf # 如果不想每次都重新编译,将改行屏蔽
touch .scmversion
make CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH} ${KCFG}
其中:
CROSS_COMPILE
被配置成arm-linux-
;ARCH
被配置成arm64
;KCFG
被配置成nanopi6_linux_defconfig
;
2.4.2 编译内核
make CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH} ${KALL} -j$(nproc)
其中:
KALL
被配置成nanopi6-images
;编译规则定义在arch/arm64/Makefile
文件;$(nproc)
:用于获取系统中可用的处理器核心数;
在arch/arm64/Makefile
文件;
# 编译生成kernel.img
kernel.img: Image.lz4
$(Q)scripts/mkkrnlimg $(objtree)/arch/arm64/boot/Image $(objtree)/kernel.img >/dev/null
@echo ' Image: kernel.img is ready'
DTBS := rk33*-nanopi*-rev*.dtb
# 调用scripts/resource_tool编译生成resource.img(由设备树、图片资源文件组成,不包含内核)
nanopi4-images: dtbs kernel.img $(LOGO) $(LOGO_KERNEL)
$(Q)$(srctree)/scripts/mkimg --dtb $(DTBS) --keep-dtb-name
2.4.3 编译驱动模块
执行make modules
命令编译驱动模块:
rm -rf ${KMODULES_OUTDIR}
mkdir -p ${KMODULES_OUTDIR}
make CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH} INSTALL_MOD_PATH=${KMODULES_OUTDIR} modules -j$(nproc)
if [ $? -ne 0 ]; then
echo "failed to build kernel modules."
exit 1
fi
其中:
- 内核模块路径
KMODULES_OUTDIR
被配置为./out/output_rk3588_kmodules
:
TOPPATH=$PWD
OUT=$TOPPATH/out
if [ ! -d $OUT ]; then
echo "path not found: $OUT"
exit 1
fi
KMODULES_OUTDIR="${OUT}/output_${SOC}_kmodules" # out/output_rk3588_kmodules
2.4.4 安装驱动模块
执行make modules_install
命令安装驱动模块:
make CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH} INSTALL_MOD_PATH=${KMODULES_OUTDIR} modules_install
if [ $? -ne 0 ]; then
echo "failed to build kernel modules."
exit 1
fi
# 用于构建并输出内核版本号
KERNEL_VER=`make CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH} kernelrelease`
(1) 接着编译cryptodev.ko
驱动,并拷贝到内核模块路径out/output_rk3588_kmodules/lib/modules/6.1.25/
;
# build cryptodev-linux
(cd ${OUT} && {
if [ ! -d cryptodev-linux ]; then
git clone https://github.com/cryptodev-linux/cryptodev-linux.git -b master cryptodev-linux
fi
(cd cryptodev-linux && {
make CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH} KERNEL_DIR=${KERNEL_SRC}
cp cryptodev.ko ${KMODULES_OUTDIR}/lib/modules/${KERNEL_VER} -afv
})
})
cryptodev-linux
是一个linux
内核模块,它提供了一个加密硬件的接口,可在用户空间中使用该接口来执行加密和解密操作。
(2) 接着编译usb wifi driver
;
if [ ${BUILD_THIRD_PARTY_DRIVER} -eq 1 ]; then
for (( i=0; i<${#KERNEL_3RD_DRIVERS[@]}; i++ ));
do
build_external_module ${KERNEL_3RD_DRIVERS[$i]} ${KERNEL_3RD_DRIVER_BRANCHES[$i]} ${KERNEL_3RD_DRIVER_NAME[$i]}
done
fi
2.4.5 更新内核模块依赖
使用depmod
命令更新内核模块依赖:
(cd ${KMODULES_OUTDIR}/lib/modules/${KERNEL_VER}/ && {
rm -rf ./build ./source
echo "depmod ${KMODULES_OUTDIR} ${KERNEL_VER} ..."
depmod -a -b ${KMODULES_OUTDIR} ${KERNEL_VER}
})
其中:
-a
选项表示更新所有已经加载或已知的内核模块的依赖关系;-b
选项用于指定内核模块所在的目录;
2.4.6 重新打包rootfs.img
执行./tools/update_kernel_bin_to_img.sh
脚本解压并重新打包rootfs.img
;
./tools/update_kernel_bin_to_img.sh ${OUT} ${KERNEL_SRC} ${TARGET_OS} ${TOPPATH}/prebuilt
其中:
OUT
配置为./out
;KERNEL_SRC
配置为./kernel-rk3588
;TARGET_OS
配置为debian-bullseye-desktop-arm64
;TOPPATH
配置为./
;
其主要工作就是:
- 挂载根文件系统
./debian-bullseye-desktop-arm64/rootfs.img
到某个路径; - 删除原有的驱动模块,即
mount_point/lib/modules/*
文件 - 使用
cp -af
将新编译的驱动模块拷贝到mount_point/lib/modules
; - 如果存在固件(比如
wifi
固件文件为brcmfmac4356-sdio.bin
),使用cp -af
将新编译的固件库拷贝到mount_point/lib/firmware
; - 重新制作根文件系统镜像文件;
2.5 编译内核头文件
编译内核头文件运行如下命令:
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# MK_HEADERS_DEB=1 BUILD_THIRD_PARTY_DRIVER=0 KERNEL_SRC=$PWD/kernel-rk3588 ./build-kernel.sh debian-bullseye-desktop-arm64
这里设置了MK_HEADERS_DEB=1
表示编译内核头文件;
这里我们分析一下内核头文件的编译过程,其实现代码如下:
if [ ${MK_HEADERS_DEB} -eq 1 ]; then
# 设置内核头文件dep包路径为 ./out/linux-headers-6.1.25.deb
KERNEL_HEADERS_DEB=${OUT}/linux-headers-${KERNEL_VER}.deb
rm -f ${KERNEL_HEADERS_DEB}
# 1. 重点 构建debian包
make CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH} bindeb-pkg
if [ $? -ne 0 ]; then
echo "failed to build kernel header."
exit 1
fi
# 跳转到 ./kernel-rk3588/debian/linux-headers目录下
(cd ${KERNEL_SRC}/debian/linux-headers && {
# 删除usr/src/linux-headers*/scripts/子目录下以 .o 结尾的文件和以 .*.cmd结尾的隐藏文件
find usr/src/linux-headers*/scripts/ \
-name "*.o" -o -name ".*.cmd" | xargs rm -rf
# 2. 设置头文件脚本目录./files/linux-headers-5.10-bin_arm64/scripts
HEADERS_SCRIPT_DIR=${TOPPATH}/files/linux-headers-5.10-bin_arm64/scripts
if [ -d ${HEADERS_SCRIPT_DIR} ]; then
# 拷贝脚本文件到 ./kernel-rk3588/debian/linux-headers/usr/src/linux-headers-6.1.25/scripts/
cp -avf ${HEADERS_SCRIPT_DIR}/* ./usr/src/linux-headers-*${KERNEL_VER}*/scripts/
if [ $? -ne 0 ]; then
echo "failed to copy bin file to /usr/src/linux-headers-${KERNEL_VER}."
exit 1
fi
else
echo "not found files/linux-headers-x.y.z-bin_arm64, why?"
exit 1
fi
find . -type f ! -path './DEBIAN/*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
})
# 3. 使用dpkg工具将指定的目录打包成一个debian软件包
dpkg-deb -Zgzip -b ${KERNEL_SRC}/debian/linux-headers ${KERNEL_HEADERS_DEB}
if [ $? -ne 0 ]; then
echo "failed to re-make deb package."
exit 1
fi
# clean up 移除./路径下的xxx.deb文件
(cd $TOPPATH && {
rm -f linux-*${KERNEL_VER}*_arm64.buildinfo
rm -f linux-*${KERNEL_VER}*_arm64.changes
rm -f linux-headers-*${KERNEL_VER}*_arm64.deb
rm -f linux-image-*${KERNEL_VER}*_arm64.deb
rm -f linux-libc-dev_*${KERNEL_VER}*_arm64.deb
})
fi
接下来我们分析一下这段代码,主要涉及三大步骤。
2.5.1 make bindeb-pkg
这里其中有一条比较重要的命令:
make CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH} bindeb-pkgmkae bindeb-pkg
make bindeb-pkg
是一个用于构建debian
包的命令,它通常用于编译linux
内核并生成对应的debian
软件包。
当执行make bindeb-pkg
命令时,它会读取当前目录下的linux
内核源代码,并根据配置文件进行内核编译。
编译过程将包括编译内核、生成模块、创建initramfs
等步骤。最后,它将生成一组二进制文件和相关的debian
控制文件,用于创建 debian
包。
对于kernel-rk3588
执行完成会在内核源码debian
目录生成以下文件;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ll kernel-rk3588/debian/
-rw-r--r-- 1 root root 6 Dec 4 22:54 arch
-rw-r--r-- 1 root root 137 Dec 4 22:54 changelog
-rw-r--r-- 1 root root 1250 Dec 4 22:54 control
-rw-r--r-- 1 root root 692 Dec 4 22:54 copyright
-rw-r--r-- 1 root root 272 Dec 4 22:57 files
drwxr-xr-x 5 root root 4096 Dec 4 22:55 linux-headers/
drwxr-xr-x 7 root root 4096 Dec 4 22:55 linux-image/
drwxr-xr-x 4 root root 4096 Dec 4 22:56 linux-image-dbg/
drwxr-xr-x 4 root root 4096 Dec 4 22:56 linux-libc-dev/
-rwxr-xr-x 1 root root 384 Dec 4 22:54 rules*
drwxr-xr-x 2 root root 4096 Dec 4 22:54 source/
同时会在kernel-rk3588
上一级目录下生成如下deb
包:
linux-image-<version>.deb
:内核镜像文件,用于安装和引导新的内核;linux-headers-<version>.deb
:内核头文件,用于开发其他软件或编译内核模块;linux-libc-dev_<version>.deb
:用于构建用户空间软件的头文件和静态库;
这些生成的debian
包可以在 debian
或基于debian
的系统上安装和使用;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ll ./
-rw-r--r-- 1 root root 8547400 Dec 4 22:56 linux-headers-6.1.25_6.1.25-3_arm64.deb
-rw-r--r-- 1 root root 32745044 Dec 4 22:56 linux-image-6.1.25_6.1.25-3_arm64.deb
-rw-r--r-- 1 root root 84501592 Dec 4 22:57 linux-image-6.1.25-dbg_6.1.25-3_arm64.deb
-rw-r--r-- 1 root root 1319152 Dec 4 22:56 linux-libc-dev_6.1.25-3_arm64.deb
-rw-r--r-- 1 root root 5660 Dec 4 22:57 linux-upstream_6.1.25-3_arm64.buildinfo
......
需要注意的是:这些deb
文件在脚本执行的最后会被删除。
2.5.2 工具拷贝
拷贝./files/linux-headers-5.10-bin_arm64/scripts/
下的编译相关的工具到./kernel-rk3588/debian/linux-headers/usr/src/linux-headers-6.1.25/scripts
下;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ll ./files/linux-headers-5.10-bin_arm64/scripts/
-rwxr-xr-x 1 root root 32688 Dec 4 21:13 asn1_compiler*
drwxr-xr-x 2 root root 4096 Dec 4 21:13 basic/
drwxr-xr-x 2 root root 4096 Dec 4 21:13 dtc/
-rwxr-xr-x 1 root root 15096 Dec 4 21:13 extract-cert*
drwxr-xr-x 2 root root 4096 Dec 4 21:13 genksyms/
-rwxr-xr-x 1 root root 23896 Dec 4 21:13 kallsyms*
drwxr-xr-x 2 root root 4096 Dec 4 21:13 kconfig/
drwxr-xr-x 2 root root 4096 Dec 4 21:13 mod/
-rwxr-xr-x 1 root root 29896 Dec 4 21:13 recordmcount*
drwxr-xr-x 4 root root 4096 Dec 4 21:13 selinux/
-rwxr-xr-x 1 root root 18792 Dec 4 21:13 sorttable*
-rwxr-xr-x 1 root root 43096 Dec 4 21:13 unifdef*
2.5.3 dpkg-deb
使用dpkg-deb
工具将指定的目录打包成一个debian
软件包;
dpkg-deb -Zgzip -b ${KERNEL_SRC}/debian/linux-headers ${KERNEL_HEADERS_DEB}
dpkg-deb
命令的含义:
dpkg-deb
: 这是一个debian
软件包管理工具,用于创建、操作和管理debian
软件包;-Zgzip
: 这是一个选项,表示使用 gzip 压缩格式来压缩数据;-b ${KERNEL_SRC}/debian/linux-headers ${KERNEL_HEADERS_DEB}
: 这部分指定了要打包的目录以及输出的软件包路径;${KERNEL_SRC}/debian/linux-headers
是要打包的目录,即./kernel-rk3588/debian/linux-headers
目录;${KERNEL_HEADERS_DEB}
是输出的debian
软件包路径,即./out/linux-headers-6.1.25.deb
目录;
这里将./kernel-rk3588/debian/linux-headers
打包成debian
软件包,软件包名称为./out/linux-headers-6.1.25.deb
;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ll out/
drwxr-xr-x 7 root root 4096 Dec 4 22:54 cryptodev-linux/
-rw-r--r-- 1 root root 11283434 Dec 4 22:57 linux-headers-6.1.25.deb # 生成的dep软件包
drwxr-xr-x 4 root root 4096 Dec 4 22:43 nft-fullcone/
drwxr-xr-x 3 root root 4096 Dec 4 22:54 output_rk3588_kmodules/
drwxr-xr-x 3 root root 4096 Dec 4 22:54 r8125/
drwxr-xr-x 22 root root 4096 Dec 4 22:58 rootfs_new/
drwxr-xr-x 8 root root 4096 Dec 4 22:46 rtl8812au/
drwxr-xr-x 9 root root 4096 Dec 4 22:44 rtl8821CU/
drwxr-xr-x 8 root root 4096 Dec 4 22:45 rtl8822bu/
drwxr-xr-x 8 root root 4096 Dec 4 22:45 rtl8822cs/
drwxr-xr-x 4 root root 16384 Dec 4 22:54 rtw88/
三、编译uboot
3.1 下载uboot
下载uboot
源代码并编译,编译完成后会自动更新debian-bullseye-desktop-arm64
目录下的相关镜像文件:
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# git clone https://github.com/friendlyarm/uboot-rockchip --depth 1 -b nanopi6-v2017.09
3.2 修改脚本
3.2.1 修改build-uboot.sh
脚本
在编译内核之前我们需要修改build-uboot.sh
脚本;将如下代码移除:
export PATH=/opt/FriendlyARM/toolchain/11.3-aarch64/bin/:$PATH
if [ ! -d /opt/FriendlyARM/toolchain/11.3-aarch64 ]; then
echo "please install aarch64-gcc-11.3 first, using these commands: "
echo " git clone https://github.com/friendlyarm/prebuilts.git -b master --depth 1"
echo " cd prebuilts/gcc-x64"
echo " sudo tar xvf toolchain-11.3-aarch64.tar.xz -C /"
exit 1
fi
3.2.2 修改./uboot-rockchip/make.sh
脚本
根据自己安装的交叉编译环境,修改make.sh
设置交叉编译工具路径::
PREBUILTS_GCC_ARM32=/usr/local/arm/12.2.1/bin
PREBUILTS_GCC_ARM64=/usr/local/arm/12.2.1/bin
同时将select_toolchain
函数以下代码:
CROSS_COMPILE_ARM32=arm-linux-gnueabihf-
CROSS_COMPILE_ARM64=aarch64-linux-gnu-
修改为:
CROSS_COMPILE_ARM32=arm-none-linux-gnueabihf-
CROSS_COMPILE_ARM64=aarch64-none-linux-gnu-
我安装的交叉编译环境位于/usr/local/arm/12.2.1
,并且我已经将其配置为全局环境变量了。
3.3 编译uboot
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# rm -rf rkbin # 删除的目的,是为了重新下载rkbin
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# UBOOT_SRC=$PWD/uboot-rockchip ./build-uboot.sh debian-bullseye-desktop-arm64
编译完成后debian-bullseye-desktop-arm64
目录下的uboot.img
被更新了;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ll out/ll debian-bullseye-desktop-arm64
-rw-r--r-- 1 root root 8072140 May 28 2023 boot.img
-rw-r--r-- 1 root root 1424 May 28 2023 dtbo.img
-rw-r--r-- 1 root root 307200 Sep 8 23:33 idbloader.img
-rw-r--r-- 1 root root 64 Nov 17 10:03 info.conf
-rw-r--r-- 1 root root 37910548 Dec 4 22:57 kernel.img
-rw-r--r-- 1 root root 471488 Dec 4 23:26 MiniLoaderAll.bin # 更新了
-rw-r--r-- 1 root root 49152 May 28 2023 misc.img
-rw-r--r-- 1 root root 470 Dec 4 22:59 parameter.txt
-rw-r--r-- 1 root root 5785600 Dec 4 22:57 resource.img
-rw-r--r-- 1 root root 3986211708 Dec 4 22:59 rootfs.img
-rw-r--r-- 1 root root 4194304 Dec 4 23:26 uboot.img # 更新了
-rw-r--r-- 1 root root 159868 Nov 17 10:03 userdata.img
3.4 build-uboot.sh
分析
如果感兴趣可以分析一下./build-uboot.sh
的主要工作流程。
3.4.1 make.sh nanopi6
进入uboot-rockchip
目录下执行如下命令 :
cd ${UBOOT_SRC}
make distclean
./make.sh nanopi6
其中:UBOOT_SRC
为./uboot-rockchip
,即uboot
源码目录。
有关make.sh
文件我们在博客Rockchip RK3399 - TPL/SPL
方式加载uboot
中有提及到,这是官方提供的一个自动构建的脚本。
我们在命令行输入:
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/uboot-rockchip# ./make.sh help
查看具体编译指令,如下图:
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/uboot-rockchip# ./make.sh help
Usage:
./make.sh [board|sub-command]
- board: board name of defconfig
- sub-command: elf*|loader|trust|uboot|--spl|--tpl|itb|map|sym|<addr>
- ini: ini file to pack trust/loader
Output:
When board built okay, there are uboot/trust/loader images in current directory
Example:
1. Build:
./make.sh evb-rk3588 --- build for evb-rk3588_defconfig
./make.sh firefly-rk3288 --- build for firefly-rk3288_defconfig
./make.sh EXT_DTB=rk-kernel.dtb --- build with exist .config and external dtb
./make.sh --- build with exist .config
./make.sh env --- build envtools
2. Pack:
./make.sh uboot --- pack uboot.img
./make.sh trust --- pack trust.img
./make.sh trust <ini> --- pack trust img with assigned ini file
./make.sh loader --- pack loader bin
./make.sh loader <ini> --- pack loader img with assigned ini file
./make.sh --spl --- pack loader with u-boot-spl.bin
./make.sh --tpl --- pack loader with u-boot-tpl.bin
./make.sh --tpl --spl --- pack loader with u-boot-tpl.bin and u-boot-spl.bin
3. Debug:
./make.sh elf --- dump elf file with -D(default)
./make.sh elf-S --- dump elf file with -S
./make.sh elf-d --- dump elf file with -d
./make.sh elf-* --- dump elf file with -*
./make.sh <no reloc_addr> --- unwind address(no relocated)
./make.sh <reloc_addr-reloc_off> --- unwind address(relocated)
./make.sh map --- cat u-boot.map
./make.sh sym --- cat u-boot.sym
因此当执行./make.sh nanopi6
时,实际上编译使用的defonfig
文件为configs/nanopi6_defconfig
。由于该脚本内容较多,这里就不去分析其编译流程了。
3.4.2 update_uboot_bin.sh
update_uboot_bin.sh
脚本用于更新./debian-bullseye-desktop-arm64
目录下的MiniLoaderAll.bin
、uboot.img
;
./tools/update_uboot_bin.sh ${UBOOT_SRC} ${TOPPATH}/${TARGET_OS}
其中:
UBOOT_SRC
为./uboot-rockchip
,即uboot
源码目录;${TOPPATH}/${TARGET_OS}
为./debian-bullseye-desktop-arm64
;
update_uboot_bin.sh
源码如下:
#!/bin/bash
set -eu
[ -f ${PWD}/mk-emmc-image.sh ] || {
echo "Error: please run at the script's home dir"
exit 1
}
if [ $# -ne 2 ]; then
echo "number of args must be 2"
exit 1
fi
# LOADER_DOT_BIN=./uboot-rockchip/rk3588_spl_loader_v1.12.112.bin
LOADER_DOT_BIN==`ls $1/rk3588_spl_loader_*.bin 2>/dev/null | sort -n | tail -1`
if [ -f ${LOADER_DOT_BIN} ]; then
cp -f ${LOADER_DOT_BIN} $2/MiniLoaderAll.bin
else
echo "not found $1/rk3588_spl_loader_*.bin, pls build u-boot first."
exit 1
fi
cp -f $1/uboot.img $2/
exit $?
四、生成并烧录固件
固件文件一般有两种:
- 单个统一固件:统一固件是由分区表、
bootloader
、uboot
、kernel
、system
等所有文件打包合并成的单个文件。一般官方正式发布的固件都是采用统一固件格式,升级统一固件将会更新主板上所有分区的数据和分区表,并且擦除主板上所有数据; - 多个分区镜像:即各个功能独立的文件,如分区表、
bootloader
、kernel
等,在开发阶段生成。独立分区镜像可以只更新指定的分区,而保持其它分区数据不被破坏,在开发过程中会很方便调试;
通过统一固件解包/打包工具,可以把统一固件解包为多个分区镜像,也可以将多个分区镜像合并为一个统一固件。
4.1 生成统一固件
将debian-bullseye-desktop-arm64
目录下的映象文件重新打包成SD
卡固件:
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ./mk-sd-image.sh debian-bullseye-desktop-arm64
Creating RAW image: out/rk3588-sd-debian-bullseye-desktop-6.1-arm64-20231205.img (7800 MB)
---------------------------------
记录了0+0 的读入
记录了0+0 的写出
0字节已复制,0.000145548 s,0.0 kB/s
----------------------------------------------------------------
[out/rk3588-sd-debian-bullseye-desktop-6.1-arm64-20231205.img] capacity = 7438MB, 7799999488 bytes
current out/rk3588-sd-debian-bullseye-desktop-6.1-arm64-20231205.img partition:
----------------------------------------------------------------
parsing ./debian-bullseye-desktop-arm64/parameter.txt:
create new GPT 9:
----------------------------------------------------------------
copy from: ./debian-bullseye-desktop-arm64 to out/rk3588-sd-debian-bullseye-desktop-6.1-arm64-20231205.img
[RAW. 0]: 300 KB | ./debian-bullseye-desktop-arm64/idbloader.img > 100% : done.
[RAW. 1]: 4096 KB | ./debian-bullseye-desktop-arm64/uboot.img > 100% : done.
[RAW. 2]: 48 KB | ./debian-bullseye-desktop-arm64/misc.img > 100% : done.
[RAW. 3]: 1 KB | ./debian-bullseye-desktop-arm64/dtbo.img > 100% : done.
[RAW. 4]: 5650 KB | ./debian-bullseye-desktop-arm64/resource.img > 100% : done.
[RAW. 5]: 37022 KB | ./debian-bullseye-desktop-arm64/kernel.img > 100% : done.
[RAW. 6]: 7882 KB | ./debian-bullseye-desktop-arm64/boot.img > 100% : done.
[RAW. 8]: 3892784 KB | ./debian-bullseye-desktop-arm64/rootfs.img > 100% : done.
[RAW. 9]: 156 KB | ./debian-bullseye-desktop-arm64/userdata.img > 100% : done.
----------------------------------------------------------------
---------------------------------
RAW image successfully created (00:04:45).
-rw-r--r-- 1 root root 7799999488 Dec 5 00:04 out/rk3588-sd-debian-bullseye-desktop-6.1-arm64-20231205.img
Tip: You can compress it to save disk space.
该sh
脚本内部调用了Rochchip
官方提供的打包工具生成的统一固件,由于打包工具并不开源,所以无法研究源码。
命令完成后,生成的统一固件位于out
目录,可以用dd
命令制作SD
启动卡。
4.2 制作SD
启动卡
在我们将SD
卡插入PC
上,在虚拟机ubuntu
中运行demsg
查看新接入的设备;
[32908.310364] loop7: detected capacity change from 0 to 8257536
[32909.079216] EXT4-fs (loop7): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[33991.894980] loop7: detected capacity change from 0 to 8126464
[33991.948702] EXT4-fs (loop7): mounted filesystem with ordered data mode. Opts: (null). Quota mode: none.
[35745.808031] usb 1-1: new high-speed USB device number 2 using ehci-pci
[35746.078673] usb 1-1: New USB device found, idVendor=14cd, idProduct=1212, bcdDevice= 1.00
[35746.078714] usb 1-1: New USB device strings: Mfr=1, Product=3, SerialNumber=2
[35746.078716] usb 1-1: Product: Mass Storage Device
[35746.078717] usb 1-1: Manufacturer: Generic
[35746.078718] usb 1-1: SerialNumber: 121220160204
[35747.340887] usb-storage 1-1:1.0: USB Mass Storage device detected
[35747.341582] scsi host33: usb-storage 1-1:1.0
[35747.342608] usbcore: registered new interface driver usb-storage
[35747.403944] usbcore: registered new interface driver uas
[35748.377640] scsi 33:0:0:0: Direct-Access Mass Storage Device 1.00 PQ: 0 ANSI: 0 CCS
[35748.378504] sd 33:0:0:0: Attached scsi generic sg3 type 0
[35748.522897] sd 33:0:0:0: [sdc] 31211520 512-byte logical blocks: (16.0 GB/14.9 GiB)
[35748.526150] sd 33:0:0:0: [sdc] Write Protect is off
[35748.526152] sd 33:0:0:0: [sdc] Mode Sense: 03 00 00 00
[35748.528185] sd 33:0:0:0: [sdc] No Caching mode page found
[35748.528254] sd 33:0:0:0: [sdc] Assuming drive cache: write through
[35748.551595] sdc: sdc1 sdc2
[35748.571109] sd 33:0:0:0: [sdc] Attached SCSI removable disk
[35802.517787] rfkill: input handler enabled
可以看到SD
卡对应的设备节点为/dev/sdc
,对应两个分区sdc1
、 sdc2
;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# ls /dev/sdc*
/dev/sdc /dev/sdc1 /dev/sdc2
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# df -hT
文件系统 类型 容量 已用 可用 已用% 挂载点
udev devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs tmpfs 791M 3.6M 787M 1% /run
/dev/sda5 ext4 98G 69G 24G 75% /
tmpfs tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/sda1 vfat 511M 4.0K 511M 1% /boot/efi
/dev/loop15 squashfs 497M 497M 0 100% /snap/gnome-42-2204/132
tmpfs tmpfs 791M 0 791M 0% /run/user/0
tmpfs tmpfs 791M 36K 791M 1% /run/user/1000
/dev/sdc2 ext4 11G 311M 9.8G 4% /media/zhengyang/userdata
/dev/sdc1 ext4 4.5G 4.4G 35M 100% /media/zhengyang/rootfs
开始制作SD
启动卡:
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588# dd if=out/rk3588-sd-debian-bullseye-desktop-6.1-arm64-20231205.img of=/dev/sdc bs=1M
4.3 Linux
下烧录固件
在Linux
下将镜像烧录到eMMC
,无须安装设备驱动,需要使用Linux_Upgrade_Tool
工具,这个是Rockchip
官方提供的linux
环境下的烧录工具。
4.3.1 安装Linux_Upgrade_Tool_1.34
下载 Linux_Upgrade_Tool_1.34.zip
, 并按以下方法安装到系统中,方便调用:
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# unzip Linux_Upgrade_Tool_1.34.zip.zip
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# cd Linux_Upgrade_Tool
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo cp upgrade_tool /usr/local/bin
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo chown root:root /usr/local/bin/upgrade_tool
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo chmod a+x /usr/local/bin/upgrade_tool
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo apt-get install lib32stdc++6
4.3.2 烧写统一固件
将开发板连接上电源,并且通过HDMI
接口连接到显示设备,连接Type-C
数据线到PC
;
按住Mask
键再长按Power
键开机(保持按下Mask
键5秒以上),将强制进入MASKROM
模式,
烧写统一固件update.img
;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool uf update.img
由于我没有统一固件,这里就不演示了。
4.3.3 烧写分区镜像
我们在开发过程中,经常会对内核、根文件系统、uboot
进行修改,在这种情况下我们只需要替换我们修改的镜像文件即可。
按住Mask
键再长按Power
键开机(保持按下Mask
键5秒以上),将强制进入MASKROM
模式,烧写分区镜像;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool ul MiniLoaderAll.bin
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -p parameter.txt
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -uboot uboot.img
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -trust trust.img
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -misc misc.img
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -dtbo dtbo.img
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -resource resource.img
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -k kernel.img
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -boot boot.img
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -rootfs rootfs.img
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool di -userdata userdata.img
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool RD
其中前两步和最后一步是必须的,中间的步骤根据实际情况进行调整。
如果想查看分区情况,执行如下命令,该命令会读取设备上的分区表信息,支持parameter
和gpt
;
root@zhengyang:/work/sambashare/rk3588/friendly/sd-fuse_rk3588/debian-bullseye-desktop-arm64# sudo upgrade_tool pl
Program Data in /root/.config/upgrade_tool
Partition Info(gpt):
NO LBA Size Name
01 0x00004000 0x00002000 uboot
02 0x00006000 0x00002000 trust
03 0x00008000 0x00002000 misc
04 0x0000a000 0x00002000 dtbo
05 0x0000c000 0x00008000 resource
06 0x00014000 0x00014000 kernel
07 0x00028000 0x00018000 boot
08 0x00040000 0x007c0000 rootfs
09 0x00800000 0x0151efdf userdata
参考文章:
[1] Rockchip RK3399 - linux-headers
制作
[2] NanoPC-T6
开发手册