橙狐适配指南:为 Redmi K60 Pro (socrates) 移植 OrangeFox Recovery
设备:Redmi K60 Pro,代号
socrates,骁龙 8 Gen 2 平台
基版:OrangeFox fox_12.1(Android 12L 分支)
日期:2026-05-10
一、适配前的准备工作
1.1 硬件评估
拿到设备的首要任务是弄清楚它的核心参数,这直接决定适配难度:
| 项目 | 值 | 影响 |
|---|---|---|
| SoC | Snapdragon 8 Gen 2 (SM8550) | 平台代号 kalama,QCOM 系 |
| 分区方案 | Virtual A/B + 独立 recovery 分区 | 不需要 BOARD_USES_RECOVERY_AS_BOOT |
| 内核 | GKI 5.15 | 内核在 vendor_boot,recovery 镜像不含内核 |
| 屏幕 | 1440×3200, 120Hz | 需要正确处理 DPI 和缩放 |
| 触屏 | Goodix | 需要 firmware + 内核模块 |
| 振动 | qcom-hv-haptics | 需要特殊处理(另有博文详述) |
| Android 版本 | 15 (HyperOS 2.0) | 远高于 OF 基版的 API 32 |
1.2 现有资源调研
在动手之前,先查清楚社区已有的东西,避免重复造轮子:
- LineageOS 已官方支持 socrates:有完整的 device tree、kernel source、vendor blobs
- skkk 的 TWRP 已适配:ROM 包中提供了可工作的
recovery_twrp.img - OrangeFox 已适配 mondrian (K60):虽然不是同一个设备,但平台相近(都是 Xiaomi Snapdragon),设备树可以作为模板
- OrangeFox 未适配 socrates:这就是我们要做的
结论:不需要从零开始。LineageOS 设备树提供硬件参数,mondrian OF 设备树提供 OF 模板,skkk 的 TWRP 提供可参考的 init 和模块。
1.3 编译环境
WSL2 Ubuntu 22.04 on Windows 11
CPU: AMD Ryzen 9 9955HX (16C/32T)
RAM: 20 GB (allocated to WSL)
Disk: F:\ 分区, 540 GB 可用
为什么用 WSL 而不是虚拟机?Android 编译涉及海量小文件 I/O,WSL2 的 ext4 性能远优于 Hyper-V 虚拟磁盘。编译时间为 8-9 分钟(32 线程)。
二、适配策略
2.1 核心思路:三方融合
LineageOS device tree (socrates) → 提取硬件参数、分区表、fstab
OFRP device tree (mondrian) → 参考 OF 特有的配置和变量
skkk TWRP recovery.img → 提取 init 脚本、内核模块、vendor blobs
↓
融合生成 socrates OFRP 设备树
2.2 目录结构
device/xiaomi/socrates/
├── AndroidProducts.mk # 产品入口
├── twrp_socrates.mk # 产品定义
├── device.mk # 设备包/HAL 配置
├── BoardConfig.mk # 板级配置(核心文件)
├── vendorsetup.sh # OrangeFox 构建变量
├── modules.load.recovery # 需要加载的内核模块列表
├── recovery/root/
│ ├── init.recovery.qcom.rc # Recovery init 脚本
│ ├── init.recovery.usb.rc # USB 初始化
│ ├── system/etc/recovery.fstab # 分区表
│ └── vendor/ # 从 skkk TWRP 提取的二进制模块/固件
└── patches/ # OrangeFox 源码补丁
2.3 BoardConfig.mk 关键配置
板级配置是设备树的核心,下面逐段说明:
架构和平台
TARGET_ARCH := arm64
TARGET_ARCH_VARIANT := armv8-a-branchprot
TARGET_BOARD_PLATFORM := kalama # SM8550 的代号
TARGET_BOARD_PLATFORM_GPU := qcom-adreno740
branchprot 是 ARMv8.5 的分支保护特性,从 LineageOS 设备树继承。
内核和分区方案
BOARD_BOOT_HEADER_VERSION := 4 # GKI 设备使用 v4
BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE := true # GKI:内核在 vendor_boot
BOARD_RECOVERYIMAGE_PARTITION_SIZE := 104857600
BOARD_SUPER_PARTITION_SIZE := 9663676416
GKI 设备的 recovery 镜像只包含 ramdisk,内核由 bootloader 从 vendor_boot 分区加载。BOARD_EXCLUDE_KERNEL_FROM_RECOVERY_IMAGE 告诉构建系统不要在 recovery.img 中放入内核。
A/B 和动态分区
AB_OTA_UPDATER := true
BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := \
system system_ext product vendor vendor_dlkm odm
socrates 有独立的 recovery 分区(不是 recovery-as-boot),同时支持 Virtual A/B。需要注意:Android 12L 构建系统不认识 system_dlkm 分区,需要从列表中移除。
主题和显示
TW_THEME := portrait_hdpi
TARGET_SCREEN_WIDTH := 1440
TARGET_SCREEN_HEIGHT := 3200
TW_FRAMERATE := 60
TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888
必须同时设置 TARGET_SCREEN_WIDTH/HEIGHT 和 TW_THEME,否则 soong 无法找到对应的 ui.xml。RGBX_8888 与 DRM 驱动需要的 XBGR8888 在内存布局上一致。
2.4 vendorsetup.sh —— OrangeFox 特性配置
# 核心特性
export OF_AB_DEVICE_WITH_RECOVERY_PARTITION=1 # 独立 recovery 分区
export FOX_VIRTUAL_AB_DEVICE=1 # VAB 设备
export OF_USE_LZ4_COMPRESSION=1 # ramdisk 压缩
# 显示
export OF_SCREEN_H=2400 # 20:9 屏幕换算值
export OF_STATUS_H=99 # 状态栏高度
export OF_HIDE_NOTCH=1 # 隐藏刘海
# 功能
export FOX_ENABLE_APP_MANAGER=1 # 应用管理器
export FOX_ENABLE_KERNELSU_SUPPORT=1 # KernelSU
export FOX_USE_BASH_SHELL=1 # bash
OF_SCREEN_H=2400 的计算方式:OrangeFox 默认 16:9 画布,20:9 屏幕的适配公式为 n × 120(n 为宽高比中"9"的系数),即 20 × 120 = 2400。
2.5 Recovery Root 文件
从 skkk TWRP 镜像中提取的文件:
| 类型 | 数量 | 来源 |
|---|---|---|
| 内核模块 (.ko) | 317 | vendor/lib/modules/1.1/ |
| 触屏固件 | 8 | vendor/firmware/goodix_* |
| Vendor HAL | 10+ | vendor/bin/hw/、vendor/lib64/ |
| Init 脚本 | 20+ | vendor/etc/init/、system/etc/init/ |
提取方法:
# 从 recovery_twrp.img 中提取 LZ4 压缩的 ramdisk
python3 -c "..." # 跳过 boot header
lz4 -d ramdisk.lz4 - | cpio -idm
三、编译流程
3.1 同步源码
OrangeFox 使用自定义的 orangefox_sync.sh 脚本,它先同步 TWRP minimal manifest(OmniROM 12.1 基础),再 patch 上 OrangeFox 自己的仓库:
mkdir -p ~/OrangeFox_sync && cd ~/OrangeFox_sync
git clone https://gitlab.com/OrangeFox/sync.git
cd sync
./orangefox_sync.sh --branch 12.1 --path ~/fox_12.1
- 下载量:约 50 GB
- 耗时:1-2 小时(取决于网络)
- 国内用户注意事项:
gerrit.googlesource.com被墙,需设置REPO_URL镜像或使用代理
3.2 应用设备补丁
socrates 需要两个 OrangeFox 源码级修改:
# 触觉反馈修复(点击卡顿的解决方案——另有博文详述)
cp patches/events_modified.cpp \
~/fox_12.1/bootable/recovery/minuitwrp/events.cpp
# 隐藏振动设置页(与 input-ff 路径冲突)
cp patches/settings_modified.xml \
~/fox_12.1/bootable/recovery/gui/theme/portrait_hdpi/pages/settings.xml
3.3 部署设备树
mkdir -p ~/fox_12.1/device/xiaomi/socrates
cp -r device/xiaomi/socrates/* ~/fox_12.1/device/xiaomi/socrates/
3.4 编译
cd ~/fox_12.1
export ALLOW_MISSING_DEPENDENCIES=true
export LC_ALL=C
source build/envsetup.sh
lunch twrp_socrates-eng
mka recoveryimage -j$(nproc)
编译分三个阶段:
| 阶段 | 内容 | 耗时 |
|---|---|---|
| Soong bootstrap | 构建 Go 编译工具链 | ~30 秒 |
| Ninja 编译 | C/C++ 源码编译 | ~1 分钟(增量)/ ~8 分钟(全量) |
| OrangeFox 打包 | ramdisk 组装、签名、zip | ~30 秒 |
3.5 产物
out/target/product/socrates/
├── recovery.img # 原始 recovery (ramdisk only, 100 MB)
├── OrangeFox-R12.0_260510-Unofficial-socrates.img # 发布版
└── OrangeFox-R12.0_260510-Unofficial-socrates.zip # 卡刷包 (~75 MB)
3.6 刷入
# 手机进入 fastboot 模式后:
fastboot flash recovery_a recovery.img
fastboot flash recovery_b recovery.img
fastboot reboot recovery
注意:
fastboot boot recovery.img在 socrates 上不可用,必须刷入分区。AVB 验证需要先通过--disable-verity --disable-verification禁用,否则卡 bootloader。
四、踩坑记录
4.1 API Level 不匹配
PRODUCT_SHIPPING_API_LEVEL := 33 会导致 BOARD_SYSTEMSDK_VERSIONS (32) 报错。因为 OF fox_12.1 基于 Android 12L (API 32),需要降低为 32。
4.2 system_dlkm 分区
这个分区在 Android 13 引入,但 OF fox_12.1 的构建系统不认识。需要从 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST 中移除。
4.3 Overlay 模块冲突
LineageOS 设备树中的 overlay 包含 xiaomi_hardware_biometrics_config_default 重复定义。Recovery 不需要这些 overlay,直接删除即可。
4.4 AVB 验证
刷入自定义 recovery 后卡 bootloader。需要用 ROM 包中的 vbmeta.img 禁用验证:
fastboot --disable-verity --disable-verification flash vbmeta_a vbmeta.img
fastboot --disable-verity --disable-verification flash vbmeta_system_a vbmeta_system.img
4.5 反复进 recovery
fastboot reboot recovery 会在 misc 分区写恢复标志。擦除即可:
fastboot erase misc
fastboot --set-active=a
fastboot reboot
4.6 点击卡顿
点击按钮和切换选项卡严重卡顿,但列表滑动正常。排除渲染、驱动问题后,定位到振动路径——AIDL vibrator service 在 Recovery 环境中不存在,每次点击都触发同步等待超时。解决方案是直接通过 Linux input force-feedback 驱动 qcom-hv-haptics。(适配过程和原理解析详见《[博文标题待定]》)
五、总结
适配一个官方不支持的设备到 OrangeFox,核心工作只有三件事:
- 找一个参考设备(mondrian),理解 OF 设备树的结构和必需的配置项
- 找一个可靠的硬件参数来源(LineageOS),确保分区表、平台代号、内核参数正确
- 找一个能工作的 TWRP 镜像(skkk),从中提取 init 脚本和内核模块——这是最关键的步骤,没有这些文件 Recovery 根本起不来
在此基础上,踩坑是不可避免的:API level、分区列表、AVB、主题缩放、振动路径,每个坑都需要逐一定位和验证。关键是保持"先跑起来再优化"的节奏,不要试图一次做对所有事。