感謝本文的做者:Alansj, DarkriftX, RyeBrye, Will, Try OP9, Tonyb486, Timmmm, Lxrose還有好多不知名的做者們在wiki上的不懈努力。php
來源:http://android-dls.com/wiki/index.php?title=HOWTO:_Unpack%2C_Edit%2C_and_Re-Pack_Boot_Images html
目錄
一、背景知識
二、boot和recovery映像的文件結構
三、對映像文件進行解包、編輯、打包的常規方法
3.一、另外一種解包、編輯、打包的方法
四、將新的映像刷回到手機
五、解包、編輯、打包爲咱們帶來了什麼
六、本文講的內容與使用update.zip刷機包不是一碼事
正文
一、背景知識
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裏面去或許會變磚。必定要注意這一點!
二、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
三、對映像文件進行解包、編輯、打包的常規方法
(注意,下面我給你您介紹的是手工命令行方式進行解包以及從新打包的方法,可是我仍然建立了兩個perl腳本,這兩個腳本可讓你您的解包和打包工做變得輕鬆許多。linux
能夠參考本文的附件android
unpack-bootimg.zip http://android-dls.com/files/apps/unpack-bootimg.zipgit
repack-bootimg.zip http://android-dls.com/files/apps/repack-bootimg.zipweb
若是你您很擅長使用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.一、另外一種解包、編輯、打包的方法
下載
split_bootimg.zip文件,在此zip文件中包含一個perl文件,split_bootimg.pl腳本,該腳本能夠讀取boot.img頭(根據
Android源碼中的bootimg.h讀取)將kernel和ramdisk讀取出來,此腳本也會輸出內核命令行和板子名字。http://android-dls.com/files/linux/split_bootimg.zip
(注意,不要使用從/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)
四、將新的映像刷回到手機
能夠將recovery.img拷貝到/system目錄下面,而後從新啓動手機,讓手機自動爲你您刷寫到mtd裏面(工做原理在上面已經提過了)。對於boot.img能夠經過將其拷貝到sd卡的根目錄,而後經過手機內的刷寫工具將此映像寫入到手機中。
例如,使用
adb工具(
Android SDK中的一個工具)將boot.img拷貝到手機的sd卡的根目錄:
adb push .
/
mynewimage.img
/
sdcard
而後經過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來恢復。
五、解包、編輯、打包爲咱們帶來了什麼
能夠修改手機開機啓動時候的畫面,具體的操做的地址爲:
http://forum.xda-developers.com/showthread.php?t=443431
六、本文講的內容與使用update.zip刷機包不是一碼事
您能夠很容易地在其餘論壇上看到關於如何自制update.zip刷機包的方法,也能夠下載到不少在網絡上共享的自制刷機包。例如:近期的多數刷機包都來自對rc30包的修改和調整。在update.zip刷機包裏面會包括新的boot.img,recovery.img以及整個system/目錄下的若干文件的替換和更新。若是您但願本身自制boot.img以及recovery.img,建議您選取相對較新的更新和版本。(選用較老的映像的話,或許會出現兼容性問題)。 shell
對Gphone文件系統鏡像的製做作一個簡單的記錄。網絡
1、鏡像的製做app
前兩天對鏡像進行了解包和簡單的分析。而後把解包後的文件又壓縮成了鏡像刷會了個人G1手機。在這裏我簡單記錄一下如何壓縮鏡像。編輯器
壓縮鏡像其實比解壓簡單得多。只要將ramdisk的文件夾和內核的zImage放在同一個文件夾下。而後將如下工具也放入同個文件夾:mkbootimg 、repack-bootimg.pl 。(此處的mkbootimg並不適合HTC版本的 G2 boot.img的製做、如需建立HTC版本的 G2 boot.img則要修改mkbootimg的源碼,具體的修改方法我會在往後放出)
以後就打開shell,進入這個文件夾,而後執行:
./repack-bootimg.pl zImage ramdisk boot.img
很快的,最後在文件夾下產生的 boot.img就是boot.img鏡像。其實repack-bootimg.pl在這行過程當中會調用同目錄下的mkbootimg。而repack-bootimg.pl的使用格式是
repack-bootimg.pl <kernel> <ramdisk-directory> <outfile>
repack-bootimg.pl具體的原理你能夠看看這個腳本的代碼。recovery.img的鏡像製做也是同樣的。
2、簡單的刷機
在有了鏡像以後,就能夠刷機了。具體方法以下:
(1)先在G1上插入SD卡,而後把G1和電腦經過USB相連。下載SDK,解包後,經過shell在tools目錄下運行:
sudo ./adb kill-server
sudo./adb push (你的boot.img鏡像路徑) /sdcard
這樣,你的boot.img鏡像就在Gphone的SD卡中了
(2)而後,執行:
sudo ./adb kill-server
sudo ./adb shell
* daemon not running. starting it now *
* daemon started successfully *
#cat /dev/zero > /dev/mtd/mtd2
write: No space left on device
#flash_image boot /sdcard/(你的boot.img鏡像名稱)
這樣,你就將新的boot.img鏡像刷進了Gphone!能夠啓動看看了.
出處:http://blog.csdn.net/zhenwenxian/article/details/5856583