什么是 lk2nd?

lk2nd 是社区为 MSM8916 设备开发的二级引导加载程序

  • 不替换原厂 bootloader(aboot/sbl1)
  • 打包成 Android boot image 格式,由原厂 bootloader 加载
  • 提供标准 Android Fastboot 协议接口
  • 自动检测硬件(屏幕、电池等)并生成设备信息
1
2
3
原厂上电 → PBL → SBL1 → aboot(原厂) → lk2nd → 主线Linux内核

Fastboot 协议接口

安装工具链

1
2
3
4
5
6
7
8
# ARM32 交叉编译 (lk2nd/lk1st)
sudo apt install -y gcc-arm-none-eabi

# ARM64 交叉编译 (内核)
sudo apt install -y gcc-aarch64-linux-gnu

# 其他工具
sudo apt install -y device-tree-compiler google-android-platform-tools-installer git

克隆仓库

1
2
3
cd ~/y927
# lk2nd(含 lk1st)
git clone https://github.com/msm8916-mainline/lk2nd.git --depth 1

编译刷入第一版lk2nd

背景

高通 MSM8916 平台启动时,aboot/lk2nd 会从硬件读取一个 board-id 值,然后用它来匹配对应的 DTS(设备树)。每个 DTS 里都声明了它适用的 board-id。

巧合

Y927 的硬件 board-id 恰好是 0x01 0x01(QRD 公版 ID),这个值和另一台手机 vivo PD1304完全相同。所以即使不用创建单独的设备树,一样可以正常启动。

编译

1
2
3
4
cd ~/y927
# 编译ARM32版本
make -j$(nproc) TOOLCHAIN_PREFIX=arm-none-eabi- lk2nd-msm8916
ls -la build-lk2nd-msm8916/

刷入

进入原厂fastboot执行

1
2
3
cd ~/y927/lk2nd
fastboot flash boot build-lk2nd-msm8916/lk2nd.img
fastboot reboot

重启

此时是可以正常进入lk2nd了的

alt text

PS: 不过这俩屏幕其实完全不一样,这里能显示完全是因为aboot已经把屏幕初始化好了,lk2nd可以直接往framebuffer里写数据了

PD1304 (Y13L) Y927 (PD1410V)
面板 IC NT35510S HX8394A
分辨率 FWVGA (480×854) 720×1280
DSI video / cmd mode video burst, 4-lane, DCDC PHY
触摸 IC EDT FT5306 Goodix GT9159 (GT9xx)
背光 GPIO 8 8 ✅
LCD ENP GPIO 97
LCD ENN GPIO 98

为什么 PD1304 的 DTB 能在 Y927 上亮屏?

aboot 残留 + lk2nd 不碰 DSI。

原厂 aboot 启动(加载的是原厂 DTB,包含 HX8394A 参数)
→ 初始化 MDP/DSI 硬件(用 HX8394A 参数)
→ 屏幕点亮,framebuffer 就绪
→ 跳转到 lk2nd

lk2nd 启动(此时的 DTB 写的是 NT35510S)
→ lk2nd 的 panel 驱动极其简单,不去碰 DSI 寄存器
→ 直接复用 aboot 留下的 framebuffer,往里画 fastboot UI
→ 屏幕继续亮,但 lk2nd 以为自己在操作 NT35510S(其实不是)

lk2nd 阶段用 PD1304 没问题(它只是个引导器,不碰 DSI),但内核阶段必须用 Y927 自己的
DTS。

DTS 设备树文件

背景

DTS(Device Tree
Source)是一种硬件描述文件。操作系统通过它知道主板上有哪些硬件、怎么驱动它们。

类比:DTS 就像一台手机的"硬件清单"——CPU 型号、屏幕参数、GPIO
引脚配置等等。操作系统启动时读这份清单,才知道自己跑在什么硬件上。

lk2nd 是一个微型引导器,它也需要自己的 DTS,比 Linux 内核的简单得多。

编译刷入第二版lk2nd

lk2nd/lk2nd/device/dts/msm8916/ 下创建:

创建 msm8916-vivo-y927.dts

完整注释版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// SPDX-License-Identifier: BSD-3-Clause

// .dtsi → "Device Tree Source Include",可复用的 DTS 片段
#include <skeleton64.dtsi> // 定义 ARM64 基础框架:CPU 数量、内存地址范围、中断控制器等
#include <lk2nd.dtsi> // 定义 lk2nd 引导器自身的框架:fastboot 接口、按键检测、USB 模式等

/ { // 根节点(硬件身份)
qcom,msm-id = <QCOM_ID_MSM8916 0>; // QCOM_ID_MSM8916 是引用了一个常量,芯片型号,MSM8916 = 206 (0xCE) 0 是芯片修订版本
qcom,board-id = <0x01 0x01>; // QRD 格式 主板ID 子板ID QRD 高通参考设计公版是0x01 为什么需要这两个值:高通平台启动时,CPU 内部 ROM 会读取硬件熔丝里的 board-id,然后遍历所有 DTS,找到 board-id 匹配的那个。就像钥匙和锁 board-id 对上了,说明"这份硬件清单是给我这台手机写的"。
};

&lk2nd { // 引用 lk2nd.dtsi 中定义好的 lk2nd 节点,表示"我要往这个节点里追加/覆盖内容"
model = "Vivo Y927 (PD1410V)"; // 设备型号名称,将显示在 fastboot 界面和日志中
compatible = "vivo,y927", "vivo,pd1304"; // 告诉系统"这台设备兼容哪些型号" 格式:"制造商,型号" 从左到右:最具体 → 最通用 作用:如果将来有代码需要区分不同手机型号,可以通过这个字符串判断。
lk2nd,dtb-files = "msm8916-vivo-y927"; // 这是最关键的一行。 lk2nd 启动 Linux 内核时,需要在 QCDT(一个包含几十个 DTB 的打包文件)里找到正确的内核设备树传给内核。

panel { // 屏幕面板配置
compatible = "vivo,pd1304-panel", "lk2nd,panel"; // 声明这是一个 vivo 面板,用 lk2nd 自带的通用 panel 驱动
qcom,mdss_dsi_hx8394a_720p_video {
compatible = "vivo,hx8394a-720p"; // 声明面板驱动 IC 是 HX8394A,分辨率 720×1280
touchscreen-compatible = "goodix,gt9xx"; // Goodix(汇顶科技)品牌 gt9xx → GT9xx 系列(Y927 实际是 GT9159)
};
};
};

去除注释版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// SPDX-License-Identifier: BSD-3-Clause
#include <skeleton64.dtsi>
#include <lk2nd.dtsi>

/ {
qcom,msm-id = <QCOM_ID_MSM8916 0>; // MSM8916 = 206 (0xCE)
qcom,board-id = <0x01 0x01>; // QRD 格式(同 PD1304)
};

&lk2nd {
model = "Vivo Y927 (PD1410V)";
compatible = "vivo,y927", "vivo,pd1304";
lk2nd,dtb-files = "msm8916-vivo-y927";

panel {
compatible = "vivo,pd1304-panel", "lk2nd,panel";
qcom,mdss_dsi_hx8394a_720p_video {
compatible = "vivo,hx8394a-720p";
touchscreen-compatible = "goodix,gt9xx";
};
};
};

注册到构建系统

编辑 ~/y927/lk2nd/lk2nd/device/dts/msm8916/rules.mk,添加:

1
$(LOCAL_DIR)/msm8916-vivo-y927.dtb \

提交代码

实测必须提交代码后编译才有效

继续编译和刷写

1
2
3
4
5
cd ~/y927/lk2nd
make TOOLCHAIN_PREFIX=arm-none-eabi- lk2nd-msm8916 clean
make -j$(nproc) TOOLCHAIN_PREFIX=arm-none-eabi- LK2ND_QCDTBS="msm8916-vivo-y927.dtb" lk2nd-msm8916
fastboot flash boot build-lk2nd-msm8916/lk2nd.img
fastboot reboot

重启

alt text

可以发现现在手机型号已经发生变化

残留问题

下方显示ARM64: unavailable这是因为原厂 tz/hyp 是 32 位,需要 lk1st + qhypstub,将在下一章开始移植