3. VIVO-Y927 Linux 内核 + BusyBox 最小系统引导启动实验
|字数总计:1.8k|阅读时长:8分钟|阅读量:|
背景
上一章节完成了 lk1st 的移植,为Linux主线内核的引导和ARM64 Linux 的启动提供了基础。此时 fastboot 正常工作,但是 fastboot boot 无法启动下一步。
本章即将进入到Linux主线内核的真正启动阶段,
获取Linux内核源码
获取内核源码
1 2 3
| cd ~/y927 git clone https://github.com/msm8916-mainline/linux.git -b wip/msm8916/7.0 --depth 1 cd linux
|
第0阶段:零外设验证内核引导启动
目标
最极简的验证:不需要串口、不需要 USB、不需要看屏幕任何输出。只需要一个秒表。
原理:
1
| 内核启动 → 挂载 initramfs → 执行 /init → sleep 15 秒 → exit 触发 panic → kernel 重启
|
观察设备行为:
- 刷入 boot.img 后重启
- 屏幕亮起(lk1st splash) → 停 ~15 秒 → 重启 → 再次亮起(lk1st)
- 如果这个循环发生了,内核就启动了。
不需要任何调试外设,不需要 DTB 写的正确——只需要内核能成功解压、初始化基础 SoC、挂载 initramfs 并运行 init 进程。
最简的骨架 DTS
只要一个骨架设备树,告诉内核这是 MSM8916 平台即可:
1 2 3 4 5 6 7 8 9 10 11
|
/dts-v1/;
#include "msm8916-pm8916.dtsi"
/ { model = "vivo Y927 (PD1410V)"; compatible = "vivo,y927", "qcom,msm8916"; chassis-type = "handset"; };
|
只有 10 行!msm8916-pm8916.dtsi 已经把 SoC 时钟、中断控制器、timer、regulator 等基础全部定义好了。内核只需要 compatible = "qcom,msm8916" 就能初始化 MSM8916 平台。
不写任何外设节点——没有串口、没有 USB、没有 eMMC。内核启动后唯一能做的事就是从 initramfs 执行 /init。
编辑Makefile linux/arch/arm64/boot/dts/qcom/Makefile
1 2 3
| dtb-$(CONFIG_ARCH_QCOM) += msm8916-vivo-y927.dtb
|
制作一个最简 initramfs
Linux 内核完成自举后,会启动用户态第一个进程,也就是 PID 为 1 的 /init 程序。
BusyBox 是遵循 GPL 协议的开源轻量工具集,被称作嵌入式 Linux 的 “瑞士军刀”。它将数百款 Linux 常用命令与工具整合为单个可执行文件,通过软链接和调用名区分不同功能,具备体积小巧、可灵活裁剪的特点,广泛应用于嵌入式设备、微型 Linux 系统及容器场景。
常规完整 Linux 系统中,/init 一般为 SysV init 或 systemd;而搭建极简 initramfs 无需这类重型初始化程序。BusyBox 内置了精简版 init,运行逻辑与 SysV init 相近,完全可以胜任最简系统的初始化工作。
编译 BusyBox
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| cd ~/y927
wget https://busybox.net/downloads/busybox-1.38.0.tar.bz2 tar xf busybox-1.38.0.tar.bz2 rm busybox-1.38.0.tar.bz2 cd busybox-1.38.0
export CROSS_COMPILE=aarch64-linux-gnu- export ARCH=arm64
make defconfig
sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
grep -E "CONFIG_(SLEEP|ASH|MOUNT|REBOOT|INIT)=" .config
sed -i 's/CONFIG_TC=y/CONFIG_TC=n/' .config
make -j$(nproc)
file busybox
|
制作 initramfs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| mkdir -p ~/y927/initramfs/simple-0 cd ~/y927/initramfs/simple-0 mkdir -p bin && cd bin cp ~/y927/busybox-1.38.0/busybox . ln -s busybox init ln -s busybox ash ln -s busybox sh ln -s busybox sleep
cd ~/y927/initramfs/simple-0 cat > init << 'EOF'
/bin/sleep 15 EOF chmod +x init
find . | cpio -o -H newc | gzip > ../initramfs-simple-0.cpio.gz
|
编译 Linux 内核
1 2
| sudo apt install flex bison bc rsync libssl-dev libelf-dev -y
|
1 2 3 4 5
| cd ~/y927/linux
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- msm8916_defconfig make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) Image.gz dtbs
|
构建 boot.img 文件
可以使用mkbootimg工具制作boot.img文件。mkbootimg是专门打包 Android Boot Image 的工具,这个工具之前在lk2nd仓库中存在。
boot.img的格式如下:
| 字段 |
大小 |
描述 |
| ANDROID! header |
2048B |
header_verrsion=0 固定 2KB |
| kernel |
- |
Image.gz + DTB |
| ramdisk |
- |
cpio.gz |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| cat arch/arm64/boot/Image.gz \ arch/arm64/boot/dts/qcom/msm8916-vivo-y927.dtb \ > vmlinuz-dtb
~/y927/lk2nd/lk2nd/scripts/mkbootimg \ --kernel vmlinuz-dtb \ --ramdisk $HOME/y927/initramfs/initramfs-simple-0.cpio.gz \ --cmdline "console=ttyMSM0,115200 panic=1" \ --base 0x80000000 \ --kernel_offset 0x00008000 \ --ramdisk_offset 0x01000000 \ --second_offset 0x00f00000 \ --tags_offset 0x00000100 \ --pagesize 2048 \ --header_version 0 \ --output boot-phase0.img
|
刷入 boot.img 文件
1 2
| fastboot flash boot boot-phase0.img fastboot reboot
|
重启后,手机会陷入 15s 的重启循环中,说明最简 Linux 内核启动成功!
第1阶段:启动 USB 模拟串口进入 Linux 进行操作
目标
阶段0验证了内核能够正常引导成功,但是看不到任何输出。本阶段的目标是通过 USB Gadget Serial 实现串口交互式输入输出,可以通过 USB 线在 PC 端与手机 Linux 系统进行交互。
设备树 DTS
编写以下 DTS 初始化 USB:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
/dts-v1/;
#include "msm8916-pm8916.dtsi" #include <dt-bindings/gpio/gpio.h>
/ { model = "vivo Y927 (PD1410V)"; compatible = "vivo,y927", "qcom,msm8916"; chassis-type = "handset";
usb_id: usb-id { compatible = "linux,extcon-usb-gpio"; id-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>; pinctrl-names = "default"; pinctrl-0 = <&usb_id_default>; }; };
&usb { dr_mode = "peripheral"; extcon = <&usb_id>, <&usb_id>; status = "okay"; };
&usb_hs_phy { extcon = <&usb_id>; status = "okay"; };
&tlmm { usb_id_default: usb-id-default { pins = "gpio110"; function = "gpio"; drive-strength = <8>; bias-pull-up; }; };
|
制作 initramfs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| BUSYBOX_BINARY=~/y927/busybox-1.38.0/busybox cd ~/y927/initramfs rm -rf phase-1 mkdir -p phase-1 && cd phase-1
mkdir -p bin dev proc sys
cp $BUSYBOX_BINARY bin/
cd bin for cmd in sh mount ls cat sleep exec echo; do ln -sf busybox $cmd done cd ..
cat > init << 'EOF'
mount -t proc proc /proc mount -t sysfs sys /sys mount -t devtmpfs dev /dev echo "===== Phase 1: kernel booted! =====" echo "Serial: $(cat /proc/cmdline)" sleep 5 exec sh </dev/ttyGS0 >/dev/ttyGS0 2>&1 EOF chmod +x init
find . | cpio -o -H newc | gzip > ../initramfs-phase-1.cpio.gz
|
内核编译配置
1 2
| cd ~/y927/linux make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- msm8916_defconfig
|
msm8916_defconfig 只需额外启用 USB gadget serial 相关选项:
1 2 3
| ./scripts/config --enable CONFIG_USB_G_SERIAL ./scripts/config --enable CONFIG_U_SERIAL_CONSOLE make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- olddefconfig
|
olddefconfig 会自动解析新选项的 Kconfig 依赖链(USB_CHIPIDEA、USB_GADGET、USB_CONFIGFS 等),避免手动改 .config 导致的依赖缺失。
编译 Linux 内核
1
| make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) Image.gz dtbs
|
产物:
arch/arm64/boot/Image.gz — 压缩内核
arch/arm64/boot/dts/qcom/msm8916-vivo-y927.dtb — 设备树 blob
构建 boot.img 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| cd ~/y927/linux
cat arch/arm64/boot/Image.gz \ arch/arm64/boot/dts/qcom/msm8916-vivo-y927.dtb \ > vmlinuz-dtb
~/y927/lk2nd/lk2nd/scripts/mkbootimg \ --kernel vmlinuz-dtb \ --ramdisk $HOME/y927/initramfs/initramfs-phase-1.cpio.gz \ --cmdline "console=ttyGS0,115200 panic=1" \ --base 0x80000000 \ --kernel_offset 0x00008000 \ --ramdisk_offset 0x01000000 \ --second_offset 0x00f00000 \ --tags_offset 0x00000100 \ --pagesize 2048 \ --header_version 0 \ --output boot-phase1.img
|
cmdline 只启用 USB 串口,不碰屏幕(无 console=tty0、无 lk2nd.pass-simplefb)。
刷入 boot.img 文件
1 2
| fastboot flash boot boot-phase1.img fastboot reboot
|
USB 串口交互式输入输出测试
PC 端安装 picocom:
1
| sudo apt install -y picocom
|
连接(需 root 权限访问 /dev/ttyACM0):
1
| sudo picocom -b 115200 /dev/ttyACM0
|
启动成功后应看到:
此时可以使用busybox中打包的所有命令
串口终端 退出 picocom:Ctrl+A 松手 → Ctrl+X。