橙狐适配指南:为 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/HEIGHTTW_THEME,否则 soong 无法找到对应的 ui.xmlRGBX_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,核心工作只有三件事:

  1. 找一个参考设备(mondrian),理解 OF 设备树的结构和必需的配置项
  2. 找一个可靠的硬件参数来源(LineageOS),确保分区表、平台代号、内核参数正确
  3. 找一个能工作的 TWRP 镜像(skkk),从中提取 init 脚本和内核模块——这是最关键的步骤,没有这些文件 Recovery 根本起不来

在此基础上,踩坑是不可避免的:API level、分区列表、AVB、主题缩放、振动路径,每个坑都需要逐一定位和验证。关键是保持"先跑起来再优化"的节奏,不要试图一次做对所有事。