(初始页面) |
(更正代码高亮格式) |
||
第45行: | 第45行: | ||
=== 安装依赖 === | === 安装依赖 === | ||
sudo apt update | |||
sudo apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev xattr openjdk-11-jdk jq android-sdk-libsparse-utils python3 python2 repo | sudo apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev xattr openjdk-11-jdk jq android-sdk-libsparse-utils python3 python2 repo | ||
必要时可以阅读[https://source.android.com/source/using-repo?hl=zh-cn Git 和 Repo] | 必要时可以阅读[https://source.android.com/source/using-repo?hl=zh-cn Git 和 Repo] | ||
=== 配置 Git 和 Repo === | === 配置 Git 和 Repo === | ||
安装完依赖后,在终端执行。 | 安装完依赖后,在终端执行。 | ||
git config --global user.name "your username" | |||
git config --global user.email "your email" | git config --global user.email "your email" | ||
=== 同步 TWRP 源码 === | === 同步 TWRP 源码 === | ||
在自己方便的地方,建立一个目录。 | 在自己方便的地方,建立一个目录。 | ||
mkdir twrp | |||
cd twrp | cd twrp | ||
根据自己在准备工作中确定的分支同步相应的源码。 | 根据自己在准备工作中确定的分支同步相应的源码。 | ||
==== TWRP-9 ==== | ==== TWRP-9 ==== | ||
repo init --depth=1 -u <nowiki>https://github.com/minimal-manifest-twrp/platform_manifest_twrp_omni.git</nowiki> -b twrp-9.0 | |||
repo sync | repo sync | ||
==== TWRP-11 ==== | ==== TWRP-11 ==== | ||
repo init --depth=1 -u <nowiki>https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git</nowiki> -b twrp-11 | |||
repo sync | repo sync | ||
==== TWRP-12.1 ==== | ==== TWRP-12.1 ==== | ||
repo init --depth=1 -u <nowiki>https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git</nowiki> -b twrp-12.1 | |||
repo sync | repo sync | ||
== 编写设备树 == | == 编写设备树 == | ||
第84行: | 第85行: | ||
===== Mac(Intel) ===== | ===== Mac(Intel) ===== | ||
brew install lz4 xz dtc openjdk@17 | |||
echo 'export PATH="/usr/local/opt/openjdk@17/bin:$PATH"' >> ~/.zshrc | echo 'export PATH="/usr/local/opt/openjdk@17/bin:$PATH"' >> ~/.zshrc | ||
source ~/.zshrc | source ~/.zshrc | ||
===== Linux: ===== | ===== Linux: ===== | ||
sudo apt update | |||
sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full android-sdk-libsparse-utils erofs-utils | sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full android-sdk-libsparse-utils erofs-utils | ||
===== Common: ===== | ===== Common: ===== | ||
git clone <nowiki>https://github.com/cfig/Android_boot_image_editor</nowiki> | |||
cd Android_boot_image_editor | cd Android_boot_image_editor | ||
==== 解包 ==== | ==== 解包 ==== | ||
<blockquote>请注意"/"表示或的意思,请不要误以为是一个东西。 | <blockquote>请注意"/"表示或的意思,请不要误以为是一个东西。 | ||
如果不确定分区寻找的是否正确,请尝试将可以的分区进行解包,并查看其ramdisk内是否包含recovery字样的文件</blockquote>将你准备好的boot/recovery/vendor_boot复制到该目录,你可以使用 GUI 或者 CLI。如: | |||
cp <出厂boot/recovery/vendor_boot的绝对路径> boot/recovery/vendor_boot.img | |||
./gradlew unpack | ./gradlew unpack | ||
我这里以 Redmi K50 为例 | 我这里以 Redmi K50 为例 | ||
10:12:13.188 [main] INFO cfig.bootimg.v3.VendorBoot - | |||
Unpack Summary of vendor_boot.img | Unpack Summary of vendor_boot.img | ||
┌───────────────────────────────────────┬──────────────────────────────────────┐ | ┌───────────────────────────────────────┬──────────────────────────────────────┐ | ||
第122行: | 第123行: | ||
10:12:13.213 [main] WARN cfig.packable.PackableLauncher - 'unpack' sequence completed | 10:12:13.213 [main] WARN cfig.packable.PackableLauncher - 'unpack' sequence completed | ||
BUILD SUCCESSFUL in 2s | BUILD SUCCESSFUL in 2s | ||
解包成功后终端会打印出以上信息,其中包含vendor_boot目录结构,我们只需要ramdisk里的部分内容就好了。 | |||
ls build/unzip_boot/root.1 # 请根据自己的分区和设备判断ramdisk的命名,一般都直接是ramdisk | |||
不出意外的话会输出以下内容 | 不出意外的话会输出以下内容 | ||
xiaolegun@xiaoleGundeMac-Pro ~/github/dump/bootedit master ? ls build/unzip_boot/root.1 | |||
acct oem | acct oem | ||
apex plat_file_contexts | apex plat_file_contexts | ||
第151行: | 第152行: | ||
odm_dlkm vendor_file_contexts | odm_dlkm vendor_file_contexts | ||
odm_file_contexts vendor_property_contexts | odm_file_contexts vendor_property_contexts | ||
odm_property_contexts | odm_property_contexts | ||
如果包含 init.recovery*的字样,恭喜你成功找到了正确的分区。将这个目录复制到一个自己方便的地方。 | 如果包含 init.recovery*的字样,恭喜你成功找到了正确的分区。将这个目录复制到一个自己方便的地方。 | ||
第158行: | 第159行: | ||
=== 初始化目录结构 === | === 初始化目录结构 === | ||
在 twrp 源码根目录输入 | 在 twrp 源码根目录输入 | ||
mkdir -p device/vendor/codename | |||
mkdir -p device/vendor/codename/recovery/root | mkdir -p device/vendor/codename/recovery/root | ||
cd device/vendor/codename | cd device/vendor/codename | ||
vendor指的是供应商,如 xiaomi、oneplus、huawei、vivo、realme。 | |||
codename指的是设备代号,小米设备可以在[https://xiaomirom.com Xiaomirom]查询,其它设备自行查询亦或是在开发者选项勾选 USB 调试通过 adb 尝试获取。 | |||
adb shell getprop ro.product.manufacturer # 供应商 | |||
adb shell getprop ro.product.device # 设备代号 | adb shell getprop ro.product.device # 设备代号 | ||
我的 Redmi K50 会打印以下信息 | 我的 Redmi K50 会打印以下信息 | ||
xiaolegun@xiaoleGundeMac-Pro ~/github/dump/bootedit master ? adb shell getprop ro.product.manufacturer | |||
Xiaomi # 无论打印出来的内容是大写还是小写,在目录结构中我们都采用小写 | Xiaomi # 无论打印出来的内容是大写还是小写,在目录结构中我们都采用小写 | ||
xiaolegun@xiaoleGundeMac-Pro ~/github/dump/bootedit master ? adb shell getprop ro.product.device | xiaolegun@xiaoleGundeMac-Pro ~/github/dump/bootedit master ? adb shell getprop ro.product.device | ||
rubens | rubens | ||
我的 IQOO NEO5 Lite 会打印以下信息 | 我的 IQOO NEO5 Lite 会打印以下信息 | ||
xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens adb shell getprop ro.product.manufacturer | |||
vivo | vivo | ||
xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens adb shell getprop ro.product.device | xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens adb shell getprop ro.product.device | ||
PD2118 | PD2118 | ||
一般只要不是山寨机,小作坊出来的机子,用这两条命令应该是可以正确获取的。 | 一般只要不是山寨机,小作坊出来的机子,用这两条命令应该是可以正确获取的。 | ||
=== 初始化构建时必要的文件 === | === 初始化构建时必要的文件 === | ||
无论是 AOSP device tree 亦或是 TWRP device tree 都基本类似于以下结构。 | 无论是 AOSP device tree 亦或是 TWRP device tree 都基本类似于以下结构。 | ||
/ | |||
├── prebuilt (存放kernel、dtb等预编译文件) # AOSP device tree若使用build kernel则没有该目录 | ├── prebuilt (存放kernel、dtb等预编译文件) # AOSP device tree若使用build kernel则没有该目录 | ||
├── recovery/root (存放一些.rc和解密blobs) # 一般用于Recovery device tree | ├── recovery/root (存放一些.rc和解密blobs) # 一般用于Recovery device tree | ||
第187行: | 第188行: | ||
├── BoardConfig.mk (板载配置文件,定义了主板必要的Flag) | ├── BoardConfig.mk (板载配置文件,定义了主板必要的Flag) | ||
├── device.mk (声明设备所需的文件和模块) | ├── device.mk (声明设备所需的文件和模块) | ||
└── <ROM>_codename.mk (声明产品特定信息,例如名称、品牌和型号,引用device.mk等) # ROM就比如lineage、arrow等,编译twrp就直接写twrp,twrp-9分支要写onmi | └── <ROM>_codename.mk (声明产品特定信息,例如名称、品牌和型号,引用device.mk等) # ROM就比如lineage、arrow等,编译twrp就直接写twrp,twrp-9分支要写onmi | ||
我们把这样的结构称为骨架树(skeleton tree)。 | 我们把这样的结构称为骨架树(skeleton tree)。 | ||
接下来我们按照以上结构为自己的设备写一份 Recovery device tree。 | 接下来我们按照以上结构为自己的设备写一份 Recovery device tree。 | ||
在终端使用touch命令创建必要的文件。 | |||
touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk | |||
ls . | ls . | ||
不出意外的话会打印出以下信息 | 不出意外的话会打印出以下信息 | ||
xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk | |||
xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens ls . | xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens ls . | ||
Android.mk BoardConfig.mk prebuilt twrp_rubens.mk | Android.mk BoardConfig.mk prebuilt twrp_rubens.mk | ||
AndroidProducts.mk device.mk recovery | AndroidProducts.mk device.mk recovery | ||
可以下一步了~ | 可以下一步了~ | ||
第206行: | 第207行: | ||
选中 Android.mk 并按照自己的资料复制并更改以下内容 | 选中 Android.mk 并按照自己的资料复制并更改以下内容 | ||
LOCAL_PATH := $(call my-dir) | |||
ifeq ($(TARGET_DEVICE),codename) | ifeq ($(TARGET_DEVICE),codename) | ||
include $(call all-subdir-makefiles,$(LOCAL_PATH)) | include $(call all-subdir-makefiles,$(LOCAL_PATH)) | ||
endif | endif | ||
* | * codename是需要你修改的部分 | ||
我修改后是这样的 | 我修改后是这样的 | ||
LOCAL_PATH := $(call my-dir) | |||
ifeq ($(TARGET_DEVICE),rubens) | ifeq ($(TARGET_DEVICE),rubens) | ||
include $(call all-subdir-makefiles,$(LOCAL_PATH)) | include $(call all-subdir-makefiles,$(LOCAL_PATH)) | ||
endif | endif | ||
==== 初始 AndroidProducts.mk 文件 ==== | ==== 初始 AndroidProducts.mk 文件 ==== | ||
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容 | 选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容 | ||
PRODUCT_MAKEFILES := \ | |||
$(LOCAL_DIR)/<ROM>_<codename>.mk | $(LOCAL_DIR)/<ROM>_<codename>.mk | ||
COMMON_LUNCH_CHOICES := \ | COMMON_LUNCH_CHOICES := \ | ||
<ROM>_<codename>-eng | <ROM>_<codename>-eng | ||
我修改后是这样的 | 我修改后是这样的 | ||
PRODUCT_MAKEFILES := \ | |||
$(LOCAL_DIR)/twrp_rubens.mk | $(LOCAL_DIR)/twrp_rubens.mk | ||
COMMON_LUNCH_CHOICES := \ | COMMON_LUNCH_CHOICES := \ | ||
twrp_rubens-eng | twrp_rubens-eng | ||
==== 初始 BoardConfig.mk 文件 ==== | ==== 初始 BoardConfig.mk 文件 ==== | ||
<blockquote> | <blockquote>将之前准备的ramdisk文件夹用新窗口打开 1.找到目录下的 prop.default 或含 prop 字样的文件。以下注释类似 ro.*.*的就是从 prop 中获取的 2.解包 boot/recovery/vendor_boot 的 json | ||
例如 build/unzip_boot/boot.json</blockquote>选中 BoardConfig.mk 并按照自己的资料复制并更改以下内容 | 例如 build/unzip_boot/boot.json</blockquote>选中 BoardConfig.mk 并按照自己的资料复制并更改以下内容 | ||
DEVICE_PATH := device/vendor/codename | |||
# Architecture | # Architecture | ||
第330行: | 第331行: | ||
# Debug | # Debug | ||
TARGET_USES_LOGD := true # 调试flag | TARGET_USES_LOGD := true # 调试flag | ||
TWRP_INCLUDE_LOGCAT := true | TWRP_INCLUDE_LOGCAT := true | ||
无注释版 | 无注释版 | ||
DEVICE_PATH := device/vendor/codename | |||
# Architecture | # Architecture | ||
第420行: | 第421行: | ||
# Debug | # Debug | ||
TARGET_USES_LOGD := true | TARGET_USES_LOGD := true | ||
TWRP_INCLUDE_LOGCAT := true | TWRP_INCLUDE_LOGCAT := true | ||
这块写了好久我也不确定对不对,请各位指正,尤其是 Kernel 部分。 | 这块写了好久我也不确定对不对,请各位指正,尤其是 Kernel 部分。 | ||
第428行: | 第429行: | ||
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容 | 选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容 | ||
DEVICE_PATH := device/xiaomi/rubens | |||
# API | # API | ||
第471行: | 第472行: | ||
# Soong namespaces | # Soong namespaces | ||
PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) # 命名空间 | PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) # 命名空间 | ||
* A/B 无缝更新部分高通和联发科不一样,联发科设备可以照抄,注意 system/bin/mtk_plpath_utils 就好。高通参考[https://github.com/sekaiacg/android_device_xiaomi_venus_TWRP/tree/android-13 venus twrp tree],并且高通的[https://git.codelinaro.org/clo/la/platform/hardware/qcom/bootctrl bootctrl]和[https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/recovery-ext gpt-utils]可以从 CLO 拿。 | * A/B 无缝更新部分高通和联发科不一样,联发科设备可以照抄,注意 system/bin/mtk_plpath_utils 就好。高通参考[https://github.com/sekaiacg/android_device_xiaomi_venus_TWRP/tree/android-13 venus twrp tree],并且高通的[https://git.codelinaro.org/clo/la/platform/hardware/qcom/bootctrl bootctrl]和[https://git.codelinaro.org/clo/la/platform/vendor/qcom-opensource/recovery-ext gpt-utils]可以从 CLO 拿。 | ||
无注释版 | 无注释版 | ||
PRODUCT_SHIPPING_API_LEVEL := 31 | |||
# A/B | # A/B | ||
第516行: | 第517行: | ||
# Soong namespaces | # Soong namespaces | ||
PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) | PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) | ||
==== 初始 twrp_rubens.mk 文件 ==== | ==== 初始 twrp_rubens.mk 文件 ==== | ||
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容 | 选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容 | ||
# Inherit from common AOSP config | |||
$(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk) | $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk) | ||
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk) | $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk) | ||
第538行: | 第539行: | ||
PRODUCT_MANUFACTURER := Xiaomi # 制造商 | PRODUCT_MANUFACTURER := Xiaomi # 制造商 | ||
PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true # 对twrp启动vendor_boot支持 | PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true # 对twrp启动vendor_boot支持 | ||
无注释版 | 无注释版 | ||
# Inherit from common AOSP config | |||
$(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk) | $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk) | ||
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk) | $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk) | ||
第558行: | 第559行: | ||
PRODUCT_MANUFACTURER := Xiaomi | PRODUCT_MANUFACTURER := Xiaomi | ||
PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true | PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true | ||
==== 初始 recovery 目录 ==== | ==== 初始 recovery 目录 ==== | ||
<blockquote>拿出我们好久之前准备的 ramdisk 叭</blockquote> | <blockquote>拿出我们好久之前准备的 ramdisk 叭</blockquote>通过tree命令我们可以查看 ramdisk 的树状图,可以很清晰的查看包含的文件 | ||
├── acct | |||
├── apex | ├── apex | ||
├── bin -> /system/bin | ├── bin -> /system/bin | ||
第602行: | 第603行: | ||
├── init.recovery.hardware.rc | ├── init.recovery.hardware.rc | ||
├── init.recovery.mt6895.rc | ├── init.recovery.mt6895.rc | ||
└── 等等等等...省略大概1000个文件吧 | └── 等等等等...省略大概1000个文件吧 | ||
<blockquote>因为避免教程时效性,我们尽可能选取 prebuilt 的办法,如 boot 和 mtk_plpath_utils 都采用预编译。</blockquote>里面有很多文件是没用的,整理一下,对我们有用的只有这些 | <blockquote>因为避免教程时效性,我们尽可能选取 prebuilt 的办法,如 boot 和 mtk_plpath_utils 都采用预编译。</blockquote>里面有很多文件是没用的,整理一下,对我们有用的只有这些 | ||
. | |||
├── first_stage_ramdisk | ├── first_stage_ramdisk | ||
│ ├── fstab.emmc | │ ├── fstab.emmc | ||
第638行: | 第639行: | ||
└── lib64 | └── lib64 | ||
└── hw | └── hw | ||
└── android.hardware.boot@1.0-impl-1.2-mtkimpl.so | └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so | ||
将它们按照以下操作复制 | 将它们按照以下操作复制 | ||
第646行: | 第647行: | ||
* system --> recovery/root/system (security 和 hw 文件夹里的内容作为备用,不要复制进去) 得到以下目录结构 | * system --> recovery/root/system (security 和 hw 文件夹里的内容作为备用,不要复制进去) 得到以下目录结构 | ||
. | |||
├── Android.mk | ├── Android.mk | ||
├── AndroidProducts.mk | ├── AndroidProducts.mk | ||
第677行: | 第678行: | ||
│ └── hw | │ └── hw | ||
│ └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so | │ └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so | ||
└── twrp_rubens.mk | └── twrp_rubens.mk | ||
打开 init.recovery.mt6895.rc 添加 | 打开 init.recovery.mt6895.rc 添加 | ||
on boot | |||
start health-hal-2-1 | start health-hal-2-1 | ||
on post-fs | on post-fs | ||
start boot-hal-1-2 | start boot-hal-1-2 | ||
例如 | 例如 | ||
on post-fs | |||
start boot-hal-1-2 | start boot-hal-1-2 | ||
第699行: | 第700行: | ||
on boot | on boot | ||
start health-hal-2-1 | start health-hal-2-1 | ||
exec u:r:update_engine:s0 root root -- /system/bin/mtk_plpath_utils | exec u:r:update_engine:s0 root root -- /system/bin/mtk_plpath_utils | ||
接下来可以开始编译咯~~ | 接下来可以开始编译咯~~ | ||
第705行: | 第706行: | ||
==== 编译 ==== | ==== 编译 ==== | ||
<blockquote>编译前请检查注释是否全部删除</blockquote>twrp 源码根目录执行 | <blockquote>编译前请检查注释是否全部删除</blockquote>twrp 源码根目录执行 | ||
. build/envsetup.sh | |||
lunch twrp_codename-eng # twrp-9为onmi | lunch twrp_codename-eng # twrp-9为onmi | ||
mka vendorbootimg/bootimage/recoveryimage | mka vendorbootimg/bootimage/recoveryimage | ||
不出意外的话一路绿灯,如果有报错的话请发邮箱至 1592501605@qq.com 咨询我 | 不出意外的话一路绿灯,如果有报错的话请发邮箱至 1592501605@qq.com 咨询我 | ||
产物在 | 产物在 out/target/product/codename/vendor_boot.img\boot.img\recovery.img | ||
手机重启到 fastboot 模式,使用 fastboot flash 刷写,例如 | 手机重启到 fastboot 模式,使用 fastboot flash 刷写,例如 | ||
fastboot flash vendor_boot /Users/xiaolegun/Downloads/vendor_boot.img | |||
则输出 | 则输出 | ||
ERROR: could not clear input pipe; result e0005000, ignoring... | |||
ERROR: could not clear output pipe; result e0005000, ignoring.... | ERROR: could not clear output pipe; result e0005000, ignoring.... | ||
Sending 'vendor_boot_a' (65536 KB) OKAY [ 1.396s] | Sending 'vendor_boot_a' (65536 KB) OKAY [ 1.396s] | ||
Writing 'vendor_boot_a' OKAY [ 0.167s] | Writing 'vendor_boot_a' OKAY [ 0.167s] | ||
Finished. Total time: 1.625s | Finished. Total time: 1.625s | ||
就可以重启按电源加音量上尝试了,我自己是一次点亮,但有 bug。 | 就可以重启按电源加音量上尝试了,我自己是一次点亮,但有 bug。 | ||
第725行: | 第726行: | ||
===== 修复 USB ===== | ===== 修复 USB ===== | ||
我看到 twrp | 我看到 twrp 控制台有很多报错,第一步肯定是先获取日志,使用logcat命令获取,在此之前先使用adb devices检测一下设备 usb 是否工作正常。 | ||
xiaolegun@xiaoleGundeMac-Pro ~ adb devices ✔ 10208 10:05:31 | |||
* daemon not running; starting now at tcp:5037 | * daemon not running; starting now at tcp:5037 | ||
* daemon started successfully | * daemon started successfully | ||
List of devices attached | List of devices attached | ||
可以看到adb没有检测到设备,原因一般是 usb 的配置不对,但 usb 是好的。这时可以尝试关闭 mtp,再开启,如果电脑有反应,那么就可以继续下一步了。 | |||
在设备树中的 recovery/root,创建 init.recovery.usb.rc 的文件 | 在设备树中的 recovery/root,创建 init.recovery.usb.rc 的文件 | ||
touch recovery/root/init.recovery.usb.rc | |||
并导入以下内容 | 并导入以下内容 | ||
on property:sys.usb.config=mtp,adb | |||
start adbd | start adbd | ||
第750行: | 第751行: | ||
symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2 | symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2 | ||
write /config/usb_gadget/g1/UDC ${sys.usb.controller} | write /config/usb_gadget/g1/UDC ${sys.usb.controller} | ||
setprop sys.usb.state ${sys.usb.config} | setprop sys.usb.state ${sys.usb.config} | ||
这是我从我维护的 MI 6X 的 device tree 拿过来的,可以在联发科设备上正常工作。这段 shell 的大致意思就是在 usb 配置节点写入 mtp 和 adb 同时工作的字符串,这样 adb 就能顺利工作了。 | 这是我从我维护的 MI 6X 的 device tree 拿过来的,可以在联发科设备上正常工作。这段 shell 的大致意思就是在 usb 配置节点写入 mtp 和 adb 同时工作的字符串,这样 adb 就能顺利工作了。 | ||
此外打开原厂 init.rc 修正一下 usb 设备的 id | 此外打开原厂 init.rc 修正一下 usb 设备的 id | ||
# MIUI ADD: START | |||
import /init.recovery.hardware.rc | import /init.recovery.hardware.rc | ||
import /miui.factoryreset.rc | import /miui.factoryreset.rc | ||
第770行: | 第771行: | ||
write /sys/class/android_usb/android0/enable 1 | write /sys/class/android_usb/android0/enable 1 | ||
setprop sys.usb.state ${sys.usb.config} | setprop sys.usb.state ${sys.usb.config} | ||
# END | # END | ||
将 | 将/sys/class/android_usb/android0/idVendor和write /sys/class/android_usb/android0/idProduct后面的 id 分别替换到/config/usb_gadget/g1/idVendor和/config/usb_gadget/g1/idProduct处理完就是这样的。 | ||
on property:sys.usb.config=mtp,adb | |||
start adbd | start adbd | ||
第787行: | 第788行: | ||
symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2 | symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2 | ||
write /config/usb_gadget/g1/UDC ${sys.usb.controller} | write /config/usb_gadget/g1/UDC ${sys.usb.controller} | ||
setprop sys.usb.state ${sys.usb.config} | setprop sys.usb.state ${sys.usb.config} | ||
接下来开机之后 adb 和 mtp 就能同时工作了。 | 接下来开机之后 adb 和 mtp 就能同时工作了。 | ||
===== 修复 Resetprop ===== | ===== 修复 Resetprop ===== | ||
接下来就可以修复其它 bug 了,我看到控制台有一堆红色的报错: | 接下来就可以修复其它 bug 了,我看到控制台有一堆红色的报错: | ||
E:Unknown File System:'/mi_ext' | |||
E:Unable to override 'external_storage.projid.enabled' due to missing libresetprop | E:Unable to override 'external_storage.projid.enabled' due to missing libresetprop | ||
挂载“/data”失败(Invalid argument) | 挂载“/data”失败(Invalid argument) | ||
这三个报错中第二个最好修,第一个次之,第三个与解密有关,放在另一个大章节讲。 | 这三个报错中第二个最好修,第一个次之,第三个与解密有关,放在另一个大章节讲。 | ||
第二个报错只需要在 BoardConfig.mk 中添加 | 第二个报错只需要在 BoardConfig.mk 中添加 | ||
# Tool | |||
TW_INCLUDE_RESETPROP := true | TW_INCLUDE_RESETPROP := true | ||
TW_INCLUDE_LIBRESETPROP := true | TW_INCLUDE_LIBRESETPROP := true | ||
不用编译测试直接秒杀 | 不用编译测试直接秒杀 | ||
===== 修复挂载 ===== | ===== 修复挂载 ===== | ||
E:Unknown File System:'/mi_ext' | |||
我们打开 recovery/root/system/etc 中的 recovery.fstab,发现里面有很多空格,我们先将它格式化一下,有实力的可以把后面的 flag 也对齐整理好。 | 我们打开 recovery/root/system/etc 中的 recovery.fstab,发现里面有很多空格,我们先将它格式化一下,有实力的可以把后面的 flag 也对齐整理好。 | ||
我比较没实力,简单格式化了一下,是这样的 | 我比较没实力,简单格式化了一下,是这样的 | ||
# 1 "vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895" | |||
# 1 "<built-in>" 1 | # 1 "<built-in>" 1 | ||
# 1 "<built-in>" 3 | # 1 "<built-in>" 3 | ||
第895行: | 第896行: | ||
/dev/block/by-name/dtbo /dtbo emmc defaults defaults | /dev/block/by-name/dtbo /dtbo emmc defaults defaults | ||
/dev/block/by-name/otp /otp emmc defaults defaults | /dev/block/by-name/otp /otp emmc defaults defaults | ||
/dev/block/by-name/vbmeta /vbmeta emmc defaults defaults | /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults | ||
这里面有很多无用分区,我们在 twrp 中操作不到,但是我也是第一次适配 MTK 设备,所以不“瞎说”误人子弟了,先把 bug 修好。 | 这里面有很多无用分区,我们在 twrp 中操作不到,但是我也是第一次适配 MTK 设备,所以不“瞎说”误人子弟了,先把 bug 修好。 | ||
像 xiaomi 这样常见的挂载错误,我自己一般都是尝试把/mnt/vendor 使用 vscode 全部删除,让我们尝试一下。并且要把这一行删除,这行在我看来是重复定义(?而且也没指定分区格式。 | 像 xiaomi 这样常见的挂载错误,我自己一般都是尝试把/mnt/vendor 使用 vscode 全部删除,让我们尝试一下。并且要把这一行删除,这行在我看来是重复定义(?而且也没指定分区格式。 | ||
/mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail | |||
整理完之后是这样的 | 整理完之后是这样的 | ||
# 1 "vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895" | |||
# 1 "<built-in>" 1 | # 1 "<built-in>" 1 | ||
# 1 "<built-in>" 3 | # 1 "<built-in>" 3 | ||
第987行: | 第988行: | ||
/dev/block/by-name/dtbo /dtbo emmc defaults defaults | /dev/block/by-name/dtbo /dtbo emmc defaults defaults | ||
/dev/block/by-name/otp /otp emmc defaults defaults | /dev/block/by-name/otp /otp emmc defaults defaults | ||
/dev/block/by-name/vbmeta /vbmeta emmc defaults defaults | /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults | ||
让我们编译试一下,值得注意的是,twrp 每次更改最好删除 out | 让我们编译试一下,值得注意的是,twrp 每次更改最好删除 out 重新编译,不要使用如make installclean等命令,可能会开机黑屏或更改不生效。 | ||
经过一分钟,编译好了,刷入,开机,启动!可以看见挂载成功被修好。 | 经过一分钟,编译好了,刷入,开机,启动!可以看见挂载成功被修好。 | ||
第996行: | 第997行: | ||
在 BoardConfig.mk 中,加入以下 flag | 在 BoardConfig.mk 中,加入以下 flag | ||
TW_Y_OFFSET := 106 #导航栏向上 | |||
TW_H_OFFSET := -106 #界面整体向下 | TW_H_OFFSET := -106 #界面整体向下 | ||
===== 修复振动 ===== | ===== 修复振动 ===== | ||
第1,005行: | 第1,006行: | ||
挂载 vendor,使用 twrp 的文件管理,在 vendor/etc/vintf/manifest 找到含有 vibrator 字样的文件。打开之后检查是否类似这样的文段 | 挂载 vendor,使用 twrp 的文件管理,在 vendor/etc/vintf/manifest 找到含有 vibrator 字样的文件。打开之后检查是否类似这样的文段 | ||
<manifest version="1.0" type="device"> | |||
<hal format="aidl" override="true"> | <hal format="aidl" override="true"> | ||
<name>android.hardware.vibrator</name> | <name>android.hardware.vibrator</name> | ||
<fqname>IVibrator/vibratorfeature</fqname> | <fqname>IVibrator/vibratorfeature</fqname> | ||
</hal> | </hal> | ||
</manifest | </manifest> | ||
那恭喜你,找对了,我的文件名是 | 那恭喜你,找对了,我的文件名是 | ||
vendor.xiaomi.hardware.vibratorfeature.service.xml | |||
将它使用adb pull放到电脑上自己方便的位置备用。 | |||
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /vendor/etc/vintf/manifest/vendor.xiaomi.hardware.vibratorfeature.service.xml . | |||
/vendor/etc/vintf/manifest/vendor.xiao...ipped. 0.2 MB/s (1718 bytes in 0.009s) | /vendor/etc/vintf/manifest/vendor.xiao...ipped. 0.2 MB/s (1718 bytes in 0.009s) | ||
不看扩展名,到 vendor/bin/hw/找到同名的 service | 不看扩展名,到 vendor/bin/hw/找到同名的 service 同样利用adb pull放电脑备用。比如我的叫 | ||
vendor.xiaomi.hardware.vibratorfeature.service | |||
然后到 vendor/etc/init/找到同名.rc 文件,拉到电脑上,在里面加一条。并在定义 service | 然后到 vendor/etc/init/找到同名.rc 文件,拉到电脑上,在里面加一条。并在定义 service 的最下面加上seclabel u:r:recovery:s0可以被 recovery 使用。 | ||
on boot | |||
start service被定义的名字 | start service被定义的名字 | ||
例如 | 例如 | ||
on post-fs-data | |||
chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/f0_save | chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/f0_save | ||
chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/osc_save | chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/osc_save | ||
第1,040行: | 第1,041行: | ||
group system input | group system input | ||
onrestart restart vibratorfeature | onrestart restart vibratorfeature | ||
seclabel u:r:recovery:s0 | seclabel u:r:recovery:s0 | ||
此外这种新设备在内核里还有振动模块需要加载,请到/vendor/modules/1.1/ | 此外这种新设备在内核里还有振动模块需要加载,请到/vendor/modules/1.1/中寻找,例如我这台设备是haptic.ko,用 adb pull 拉取到电脑上,然后 | ||
* haptic.ko --> recovery/root/vendor/modules/1.1 | * haptic.ko --> recovery/root/vendor/modules/1.1 | ||
第1,050行: | 第1,051行: | ||
在 BoardConfig.mk 中加入以下 flag | 在 BoardConfig.mk 中加入以下 flag | ||
TW_SUPPORT_INPUT_AIDL_HAPTICS := true | |||
将备用文件按照以下操作复制 | 将备用文件按照以下操作复制 | ||
第1,059行: | 第1,060行: | ||
之后编译,刷入,开机,喜提冻屏...... | 之后编译,刷入,开机,喜提冻屏...... | ||
问题不大,使用adb logcat抓取日志 | |||
adb logcat > log.log | |||
打开 | 打开 log,搜索F linker、linker、library、beginning of crash这几个关键词,我搜索第一个就出来了。 | ||
F linker : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service": library "android.hardware.vibrator-V1-ndk_platform.so" not found: needed by main executable | |||
这段报错的意思就是vendor.xiaomi.hardware.vibratorfeature.service找不到android.hardware.vibrator-V1-ndk_platform.so这个库,所以无法正常工作。 | |||
打开 BoardConfig.mk 加入以下 flag | 打开 BoardConfig.mk 加入以下 flag | ||
# Library | |||
TARGET_RECOVERY_DEVICE_MODULES += \ | TARGET_RECOVERY_DEVICE_MODULES += \ | ||
android.hardware.vibrator-V1-ndk_platform.vendor | android.hardware.vibrator-V1-ndk_platform.vendor | ||
TW_RECOVERY_ADDITIONAL_RELINK_LIBRARY_FILES += \ | TW_RECOVERY_ADDITIONAL_RELINK_LIBRARY_FILES += \ | ||
$(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator-V1-ndk_platform.so | $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator-V1-ndk_platform.so | ||
再次编译尝试 | 再次编译尝试 | ||
开机之后依然冻屏,继续抓 log,查找 | 开机之后依然冻屏,继续抓 log,查找 | ||
F linker : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service": library "vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so" not found: needed by main executable | |||
vendor.hardware.vibratorfeature字样和我们之前导入的文件长得差不多,一般都是供应商专有文件,所以去设备提取,路径在 vendor/lib64 里,虽然设备冻屏了,但我们可以用adb pull直接拉取到电脑。就像这样。 | |||
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb shell mount /vendor | |||
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /vendor/lib64/vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so . | xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /vendor/lib64/vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so . | ||
/vendor/lib64/vendor.hardware.vibratorfeature.IVi...led, 0 skipped. 14.7 MB/s (33552 bytes in 0.002s | /vendor/lib64/vendor.hardware.vibratorfeature.IVi...led, 0 skipped. 14.7 MB/s (33552 bytes in 0.002s | ||
将这个文件按照以下提示操作 | 将这个文件按照以下提示操作 | ||
第1,087行: | 第1,088行: | ||
还是冻屏,继续抓 log | 还是冻屏,继续抓 log | ||
F linker : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service": library "libtinyalsa.so" not found: needed by main executable | |||
这个 library twrp 的源码中应该没有,去设备拿一个 prebuilt 吧 | 这个 library twrp 的源码中应该没有,去设备拿一个 prebuilt 吧 | ||
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb shell mount /system_root | |||
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /system_root/system/lib64/libtinyalsa.so . | xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /system_root/system/lib64/libtinyalsa.so . | ||
/system_root/system/lib64/libtinyalsa.so: 1 file ...led, 0 skipped. 13.6 MB/s (45032 bytes in 0.003s | /system_root/system/lib64/libtinyalsa.so: 1 file ...led, 0 skipped. 13.6 MB/s (45032 bytes in 0.003s | ||
将这个文件按照以下提示操作 | 将这个文件按照以下提示操作 | ||
第1,098行: | 第1,099行: | ||
编译测试 | 编译测试 | ||
我艹了,还是冻屏,这次搜那几个关键词都搜不到了,搜vibrator看看这鬼东西报什么 | |||
E vendor.xiaomi.hardware.vibratorfeature.service: fail to load lib : /vendor/lib64/libaachaptics.so | |||
这次都直接给路径了,直接拿。 | 这次都直接给路径了,直接拿。 | ||
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb shell mount /vendor | |||
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /vendor/lib64/libaachaptics.so . | xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /vendor/lib64/libaachaptics.so . | ||
/vendor/lib64/libaachaptics.so: 1 file pulled, 0 skipped. 15.8 MB/s (56232 bytes in 0.003s) | /vendor/lib64/libaachaptics.so: 1 file pulled, 0 skipped. 15.8 MB/s (56232 bytes in 0.003s) | ||
将这个文件按照以下提示操作 | 将这个文件按照以下提示操作 | ||
第1,111行: | 第1,112行: | ||
==== 修复 CPU 温度 ==== | ==== 修复 CPU 温度 ==== | ||
使用adb shell + grep命令在手机节点里搜索 type 关键词。 | |||
xiaolegun@xiaoleGundeMac-Pro ~ adb shell 'grep "cp_master" /sys/class/thermal/*/type' | |||
/sys/class/thermal/thermal_zone54/type:cp_master | /sys/class/thermal/thermal_zone54/type:cp_master | ||
xiaolegun@xiaoleGundeMac-Pro ~ adb shell 'grep "cpu" /sys/class/thermal/*/type' | xiaolegun@xiaoleGundeMac-Pro ~ adb shell 'grep "cpu" /sys/class/thermal/*/type' | ||
第1,126行: | 第1,127行: | ||
/sys/class/thermal/thermal_zone7/type:cpu_big3 | /sys/class/thermal/thermal_zone7/type:cpu_big3 | ||
/sys/class/thermal/thermal_zone8/type:cpu_big4 | /sys/class/thermal/thermal_zone8/type:cpu_big4 | ||
/sys/class/thermal/thermal_zone9/type:cpu_big5 | /sys/class/thermal/thermal_zone9/type:cpu_big5 | ||
我这里选用cp_master节点来读取温度。我的节点路径为/sys/class/thermal/thermal_zone54在后面添加 temp 来读取温度,你可以使用cat来检测节点是否可以正常读取温度 | |||
adb shell 'cat /sys/class/thermal/thermal_zone54/temp' | |||
如果返回如 | 如果返回如 | ||
28000 | |||
这种类似的数值,那多半是没有问题的。 | 这种类似的数值,那多半是没有问题的。 | ||
我们在 BoardConfig.mk 中加入 | 我们在 BoardConfig.mk 中加入 | ||
TW_CUSTOM_CPU_TEMP_PATH := "/sys/class/thermal/thermal_zone54/temp" | |||
至此 cpu 温度就修复好了。 | 至此 cpu 温度就修复好了。 | ||
2024年2月20日 (二) 10:53的版本
为新设备编写 Recovery 的设备树
作者: Dark(xiaoleGun)
时间: 2024.2.20
协作者:
一些自序
这篇教程中可能有些不对的地方,请各位指正,我也刚接触 Android 设备测开发两年,而且只有在节假日的时候有空一个人瞎捣鼓,为了薅 mjw 羊毛,故写这篇教程,而且我个人更推荐 Aosp Recovery 刷写第三方 ROM,TWRP 可能多多少少有些问题。Root 之类的不需要 TWRP 也可以,可以找到原机 boot 使用 Magisk 进行修补,也可以使用 KernelSU。另外我的语文功底不是很好,写不出辞藻,只能是北方地道的大白话,见谅哈 🤣///
准备工作
1.一颗勇敢的、不怕困难的强大心脏。
两颗心好勇敢 -- Falling in love
2.电脑配置:
硬件 | 需求 |
---|---|
CPU | 四核或更多 |
内存 | 8G 或更多 |
硬盘 | 至少 80G 空余空间 |
系统 | WSL 或实体 Linux,建议 Debian 系 |
3.足够的空闲时间。
4.Vscode 和 🤏Linux 知识储备
5.一台完好无损的新设备。
6.设备原厂的 boot/recovery/vendor_boot 镜像。(推荐 recovery 分区,因为里面包含一些启动必须的.rc(run command),如果没有该分区,寻找包含官方 recovery 内容的分区。值得注意的是部分设备 recovery 合并到了 boot 中,或是存在于 vendor_boot)
7.查看自己的设备出厂 Android 版本并确定用途,是用于官方 ROM 还是第三方类原生。出厂版本为 9 及以上的可以使用 twrp-11 及以上分支,9 以下使用 twrp-9 分支。
配置环境
安装依赖
sudo apt update sudo apt-get install bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev xattr openjdk-11-jdk jq android-sdk-libsparse-utils python3 python2 repo
必要时可以阅读Git 和 Repo
配置 Git 和 Repo
安装完依赖后,在终端执行。
git config --global user.name "your username" git config --global user.email "your email"
同步 TWRP 源码
在自己方便的地方,建立一个目录。
mkdir twrp cd twrp
根据自己在准备工作中确定的分支同步相应的源码。
TWRP-9
repo init --depth=1 -u https://github.com/minimal-manifest-twrp/platform_manifest_twrp_omni.git -b twrp-9.0 repo sync
TWRP-11
repo init --depth=1 -u https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git -b twrp-11 repo sync
TWRP-12.1
repo init --depth=1 -u https://github.com/minimal-manifest-twrp/platform_manifest_twrp_aosp.git -b twrp-12.1 repo sync
编写设备树
最基本的开机部分我通过 Redmi K50 做示例,并选取 TWRP-12.1 分支。 解密部分会单独成一个章节并分为高通和联发科。
获取资料
小米设备一般可以在Xiaomirom中的线刷包获取 boot/recovery/vendor_boot 镜像,其它设备请自行寻找。
安装工具和依赖
将准备工作中准备的 boot/recovery/vendor_boot 镜像解包,可以用任何工具,我这里使用Android_boot_image_editor按照自述文件进行依赖安装操作:
Mac(Intel)
brew install lz4 xz dtc openjdk@17 echo 'export PATH="/usr/local/opt/openjdk@17/bin:$PATH"' >> ~/.zshrc source ~/.zshrc
Linux:
sudo apt update sudo apt install git device-tree-compiler lz4 xz-utils zlib1g-dev openjdk-17-jdk gcc g++ python3 python-is-python3 p7zip-full android-sdk-libsparse-utils erofs-utils
Common:
git clone https://github.com/cfig/Android_boot_image_editor cd Android_boot_image_editor
解包
请注意"/"表示或的意思,请不要误以为是一个东西。 如果不确定分区寻找的是否正确,请尝试将可以的分区进行解包,并查看其ramdisk内是否包含recovery字样的文件
将你准备好的boot/recovery/vendor_boot复制到该目录,你可以使用 GUI 或者 CLI。如:
cp <出厂boot/recovery/vendor_boot的绝对路径> boot/recovery/vendor_boot.img ./gradlew unpack
我这里以 Redmi K50 为例
10:12:13.188 [main] INFO cfig.bootimg.v3.VendorBoot - Unpack Summary of vendor_boot.img ┌───────────────────────────────────────┬──────────────────────────────────────┐ │What │Where │ └───────────────────────────────────────┴──────────────────────────────────────┘ ┌───────────────────────────────────────┬──────────────────────────────────────┐ │image info │build/unzip_boot/vendor_boot.json │ ├───────────────────────────────────────┼──────────────────────────────────────┤ │ramdisk │build/unzip_boot/ramdisk.img.lz4 │ │-- PLATFORM ramdisk[1/1] │build/unzip_boot/ramdisk.1.lz4 │ │------- extracted rootfs │build/unzip_boot/root.1 │ ├───────────────────────────────────────┼──────────────────────────────────────┤ │dtb │build/unzip_boot/dtb │ ├───────────────────────────────────────┼──────────────────────────────────────┤ │AVB info │build/unzip_boot/vendor_boot.avb.json │ │\-- signing key │NONE │ └───────────────────────────────────────┴──────────────────────────────────────┘ 10:12:13.213 [main] WARN cfig.packable.PackableLauncher - 'unpack' sequence completed BUILD SUCCESSFUL in 2s
解包成功后终端会打印出以上信息,其中包含vendor_boot目录结构,我们只需要ramdisk里的部分内容就好了。
ls build/unzip_boot/root.1 # 请根据自己的分区和设备判断ramdisk的命名,一般都直接是ramdisk
不出意外的话会输出以下内容
xiaolegun@xiaoleGundeMac-Pro ~/github/dump/bootedit master ? ls build/unzip_boot/root.1 acct oem apex plat_file_contexts bin plat_property_contexts bugreports postinstall config proc d product data product_file_contexts data_mirror product_property_contexts debug_ramdisk prop.default default.prop res dev sdcard etc second_stage_resources first_stage_ramdisk sepolicy init storage init.recovery.hardware.rc sys init.recovery.mt6895.rc system lib system_ext linkerconfig system_ext_file_contexts miui.factoryreset.fstab system_ext_property_contexts miui.factoryreset.rc tmp mnt vendor odm vendor_dlkm odm_dlkm vendor_file_contexts odm_file_contexts vendor_property_contexts odm_property_contexts
如果包含 init.recovery*的字样,恭喜你成功找到了正确的分区。将这个目录复制到一个自己方便的地方。
至此资料已经大致齐全了,解密的资料会在解密章节来讲解如何获取。
初始化目录结构
在 twrp 源码根目录输入
mkdir -p device/vendor/codename mkdir -p device/vendor/codename/recovery/root cd device/vendor/codename
vendor指的是供应商,如 xiaomi、oneplus、huawei、vivo、realme。
codename指的是设备代号,小米设备可以在Xiaomirom查询,其它设备自行查询亦或是在开发者选项勾选 USB 调试通过 adb 尝试获取。
adb shell getprop ro.product.manufacturer # 供应商 adb shell getprop ro.product.device # 设备代号
我的 Redmi K50 会打印以下信息
xiaolegun@xiaoleGundeMac-Pro ~/github/dump/bootedit master ? adb shell getprop ro.product.manufacturer Xiaomi # 无论打印出来的内容是大写还是小写,在目录结构中我们都采用小写 xiaolegun@xiaoleGundeMac-Pro ~/github/dump/bootedit master ? adb shell getprop ro.product.device rubens
我的 IQOO NEO5 Lite 会打印以下信息
xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens adb shell getprop ro.product.manufacturer vivo xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens adb shell getprop ro.product.device PD2118
一般只要不是山寨机,小作坊出来的机子,用这两条命令应该是可以正确获取的。
初始化构建时必要的文件
无论是 AOSP device tree 亦或是 TWRP device tree 都基本类似于以下结构。
/ ├── prebuilt (存放kernel、dtb等预编译文件) # AOSP device tree若使用build kernel则没有该目录 ├── recovery/root (存放一些.rc和解密blobs) # 一般用于Recovery device tree ├── Android.mk (Android构建系统首先会检查每个目录的Android.mk,里面包含一些判断,由它包括其所在目录中所有Makefile) ├── AndroidProducts.mk (声明产品的Makefile和lunch时可用的构建类型) ├── BoardConfig.mk (板载配置文件,定义了主板必要的Flag) ├── device.mk (声明设备所需的文件和模块) └── <ROM>_codename.mk (声明产品特定信息,例如名称、品牌和型号,引用device.mk等) # ROM就比如lineage、arrow等,编译twrp就直接写twrp,twrp-9分支要写onmi
我们把这样的结构称为骨架树(skeleton tree)。
接下来我们按照以上结构为自己的设备写一份 Recovery device tree。
在终端使用touch命令创建必要的文件。
touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk ls .
不出意外的话会打印出以下信息
xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens touch Android.mk AndroidProducts.mk BoardConfig.mk device.mk twrp_rubens.mk xiaolegun@xiaoleGundeMac-Pro ~/github/tmp/device/xiaomi/rubens ls . Android.mk BoardConfig.mk prebuilt twrp_rubens.mk AndroidProducts.mk device.mk recovery
可以下一步了~
初始 Android.mk 文件
打开 Vscode 并打开设备树目录,你足够强也可以使用 nano、vim 编辑。
选中 Android.mk 并按照自己的资料复制并更改以下内容
LOCAL_PATH := $(call my-dir) ifeq ($(TARGET_DEVICE),codename) include $(call all-subdir-makefiles,$(LOCAL_PATH)) endif
- codename是需要你修改的部分
我修改后是这样的
LOCAL_PATH := $(call my-dir) ifeq ($(TARGET_DEVICE),rubens) include $(call all-subdir-makefiles,$(LOCAL_PATH)) endif
初始 AndroidProducts.mk 文件
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容
PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/<ROM>_<codename>.mk COMMON_LUNCH_CHOICES := \ <ROM>_<codename>-eng
我修改后是这样的
PRODUCT_MAKEFILES := \ $(LOCAL_DIR)/twrp_rubens.mk COMMON_LUNCH_CHOICES := \ twrp_rubens-eng
初始 BoardConfig.mk 文件
将之前准备的ramdisk文件夹用新窗口打开 1.找到目录下的 prop.default 或含 prop 字样的文件。以下注释类似 ro.*.*的就是从 prop 中获取的 2.解包 boot/recovery/vendor_boot 的 json 例如 build/unzip_boot/boot.json
选中 BoardConfig.mk 并按照自己的资料复制并更改以下内容
DEVICE_PATH := device/vendor/codename # Architecture TARGET_ARCH := arm64 # ro.bionic.arch TARGET_ARCH_VARIANT := armv8-a # 64位默认变体 TARGET_CPU_ABI := arm64-v8a # ro.vendor.product.cpu.abilist64 (至少在小米设备上没有找到ro.product.cpu.abilist) TARGET_CPU_ABI2 := # 64位留空 TARGET_CPU_VARIANT := generic # 默认一般都是通用 TARGET_CPU_VARIANT_RUNTIME := cortex-a55 # ro.bionic.cpu_variant TARGET_2ND_ARCH := arm # ro.bionic.2nd_arch TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT) TARGET_2ND_CPU_ABI := armeabi-v7a # ro.vendor.product.cpu.abilist32第一个 TARGET_2ND_CPU_ABI2 := armeabi # ro.vendor.product.cpu.abilist32第二个 TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT) TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT) # Assertation TARGET_OTA_ASSERT_DEVICE := rubens # codename # Bootloader TARGET_BOOTLOADER_BOARD_NAME := rubens # ro.product.board TARGET_NO_BOOTLOADER := true TARGET_USES_UEFI := true # Build Rule ALLOW_MISSING_DEPENDENCIES := true # 为了recovery不健全的依赖 # Kernel - 注释会说明在boot/recovery/vendor_boot.json中对应的变量 BOARD_BOOTIMG_HEADER_VERSION := 4 # headerVersion BOARD_KERNEL_BASE := 0x3fff8000 # (kernelLoadAddr - 32KB) qcom设备base为0,且没有偏移(offset) BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2 # cmdline BOARD_KERNEL_PAGESIZE := 4096 # pageSize BOARD_RAMDISK_OFFSET := 0x26f08000 # (ramdisk,loadAddr - BOARD_KERNEL_BASE) BOARD_KERNEL_TAGS_OFFSET := 0x07c88000 # (tagsLoadAddr - BOARD_KERNEL_BASE) BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOTIMG_HEADER_VERSION) BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET) BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET) # Kernel - prebuilt TARGET_PREBUILT_KERNEL := $(DEVICE_PATH)/prebuilt/kernel # 预编译内核相对于android源码根目录的相对路径,vendor_boot机型不需要 TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img # 同上 BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB) # Partitions BOARD_FLASH_BLOCK_SIZE := 262144 # (BOARD_KERNEL_PAGESIZE * 64) BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864 # boot/recovery/vendor_boot镜像的字节大小需原厂或手机完整提取出来的,不定义会报错 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864 # 同上 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864 # 同上 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4 # 分区类型,查看ramdisk中fstab定义的类型 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4 TARGET_COPY_OUT_VENDOR := vendor # 定义vendor目录,例如copy专有blobs要用 BOARD_SUPER_PARTITION_SIZE := 9126805504 # 可以通过blockdev --getsize64 /dev/block/bootdevice/by-name/super获取,需root,如果无法root可以直接使用这个值,不影响twrp启动,可以后续修正 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions # xiaomi根据你获取资料的vendor替换,是一个动态分区组 BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm # 根据fstab内的定义,一般flag包含logical都属于动态分区组的一部分 BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200 # (BOARD_SUPER_PARTITION_SIZE - 4MB) # Platform TARGET_BOARD_PLATFORM := mt6895 # ro.board.platform # Recovery - 基本通用的不影响启动 BOARD_HAS_LARGE_FILESYSTEM := true TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888 TARGET_USERIMAGES_USE_EXT4 := true TARGET_USERIMAGES_USE_F2FS := true # Treble BOARD_VNDK_VERSION := current # 声明VNDK版本 # Vendor_boot recovery ramdisk BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true # 将recovery文件复制到vendor_boot # Boot recovery ramdisk #BOARD_USES_RECOVERY_AS_BOOT := true recovery ramdisk合并在boot中启用 # Verified Boot BOARD_AVB_ENABLE := true BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3 # TWRP Configurations TW_DEFAULT_LANGUAGE := zh_CN # 默认为中文 TW_EXTRA_LANGUAGES := true # 额外的语言 TW_THEME := portrait_hdpi # 主题 TW_INCLUDE_FASTBOOTD := true # 包括fastbootd,为动态分区 # 其它flag还有很多,可以在https://xdaforums.com/t/twrp-flags-for-boardconfig-mk.3333970 查找, # 这篇文章也很老了,但我并不推荐twrp,所以flag我也不是很了解,多翻翻github:) # Debug TARGET_USES_LOGD := true # 调试flag TWRP_INCLUDE_LOGCAT := true
无注释版
DEVICE_PATH := device/vendor/codename # Architecture TARGET_ARCH := arm64 TARGET_ARCH_VARIANT := armv8-a TARGET_CPU_ABI := arm64-v8a TARGET_CPU_ABI2 := TARGET_CPU_VARIANT := generic TARGET_CPU_VARIANT_RUNTIME := cortex-a55 TARGET_2ND_ARCH := arm TARGET_2ND_ARCH_VARIANT := $(TARGET_ARCH_VARIANT) TARGET_2ND_CPU_ABI := armeabi-v7a TARGET_2ND_CPU_ABI2 := armeabi TARGET_2ND_CPU_VARIANT := $(TARGET_CPU_VARIANT) TARGET_2ND_CPU_VARIANT_RUNTIME := $(TARGET_CPU_VARIANT) # Assertation TARGET_OTA_ASSERT_DEVICE := rubens # Bootloader TARGET_BOOTLOADER_BOARD_NAME := rubens TARGET_NO_BOOTLOADER := true TARGET_USES_UEFI := true # Build Rule ALLOW_MISSING_DEPENDENCIES := true # Kernel BOARD_BOOT_HEADER_VERSION := 4 BOARD_KERNEL_BASE := 0x3fff8000 BOARD_KERNEL_CMDLINE := bootopt=64S3,32N2,64N2 BOARD_KERNEL_PAGESIZE := 4096 BOARD_RAMDISK_OFFSET := 0x26f08000 BOARD_KERNEL_TAGS_OFFSET := 0x07c88000 BOARD_MKBOOTIMG_ARGS += --header_version $(BOARD_BOOT_HEADER_VERSION) BOARD_MKBOOTIMG_ARGS += --ramdisk_offset $(BOARD_RAMDISK_OFFSET) BOARD_MKBOOTIMG_ARGS += --tags_offset $(BOARD_KERNEL_TAGS_OFFSET) BOARD_KERNEL_IMAGE_NAME := Image # Kernel - prebuilt TARGET_PREBUILT_DTB := $(DEVICE_PATH)/prebuilt/dtb.img BOARD_MKBOOTIMG_ARGS += --dtb $(TARGET_PREBUILT_DTB) # Partitions BOARD_FLASH_BLOCK_SIZE := 262144 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864 BOARD_RECOVERYIMAGE_PARTITION_SIZE := 67108864 BOARD_VENDOR_ROOTIMAGE_PARTITION_SIZE := 67108864 BOARD_SYSTEMIMAGE_PARTITION_TYPE := ext4 BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE := ext4 BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4 TARGET_COPY_OUT_VENDOR := vendor BOARD_SUPER_PARTITION_SIZE := 9126805504 BOARD_SUPER_PARTITION_GROUPS := xiaomi_dynamic_partitions BOARD_XIAOMI_DYNAMIC_PARTITIONS_PARTITION_LIST := system vendor product system_ext odm vendor_dlkm odm_dlkm BOARD_XIAOMI_DYNAMIC_PARTITIONS_SIZE := 9122611200 # Platform TARGET_BOARD_PLATFORM := mt6895 # Recovery BOARD_HAS_LARGE_FILESYSTEM := true TARGET_RECOVERY_PIXEL_FORMAT := RGBX_8888 TARGET_USERIMAGES_USE_EXT4 := true TARGET_USERIMAGES_USE_F2FS := true # Treble BOARD_VNDK_VERSION := current # Vendor_boot recovery ramdisk BOARD_MOVE_RECOVERY_RESOURCES_TO_VENDOR_BOOT := true # Boot recovery ramdisk #BOARD_USES_RECOVERY_AS_BOOT := true # Verified Boot BOARD_AVB_ENABLE := true BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --flags 3 # TWRP Configurations TW_DEFAULT_LANGUAGE := zh_CN TW_EXTRA_LANGUAGES := true TW_THEME := portrait_hdpi TW_INCLUDE_FASTBOOTD := true # Debug TARGET_USES_LOGD := true TWRP_INCLUDE_LOGCAT := true
这块写了好久我也不确定对不对,请各位指正,尤其是 Kernel 部分。
初始 device.mk 文件
- 准备好 prop.default
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容
DEVICE_PATH := device/xiaomi/rubens # API PRODUCT_SHIPPING_API_LEVEL := 31 # ro.board.first_api_level # A/B AB_OTA_UPDATER := true # 启用A/B无缝更新 AB_OTA_PARTITIONS += \ # 定义A/B分区,参考fstab boot \ dtbo \ system \ product \ vendor \ odm \ odm_dlkm \ vbmeta \ vendor_boot \ vendor_dlkm \ vbmeta_system \ vbmeta_vendor PRODUCT_PACKAGES += \ update_engine \ update_engine_sideload \ update_verifier \ checkpoint_gc AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_vendor=true \ POSTINSTALL_PATH_vendor=bin/checkpoint_gc \ FILESYSTEM_TYPE_vendor=ext4 \ POSTINSTALL_OPTIONAL_vendor=true # Dynamic PRODUCT_USE_DYNAMIC_PARTITIONS := true # 动态分区 # Soong namespaces PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH) # 命名空间
- A/B 无缝更新部分高通和联发科不一样,联发科设备可以照抄,注意 system/bin/mtk_plpath_utils 就好。高通参考venus twrp tree,并且高通的bootctrl和gpt-utils可以从 CLO 拿。
无注释版
PRODUCT_SHIPPING_API_LEVEL := 31 # A/B AB_OTA_UPDATER := true AB_OTA_PARTITIONS += \ boot \ dtbo \ system \ product \ vendor \ odm \ odm_dlkm \ vbmeta \ vendor_boot \ vendor_dlkm \ vbmeta_system \ vbmeta_vendor PRODUCT_PACKAGES += \ update_engine \ update_engine_sideload \ update_verifier \ checkpoint_gc AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/mtk_plpath_utils \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_vendor=true \ POSTINSTALL_PATH_vendor=bin/checkpoint_gc \ FILESYSTEM_TYPE_vendor=ext4 \ POSTINSTALL_OPTIONAL_vendor=true # Dynamic PRODUCT_USE_DYNAMIC_PARTITIONS := true # Soong namespaces PRODUCT_SOONG_NAMESPACES += $(DEVICE_PATH)
初始 twrp_rubens.mk 文件
选中 AndroidProducts.mk 并按照自己的资料复制并更改以下内容
# Inherit from common AOSP config $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用 # Inherit from TWRP product configuration $(call inherit-product, vendor/twrp/config/common.mk) # twrp-9分支改为onmi # Device specific configs $(call inherit-product, device/xiaomi/rubens/device.mk) # Device identifier PRODUCT_DEVICE := rubens # 设备型号 PRODUCT_NAME := twrp_rubens # 设备名称 PRODUCT_BRAND := Redmi # 自定义品牌,如果有 PRODUCT_MODEL := 22041211AC # 产品最终用户可见名称 PRODUCT_MANUFACTURER := Xiaomi # 制造商 PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true # 对twrp启动vendor_boot支持
无注释版
# Inherit from common AOSP config $(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota/launch_with_vendor_ramdisk.mk) # vab加载到vendor boot里使用 # Inherit from TWRP product configuration $(call inherit-product, vendor/twrp/config/common.mk) # Device specific configs $(call inherit-product, device/xiaomi/rubens/device.mk) # Device identifier PRODUCT_DEVICE := rubens PRODUCT_NAME := twrp_rubens PRODUCT_BRAND := Redmi PRODUCT_MODEL := 22041211AC PRODUCT_MANUFACTURER := Xiaomi PRODUCT_PROPERTY_OVERRIDES += ro.twrp.vendor_boot=true
初始 recovery 目录
拿出我们好久之前准备的 ramdisk 叭
通过tree命令我们可以查看 ramdisk 的树状图,可以很清晰的查看包含的文件
├── acct ├── apex ├── bin -> /system/bin ├── bugreports -> /data/user_de/0/com.android.shell/files/bugreports ├── config ├── d -> /sys/kernel/debug ├── data ├── data_mirror ├── debug_ramdisk ├── default.prop -> prop.default ├── dev ├── etc -> /system/etc ├── first_stage_ramdisk │ ├── fstab.emmc │ ├── fstab.mt6895 │ └── system │ ├── bin │ │ ├── e2fsck │ │ ├── linker64 │ │ ├── linker_asan64 -> linker64 │ │ └── snapuserd │ └── lib64 │ ├── ld-android.so │ ├── libbase.so │ ├── libc++.so │ ├── libc.so │ ├── libdl.so │ ├── libext2_blkid.so │ ├── libext2_com_err.so │ ├── libext2_e2p.so │ ├── libext2_quota.so │ ├── libext2_uuid.so │ ├── libext2fs.so │ ├── liblog.so │ ├── libm.so │ ├── libsparse.so │ └── libz.so ├── init -> /system/bin/init ├── init.recovery.hardware.rc ├── init.recovery.mt6895.rc └── 等等等等...省略大概1000个文件吧
因为避免教程时效性,我们尽可能选取 prebuilt 的办法,如 boot 和 mtk_plpath_utils 都采用预编译。
里面有很多文件是没用的,整理一下,对我们有用的只有这些
. ├── first_stage_ramdisk │ ├── fstab.emmc │ └── fstab.mt6895 ├── init.recovery.mt6895.rc ├── lib │ └── modules │ ├── 8250_mtk.ko │ ├── adapter_class.ko │ ├── adsp.ko │ ├── aee_aed.ko │ ├── aee_hangdet.ko │ ├── aee_rs.ko │ ├── blocktag.ko │ ├── bootprof.ko │ ├── bq28z610.ko │ ├── cache-parity.ko │ ├── cfg80211.ko │ ├── charger_class.ko │ └── 省略一百多个模块,这个目录里的东西全要 └── system ├── bin │ └── mtk_plpath_utils ├── etc │ ├── init │ │ │── mtk-plpath-utils.rc │ │ └──hw │ │ └──init.rc │ ├── recovery.fstab │ ├── security │ │ └── otacerts.zip │ └── ueventd.rc └── lib64 └── hw └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so
将它们按照以下操作复制
- first_stage_ramdisk --> recovery/root/first_stage_ramdisk
- init.recovery.mt6895.rc --> recovery/root/init.recovery.mt6895.rc
- lib --> recovery/root/lib
- system --> recovery/root/system (security 和 hw 文件夹里的内容作为备用,不要复制进去) 得到以下目录结构
. ├── Android.mk ├── AndroidProducts.mk ├── BoardConfig.mk ├── device.mk ├── prebuilt ├── recovery │ └── root │ ├── first_stage_ramdisk │ │ ├── fstab.emmc │ │ └── fstab.mt6895 │ ├── init.recovery.mt6895.rc │ ├── lib │ │ └── modules │ │ ├── 8250_mtk.ko │ │ ├── adapter_class.ko │ │ ├── adsp.ko │ │ ├── aee_aed.ko │ │ ├── aee_hangdet.ko │ │ ├── aee_rs.ko │ │ ├── blocktag.ko │ │ └── 省略.... │ └── system │ ├── bin │ │ └── mtk_plpath_utils │ ├── etc │ │ ├── recovery.fstab │ │ └── ueventd.rc │ └── lib64 │ └── hw │ └── android.hardware.boot@1.0-impl-1.2-mtkimpl.so └── twrp_rubens.mk
打开 init.recovery.mt6895.rc 添加
on boot start health-hal-2-1 on post-fs start boot-hal-1-2
例如
on post-fs start boot-hal-1-2 on init setprop sys.usb.configfs 1 setprop sys.usb.controller "11201000.usb0" setprop sys.usb.ffs.aio_compat 1 on fs && property:ro.debuggable=0 # distinguish USB shoulde connect or not, i.e. CDP vs SDP # set charging free due to it wait for USB activation on boot start health-hal-2-1 exec u:r:update_engine:s0 root root -- /system/bin/mtk_plpath_utils
接下来可以开始编译咯~~
编译
编译前请检查注释是否全部删除
twrp 源码根目录执行
. build/envsetup.sh lunch twrp_codename-eng # twrp-9为onmi mka vendorbootimg/bootimage/recoveryimage
不出意外的话一路绿灯,如果有报错的话请发邮箱至 1592501605@qq.com 咨询我
产物在 out/target/product/codename/vendor_boot.img\boot.img\recovery.img
手机重启到 fastboot 模式,使用 fastboot flash 刷写,例如
fastboot flash vendor_boot /Users/xiaolegun/Downloads/vendor_boot.img
则输出
ERROR: could not clear input pipe; result e0005000, ignoring... ERROR: could not clear output pipe; result e0005000, ignoring.... Sending 'vendor_boot_a' (65536 KB) OKAY [ 1.396s] Writing 'vendor_boot_a' OKAY [ 0.167s] Finished. Total time: 1.625s
就可以重启按电源加音量上尝试了,我自己是一次点亮,但有 bug。
修 BUG
修复 USB
我看到 twrp 控制台有很多报错,第一步肯定是先获取日志,使用logcat命令获取,在此之前先使用adb devices检测一下设备 usb 是否工作正常。
xiaolegun@xiaoleGundeMac-Pro ~ adb devices ✔ 10208 10:05:31 * daemon not running; starting now at tcp:5037 * daemon started successfully List of devices attached
可以看到adb没有检测到设备,原因一般是 usb 的配置不对,但 usb 是好的。这时可以尝试关闭 mtp,再开启,如果电脑有反应,那么就可以继续下一步了。
在设备树中的 recovery/root,创建 init.recovery.usb.rc 的文件
touch recovery/root/init.recovery.usb.rc
并导入以下内容
on property:sys.usb.config=mtp,adb start adbd on property:sys.usb.ffs.ready=1 && property:sys.usb.config=mtp,adb write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "mtp_adb" rm /config/usb_gadget/g1/configs/b.1/f1 rm /config/usb_gadget/g1/configs/b.1/f2 rm /config/usb_gadget/g1/configs/b.1/f3 rm /config/usb_gadget/g1/configs/b.1/f4 rm /config/usb_gadget/g1/configs/b.1/f5 write /config/usb_gadget/g1/idVendor 0x18d1 write /config/usb_gadget/g1/idProduct 0x2d08 symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1 symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2 write /config/usb_gadget/g1/UDC ${sys.usb.controller} setprop sys.usb.state ${sys.usb.config}
这是我从我维护的 MI 6X 的 device tree 拿过来的,可以在联发科设备上正常工作。这段 shell 的大致意思就是在 usb 配置节点写入 mtp 和 adb 同时工作的字符串,这样 adb 就能顺利工作了。
此外打开原厂 init.rc 修正一下 usb 设备的 id
# MIUI ADD: START import /init.recovery.hardware.rc import /miui.factoryreset.rc # END import /init.recovery.${ro.hardware}.rc ########### 省略一万字 # MIUI ADD: START on property:sys.usb.config=mtp,adb && property:sys.usb.configfs=0 write /sys/class/android_usb/android0/enable 0 write /sys/class/android_usb/android0/idVendor 2717 write /sys/class/android_usb/android0/idProduct 904D write /sys/class/android_usb/android0/functions mtp,adb write /sys/class/android_usb/android0/enable 1 setprop sys.usb.state ${sys.usb.config} # END
将/sys/class/android_usb/android0/idVendor和write /sys/class/android_usb/android0/idProduct后面的 id 分别替换到/config/usb_gadget/g1/idVendor和/config/usb_gadget/g1/idProduct处理完就是这样的。
on property:sys.usb.config=mtp,adb start adbd on property:sys.usb.ffs.ready=1 && property:sys.usb.config=mtp,adb write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "mtp_adb" rm /config/usb_gadget/g1/configs/b.1/f1 rm /config/usb_gadget/g1/configs/b.1/f2 rm /config/usb_gadget/g1/configs/b.1/f3 rm /config/usb_gadget/g1/configs/b.1/f4 rm /config/usb_gadget/g1/configs/b.1/f5 write /config/usb_gadget/g1/idVendor 0x2717 write /config/usb_gadget/g1/idProduct 0x904D symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1 symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2 write /config/usb_gadget/g1/UDC ${sys.usb.controller} setprop sys.usb.state ${sys.usb.config}
接下来开机之后 adb 和 mtp 就能同时工作了。
修复 Resetprop
接下来就可以修复其它 bug 了,我看到控制台有一堆红色的报错:
E:Unknown File System:'/mi_ext' E:Unable to override 'external_storage.projid.enabled' due to missing libresetprop 挂载“/data”失败(Invalid argument)
这三个报错中第二个最好修,第一个次之,第三个与解密有关,放在另一个大章节讲。
第二个报错只需要在 BoardConfig.mk 中添加
# Tool TW_INCLUDE_RESETPROP := true TW_INCLUDE_LIBRESETPROP := true
不用编译测试直接秒杀
修复挂载
E:Unknown File System:'/mi_ext'
我们打开 recovery/root/system/etc 中的 recovery.fstab,发现里面有很多空格,我们先将它格式化一下,有实力的可以把后面的 flag 也对齐整理好。
我比较没实力,简单格式化了一下,是这样的
# 1 "vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 341 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895" 2 # 173 "vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895" system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount product /product erofs ro wait,slotselect,avb,logical,first_stage_mount product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount mi_ext /mnt/vendor/mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail mi_ext /mnt/vendor/mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail /mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail overlay /product/overlay overlay ro,lowerdir=/mnt/vendor/mi_ext/product/overlay/:/product/overlay check,nofail overlay /product/app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/app/:/product/app check,nofail overlay /product/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/priv-app/:/product/priv-app check,nofail overlay /product/lib overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib/:/product/lib check,nofail overlay /product/lib64 overlay ro,lowerdir=/mnt/vendor/mi_ext/product/lib64/:/product/lib64 check,nofail overlay /product/bin overlay ro,lowerdir=/mnt/vendor/mi_ext/product/bin/:/product/bin check,nofail overlay /product/framework overlay ro,lowerdir=/mnt/vendor/mi_ext/product/framework/:/product/framework check,nofail overlay /product/media overlay ro,lowerdir=/mnt/vendor/mi_ext/product/media/:/product/media check,nofail overlay /product/opcust overlay ro,lowerdir=/mnt/vendor/mi_ext/product/opcust/:/product/opcust check,nofail overlay /product/data-app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/data-app/:/product/data-app check,nofail overlay /product/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail overlay /product/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail overlay /system/app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail overlay /system/priv-app overlay ro,lowerdir=/mnt/vendor/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail overlay /system/etc/sysconfig overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail overlay /system/etc/permissions overlay ro,lowerdir=/mnt/vendor/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable /dev/block/by-name/protect1 /mnt/vendor/protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /dev/block/by-name/protect2 /mnt/vendor/protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /dev/block/by-name/nvdata /mnt/vendor/nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /dev/block/by-name/nvcfg /mnt/vendor/nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /dev/block/by-name/persist /mnt/vendor/persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto /dev/block/by-name/frp /persistent emmc defaults defaults /dev/block/by-name/nvram /nvram emmc defaults defaults /dev/block/by-name/proinfo /proinfo emmc defaults defaults /dev/block/by-name/lk /bootloader emmc defaults defaults /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults /dev/block/by-name/para /para emmc defaults defaults /dev/block/by-name/misc /misc emmc defaults defaults /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta /dev/block/by-name/logo /logo emmc defaults defaults /dev/block/by-name/expdb /expdb emmc defaults defaults /dev/block/by-name/seccfg /seccfg emmc defaults defaults /dev/block/by-name/tee1 /tee1 emmc defaults defaults /dev/block/by-name/tee2 /tee2 emmc defaults defaults /dev/block/by-name/scp1 /scp1 emmc defaults defaults /dev/block/by-name/scp2 /scp2 emmc defaults defaults /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults /dev/block/by-name/md1img /md1img emmc defaults defaults /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults /dev/block/by-name/md3img /md3img emmc defaults defaults /dev/block/by-name/gz1 /gz1 emmc defaults defaults /dev/block/by-name/gz2 /gz2 emmc defaults defaults /dev/block/by-name/spmfw /spmfw emmc defaults defaults /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults /dev/block/by-name/pi_img /pi_img emmc defaults defaults /dev/block/by-name/boot_para /boot_para emmc defaults defaults /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults /dev/block/by-name/dtbo /dtbo emmc defaults defaults /dev/block/by-name/otp /otp emmc defaults defaults /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults
这里面有很多无用分区,我们在 twrp 中操作不到,但是我也是第一次适配 MTK 设备,所以不“瞎说”误人子弟了,先把 bug 修好。
像 xiaomi 这样常见的挂载错误,我自己一般都是尝试把/mnt/vendor 使用 vscode 全部删除,让我们尝试一下。并且要把这一行删除,这行在我看来是重复定义(?而且也没指定分区格式。
/mnt/vendor/mi_ext /mi_ext none ro,bind wait,nofail
整理完之后是这样的
# 1 "vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895" # 1 "<built-in>" 1 # 1 "<built-in>" 3 # 341 "<built-in>" 3 # 1 "<command line>" 1 # 1 "<built-in>" 2 # 1 "vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895" 2 # 173 "vendor/mediatek/proprietary/hardware/fstab/mt6895/fstab.in.mt6895" system /system erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey system /system ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey vendor /vendor erofs ro wait,slotselect,avb,logical,first_stage_mount vendor /vendor ext4 ro wait,slotselect,avb,logical,first_stage_mount product /product erofs ro wait,slotselect,avb,logical,first_stage_mount product /product ext4 ro wait,slotselect,avb,logical,first_stage_mount mi_ext /mi_ext erofs ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail mi_ext /mi_ext ext4 ro wait,slotselect,avb=vbmeta,logical,first_stage_mount,nofail overlay /product/overlay overlay ro,lowerdir=/mi_ext/product/overlay/:/product/overlay check,nofail overlay /product/app overlay ro,lowerdir=/mi_ext/product/app/:/product/app check,nofail overlay /product/priv-app overlay ro,lowerdir=/mi_ext/product/priv-app/:/product/priv-app check,nofail overlay /product/lib overlay ro,lowerdir=/mi_ext/product/lib/:/product/lib check,nofail overlay /product/lib64 overlay ro,lowerdir=/mi_ext/product/lib64/:/product/lib64 check,nofail overlay /product/bin overlay ro,lowerdir=/mi_ext/product/bin/:/product/bin check,nofail overlay /product/framework overlay ro,lowerdir=/mi_ext/product/framework/:/product/framework check,nofail overlay /product/media overlay ro,lowerdir=/mi_ext/product/media/:/product/media check,nofail overlay /product/opcust overlay ro,lowerdir=/mi_ext/product/opcust/:/product/opcust check,nofail overlay /product/data-app overlay ro,lowerdir=/mi_ext/product/data-app/:/product/data-app check,nofail overlay /product/etc/sysconfig overlay ro,lowerdir=/mi_ext/product/etc/sysconfig/:/product/etc/sysconfig check,nofail overlay /product/etc/permissions overlay ro,lowerdir=/mi_ext/product/etc/permissions/:/product/etc/permissions check,nofail overlay /system/app overlay ro,lowerdir=/mi_ext/system/app/:/product/pangu/system/app/:/system/app check,nofail overlay /system/priv-app overlay ro,lowerdir=/mi_ext/system/priv-app/:/product/pangu/system/priv-app/:/system/priv-app check,nofail overlay /system/framework overlay ro,lowerdir=/product/pangu/system/framework/:/system/framework check,nofail overlay /system/etc/sysconfig overlay ro,lowerdir=/mi_ext/system/etc/sysconfig/:/system/etc/sysconfig check,nofail overlay /system/etc/permissions overlay ro,lowerdir=/mi_ext/system/etc/permissions/:/product/pangu/system/etc/permissions/:/system/etc/permissions check,nofail system_ext /system_ext erofs ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey system_ext /system_ext ext4 ro wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey odm /odm erofs ro wait,slotselect,avb,logical,first_stage_mount odm /odm ext4 ro wait,slotselect,avb,logical,first_stage_mount vendor_dlkm /vendor_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount odm_dlkm /odm_dlkm erofs ro wait,slotselect,avb,logical,first_stage_mount /dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount /dev/block/by-name/userdata /data f2fs noatime,nosuid,nodev,discard,noflush_merge,fsync_mode=nobarrier,reserve_root=134217,resgid=1065,checkpoint_merge,gc_merge,inlinecrypt wait,check,formattable,quota,latemount,resize,reservedsize=128m,checkpoint=fs,fileencryption=aes-256-xts:aes-256-cts:v2+inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,fsverity /dev/block/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable /dev/block/by-name/protect1 /protect_f ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /dev/block/by-name/protect2 /protect_s ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /dev/block/by-name/nvdata /nvdata ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /dev/block/by-name/nvcfg /nvcfg ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /dev/block/by-name/persist /persist ext4 noatime,nosuid,nodev,noauto_da_alloc,commit=1,nodelalloc wait,check,formattable /devices/platform/soc/11240000.mmc* auto auto defaults voldmanaged=sdcard1:auto,encryptable=userdata /devices/platform/usb_xhci* auto vfat defaults voldmanaged=usbotg:auto /devices/platform/soc/11201000.usb0/11200000.xhci* auto vfat defaults voldmanaged=usbotg:auto /dev/block/by-name/frp /persistent emmc defaults defaults /dev/block/by-name/nvram /nvram emmc defaults defaults /dev/block/by-name/proinfo /proinfo emmc defaults defaults /dev/block/by-name/lk /bootloader emmc defaults defaults /dev/block/by-name/lk2 /bootloader2 emmc defaults defaults /dev/block/by-name/para /para emmc defaults defaults /dev/block/by-name/misc /misc emmc defaults defaults /dev/block/by-name/boot /boot emmc defaults first_stage_mount,nofail,slotselect /dev/block/by-name/vbmeta_vendor /vbmeta_vendor emmc defaults first_stage_mount,nofail,slotselect /dev/block/by-name/vbmeta_system /vbmeta_system emmc defaults first_stage_mount,nofail,slotselect,avb=vbmeta /dev/block/by-name/logo /logo emmc defaults defaults /dev/block/by-name/expdb /expdb emmc defaults defaults /dev/block/by-name/seccfg /seccfg emmc defaults defaults /dev/block/by-name/tee1 /tee1 emmc defaults defaults /dev/block/by-name/tee2 /tee2 emmc defaults defaults /dev/block/by-name/scp1 /scp1 emmc defaults defaults /dev/block/by-name/scp2 /scp2 emmc defaults defaults /dev/block/by-name/sspm_1 /sspm_1 emmc defaults defaults /dev/block/by-name/sspm_2 /sspm_2 emmc defaults defaults /dev/block/by-name/dpm_1 /dpm_1 emmc defaults defaults /dev/block/by-name/dpm_2 /dpm_2 emmc defaults defaults /dev/block/by-name/mcupm_1 /mcupm_1 emmc defaults defaults /dev/block/by-name/mcupm_2 /mcupm_2 emmc defaults defaults /dev/block/by-name/md1img /md1img emmc defaults defaults /dev/block/by-name/md1dsp /md1dsp emmc defaults defaults /dev/block/by-name/md1arm7 /md1arm7 emmc defaults defaults /dev/block/by-name/md3img /md3img emmc defaults defaults /dev/block/by-name/gz1 /gz1 emmc defaults defaults /dev/block/by-name/gz2 /gz2 emmc defaults defaults /dev/block/by-name/spmfw /spmfw emmc defaults defaults /dev/block/by-name/audio_dsp /audio_dsp emmc defaults defaults /dev/block/by-name/pi_img /pi_img emmc defaults defaults /dev/block/by-name/boot_para /boot_para emmc defaults defaults /dev/block/by-name/odmdtbo /odmdtbo emmc defaults defaults /dev/block/by-name/dtbo /dtbo emmc defaults defaults /dev/block/by-name/otp /otp emmc defaults defaults /dev/block/by-name/vbmeta /vbmeta emmc defaults defaults
让我们编译试一下,值得注意的是,twrp 每次更改最好删除 out 重新编译,不要使用如make installclean等命令,可能会开机黑屏或更改不生效。
经过一分钟,编译好了,刷入,开机,启动!可以看见挂载成功被修好。
修复屏幕显示
可以看到我们现在屏幕的顶部的时间被摄像头挖孔挡住了。我们使用两个偏移 Flag 来修复它。
在 BoardConfig.mk 中,加入以下 flag
TW_Y_OFFSET := 106 #导航栏向上 TW_H_OFFSET := -106 #界面整体向下
修复振动
仅供参考,研究半天发现只有解密功能正常才能修振动,不然会冻屏!!! 不一定正确,也不一定普遍,仅供指路
老设备一般都是正常的,不需要额外处理,新设备使用 aidl hal 需要我们自己处理一下让 service 正常工作。
挂载 vendor,使用 twrp 的文件管理,在 vendor/etc/vintf/manifest 找到含有 vibrator 字样的文件。打开之后检查是否类似这样的文段
<manifest version="1.0" type="device"> <hal format="aidl" override="true"> <name>android.hardware.vibrator</name> <fqname>IVibrator/vibratorfeature</fqname> </hal> </manifest>
那恭喜你,找对了,我的文件名是
vendor.xiaomi.hardware.vibratorfeature.service.xml
将它使用adb pull放到电脑上自己方便的位置备用。
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /vendor/etc/vintf/manifest/vendor.xiaomi.hardware.vibratorfeature.service.xml . /vendor/etc/vintf/manifest/vendor.xiao...ipped. 0.2 MB/s (1718 bytes in 0.009s)
不看扩展名,到 vendor/bin/hw/找到同名的 service 同样利用adb pull放电脑备用。比如我的叫
vendor.xiaomi.hardware.vibratorfeature.service
然后到 vendor/etc/init/找到同名.rc 文件,拉到电脑上,在里面加一条。并在定义 service 的最下面加上seclabel u:r:recovery:s0可以被 recovery 使用。
on boot start service被定义的名字
例如
on post-fs-data chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/f0_save chown system system /sys/bus/i2c/drivers/aw8697_haptic/2-005a/osc_save chown system system /sys/bus/i2c/drivers/aw8697_haptic/3-005a/osc_save # 省略一万字 on boot start vibratorfeature-hal-service service vibratorfeature-hal-service /vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service class hal user system group system input onrestart restart vibratorfeature seclabel u:r:recovery:s0
此外这种新设备在内核里还有振动模块需要加载,请到/vendor/modules/1.1/中寻找,例如我这台设备是haptic.ko,用 adb pull 拉取到电脑上,然后
- haptic.ko --> recovery/root/vendor/modules/1.1
至此所有必要的资料就准备好了。可能开机后仍然不工作,需要抓取 log 补缺失的 library,当然这是后话了。
开干!
在 BoardConfig.mk 中加入以下 flag
TW_SUPPORT_INPUT_AIDL_HAPTICS := true
将备用文件按照以下操作复制
- vendor.xiaomi.hardware.vibratorfeature.service.xml --> recovery/root/vendor/etc/vintf/manifest
- vendor.xiaomi.hardware.vibratorfeature.service --> recovery/root/vendor/bin/hw
- vendor.xiaomi.hardware.vibratorfeature.service.rc --> recovery/root/vendor/etc/init
之后编译,刷入,开机,喜提冻屏......
问题不大,使用adb logcat抓取日志
adb logcat > log.log
打开 log,搜索F linker、linker、library、beginning of crash这几个关键词,我搜索第一个就出来了。
F linker : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service": library "android.hardware.vibrator-V1-ndk_platform.so" not found: needed by main executable
这段报错的意思就是vendor.xiaomi.hardware.vibratorfeature.service找不到android.hardware.vibrator-V1-ndk_platform.so这个库,所以无法正常工作。
打开 BoardConfig.mk 加入以下 flag
# Library TARGET_RECOVERY_DEVICE_MODULES += \ android.hardware.vibrator-V1-ndk_platform.vendor TW_RECOVERY_ADDITIONAL_RELINK_LIBRARY_FILES += \ $(TARGET_OUT_SHARED_LIBRARIES)/android.hardware.vibrator-V1-ndk_platform.so
再次编译尝试
开机之后依然冻屏,继续抓 log,查找
F linker : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service": library "vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so" not found: needed by main executable
vendor.hardware.vibratorfeature字样和我们之前导入的文件长得差不多,一般都是供应商专有文件,所以去设备提取,路径在 vendor/lib64 里,虽然设备冻屏了,但我们可以用adb pull直接拉取到电脑。就像这样。
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb shell mount /vendor xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /vendor/lib64/vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so . /vendor/lib64/vendor.hardware.vibratorfeature.IVi...led, 0 skipped. 14.7 MB/s (33552 bytes in 0.002s
将这个文件按照以下提示操作
- vendor.hardware.vibratorfeature.IVibratorExt-V1-ndk_platform.so --> recovery/root/vendor/lib64
继续编译测试
还是冻屏,继续抓 log
F linker : CANNOT LINK EXECUTABLE "/vendor/bin/hw/vendor.xiaomi.hardware.vibratorfeature.service": library "libtinyalsa.so" not found: needed by main executable
这个 library twrp 的源码中应该没有,去设备拿一个 prebuilt 吧
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb shell mount /system_root xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /system_root/system/lib64/libtinyalsa.so . /system_root/system/lib64/libtinyalsa.so: 1 file ...led, 0 skipped. 13.6 MB/s (45032 bytes in 0.003s
将这个文件按照以下提示操作
- libtinyalsa.so --> recovery/root/system/lib64
编译测试
我艹了,还是冻屏,这次搜那几个关键词都搜不到了,搜vibrator看看这鬼东西报什么
E vendor.xiaomi.hardware.vibratorfeature.service: fail to load lib : /vendor/lib64/libaachaptics.so
这次都直接给路径了,直接拿。
xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb shell mount /vendor xiaolegun@xiaoleGundeMac-Pro ~/github/$/mjw adb pull /vendor/lib64/libaachaptics.so . /vendor/lib64/libaachaptics.so: 1 file pulled, 0 skipped. 15.8 MB/s (56232 bytes in 0.003s)
将这个文件按照以下提示操作
- libaachaptics.so --> recovery/root/vendor/lib64
至此应该没什么问题了,但是有个 flag 貌似要操作 data 内的东西,未解密会导致冻屏,所以等修完解密后再来修振动。
修复 CPU 温度
使用adb shell + grep命令在手机节点里搜索 type 关键词。
xiaolegun@xiaoleGundeMac-Pro ~ adb shell 'grep "cp_master" /sys/class/thermal/*/type' /sys/class/thermal/thermal_zone54/type:cp_master xiaolegun@xiaoleGundeMac-Pro ~ adb shell 'grep "cpu" /sys/class/thermal/*/type' /sys/class/thermal/thermal_zone1/type:cpu_little1 /sys/class/thermal/thermal_zone10/type:cpu_bigbig1 /sys/class/thermal/thermal_zone11/type:cpu_big6 /sys/class/thermal/thermal_zone12/type:cpu_bigbig2 /sys/class/thermal/thermal_zone2/type:cpu_little2 /sys/class/thermal/thermal_zone3/type:cpu_little3 /sys/class/thermal/thermal_zone4/type:cpu_little4 /sys/class/thermal/thermal_zone5/type:cpu_big1 /sys/class/thermal/thermal_zone6/type:cpu_big2 /sys/class/thermal/thermal_zone7/type:cpu_big3 /sys/class/thermal/thermal_zone8/type:cpu_big4 /sys/class/thermal/thermal_zone9/type:cpu_big5
我这里选用cp_master节点来读取温度。我的节点路径为/sys/class/thermal/thermal_zone54在后面添加 temp 来读取温度,你可以使用cat来检测节点是否可以正常读取温度
adb shell 'cat /sys/class/thermal/thermal_zone54/temp'
如果返回如
28000
这种类似的数值,那多半是没有问题的。
我们在 BoardConfig.mk 中加入
TW_CUSTOM_CPU_TEMP_PATH := "/sys/class/thermal/thermal_zone54/temp"
至此 cpu 温度就修复好了。
后序
这是我玩 Android 两年内第一次写关于 Android 的文章,内容和措辞可能不是很准确,再加上开学焦虑,租房因租金和房源不顺利,写的很乱,请各位指正。
此外有什么不懂得,多翻github,善用github搜索,多看看大佬们是怎么解决的。
解密等有空补,先补作业。