Android平台刷机包制作研究


android平台的刷机包的问题。总算说服自己研究一下如何制作一个android平台的刷机包,可能我了解的方法还不是很全面,也走了不少的弯路,但是以此做为一串探索的足迹,希望能为来者节约宝贵的时间,也请对此感兴趣的各位同仁尽量避免偶曾经犯过的错误。

在此先要明确声明一下:
由于android平台的更新换代过于频繁,偶的做法不一定好用,也不一定完全正确(只是记录一下偶在自己的nexus one上面做的一些实验而已)。依照偶的做法出现了您的手机出现任何问题,偶都是不负责的喔!!

英文好的朋友可以不必看着偶聒噪,直接看英文官方的参考网站即可:
http://forum.xda-developers.com/showthread.php?t=566235
http://android-dls.com/wiki/index.php?title=HOWTO:_Unpack%2C_Edit%2C_and_Re-Pack_Boot_Images

只用android源代码做一些简单实验的朋友可以参考下面这几个网站:
http://nhenze.net/?tag=build-android
http://developer.htc.com/adp.html

说起android刷机包,听起来非常神秘,实际上它仅仅是一个经过数字签名的zip压缩包而已。如果要自己制作刷机包,则必须了解刷机包的基本工作原理,偶首先从android系统的启动说起:

android系统启动的时候,首先会进行一些诸如硬件自检之类的操作,这些操作完成以后(至少它应该知道当前的机器有没有电),会检查一下当前手机按键的状态(接下来就是所谓刷机模式切换了,不同的android手机有不同的按键组合用来进入刷机模式),如果此时按键状态处于刷机组合,那么系统会调用ROM里面的一个叫做recovery的程序(这时就是进入了所谓的刷机程序了,它只是一个工具性质程序,用于检查刷机包的完整性和数字签名的合法性。对于目前大多数root过的机器而言,数字签名的合法性都不会成问题,然后由recovery程序将刷机包进行解压,然后把刷机包里面的文件写入到ROM中去,以此完成刷机过程);如果此时按键没有标明是刷机模式,那么系统会创建内存盘,开始从ROM里面载入相应的文件系统,并把相关的文件拷贝到内存盘中,进而引导linux启动,然后是启动虚拟机dalvik,然后就是创建工作进程载入和运行framework,然后就会看到待机的画面。当然在这个过程中还发生了许多事情,启动了许多服务,为了简化起见,对于启动过程偶只讲解到此,感兴趣的朋友可以自己结合着linux的启动过程加以对比来学习。

现在来总结一下,实际上刷机包就是一个ROM文件的压缩包,进入刷机模式后,recovery程序会把刷机包里面的文件写入ROM存储区替换ROM存储区的原有文件;当下次启动手机的时候,会从ROM中载入刚刚替换过的文件,并利用这些文件来启动和运行系统。这就是刷机包的全部功能和作用,看不懂的朋友可以反复看几次,刷机的本质就是文件的覆盖和替换操作,偶相信各位一定能看懂!

OK,现在大家已经知道ROM文件的zip压缩包就是所谓的刷机包。制作刷机包的过程就是准备这些文件,然后重新把这些文件压缩成一个zip包的过程,在制作的最后,使用签名工具签个名,就可以测试和发布刷机包了。虽然说起来就是一句话的事情,但是实际上准备这些文件的过程是非常痛苦和漫长的。

那么update.zip压缩包里面的都包含哪些文件?这些文件又都是如何做出来的呢?hoho,现在开始渐渐接触到问题的本质了,解压缩这个update.zip压缩包以后我们可以看到两个目录和一个文件:

boot.img   <---文件,这是编译内核源代码生成的内核映像,然后与android源码编译出来的ramdisk.img一起通过mkbootimg工具创建出来的,图省事的朋友也可以从网上其他的刷机包里面拷贝一个能用的出来即可,基本上都差不多。

META-INF   <---目录,这个目录是手工创建的,主要用来存放一个升级脚本update-script(这个脚本的内容与system目录中包含的文件有很大关联)以及保存若干刷机包内的apk文件的签名。

system   <---目录,这个目录就是编译android的平台源代码生成的,

其实最好的学习方式就是把现在互联网上的那些update.zip包给解包,然后自己一个一个文件地看和分析,然后修改,尝试做自己的刷机包。

对于这个boot.img,基本思路是编译android kernel代码,生成内核image然后利用mkbootimg感兴趣的朋友可以参考下面这两个wiki网站:
http://android-dls.com/wiki/index.php?title=HOWTO:_Unpack%2C_Edit%2C_and_Re-Pack_Boot_Images

http://android-dls.com/wiki/index.php?title=Replace_Recovery_Partition

下面的做法偶都是在linux下面完成的(slackware 13.1):
(1)下载和编译android的源代码,具体过程不再赘述
如果各位还不知道repo sync之类的命令的话,可以参考网上的关于下载android源代码以及编译的文章,据偶所知这些文章非常丰富。编译之前一定要注意平台的选择,不同平台的驱动程序是不一样的!这些参数可以通过:
$ cd android-src    <---进入android的源代码目录
$ . build/envsetup.sh <---设置环境变量,运行完毕后,你可以输入一下help命令,看看google的团队提供了多少有用的便利命令,这对于我们以后修改代码重新编译非常有帮助。
$ lunch generic-eng   <---开始配置android的源代码的编译选项
运行上述命令后会看到如下输出:
wayne@wayne:~/android-src$ lunch generic-eng

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.1-update1
TARGET_PRODUCT=generic
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=ECLAIR
============================================

$ make -j2   <---只有双核的CPU的朋友可以尝试此参数,四核的朋友可以试试-j4,否则就老老实实运行make即可:D。

然后就是一个漫长的等待,这个时间大概有1-2小时左右(偶的机器比较慢),完全编译完毕以后硬盘的占用大概需要8个G左右。

(2)编译完成以后,进入wayne@wayne:~/android-src/out/target/product/generic目录,应该会看到如下的文件:
android-info.txt  
data                 
obj                       
ramdisk.img  
sdk      
system      
userdata.img
clean_steps.mk    
installed-files.txt  
previous_build_config.mk  
root         
symbols  
system.img
这里的system.img是不是很眼熟?!对拉,这个就是刷机包里面好像也有一个叫做什么system的目录,那么这个system.img里面都有什么呢?这里面的东西其实就是当前目录下的一个叫做system的目录里面的内容了,只是保存成了yaffs文件系统的格式。我们可以通过unyaffs工具来把system.img给解开来看看,就明白偶说话了。
unyaffs的代码下载地址为:
http://code.google.com/p/unyaffs/downloads/list
编译方法非常地简单,只需要下载源代码,然后运行:
$ gcc -c unyaffs.c
$ gcc -o unyaffs unyaffs.o
即可生成这个unyaffs的解包工具,利用这个工具就可以把自己生成的system.img进行解包,然后修改里面的内容了。
unyaffs使用方法非常简单:
$ unyaffs system.img [回车]
即可将system.img解包成一个叫做system的目录,里面包含了整个android的文件系统(何为文件系统?!如果提出这个问题的话,偶就不多说什么了,回家啃啃大学里面计算机专业的操作系统那本书吧)

(3)刚刚开始,不适合一切从头来,还是老实一些,先从修改别的大牛们做得刷机包开始吧
首先拷贝一个从网上下载下来的刷机包,然后找一个目录解压缩(当然,这是最保险的做法,自己做这些目录也没有任何问题,只是比较费时间而已)
$ unzip xxxxxx.zip   <--- 这个xxxxx.zip就是从网上下载的某刷机包(一定要跟你的代码版本基本一致喔,偶在这里用的是2.1的刷机包)

(4)替换原有的system目录
解压缩刷机包以后,会看到在开篇的时候提到的两个目录,一个文件:
boot.img
META-INF
system
好了,可以把system目录拷贝到别的路径下备份一给,防止这些修改发生别的问题。然后把wayne@wayne:~/android-src/out/target/product/generic这个目录下面的system拷贝到当前的工作目录下。注意,这个system目录里面有很多“符号链接”指向了toolbox。这些链接其实没啥用,可以通过后面的update-script自动进行创建的,因此,需要用一个脚本把这些链接都删掉。
可以参考:
http://forum.xda-developers.com/showthread.php?t=566235
这个网页附件给出来的DeleteExtras.txt改写成一个DeleteExtras.sh脚本来清除这些符号链接。

(5)修改update-script脚本
修改META-INF/com/google/android目录下的那个叫做update-script的脚本,只要修改一下即可,主要是删除一些不存在的文件以及增加一些文件的权限之类的定义(语法十分清晰,一目了然)。把需要“预装”到刷机包里面的apk安装程序都准备好,将这些apk拷贝到system/app目录下即可。那个boot.img能不改就不改,因为这东西涉及到驱动和内核的问题,出了问题刷机包就启动不了了。

(6)重新打包成update.zip
$ zip -r update.zip .   <---注意这最后的“.”是必不可少的,代表是当前路径下的意思。

(7)为做好的刷机包签名
在上面提到的链接中,有一个叫做AutoSign的工具,打开一看是一个jar格式的工具包。可是让人郁闷的是这个工具包的作者在制作jar包的时候,忘记了在MANIFEST.MF中添加一个叫做:
Main-Class: testsign
的入口指定,偶重新折腾了一下,总算是利用手头的工具,重新做了一个jar包,才解决这个问题。
为了方便大家的使用,偶将这个修改后的签名工具做为附件贴出来,以节约大家的时间。
另外,需要提一下的是,这个签名工具是使用jdk1.6.10的jdk制作的,因此,要求各位的java配套工具的版本一定要满足。
运行如下命令对刷机包进行签名:
$ java -jar testsign.jar update.zip update_signed.zip

ok,签名完毕后,就可以备份一下手机里面的东西,测试一下了。

以下是偶翻译的关于boot.img和recovery.img的编辑和修改方面的文章,希望能够为感兴趣的朋友节约一些看资料的时间。感谢本文的作者:Alansj, DarkriftX, RyeBrye, Will, Try OP9, Tonyb486, Timmmm, Lxrose还有好多不知名的作者们在wiki上的不懈努力。

如何解包/编辑/大包boot.img文件

很多人用自己的方式解决了boot.img的解包/编辑/打包的问题,有人要求我来写一篇关于boot和recovery映像的文件结构和如何对其编辑的文章,于是就有了下面这篇文章。

目录
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
(注意added by lxros,只有手机获取了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了)。

/*
** +-----------------+ 
** | 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进程以及init.rc(可以用于设置很多系统的参数)等文件。如果你您希望了解更多关于此文件的信息可以参考以下网址:
http://git.source.android.com/?p=kernel/common.git;a=blob;f=Documentation/filesystems/ramfs-rootfs-initramfs.txt
以下是一个典型的ramdisk中包含的文件列表:
./init.trout.rc
./default.prop
./proc
./dev
./init.rc
./init
./sys
./init.goldfish.rc
./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脚本,这两个脚本可以让你您的解包和打包工作变得轻松许多。可以参考本文的附件unpack-bootimg.zip和repack-bootimg.zip)

如果你您很擅长使用16进制编辑器的话,你您可以打开boot.img或者recovery.img,然后跳过开始的2K的头数据,然后寻找一大堆0的数据,在这一堆0的数据后面,紧跟着1F 8B这两个数字(1F 8B是gzip格式的文件的结束标记)。从此文件开始的地方(跳过2K的头),一大堆0后面紧跟着到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 > ../newramdisk.cpio.gz

最后一步就是通过mkbootimg这个工具,把kernel和ramdisk打包在一起,生成一个boot.img:

mkbootimg --cmdline 'no_console_suspend=1 console=null' --kernel your-kernel-file --ramdisk newramdisk.cpio.gz -o mynewimage.img

这里的mkbootimg工具会在编译android的源代码的时候会在~/android-src/out/host/linux-x86/bin目录下面自动生成。
下载地址:
http://git.source.android.com/?p=platform/system/core.git;a=tree;f=mkbootimg

现在,如果不想背这些复杂的命令或者摆弄那个让人眩晕的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 boot.img-ramdisk.gz ... complete.

解包ramdisk的命令如下:
% mkdir ramdisk
% cd ramdisk
% gzip -dc ../boot.img-ramdisk.gz | cpio -i
% cd ..

解码完毕后,就可以修改了(例如,在default.prop设置ro.secure=0等等)

使用mkbootfs工具(mkbootfs工具是编译完毕Android源代码以后,就会在~/android-src/out/host/linux-x86/bin自动生成)来重新创建ramdisk,可以使用如下命令来操作:
% mkbootfs ./ramdisk | gzip > ramdisk-new.gz

使用mkbootimg来重新创建boot.img,mkbootimg也可以在~/android-src/out/host/linux-x86/bin目录中可以找到:
% mkbootimg --cmdline 'no_console_suspend=1 console=null' --kernel boot.img-kernel --ramdisk ramdisk-new.gz -o boot-new.img
(注意:console=null的命令行选现是从TC4-RC30的boot.img引入的,用以去掉root shell)

4、将新的映像刷回到手机
可以将recovery.img拷贝到/system目录下面,然后重新启动手机,让手机自动为你您刷写到mtd里面(工作原理在上面已经提过了)。对于boot.img可以通过将其拷贝到sd卡的根目录,然后通过手机内的刷写工具将此映像写入到手机中。

例如,使用adb工具将boot.img拷贝到手机的sd卡的根目录:
adb push ./mynewimage.img /sdcard
然后通过adb shell登录手机的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、解包、编辑、打包为我们带来了什么
可以修改手机开机启动时候的画面,具体的操作的地址为:
http://forum.xda-developers.com/showthread.php?t=443431

6、本文讲的内容与使用update.zip刷机包不是一码事
您可以很容易地在其他论坛上看到关于如何自制update.zip刷机包的方法,也可以下载到很多在网络上共享的自制刷机包。例如:近期的多数刷机包都来自对rc30包的修改和调整。在update.zip刷机包里面会包括新的boot.img,recovery.img以及整个system/目录下的若干文件的替换和更新。如果您希望自己自制boot.img以及recovery.img,建议您选取相对较新的更新和版本。(选用较老的映像的话,或许会出现兼容性问题)。

祝各位好运


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值