[教程]如何解包/编辑/打包android系统的boot.img⽂件..
====
如何解包/编辑/打包android系统的boot.img⽂件
⾸先声明这是转帖,LINUX环境⼤家可以⽤VMWARE来虚拟,可以下载UBUNTU
⽬录
1、背景知识
2、boot和recovery映像的⽂件结构
3、对映像⽂件进⾏解包、编辑、打包的常规⽅法
3.1、另⼀种解包、编辑、打包的⽅法
4、将新的映像刷回到⼿机
5、解包、编辑、打包为我们带来了什么
6、本⽂讲的内容与使⽤update.zip刷机包不是⼀码事
正⽂
1、背景知识
Android⼿机的⽂件系统有许多存储器组成,以下是在adb shell下⾯的输出:
#cat/proc/mtd
dev:        size        erasesize    name
mtd0:  00040000    00020000    "misc"
mtd1:  00500000    00020000    "recovery"
mtd2:  00280000    00020000    "boot"
mtd3:  04380000    00020000    "system"
mtd4:  04380000    00020000    "cache"
mtd5:  04ac0000    00020000      "userdata"
注意,不同的⼿机在上述存储设备的顺序可能会各不相同!⼀定要检查您的⼿机,确定在以下的操作中选择正确的设备号(mtdX,这个X的序号⼀定要检查清楚)。
在本向导中,我们主要描述对"recovery"和"boot"的存储设备进⾏操作;"system"存储设备保存了android系统⽬录的所有数据(在系统启动后会挂载到“system/”⽬录);“userdata”存储设备将保存了android数据⽬录中的所有数据(在系统启动后会挂载到“data/”⽬录,⾥⾯是会有很多应⽤数据以及⽤户的preference之类的配置数据)。
从上⾯的输出可以看出来,recovery和boot分区对应着/dev/mtd/mtd1和/dev/mtd/mtd2,在你您开始做任何修改之前⼀定要做两件事情,第⼀件事情,⼀定要先对这两个分区进⾏备份。
可以使⽤如下命令进⾏备份:
# cat/dev/mtd/mtd1>/sdcard/recovery.img
# cat/dev/mtd/mtd2>/sdcard/boot.img
(注意,只有⼿机获取了ROOT权限以后才能够执⾏上述的备份命令)
第⼆件事情,你您应该把你您最喜欢的update.zip刷机包放置到你您的sd卡的根⽬录上⾯。如此⼀来,即使你您在后续的操作中出了问题,也可以启动到recovery模式进⾏恢复。
另外⼀个你您需要知道的重要⽂件是在android系统⽬录下的/system/recovery.img,此⽂件是mtd1存储设备的完全拷贝。这个⽂件在每次关机的时候,会⾃动地被写回到mtd1存储设备⾥⾯。
这会意味着两个事情:
(1)任何对/dev/mtd/mtd1中数据的直接修改都会在下⼀次重启⼿机以后消失。
(2)如果希望对/dev/mtd/mtd1进⾏修改,最简单的做法是⽤你您⾃⼰的recovery.img替换掉/system/recovery.img。当你您创建⾃⼰的update.zip刷机包的时候(特别是在做刷机包的适配的时候),如果你您忘记替换这个/system/recovery.img,这个recovery.img就会在关机的时候被烧写到mtd1⾥⾯去或许会变砖。⼀定要注意这⼀点!
(译者的话,关于这个/system/recovery.img⽂件,在2.1的android的平台⾥⾯并没有到,或许这个机制已经out了?!或者偶本⼈对这段话的理解不够深⼊?!希望明⽩的朋友不吝斧正)
2、boot和recovery映像的⽂件结构
boot和recovery映像并不是⼀个完整的⽂件系统,它们是⼀种android⾃定义的⽂件格式,该格式包括了2K的⽂件头,后⾯紧跟着是⽤gzip压缩过的内核,再后⾯是⼀个ramdisk内存盘,然后紧跟着第⼆阶段的载⼊器程序(这个载⼊器程序是可选的,在某些映像中或许没有这部分)。此类⽂件的定义可以从源代码android-src/system/core/mkbootimg到⼀个叫做
bootimg.h的⽂件。
(译者的话,原⽂是⼀个叫做mkbootimg.h的⽂件,但从Android 2.1的代码来看,该⽂件名应该是改为bootimg.h了)。
(译者的话,原⽂是⼀个叫做mkbootimg.h的⽂件,但从Android 2.1的代码来看,该⽂件名应该是改为bootimg.h了)。
/*
** +-----------------+
** | boot header    | 1 page
** +-----------------+
** | kernel              | n pages
** +-----------------+
** | ramdisk          | m pages
** +-----------------+
** | second stage    | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
**    the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr.  kernel_args[] is
**    appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
**    else: jump to kernel_addr
*/
ramdisk映像是⼀个最基础的⼩型⽂件系统,它包括了初始化系统所需要的全部核⼼⽂件,例如:初始化init进程以及(可以⽤于设置很多系统的参数)等⽂件。
以下是⼀个典型的ramdisk中包含的⽂件列表:
./
./default.prop
./proc
./dev
./
./init
./sys
./
./sbin
./sbin/adbd
./system
./data
recovery映像包含了⼀些额外的⽂件,例如⼀个叫做recovery的⼆进制程序,以及⼀些对该程序⽀持性的资源图⽚⽂件(当你您按下
home+power组合键的时候就会运⾏这个recovery程序)。
典型的⽂件列表如下:
./res
./res/images
./res/images/progress_bar_empty_left_round.bmp
./res/images/icon_firmware_install.bmp
./res/images/indeterminate3.bmp
./res/images/progress_bar_fill.bmp
./res/images/progress_bar_left_round.bmp
./res/images/icon_error.bmp
./res/images/indeterminate1.bmp
./res/images/progress_bar_empty_right_round.bmp
./res/images/icon_firmware_error.bmp
./res/images/progress_bar_right_round.bmp
./res/images/indeterminate4.bmp
./res/images/indeterminate5.bmp
./res/images/indeterminate6.bmp
./res/images/progress_bar_empty.bmp
.
/res/images/indeterminate2.bmp
./res/images/icon_unpacking.bmp
./res/images/icon_installing.bmp
./sbin/recovery
3、对映像⽂件进⾏解包、编辑、打包的常规⽅法
(注意,下⾯我给你您介绍的是⼿⼯命令⾏⽅式进⾏解包以及重新打包的⽅法,但是我仍然创建了两个perl脚本,这两个脚本可以让你您的解包和打包⼯作变得轻松许多。
如果你您很擅长使⽤16进制编辑器的话,你您可以打开boot.img或者recovery.img,然后跳过开始的2K的头数据,然后寻⼀⼤堆0的数据,在这⼀堆0的数据后⾯,紧跟着1F 8B这两个数字(1F 8B是gzip格式的⽂件的结束标记)。从此⽂件开始的地⽅(跳过2K的头),⼀⼤堆0后⾯紧跟着到1F 8B这两个数字为⽌的全部数据(不包括1F 8B),就是gzip压缩过的linux内核。从1F 8B开始⼀直到⽂件的结尾包含的全部数据,就是ramdisk内存盘的数据。你您可以把把内核和ramdisk两个⽂件分别保存下来,在进⾏分别的修改和处理。我们可以通过un-cpio和un-gzip操作来读取ramdisk⽂件中的数据,可以使⽤如下的命令来实现这个⽬的,以下操作会⽣成⼀个⽬录,直接cd进去就可以看到ramdisk 中的
数据了:
gunzip -c ../your-ramdisk-file | cpio -i
此命令可以将ramdisk中的所有的⽂件解包到当前的⼯作⽬录下⾯,然后就可以对它进⾏编辑了。
当需要重新打包ramdisk的时候,就需要re-cpio然后re-gzip这些数据和⽬录,可以通过如下命令来实现:(cpio会把所有当前⽬录下⾯的⽂件都打包进去,因此,在进⾏此步骤之前,请把不需要的⽂件都清除掉。)
find . | cpio -o -H newc | gzip > ../
最后⼀步就是通过 mkbootimg这个⼯具,把kernel和ramdisk打包在⼀起,⽣成⼀个boot.img:
mkbootimg --cmdline 'no_console_suspend=1 console=null'
--kernel your-kernel-file --ramdisk -o mynewimage.img
这⾥的mkbootimg⼯具会在编译android的源代码的时候会在~/android-src/out/host/linux-x86/bin⽬录下⾯⾃动⽣成。
现在,如果不想背这些复杂的命令或者摆弄那个让⼈眩晕的16进制编辑器的话,可以尝试使⽤我编写的⽤于解包和打包的perl脚本了。希望这些脚本能够节约各位的键盘。
3.1、另⼀种解包、编辑、打包的⽅法
下载 split_bootimg.zip⽂件,在此zip⽂件中包含⼀个perl⽂件,split_bootimg.pl脚本,该脚本可以读取boot.img头(根据 Android源码中的bootimg.h读取)将kernel和ramdisk读取出来,此脚本也会输出内核命令⾏和板⼦名字。
(注意,不要使⽤从/dev/mtd/mtd2直接拷贝出来的boot.img,此映像可能在读取过程遭到损坏。)
下⾯是⼀个从TC4-RC28更新中提取出来的boot.img进⾏解包操作:
% ./split_bootimg.pl boot.img
Page size: 2048 (0x00000800)
Kernel size: 1388548 (0x00153004)
Ramdisk size: 141518 (0x000228ce)
Second size: 0 (0x00000000)
Board name:
Command line: no_console_suspend=1
Writing boot.img-kernel ... complete.
Writing ... complete.
解包ramdisk的命令如下:
% mkdir ramdisk
% cd ramdisk
% gzip -dc ../ | cpio -i
% cd ..
解码完毕后,就可以修改了(例如,在default.prop设置ro.secure=0等等)
使⽤mkbootfs⼯具(mkbootfs⼯具是编译完毕Android源代码以后,就会在~/android-src/out/host/linux-x86/bin⾃动⽣成)来重新创建ramdisk,可以使⽤如下命令来操作:
% mkbootfs ./ramdisk | gzip >
使⽤mkbootimg来重新创建boot.img,mkbootimg也可以在~/android-src/out/host/linux-x86/bin⽬录中可以到:
% mkbootimg --cmdline 'no_console_suspend=1 console=null'
--kernel boot.img-kernel -- -o boot-new.img
(注意:console=null的命令⾏选现是从TC4-RC30的boot.img引⼊的,⽤以去掉root shell)
4、将新的映像刷回到⼿机
可以将recovery.img拷贝到/system⽬录下⾯,然后重新启动⼿机,让⼿机⾃动为你您刷写到mtd⾥⾯(⼯作原理在上⾯已经提过了)。对于boot.img可以通过将其拷贝到sd卡的根⽬录,然后通过⼿机内的刷写⼯具将此映像写⼊到⼿机中。
例如,使⽤ adb⼯具( Android SDK中的⼀个⼯具)将boot.img拷贝到⼿机的sd卡的根⽬录:
adb push ./mynewimage.img /sdcard
然后通过adb shell登录⼿机(获取过 ROOT的)的shell交互模式,利⽤命令⾏进⾏交互:
然后通过adb shell登录⼿机(获取过 ROOT的)的shell交互模式,利⽤命令⾏进⾏交互:
# cat /dev/zero >/dev/mtd/mtd2
write: No space left on device [this is ok, you can ignore]
# flash_image boot /sdcard/mynewimage.img
然后重启⼿机。
如果⼿机能够正常启动,那么祝贺你您,你您的修改和替换已经成功了;如果不能够顺利启动,则需要重新启动进⼊recovery模式,并且使⽤update.zip来恢复。
5、解包、编辑、打包为我们带来了什么
可以修改⼿机开机启动时候的画⾯
gzip是什么文件夹
You can display a "splash" screen of sorts upon boot. You just have to have a file named initlogo.rle in your root directory. The trick is that the root directory is overwritten each time you boot with the contents of your boot image (mtd2). There are instructions elsewhere on the forums for updating this image.
You can prove to yourself that this works by just copying logo.rle to initlogo.rle in your updated boot image and you will see the "G1" screen twice.
The hurdle I'm running into is generating my own images. There is a program called [url=]to565[/url] that takes in an image and spits out the resulting image in the appropriate format (give it the -r flag to generate an rle) [edit, correct flag is -rle]. However, everything I generate with this just looks like random colored bars when I boot up (and sometimes at the bottom of the screen I see part of whatever was left in the framebuffer when I shut down). Supposedly to565 takes in a raw rgb888 file, and perhaps I'm not generating those properly. I tried saving to "raw image" from gimp but so far everything is just different variations on colored bars.
I may give up at this point, but I thought others might be interesting in picking up where I left off.
6、本⽂讲的内容与使⽤update.zip刷机包不是⼀码事
您可以很容易地在其他论坛上看到关于如何⾃制update.zip刷机包的⽅法,也可以下载到很多在⽹络上共享的⾃制刷机包。例如:近期的多数刷机包都来⾃对rc30包的修改和调整。在update.zip刷机包⾥⾯会包括新的boot.img,recovery.img以及整个system/⽬录下的若⼲⽂件的替换和更新。如果您希望⾃⼰⾃制boot.img以及recovery.img,建议您选取相对较新的更新和版本。(选⽤较⽼的映像的话,或许会出现兼容性问题)。