Essential PH-1刷LineageOS 16卡在提取文件?手把手教你从A/B OTA的boot.img里挖出recovery.img

张开发
2026/4/20 23:51:32 15 分钟阅读

分享文章

Essential PH-1刷LineageOS 16卡在提取文件?手把手教你从A/B OTA的boot.img里挖出recovery.img
Essential PH-1刷机实战从boot.img提取recovery.img的完整指南Essential PH-1作为一款采用A/B分区架构的设备在刷入LineageOS等第三方ROM时常常会遇到一个特殊问题——系统无法直接获取独立的recovery镜像。这导致许多用户在Extract proprietary blobs步骤卡住无法继续刷机流程。本文将详细解析这一问题的技术背景并提供一套经过实战验证的解决方案。1. 问题背景与技术原理Essential PH-1采用了Google推荐的A/B无缝更新机制也称为Seamless Updates这种设计将系统分为两个相同的分区A和B允许在后台下载更新并在重启时快速切换。这种机制带来一个副作用传统的recovery分区被整合到了boot镜像中。具体来说在A/B设备中Recovery功能被集成到boot.img的ramdisk部分系统通过设置不同的启动参数来决定进入常规系统还是恢复模式OTA更新包中不再包含独立的recovery.img文件这种设计优化了更新体验但也给自定义ROM刷机带来了挑战。当我们需要从官方ROM中提取专有文件proprietary blobs时许多脚本如extract-files.sh会尝试访问recovery分区中的文件而这一分区实际上并不存在独立镜像。2. 准备工作与环境搭建在开始提取操作前需要准备以下环境和工具2.1 硬件与软件需求Essential PH-1设备一台已解锁bootloader配置良好的Linux开发环境推荐Ubuntu 20.04至少50GB可用磁盘空间Python 3.6运行环境2.2 必要工具安装执行以下命令安装所需工具sudo apt update sudo apt install -y python3-pip git-core gnupg flex bison gperf build-essential \ zip curl zlib1g-dev gcc-multilib g-multilib libc6-dev-i386 \ lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache \ libgl1-mesa-dev libxml2-utils xsltproc unzip安装Python依赖pip3 install google-cloud protobuf google backports.lzma2.3 获取官方固件包从官方渠道下载最新的Essential PH-1固件包.zip格式这将作为我们提取boot.img的源文件。3. 从OTA包提取boot.imgEssential PH-1采用Payload-based OTA格式我们需要特殊工具来处理这种打包方式。3.1 解压OTA包首先解压下载的固件包unzip essential_ph1_ota_xxxxxx.zip -d ota_package解压后会得到若干文件其中最重要的就是payload.bin。3.2 使用payload-dumper工具我们需要使用payload-dumper.py工具来提取payload.bin中的分区镜像git clone https://github.com/vm03/payload_dumper.git cd payload_dumper python3 payload_dumper.py ../ota_package/payload.bin提取完成后输出目录中会包含所有分区镜像其中就包括我们需要的boot.img。注意不同版本的payload-dumper可能需要不同的Python依赖如果遇到错误请根据提示安装相应包4. 从boot.img提取recovery镜像这是整个过程中技术性最强的部分需要分析Android boot镜像格式并正确提取ramdisk。4.1 分析boot.img结构Android boot镜像的标准结构如下----------------- | boot header | 1 page (通常4KB) ----------------- | kernel | n pages ----------------- | ramdisk | m pages ----------------- | second stage | o pages (可选) -----------------我们可以使用hexdump查看boot.img的头部信息hexdump -C -n 32 boot.img典型输出如下00000000 41 4e 44 52 4f 49 44 21 a4 1c f2 00 00 80 00 00 |ANDROID!........| 00000010 1a 1c cc 00 00 00 20 02 00 00 00 00 00 00 f0 00 |...... .........|关键字段解析0x00-0x07: 魔数ANDROID!0x08-0x0B: kernel大小小端序0x0C-0x0F: kernel加载地址0x10-0x13: ramdisk大小0x14-0x17: ramdisk加载地址4.2 计算ramdisk偏移量根据头部信息计算ramdisk在文件中的实际位置获取page size通常是4096echo $((0x$(hexdump -s 36 -n 4 -e /4 %08x\n boot.img)))计算kernel占用的页数kernel_size$((0x$(hexdump -s 8 -n 4 -e /4 %08x\n boot.img))) kernel_pages$(( (kernel_size 4095) / 4096 ))ramdisk起始偏移ramdisk_offset$(( (1 kernel_pages) * 4096 ))4.3 提取ramdisk内容使用dd命令提取ramdisk部分dd ifboot.img oframdisk-recovery.img bs4096 skip$((ramdisk_offset/4096))5. 解压和提取recovery文件获取到的ramdisk-recovery.img实际上是经过压缩的存档需要进一步处理。5.1 识别文件类型首先检查文件格式file ramdisk-recovery.img输出通常是ramdisk-recovery.img: gzip compressed data, from Unix5.2 解压ramdisk重命名并解压gzip文件mv ramdisk-recovery.img ramdisk-recovery.gz gunzip ramdisk-recovery.gz然后检查解压后的文件file ramdisk-recovery应该看到ramdisk-recovery: ASCII cpio archive (SVR4 with no CRC)5.3 提取cpio存档创建目录并提取文件mkdir recovery cd recovery cpio -idv ../ramdisk-recovery成功执行后recovery目录中将包含完整的恢复模式文件系统。6. 验证与使用提取的文件现在可以检查提取的文件是否完整ls -l关键文件应该包括init恢复模式的主初始化程序init.rc初始化脚本fstab.*文件系统挂载配置各种二进制文件和库这些文件现在可以用于提供给extract-files.sh脚本提取专有blobs手动复制到LineageOS源码树的vendor目录调试和修改恢复模式功能7. 常见问题与解决方案在实际操作中可能会遇到以下问题7.1 payload-dumper执行失败现象Python脚本报错或无法解析payload.bin解决确保安装了所有依赖pip3 install -r requirements.txt尝试更新工具到最新版本检查payload.bin是否完整MD5校验7.2 ramdisk提取不完整现象解压后的文件系统缺失关键文件解决重新检查boot.img头部信息计算是否正确尝试不同的page size有些设备可能使用2048使用binwalk工具辅助分析镜像结构7.3 cpio提取失败现象cpio命令报Malformed cpio archive错误解决确保文件完全解压gunzip -v ramdisk-recovery.gz尝试不同的cpio选项cpio -idumv ../ramdisk-recovery手动修复损坏的存档头部8. 高级技巧与优化建议对于需要频繁进行此操作的用户可以考虑以下优化自动化脚本将整个流程编写为shell脚本只需提供boot.img即可自动完成提取Docker环境创建包含所有依赖的Docker镜像避免污染主机环境二进制补丁直接修改boot.img头部信息来简化提取过程版本管理对不同版本的提取文件进行归档便于回溯和比较#!/bin/bash # 自动化提取脚本示例 BOOTIMG$1 PAGE_SIZE4096 # 解析头部信息 KERNEL_SIZE$(hexdump -s 8 -n 4 -e /4 %d\n $BOOTIMG) RAMDISK_SIZE$(hexdump -s 16 -n 4 -e /4 %d\n $BOOTIMG) # 计算偏移 KERNEL_PAGES$(( (KERNEL_SIZE PAGE_SIZE - 1) / PAGE_SIZE )) RAMDISK_OFFSET$(( (1 KERNEL_PAGES) * PAGE_SIZE )) # 提取ramdisk dd if$BOOTIMG oframdisk-recovery.img bs$PAGE_SIZE skip$((RAMDISK_OFFSET/PAGE_SIZE)) # 解压处理 mv ramdisk-recovery.img ramdisk-recovery.gz gunzip ramdisk-recovery.gz mkdir -p recovery cd recovery cpio -idv ../ramdisk-recovery echo 提取完成文件位于recovery目录这套方法不仅适用于Essential PH-1经过适当调整也可用于其他采用A/B分区的设备。我在实际帮朋友修复Nokia 6.1 Plus时发现虽然具体参数不同但基本思路完全一致。最关键的是准确解析boot.img头部信息这需要一些耐心和十六进制计算能力。

更多文章