[原创] Android 提取并重新制作 boot.img

阅读前提

需要能成功编译并运行 Android 源码。具体可参考我之前写的另一篇文章:[原创] Ubuntu 18.04 LTS 编译原生 5.1.1 r26_LMY48Y 并刷机 Nexus 6

系统环境

本人系统环境如下:

OS 环境:Ubuntu 18.04.2 LTS X64 Desktop
内核版本:Linux version 4.15.0-51-generic (buildd@lgw01-amd64-059) (gcc version 7.3.0 (Ubuntu 7.3.0-16ubuntu3))

提取 boot.img

提取 boot.img 需要 split_bootimg.pl 工具。我已经将该工具添加到了 PATH 中,方便使用。

提取后,会得到 boot.img-kernelboot.img-ramdisk.gz 这两个文件。
解压 boot.img-ramdisk.gz 后会发现 boot.img-ramdisk 文件是 ASCII cpio archive 格式的,因此需要用 cpio 工具进行解压。
进一步提取后,最终会在 ramdisk 文件夹得到 boot.img-ramdisk 的所有代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
$ cd ~/android-source/android-5.1.1_r26/out/target/product/shamu/
$ mkdir boot-source
$ cd boot-source
$ cp ../boot.img .
$ split_bootimg.pl boot.img
Page size: 2048 (0x00000800)
Kernel size: 7204461 (0x006dee6d)
Ramdisk size: 721879 (0x000b03d7)
Second size: 0 (0x00000000)
Board name:
Command line: console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 androidboot.hardware=shamu msm_rtb.filter=0x37 ehci-hcd.park=3 utags.blkdev=/dev/block/platform/msm_sdcc.1/by-name/utags utags.backup=/dev/block/platform/msm_sdcc.1/by-name/utagsBackup coherent_pool=8M
Writing boot.img-kernel ... complete.
Writing boot.img-ramdisk.gz ... complete.

$ ll
总用量 15500
drwxr-xr-x 2 yhz61010 yhz61010 4096 6月 18 13:23 ./
drwxr-xr-x 13 yhz61010 yhz61010 4096 6月 18 10:58 ../
-rw-r--r-- 1 yhz61010 yhz61010 7931175 6月 18 13:23 boot.img
-rw-r--r-- 1 yhz61010 yhz61010 7204461 6月 18 13:23 boot.img-kernel
-rw-r--r-- 1 yhz61010 yhz61010 721879 6月 18 13:23 boot.img-ramdisk.gz

$ gzip -d boot.img-ramdisk.gz
$ file boot.img-ramdisk
boot.img-ramdisk: ASCII cpio archive (SVR4 with no CRC)

$ mkdir ramdisk
$ cd ramdisk/
$ cpio -i < ../boot.img-ramdisk
2504 blocks

$ ll
总用量 704
drwxr-xr-x 9 yhz61010 yhz61010 4096 6月 18 13:47 ./
drwxr-xr-x 3 yhz61010 yhz61010 4096 6月 18 13:47 ../
lrwxrwxrwx 1 yhz61010 yhz61010 13 6月 18 13:47 charger -> /sbin/healthd
drwxrwx--x 2 yhz61010 yhz61010 4096 6月 18 13:47 data/
-rw-r--r-- 1 yhz61010 yhz61010 402 6月 18 13:47 default.prop
drwxr-xr-x 2 yhz61010 yhz61010 4096 6月 18 13:47 dev/
-rw-r--r-- 1 yhz61010 yhz61010 18007 6月 18 13:47 file_contexts
-rw-r----- 1 yhz61010 yhz61010 3310 6月 18 13:47 fstab.shamu
-rwxr-x--- 1 yhz61010 yhz61010 375344 6月 18 13:47 init*
-rwxr-x--- 1 yhz61010 yhz61010 944 6月 18 13:47 init.environ.rc*
-rwxr-x--- 1 yhz61010 yhz61010 5108 6月 18 13:47 init.mmi.touch.sh*
-rwxr-x--- 1 yhz61010 yhz61010 21728 6月 18 13:47 init.rc*
-rwxr-x--- 1 yhz61010 yhz61010 164 6月 18 13:47 init.shamu.diag.rc*
-rwxr-x--- 1 yhz61010 yhz61010 5553 6月 18 13:47 init.shamu.power.rc*
-rwxr-x--- 1 yhz61010 yhz61010 19782 6月 18 13:47 init.shamu.rc*
-rwxr-x--- 1 yhz61010 yhz61010 11573 6月 18 13:47 init.shamu.usb.rc*
-rwxr-x--- 1 yhz61010 yhz61010 1927 6月 18 13:47 init.trace.rc*
-rwxr-x--- 1 yhz61010 yhz61010 3885 6月 18 13:47 init.usb.rc*
-rwxr-x--- 1 yhz61010 yhz61010 301 6月 18 13:47 init.zygote32.rc*
drwxr-xr-x 2 yhz61010 yhz61010 4096 6月 18 13:47 proc/
-rw-r--r-- 1 yhz61010 yhz61010 2870 6月 18 13:47 property_contexts
drwxr-xr-x 3 yhz61010 yhz61010 4096 6月 18 13:47 res/
drwxr-x--- 2 yhz61010 yhz61010 4096 6月 18 13:47 sbin/
-rw-r--r-- 1 yhz61010 yhz61010 471 6月 18 13:47 seapp_contexts
-rw-r--r-- 1 yhz61010 yhz61010 74 6月 18 13:47 selinux_version
-rw-r--r-- 1 yhz61010 yhz61010 142882 6月 18 13:47 sepolicy
-rw-r--r-- 1 yhz61010 yhz61010 9632 6月 18 13:47 service_contexts
drwxr-xr-x 2 yhz61010 yhz61010 4096 6月 18 13:47 sys/
drwxr-xr-x 2 yhz61010 yhz61010 4096 6月 18 13:47 system/
-rw-r--r-- 1 yhz61010 yhz61010 4464 6月 18 13:47 ueventd.rc
-rw-r--r-- 1 yhz61010 yhz61010 3171 6月 18 13:47 ueventd.shamu.rc
-rw-r--r-- 1 yhz61010 yhz61010 524 6月 18 13:47 verity_key

另外,用 cpio 工具进行解压时,还可以将 gzipcpio 两条命令合成一条,执行后,不会直接解压 boot.img-ramdisk.gz,但是会将解压结果输出到控制台后直接通过 cpio -i 命令将文件解压到当前文件夹:

1
2
3
$ cd ramdisk/
$ gzip -dc ../boot.img-ramdisk.gz | cpio -i
#2504 blocks

adb root

得到上面的代码后,若要进行 adb 永久 root 也就是进入 adb shell 后直接使用的是 root 用户,需要做如下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ cd ~/android-source/android-5.1.1_r26/out/target/product/shamu/boot-source/ramdisk/
$ vim default.prop
#
# ADDITIONAL_DEFAULT_PROPERTIES
#
ro.secure=1
ro.allow.mock.location=0
ro.debuggable=1
ro.zygote=zygote32
camera.disable_zsl_mode=0
persist.camera.HAL3.enabled=1
persist.camera.ois.disable=0
persist.sys.usb.config=mtp,adb
ro.qualcomm.perf.cores_online=2
dalvik.vm.dex2oat-Xms=64m
dalvik.vm.dex2oat-Xmx=512m
dalvik.vm.image-dex2oat-Xms=64m
dalvik.vm.image-dex2oat-Xmx=64m
ro.dalvik.vm.native.bridge=0

对文件进行如下修改:

1
2
ro.secure=0
ro.debuggable=1

这样你的 adb 就是 root 的了。

重新生成 boot.img

重新生成 boot.img 需要 mkbootimgmkbootfs 工具,这些工具在编译 Android 源码时会生成,生成的位置如下:
~/android-source/android-5.1.1_r26/out/host/linux-x86/bin/
另外还需要 boot_info.sh 工具。

查看 boot.img 信息

首先使用 boot_info.sh 工具查看 boot.img 的信息:

1
2
3
4
5
6
$ cd ~/android-source/android-5.1.1_r26/out/target/product/shamu/boot-source/
$ ./boot_info.sh boot.img
PAGE SIZE: 2048
BASE ADDRESS: 0x00000000
RAMDISK ADDRESS: 0x0000000b
CMDLINE: 'console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 androidboot.hardware=shamu msm_rtb.filter=0x37 ehci-hcd.park=3 utags.blkdev=/dev/block/platform/msm_sdcc.1/by-name/utags utags.backup=/dev/block/platform/msm_sdcc.1/by-name/utagsBackup coherent_pool=8M'

注意

这里需要记录下 PAGE SIZEBASE ADDRESSCMDLINE 这三个信息的值,下面会用到这些信息。

生成新的 boot 镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ cd ~/android-source/android-5.1.1_r26/out/target/product/shamu/boot-source/
$ ~/android-source/android-5.1.1_r26/out/host/linux-x86/bin/mkbootfs ./ramdisk | gzip > ramdisk.img.gz
# 生成新的 boot 镜像
$ ~/android-source/android-5.1.1_r26/out/host/linux-x86/bin/mkbootimg --cmdline "console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 androidboot.hardware=shamu msm_rtb.filter=0x37 ehci-hcd.park=3 utags.blkdev=/dev/block/platform/msm_sdcc.1/by-name/utags utags.backup=/dev/block/platform/msm_sdcc.1/by-name/utagsBackup coherent_pool=8M" --base 0x00000000 --pagesize 2048 --kernel boot.img-kernel --ramdisk ramdisk.img.gz -o newboot.img

$ ll
总用量 24508
drwxr-xr-x 3 yhz61010 yhz61010 4096 6月 18 18:11 ./
drwxr-xr-x 13 yhz61010 yhz61010 4096 6月 18 15:18 ../
-rw-r--r-- 1 yhz61010 yhz61010 7931175 6月 18 18:04 boot.img
-rw-r--r-- 1 yhz61010 yhz61010 7204461 6月 18 18:04 boot.img-kernel
-rw-r--r-- 1 yhz61010 yhz61010 1282048 6月 18 18:04 boot.img-ramdisk
-rwxr-xr-x 1 yhz61010 yhz61010 648 6月 18 18:03 boot_info.sh*
-rw-r--r-- 1 yhz61010 yhz61010 7931904 6月 18 18:11 newboot.img
drwxr-xr-x 9 yhz61010 yhz61010 4096 6月 18 18:05 ramdisk/
-rw-r--r-- 1 yhz61010 yhz61010 723203 6月 18 18:10 ramdisk.img.gz

这里需要注意 mkbootimg 命令的参数,--cmdline--base--pagesize 的值就是刚刚在查看 boot.img 信息中得到的结果。

执行后会得到新的 boot 镜像文件 newboot.img。之后就可以使用该 boot 镜像进行刷机了。

参考文献

坚持原创及高品质技术分享,您的支持将鼓励我继续创作!