Android ROM的製作與燒錄

Android編譯生成的三個鏡像文件
Android源碼編譯後,在out/target/product/generic下生成的三個鏡像文件:ramdisk.img,system.img,userdata.img以及它們對應的目錄樹root,system,data。ramdisk.img是根文件系統,system.img包括了主要的包、庫等文件,userdata.img包括了一些用戶數據,android加載這3個映像文件後,會把 system和 userdata分別加載到 ramdisk文件系統中的system和 data目錄下。
三個鏡像文件及其三個目錄樹之間的生成關係是我們進行ROM製作的基礎,下面將做詳細介紹。
Ramdisk.img
Ramdisk鏡像是採用cpio打包,gzip壓縮的。用file驗證:
# file ramdisk.img
輸出:
# ramdisk.img: gzip compressed data, from Unix
爲了便於說明問題,我們將ramdisk.img拷貝到其它一個目錄,然後按以下步驟將ramdisk.img還原爲目錄樹:
# mv ramdisk.img ramdisk.img.gz 
# gunzip ramdisk.img.gz
# mkdir ramdisk
#cd ramdisk
# cpio –i –F ../ramdisk.img
這樣,就得到一個完整的ramdisk目錄,與out/target/product/generic/root對比後,我們發現它們是一樣的內容。
通過執行以下的操作,我們可由目錄樹再生成ramdisk鏡像
# cd ramdisk
# find . | cpio -o -H newc | gzip > ../ramdisk-new.img

system.img & userdata.img
這兩個鏡像都屬於yaffs2文件格式,生成方式是一樣的。我們就以system.img爲例來說明。
System.img >> system目錄樹
所需工具unyaffs, 下載地址 http://code.google.com/p/unyaffs/downloads/list
# mkdir system
# cd system
# unyaffs ../system.img
system目錄樹 >> system.img
所需工具 mkyaffs2image,Android源碼編譯後會生成該工具,在 out/host/linux-x86/bin 目錄下。
命令格式:
# mkyaffs2image system/ system_new.img

瞭解以上方法的意義在於,我們可以對鏡像文件鏡像修改,定製,以符合自己的需求。

Android ROM的製作方法
網上有很多製作Android ROM的教程,這裏羅列一些鏈接:
北理工的陳罡寫的兩篇文章,是我目前發現的最好的教程,寫的非常詳細
http://blog.chinaunix.net/u/26691/showart_2193396.html
http://blog.chinaunix.net/u/26691/showart_2194274.html
這兩篇文章參考了國外論壇的幾個經典教程:
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
國內還有一篇文章寫的也不錯,這篇文章更側重於製作類似Patch的ROM包
http://www.cnmsdn.com/html/201002/1267213800ID1030.html

這裏基於自己的理解和測試,總結了一些方法步驟。
1.從可用的ROM起步
Android 的ROM包通常稱爲update.zip包,你可以到www.hiapk.com上下載現成的.zip包。要學習ROM包的製作,我們可以從這樣一個zip包開始。解開zip包後,通常有這樣一些內容:
boot.img    文件    這是編譯內核源代碼生成的內核映像,然後與android源碼編譯出來的ramdisk.img一起通過mkbootimg工具創建出來的,圖省事的朋友也可以從網上其他的刷機包裏面拷貝一個能用的出來即可,基本上都差不多。
META-INF    目錄    這個目錄是手工創建的,主要用來存放一個升級腳本update-script(這個腳本的內容與system目錄中包含的文件有很大關聯)以及簽名。
system    目錄    這個目錄就是編譯android的平臺源代碼生成的
要創建自己的ROM,我們通常會涉及到以下的一些工作:
1.    編譯內核生成內核映像。但一般情況下,我們沒有必要自己去編,直接從刷機包裏面取出一個就可以。譬如,你要做一個2.2版本的升級包。可以到網上找一個與自己機型相匹配的刷機包,從裏面取出相應的kernel.img。
2.    ramdisk.img的修改。ramdisk.img 是根文件系統,裏面包含了啓動配置腳本。
3.    update-script的修改。
4.    System的修改。
我們先做個簡單的測試工作,來爲後面更復雜的工作做好鋪墊。測試內容爲:先對zip進行解包,然後分別在ramdisk和system的根目錄下添加一個小文件,接着,生成新的ROM,並驗證ROM是否可用。
詳細的步驟可以參考http://blog.chinaunix.net/u/26691/showart_2194274.html。這裏要指出的是,這篇文章以及網上許多類似網站提到的方法都是針對HTC G1或 Nexus one的。而我在測試的時候,用的是HTC G3 Hero。以上的方法導致的一個後果是,重新打包後再燒錄,機器無法正常啓動,adb shell也無法登陸。後來在國外的一篇博客上看到了對此問題的說明,問題的根源很簡單,從G3開始,打包的時候需要指定 “--base”參數。對於Hero,參數爲”--base 0x19200000”,但對於其它型號的機器,”--base"要設定爲多少,需要參考內核代碼的實現。
解包打包可用兩個腳本完成unpack-bootimg.pl, repack-bootimg.pl。其中打包腳本用到的mkbootimg工具,在out/host/linux-x86/bin目錄下。unpack-bootimg.pl可直接將boot.img生成內核鏡像boot.img-kernel和ramdisk目錄樹boot.img-ramdisk。repack-bootimg.pl可將boot.img-kernel和boot.img-ramdisk重新生成boot.img。
在解包後,我們在ramdisk和system目錄下,各添加一個測試小文件(譬如叫mytest)。做完這些開始組包,重新生成update.zip。到這裏我們的工作並沒有完全結束,還有最後的一步——簽名。簽名需要用到簽名工具testsign.jar,這是一個基於java 1.6版本的工具。在編譯Android源碼的時候,我們強調要用java 1.5。在這裏,我們必須切換到1.6版本。切換辦法見這裏。

2.利用自己編譯的鏡像生成ROM
1)重新生成boot.img
將前面解包得到的boot.img-ramdisk 和 編譯源碼後out/target/product/generic/下的root目錄樹放在一個目錄下,然後用repack-bootimg.pl重新生成boot.img
2) 創建一個目錄 myupdate,將上面生成的boot.img放到這個目錄下
3)將編譯Android後,out/target/product/generic/生成的system目錄樹拷貝到myupdate目錄
4)在myupdate目錄下創建update-script腳本目錄
# mkdir -p META-INF/com/google/android
5)刪除system/bin目錄下的“符號鏈接”,創建update-script腳本
update-script腳本的語法可以參考 這裏 。研究原有的update-script腳本,我們可以大致看出update-script負責文件刪除拷貝,權限設置,符號鏈接創建等工作。我們可以在原有update-script的基礎上進行修改以得到我們自己的update-script。這裏,我們要注意的是,要保證update-script的link創建成功,必須把/system/bin下的link刪除。我們可以用一個腳本來做這個工作 delsymlink。我修改後與自己編譯的Android2.2 system目錄樹相匹配的腳本。
6)重新打包並簽名
7)自制ROM下載時報錯
在試驗過程中,我經常遇到如下的報錯
Can't open/sdcard/download/update.hiapk
問題原因:當 update-script 中有命令操作錯誤,腳本就會停止,並報這個錯誤,解決的辦法就是修正腳本。你可以從這個錯誤前面的提示,知道腳本哪一行出錯了。

3. 創建一個Patch功能的ROM
很多時候,你並不需要創建一個完整的ROM包。你需要的只是,添加刪除或修改一些功能(譬如你僅想添加一個應用,或者你想添加busybox工具)。我們可以參考這裏,來實現這個目的。
我用一個簡單的例子來說明這個過程。該例子是在system目錄下添加一個mytest文件,同時創建一個指向這個文件的符合鏈接mylink。以下是過程:
1)    創建patch_update目錄,並在該目錄下執行
# mkdir system
# mkdir –p META-INF/com/google/android
2)    在system目錄下生成mytest文件
3)    在 META-INF/com/google/android 創建如下的update-script
show_progress 0.1 0

copy_dir PACKAGE:system SYSTEM:
symlink mytest SYSTEM:mylink

set_perm 0 0 0755 SYSTEM:mytest


4) 打包簽名

如果前面的3步曲,你已經很好的掌握了,應付你的日常工作應該沒有太大的問題。但要成爲真正的ROM高手,你還有很多東西要修煉。你要了解整個啓動過程,內核編譯,Android源碼的編譯及配置,文件系統及啓動配置。。。

燒錄 Android 機器
HTC的官網上有一篇文章 這裏 詳細介紹了鏡像包及燒機方法。通常用兩種燒錄方式:recovery模式,fastboot模式。通過一些組合鍵,可以進入燒錄模式。以HTC G3 Hero爲例,“Home + Power”同時按,可以進入Recovery模式,“Back + Power”可以進入fastboot模式。
Recovery模式比較常用,它相當菜單界面的下載模式。直接把前面所述的update.zip文件放到SD卡上,然後通過在機器上操作控制菜單,就可完成燒錄。Fastboot是基於命令行的較低級的下載模式,它可直接燒錄.img文件。Fastboot工具也在out/host/linux-x86/bin目錄下。
在我測試過程中,發現fastboot模式無法燒錄,當我試圖燒錄system.img的時候,出現下面的出錯信息:
# fastboot flash system system.img
# writing 'system'... INFOsignature checking...
FAILED (remote: signature verify fail)
在網上查了之後,發現這和簽名有關係,SPL要重新刷一下才可,默認是SPL-on,即檢測簽名,改成SPL-off,就不會出現這個問題,目前沒有什麼好辦法來處理這個問題。好在recovery模式已經能很好地滿足需求了,可以先放棄fastboot。
如果你通過recovery模式燒錄後,發現系統無法正常啓動,沒有關係,recovery還是可以進去的。在recovery模式下,你可以通過adb shell登陸機器。可能你進去後,發現SD卡並沒有掛接上來(執行mount就可以查看掛載情況)。但recovry模式要求update.zip必須放在SD卡根目錄下,怎麼辦?很簡單,執行“mount –a”就可把SD卡區域掛接上來。如果這招也不行,還有一招,就是把userdata分區手動掛接到sdcard目錄,這樣就騙過了recovery。
# mount /dev/mtdblock5 /sdcard
然後,你再用adb push把新的update.zip拷貝到sdcard目錄,重新進行燒錄。一般來說,在執行“Flash zip from sdcard”之前,都要先進行Wipe操作,以清除舊的用戶數據。

如何更新recovery?

可以參考http://bbs.gfan.com/viewthread.php?tid=66973,按照這個攻略,把自己的G3 Hero更新成了recovery-RA-hero-v1.6.2-blue.img。不過,一般無特別的需求,最好不要更新recovery。畢竟有一定風險,一不小心就成了板磚。

其它參考信息:
知名的Android論壇:
國內:www.hiapk.com
國外:http://android-dls.com 很多國內論壇的文章都是參考或翻譯http://android-dls.com 的
國內一個很好的博客:http://xy0811.spaces.live.com/ ,有很多對Android的研究專題
國外一個很好的博客:http://blog.coralic.nl/category/android/ ,這個博客幫我解決了在燒錄 HTC G3 HERO的時候,自己打的ROM包燒錄後無法啓動的問題

Android 文件系統
http://www.ibm.com/developerworks/cn/linux/l-k26initrd/
http://developer.51cto.com/art/201001/180468.htm
http://git.source.android.com/?p=kernel/common.git;a=blob;f=Documentation/filesystems/ramfs-rootfs-initramfs.txt
http://dev.firnow.com/course/6_system/linux/Linuxjs/20090901/173312.html
Android init腳本的語法
http://blog.chinaunix.net/u3/103613/showart.php?id=2237012
http://www.kandroid.org/android_pdk/bring_up.html
發佈了21 篇原創文章 · 獲贊 2 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章