首先聲明這是轉帖,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了)。
/*
** +-----------------+
** | 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 http://android-dls.com/files/apps/unpack-bootimg.zip
repack-bootimg.zip http://android-dls.com/files/apps/repack-bootimg.zip
如果你您很擅長使用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 > ../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讀取出來,此指令碼也會輸出核心命令列和板子名字。 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)
4、將新的映像刷回到手機
可以將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來恢複。
5、解包、編輯、打包為我們帶來了什麼
可以修改手機開機啟動時候的畫面,具體的操作的地址為:
http://forum.xda-developers.com/showthread.php?t=443431
nitlogo.rle: display an image on boot
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 to565 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,建議您選取相對較新的更新和版本。(選用較老的映像的話,或許會出現相容性問題)。