ROM定製修改鏡像

在ROM定製中,通常需要修改 system.imguserdata.imgboot.imgrecovery.img這四個鏡像文件。

一、修改系統鏡像(system.img)

一、 判斷文件類型

system.img 文件格式有yaffs2 格式和 ext 格式兩種。解壓前應當用在linux下用file命令對文件格式進行判斷。

$ file system.img

yaffs 格式會輸出:system.img: VMS Alpha executable
ext 格式會輸出:system.img:data

二、解壓

對於system.img文件,通常使用 unyaffs命令進行解壓。unyaffs 源碼文件地址 : ,在烏班圖下輸入下面的命令進行編譯:

gcc -o unyaffs unyaffs.c

解壓 system.img 文件的命令如下:

$ unyaffs system.img

對於 ext 文件格式類型文件,使用<Android源碼根目錄>/out/host/linux-x86/bin目錄中的simg2img 二進制文件將system.img轉換爲普通的linux鏡像文件(ext4)文件格式

$ simg2img system.img  system.img.raw

file system.img.raw 命令查看 system.img.raw 文件的格式,會發現輸出:

$ file system.img.raw
system.img.raw: Linux rev 1.0 ext4 filesystem data, UUID=57f8f4bc-abf4-655f-bf67-946fc0f9f25b (extents) (large files)

system.img.raw 文件類型爲 ext4 類型
然後在/mnt 目錄中創建一個system 子目錄,並執行下面的命令掛載系統鏡像`

$ sudo mount -t ext4 -o loop system.img.raw  /mnt/system

三、重打包

對於ext4文件系統,修改完系統鏡像後,需要使用make_ext4fs 命令將/mnt/system目錄重新生成system.img文件。該文件的目錄爲:

<Android 源代碼根目錄> /out/host/linux-x86/bin

在linux終端執行執行如下的命令生成system.img 文件

$ make_ext4fs  -s -l 512M -a system newsystem.img /home/aosp444/unyaffs/system

-s 指 Sparse 文件格式的鏡像文件。掛載Sparse格式的鏡像文件,需要首先使用simg2img 命令進行掛載。

-l 是指鏡像文件刷入設備後所佔非分區大小。一般略大於 img 鏡像文件
-a 指的是掛載點 這裏指的是 system

對於yaff2 文件系統 ,修改完系統鏡像後,需要使用out/host/linux-x86/bin/mkyaffs2image 文件進行重打包,打包命令

$ mkyaffs2image -f  system   newsystem.img

二、用戶數據鏡像(userdata.img)

安卓設備的內部存儲器被劃分爲不同的分區。其中userdata.img屬於userdata 分區,該分區指是內存,內部存儲器的剩餘部分被視爲外部存儲、屬於sdcard 分區。
使用simg2img 文件對鏡像進行轉換成’ext4’ 格式的文件

$ simg2img userdata.img userdata.img.raw

在當前目錄下創建userdata文件夾,將userdata.img.raw 文件掛載到該目錄下。

$ sudo mount -t ext4 -o loop userdata.img.raw  ./userdata

進入userdata 目錄後看到該目錄下只有lost+found目錄,
查看該掛載點的大小

aosp444@aosp444-virtual-machine:~/unyaffs/userdata$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda6        14G  3.4G  9.6G  27% /
udev            2.0G  4.0K  2.0G   1% /dev
tmpfs           394M  776K  394M   1% /run
none            5.0M     0  5.0M   0% /run/lock
none            2.0G  152K  2.0G   1% /run/shm
/dev/sda1       180M   32M  136M  19% /boot
/dev/sda7       137G  125G  4.9G  97% /home
/dev/sr0        758M  758M     0 100% /media/Ubuntu 12.04.5 LTS amd64
/dev/loop0      992M  268M  709M  28% /mnt/system
/dev/loop1      992M  268M  709M  28% /home/aosp444/unyaffs/system
/dev/loop2       13G   33M   13G   1% /home/aosp444/unyaffs/userdata
aosp444@aosp444-virtual-machine:~/unyaffs/userdata$ 

掛載點的大小爲13左右

userdata目錄下新建一個app目錄,將apk文件放入其中
重新打包該文件

$ make_ext4fs -s -l 13G -a data userdata.img.new   ./userdata

然後使用下面的命令將userdata.img.new 文件刷入手機

$ adb reboot bootloader
$ fastboot flash userdata userdata.img.new

發現之前複製到app 目錄中的apk文件安裝到了手機中。

三、內存磁盤鏡像(ramdisk.img)

ramdisk.img 其實是對root目錄的打包和壓縮,ramdisk根文件系統中包含一些對於啓動android的很重要的文件,比如內核啓動完後加載的第一個進程init、一些重要的配置文件等,總之它控制着整個android的啓動。根據 init.rc,init.goldfish.rc來初始化並裝載系統庫、程序等直到開機完成。init.rc腳本包括了文件系統初始化、裝載的許多過程。ramdisk.img最後和kernel一起打包生成boot.img鏡像。
ramdisk.img是一個普通的zip文件,可以用gunzip命令對其進行解壓

$ gunzip -c  ramdisk.img  >   ramdisk.cpio

解壓後並不是原始文件和目錄,而是由cpio命令備份還原的文件,還需要繼續還原

$ cpio -i < ../ramdisk.cpio
drwxrwxr-x 9 aosp444 aosp444   4096 Jul 27 22:00 ./
drwxrwxr-x 3 aosp444 aosp444   4096 Jul 27 21:58 ../
-rwxr-x--- 1 aosp444 aosp444 272364 Jul 27 22:00 charger*
drwxrwx--x 2 aosp444 aosp444   4096 Jul 27 22:00 data/
-rw-r--r-- 1 aosp444 aosp444    286 Jul 27 22:00 default.prop
drwxr-xr-x 2 aosp444 aosp444   4096 Jul 27 22:00 dev/
-rw-r--r-- 1 aosp444 aosp444   8983 Jul 27 22:00 file_contexts
-rw-r----- 1 aosp444 aosp444   2653 Jul 27 22:00 fstab.hammerhead
-rwxr-x--- 1 aosp444 aosp444 179484 Jul 27 22:00 init*
-rwxr-x--- 1 aosp444 aosp444    919 Jul 27 22:00 init.environ.rc*
-rwxr-x--- 1 aosp444 aosp444  16671 Jul 27 22:00 init.hammerhead.rc*
-rwxr-x--- 1 aosp444 aosp444   5710 Jul 27 22:00 init.hammerhead.usb.rc*
-rwxr-x--- 1 aosp444 aosp444  20177 Jul 27 22:00 init.rc*
-rwxr-x--- 1 aosp444 aosp444   1795 Jul 27 22:00 init.trace.rc*
-rwxr-x--- 1 aosp444 aosp444   3915 Jul 27 22:00 init.usb.rc*
drwxr-xr-x 2 aosp444 aosp444   4096 Jul 27 22:00 proc/
-rw-r--r-- 1 aosp444 aosp444   2161 Jul 27 22:00 property_contexts
drwxr-xr-x 3 aosp444 aosp444   4096 Jul 27 22:00 res/
drwxr-x--- 2 aosp444 aosp444   4096 Jul 27 22:00 sbin/
-rw-r--r-- 1 aosp444 aosp444    656 Jul 27 22:00 seapp_contexts
-rw-r--r-- 1 aosp444 aosp444  74890 Jul 27 22:00 sepolicy
drwxr-xr-x 2 aosp444 aosp444   4096 Jul 27 22:00 sys/
drwxr-xr-x 2 aosp444 aosp444   4096 Jul 27 22:00 system/
-rw-r--r-- 1 aosp444 aosp444   2204 Jul 27 22:00 ueventd.hammerhead.rc
-rw-r--r-- 1 aosp444 aosp444   4024 Jul 27 22:00 ueventd.rc

上面的命令可以合成如下的一行:

$ gunzip -c ../ramdisk.img  | cpio -i

busybox 二進制文件放入ramdisk中的sbin目錄,
在解壓出的目錄中,執行下面的目錄進行壓縮

$  mkbootfs . | minigzip > ../ramdisk.img.new

四、Linux 內核鏡像(boot.img)

Android linux內核鏡像包含了內核二進制文件(zImage)和內存磁盤鏡像(ramdisk.img),一般對應的鏡像文件是boot.img.由於ramdisk.img中包含的init命令是與Linux內核第一個交互的程序,所以boot.img 鏡像包括zImageramdisk.img 。當linux內核調用init後。系統就會根據init.rc 及相關文件中的代碼對整個Android系統進行初始化。其中主要的初始化工作就是建立如/systemdata等系統目錄,然後使用mount 命令將相應的鏡像掛載到這些目錄上。
unpackbootimg命令將boot.img解壓

drwxrwxr-x 2 aosp444 aosp444    4096 Jul 28 12:00 ./
drwxrwxr-x 3 aosp444 aosp444    4096 Jul 28 11:02 ../
-rw-rw-r-- 1 aosp444 aosp444       9 Jul 28 12:00 boot.img-base
-rw-rw-r-- 1 aosp444 aosp444       1 Jul 28 12:00 boot.img-board
-rw-rw-r-- 1 aosp444 aosp444     107 Jul 28 12:00 boot.img-cmdline
-rw-rw-r-- 1 aosp444 aosp444       9 Jul 28 12:00 boot.img-kerneloff
-rw-rw-r-- 1 aosp444 aosp444       5 Jul 28 12:00 boot.img-pagesize
-rw-rw-r-- 1 aosp444 aosp444  498994 Jul 28 12:00 boot.img-ramdisk.gz
-rw-rw-r-- 1 aosp444 aosp444       9 Jul 28 12:00 boot.img-ramdiskoff
-rw-rw-r-- 1 aosp444 aosp444       9 Jul 28 12:00 boot.img-tagsoff
-rw-rw-r-- 1 aosp444 aosp444 8405280 Jul 28 12:00 boot.img-zImage

除了zImage和random.gz兩個主要的文件外,其它幾個都是參數的配置文件 其中cmdlinebasepagesize 這三個參數需要自己制定。

然後使用mkbootimg命令進行重打包, 將配置參數替換成解壓出的值進行重打包

$ mkbootimg  --base 0 --pagesize 2048 --kernel_offset 0x00008000 --ramdisk_offset 0x02900000 --second_offset 0x00f00000 --tags_offset 0x02700000 --cmdline 'console=ttyHSL0,115200,n8 androidboot.hardware=hammerhead user_debug=31 maxcpus=2 msm_watchdog_v2.enable=1'  --kernel boot.img-zImage --ramdisk boot.img-ramdisk.gz   -o boot.img.new

bootimg相關的工具
mkbootimg_tools:https://github.com/xiaolu/mkbootimg_tools(不用設置參數)
bootimg-tools :https://github.com/pbatard/bootimg-tools

五、製作已經有ROOT權限的ROM

製作已有root權限的ROM,需要將su二進制文件放到解壓的system.img 文中 /system/xbin目錄中,再重打包成system.img。 但這樣從PC 進入Android系統的Shell 時,默認並不是ROOT權限,還要執行su 命令纔會切換到ROOT權限,而且也不執行adb remount 對系統目錄(/system/app)寫入的權限。需要修改Linux 內核鏡像文件(boot.img)中ramdisk.img文件中的default.prop 文件。

ro.secure=0
ro.allow.mock.location=1
ro.debuggable=1
persist.sys.usb.config=mtp,adb
ro.adb.secure=1
persist.service.adb.enable=1

六、Recovery鏡像(recovery.img)

Recovery鏡像只用於刷機,它與boot.img一樣都包含linux(zImage)文件和ramdisk.img 文件,只不過ramdisk.img文件不一樣。.它們內核調用的init命令和init.rc文件內容不一樣。
它的解壓也使用unpackbootimg命令
ramdisk.gz 解壓也使用gunzipcpio
打包使用mkbootimg
具體操作可以參考boot.img

七、緩存鏡像(cache.img)

cache.img鏡像存儲系統或用戶產生的臨時數據,它實際上是一個空的ext4格式的文件系統鏡像

$ mkdir -p /mnt/rom/cache
$ make_ext4fs -s -l 256M -a cache cache.img /mnt/rom/cahe

八、製作Bootloader ROM

Bootloader ROM 包中主要包含system.img userdata.imgboot.imgrecovery.img 四個鏡像文件,將這是個文件壓縮成一個zip文件(文件名可以隨意取)。爲了對壓縮包能刷的android設備進行限制, 可在壓縮包中包含一個android-info.txt 文件。下面是nexus5 android-info.txt文件中 的內容,科長/proc/cpuinfo中查看board的信息。

require board=hammerhead
require version-bootloader=HHZ11k
require version-baseband=M8974A-2.0.50.1.16

刷機命令

fastboot -w update update.zip

九、製作Recovery ROM

Bootloader ROM 只能對整個分區進行更新,如果需要更新分區中的一部分,則需要recovery ROM。
recovery ROM 刷機時通常不會刷recovery分區,並且清楚用戶和Cache數據。主要對boot分區和system 分區進行更新。
Recovery ROM 壓縮包的格式爲zip,通常由一個三部分組成:

  • META-INF目錄:包含存儲簽名文件、更新腳本等內容
  • system目錄:要複製到System分區的文件。目錄結構應當與system分區一樣。
  • boot.img文件:內核鏡像文件。

META-INF目錄比較特別:除了簽名外,還包括如下兩個非常重要的文件:

META-INF/com/google/android/updater-script
META-INF/com/google/android/update-binary

update-binary是一個腳本解釋器,解釋腳本文件updater-script ,updater-script腳本語言爲Edify語言,是Android系統內嵌的微型語言之一。 製作Recovery ROM 過程中需要編寫updater-script
下面製作一個Recovery包,將 subusybox複製到系統system分區中
一、建立system目錄
建立一個system/xbin目錄,並將su和busy文件複製進去
二、建立META-INF目錄
建立META-INF目錄,並在目錄中建立META-INF/com/google/android 目錄,並將update-binary 複製進去,新建一個updater-script 文件,update-binary 可以找到相應設備的recovery更新包中獲取
三、編寫更新腳本

ui_print("*********************");
ui_print("My First Recovery Update");
ui_print("*********************");

ui_print("----Mounting /system ----");

run_program("/sbin/busybox", "mount","-o", "rw", "/system");

ui_print("----Delete /system/xbin/su ----");
delete("/system/xbin/su");

ui_print("----Delete /system/xbin/busybox ----");
delete("/system/xbin/busybox");

ui_print("----Extracting files");
package_extract_dir("system", "/system");

ui_print("----- Setting permissions");
set_perm(0, 0, 0777, "/system/xbin/su");
set_perm(0, 0, 0777, "/system/xbin/busybox");

unmount("/system");
ui_print("finished");

四、生成壓縮包
用zip壓縮文件將META-INFsystem 目錄壓縮成zip文件。
五、簽名
簽名是非必須的,Clockworkmod Recovery允許刷未簽名的ROM.

java -jar signapk.jar -w testkey.x509.pem  testkey.pk8  update.zip signed-update.zip

注意事項:
- recovery刷機包中目錄不應該包含雙字節
- package_extract_dir 不會創建目錄,目錄應該跟system分區標準目錄一致
下面
製作
參考文章:
1. http://blog.163.com/zz_forward/blog/static/212898222201592810729837/
2. 《Android 深度探索 卷2》

發佈了45 篇原創文章 · 獲贊 31 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章