高通 Linux 1.7 编译
高通 Linux(QLI)是一款专为高通芯片设计和优化的嵌入式 Linux 发行版。即高通官方 BSP/SDK。
它提供了一套经过筛选和验证的软件栈,涵盖引导加载程序、内核以及用户空间,使开发者能为高通硬件构建程序。
QLI 是基于 yocto 的,自定义 QLI 需要对 yocto 有足够了解。
环境准备
需要 Ubuntu22 X86_64 Host 环境,强烈建议 docker
请自行上网搜索 docker 的安装方法和配置网络代理方法。
安装好 docker 之后,执行:
# 拉取 ubuntu22 基本镜像
docker pull ubuntu:22.04
# 创建容器
# -v src:des 表示将主机 src 目录挂载到容器的 des 目录,方便容器内访问项目文件,自行设置
# --name 表示容器名称,自行起一个
# --hostname 表示容器的 hostname,自行起一个
docker run --privileged -v /home/xxx/project:/home/xxx/project \
--name container_name --hostname host_name -it ubuntu:22.04 /bin/bash容器启动后,在容器内安装环境:
sudo apt update
sudo apt install build-essential crossbuild-essential-arm64 \
bash-completion vim sudo locales time rsync bc python2 python3
sudo apt install git lz4 zstd diffstat qemu-user-static \
xmlstarlet texinfo chrpath libarchive-dev ssh libselinux1-dev \
fakechroot libiberty-dev liblz4-tool qemu-user-static qemu-user \
gawk libwayland-dev fakeroot libpam0g-dev binutils-dev util-linux \
uuid-dev m4 zip unzip cpio wget python3-pip lib32stdc++6 \
binfmt-support binutils kconfig-frontends python3-rosdep2 libgtest-dev \
python3-lxml libncurses5 pkg-config flex bison libxml2-utils \
libxml-simple-perl whiptail language-pack-en file zlib1g-dev
sudo apt install gnupg curl libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev \
libx11-dev lib32z1-dev libgl1-mesa-dev xsltproc fontconfig
sudo rm -rf /lib/ld-linux-aarch64.so.1
sudo ln -sf /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 /lib/ld-linux-aarch64.so.1
sudo ln -sf /bin/bash /bin/sh
sudo ln -sf /usr/bin/python3 /usr/bin/python
pip3 install dtschema==2021.10
pip3 install jsonschema==4.0.0
pip3 install ruamel.yaml==0.17.17
pip3 install jinja2
pip3 install click
pip3 install lark配置 git
git config --global user.email <Your email ID>
git config --global user.name <"Your Name">
git config --global http.postBuffer 1048576000
git config --global http.maxRequestBuffer 1048576000
git config --global http.lowSpeedLimit 0
git config --global http.lowSpeedTime 999999
git config --global http.followRedirects true下载
从容器中退出,回到宿主机。前往 下载页面 下载 SDK。
将下载好的压缩包存放到容器能访问到的地方(前文创建容器时 -v 的位置),检查分卷压缩的 md5 值:
md5sum ./qcom-linux-*split*将得到值与 SDK 附带的 md5sum.txt 进行比较,确认无误后解压并检出代码:
cat ./qcom-linux-1.7.tgz.split* | tar zx
cd qcom-linux-1.7
git checkout -f HEAD编译
回到容器,移动到 SDK 根目录。里面存在现成的编译脚本。
ffbuild.sh : 主编译脚本。自动编译。
bbenv.sh : yocto 环境初始化脚本,用于启动环境进行手动编译。
完整编译
# 先执行 lunch 选择编译目标
./ffbuild.sh lunch
# 然后进行编译
./ffbuild.sh image注意:如果因为网络问题导致 tensorflow-lite 一直编译失败,可以使用 remove_tensorflow-lite.patch 补丁去除该功能再尝试编译。
输出目录: build-qcom-wayland/tmp-glibc/deploy/images/<TARGET>/qcom-multimedia-image 其中 TARGET 表示你选择的编译目标型号,后文同理。使用该目录即可进行烧录。
注意:默认生成的是 ufs 固件。
对于 QCS6490 产品,需要做如下操作将它改为 emmc 版本:
# 进入到刷机包里面
cd build-qcom-wayland/tmp-glibc/deploy/images/<TARGET>/qcom-multimedia-image
# 删除原本 ufs 的 xml
rm rawprogram*.xml
rm patch*.xml
# 复制 emmc 的 xml 和 bin
cp partition_emmc/rawprogram[0-1].xml ./
cp partition_emmc/patch[0-1].xml ./
cp partition_emmc/*.bin ./自定义内核
使用 yocto 的 devtool 工具进行内核的自定义:
# 启动 yocto 环境
source bbenv.sh
# 检查工作区状态,第一次执行应该会显示当前无工作区
devtool status
# 创建内核工作区,linux-qcom-custom 为内核配方的名称
devtool modify linux-qcom-custom
# 等待上一步完成后,内核代码会位于工作区中,可以前往修改
cd workspace/sources/linux-qcom-custom
# 修改完毕后回到编译目录,重新检查工作区状态
cd /path/to/sdk/build-qcom-wayland
devtool status
# 确认 devtool status 能正确识别到 linux-qcom-custom 工作区后,可进行编译
bitbake linux-qcom-custom qcom-multimedia-image只编译设备树
后续开发只修改设备树可以:
# 启动 yocto 环境
source bbenv.sh
# 用 bitbake 编译 dtb
bitbake dtb-qcom-image生成的文件是:build-qcom-wayland/tmp-glibc/deploy/images/<TARGET>/dtb-qcom-image-*.vfat 重命名为 dtb.bin 即可。
制作 Ubuntu 固件
Ubuntu 系统不支持直接编译,请前往下载中心下载发布的现成固件。如有自定义需求,需要将 QLI 编译生成的 kernel、modules、firmware 等部分移植到 Ubuntu 系统中。
准备工作
先将 QLI 的一些编译产物复制到方便的地方,这里以 ~/work 为例:
# dtb
cp build-qcom-wayland/tmp-glibc/deploy/images/<TARGET>/dtb-qcom-image-<TARGET>.rootfs-*.vfat ~/work/
# kernel
cp -rfd build-qcom-wayland/tmp-glibc/work/<TARGET>-qcom-linux/linux-qcom-custom/6.6/image/boot ~/work/
# modules
cp -rfd build-qcom-wayland/tmp-glibc/work/<TARGET>-qcom-linux/qcom-multimedia-image/1.0/rootfs/usr/lib/modules ~/work/
cp -rfd build-qcom-wayland/tmp-glibc/work/<TARGET>-qcom-linux/qcom-multimedia-image/1.0/rootfs/usr/lib/modules-load.d ~/work/
# firmware
cp -rfd build-qcom-wayland/tmp-glibc/work/<TARGET>-qcom-linux/qcom-multimedia-image/1.0/rootfs/usr/lib/firmware ~/work/将下载好的 Ubuntu 固件解压到方便的地方,这里以 ~/ubun_firmware 为例。
准备脚本 setup.sh 放入 ~/ubun_firmware/ 下,脚本内容为:
#!/bin/bash
usage() {
echo "Usage:"
echo "$0 xxxx.img ----- mount and prepare chroot for this image"
echo "$0 umount ----- umount image"
}
if [[ $# != 1 ]]; then
usage
exit 1
fi
img=$1
mkdir mnt &> /dev/null
do_losetup() {
dev=$(sudo losetup --sector-size=4096 --find --show --partscan $img)
if [[ -n $dev ]]; then
echo "Modify image: $img"
echo "======================="
return 0
else
return 1
fi
}
do_mount() {
if [[ -b "${dev}p3" ]]; then
sudo mount "${dev}p3" mnt || return 1
sudo mount "${dev}p1" mnt/boot/efi || return 1
else
sudo mount "${dev}" mnt || return 1
fi
return 0
}
prepare_chroot() {
sudo mount --bind /dev mnt/dev || return 1
sudo mount --bind /dev/pts mnt/dev/pts || return 1
sudo mount -t proc proc mnt/proc || return 1
sudo mount -t sysfs sysfs mnt/sys || return 1
echo "chroot ready !"
echo "Run \"sudo chroot mnt /bin/bash\" to start."
return 0
}
do_umount() {
sudo umount -R mnt && sudo losetup -D
}
case $1 in
*.img) do_losetup && do_mount && prepare_chroot ;;
umount) do_umount ;;
*) usage ;;
esac最终效果如下:
~/work/
├── boot
├── dtb.bin
├── firmware
├── modules
└── modules-load.d
~/ubun_firmware/
├── aop.mbn
├── cpucp.elf
......
├── prog_firehose_ddr.elf
├── prog_firehose_lite.elf
├── rawprogram0.xml
......
├── setup.sh
......然后将 ~/work 和 ~/ubun_firemware 全部复制到设备上,下面的操作需要在 arm64 设备上进行以避免架构不同带来的错误。
开始移植
复制设备树
cp ~/work/dtb.bin ~/ubun_firmware/挂载文件系统
使用 setup.sh 脚本进行挂载:
cd ~/ubun_firmware
./setup.sh iot-qualcomm-dragonwing-classic-desktop-2404*.img顺利的话,此时文件系统已经挂载在当前的 mnt 目录下。
复制文件
复制文件必须使用 root 权限!
# 复制 kernel 相关
sudo cp ~/work/boot/System.map* ~/ubun_firmware/mnt/boot/
sudo cp ~/work/boot/config-* ~/ubun_firmware/mnt/boot/
sudo cp ~/work/boot/Image-* ~/ubun_firmware/mnt/boot/vmlinuz-*
# 删除旧的 modules 和 firmware
sudo rm -rf ~/ubun_firmware/mnt/usr/lib/modules
sudo rm -rf ~/ubun_firmware/mnt/usr/lib/modules-load.d
sudo rm -rf ~/ubun_firmware/usr/lib/firmware
# 复制新的 modules 和 firmware
sudo cp -rfd ~/work/modules ~/ubun_firmware/mnt/usr/lib/
sudo cp -rfd ~/work/modules-load.d ~/ubun_firmware/mnt/usr/lib/
sudo cp -rfd ~/work/firmware ~/ubun_firmware/mnt/usr/lib/
# 确保文件改动生效
syncchroot 自定义(可选)
如果还有额外定制需求,可以 chroot 到文件系统中进行操作。
cd ~/ubun_firmware/
# 备份并复制 resolv.conf
sudo mv mnt/etc/resolv.conf mnt/etc/resolv.conf.bk
sudo cp /etc/resolv.conf mnt/etc/
# chroot 进入文件系统
sudo chroot mnt /bin/bash此时可以进行 apt 安装软件或其他操作。定制结束后:
# 还原 resolv.conf
rm /etc/resolv.conf
mv /etc/resolv.conf.bk /etc/resolv.conf
# 退出 chroot
exit
# 确保文件改动生效
sync
