1. 程式人生 > >安卓手機檔案系統 roots recovery bootimg

安卓手機檔案系統 roots recovery bootimg

這篇文章是轉自機FAN論壇!個人認為很有意義特轉
bootimg.rar (2.28 MB, 下載次數: 5783) 2011-10-25 02:08 上傳 下載次數: 5783
下載積分: 金幣 -1 元 為U8800簡單的寫了下注視!!
背景知識
一、Android手機的檔案系統
Android手機的檔案系統有許多儲存器組成,以下是在adb shell下面的輸出:
#
  • cat/proc/mtd

複製程式碼
  下載 (40.17 KB)
2011-7-5 12:39


注意,不同的手機在上述儲存裝置的順序可能會各不相同!一定要檢查您的手機,確定在以下的操作中選擇正確的裝置號(mtdX,這個X的序號一定要檢查清楚)。
根目錄以及分割槽的定義(在Android原始碼的root.c檔案中定義)

根目錄: Linux 塊裝置 /掛載點/ 檔案系統 大小 描述
BOOT: /dev/mtdblock[?] / (RAM) Raw 核心、記憶體盤和引導配置。
DATA: /dev/mtdblock5 /data/ yaffs2 91904kb 使用者、系統配置,軟體配置以及軟體(沒有a2sd的話)
CACHE: /dev/mtdblock4 /cache/ yaffs2 30720kb OTA快取,recovery/更新配置及臨時資料夾
MISC: /dev/mtdblock[?] N/A Raw,[?]kb (等待新增)
PACKAGE: (相對於刷機包) N/A 刷機包的偽檔案系統。
RECOVERY: /dev/mtdblock[?]
/ (RAM) Raw,[?]kb recovery和更新環境的核心和記憶體盤。類似於BOOT:。
SDCARD: /dev/mmcblk0(p1) /sdcard/ fat32 32MB-32GB TF卡。通常刷機包就放在這裡。
SYSTEM: /dev/mtdblock3 /system/ yaffs2 92160kb 系統分割槽,靜態且是隻讀的。
TMP: /tmp/ (RAM) 標準的Linux臨時資料夾 在關機/重啟時清空。


您首先應該要做的事情是使用您的recovery對您的ROM進行備份,以免操作失誤照成資料的丟失!
二、boot和recovery映像的檔案結構
boot和recovery映像並不是一個完整的檔案系統,它們是一種
android
自定義的檔案格式,該格式包括了2K的檔案頭,後面緊跟著是用gzip壓縮過的核心,再後面是一個ramdisk記憶體盤,然後緊跟著第二階段的載入器程式(這個載入器程式是可選的,在某些映像中或許沒有這部分)。

/*
** +-----------------+
** | 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
*/

boot的ramdisk映像是一個最基礎的小型檔案系統,它包括了初始化系統所需要的全部核心檔案,例如:初始化init程序以及init.rc(可以用於設定很多系統的引數)等檔案。
以下是一個典型的ramdisk中包含的檔案目錄列表:
│  default.prop
│  init
│  init.goldfish.rc
│  init.rc
│  init.swift.rc
│  initlogo.rle               //開機第二屏圖片
│  ueventd.goldfish.rc
│  ueventd.rc
│  ueventd.swift.rc

├─data
├─dev
├─proc
├─sbin
│      adbd

├─sys
└─system

recovery的ramdisk映像包含了一些額外的檔案,例如一個叫做recovery的二進位制程式,以及一些對該程式支援性的資源圖片檔案(當您按下home+power組合鍵的時候就會執行這個recovery程式)。典型的檔案列表如下:
│  default.prop
│  init
│  init.rc
│  initlogo.rle              //開機第二屏圖片
│  ueventd.goldfish.rc
│  ueventd.rc
│  ueventd.swift.rc

├─data
├─dev
├─etc
│      recovery.fstab

├─proc
├─res
│  │  keys
│  │
│  └─images
│          icon_clockwork.png
│          icon_error.png
│          icon_installing.png
│          indeterminate1.png
│          indeterminate2.png
│          indeterminate3.png
│          indeterminate4.png
│          indeterminate5.png
│          indeterminate6.png
│          progress_empty.png
│          progress_fill.png

├─sbin
│      adbd
│      e2fsck
│      fix_permissions
│      killrecovery.sh
│      mke2fs
│      nandroid-md5.sh
│      parted
│      recovery
│      sdparted
│      tune2fs

├─sys
├─system
│  └─bin
└─tmp

使用方法
工具主要語言為python,分兩處版本,原始檔   bootimg.py.gz (7.11 KB) 及windows下可執行檔案exe   bootimg.exe.gz (2.27 MB) ,內容及用法完全一致。

執行方法:
      在cmd下cd到檔案所在目錄,輸入"bootimg.exe  功能 [引數]"(用原始檔的話就是bootimg.py)

目前支援以下功能:
        --repack-ramdisk    生成 ramdisk
        --unpack-ramdisk   解開 ramdisk
        --repack-bootimg   生成 bootimg (包括boot.img及recovery.img)
        --unpack-bootimg  解開 bootimg (包括boot.img及recovery.img)
        --unpack-updata    解開 updata.app
        --unpack-yafffs      解開 yafffs    (包括data.img及system.img)
下面一一說明功能中的引數。
--unpack-updata [檔案]
[檔案]為空時,預設使用UPDATA.APP
解開後,會有四個檔案,boot.img, recovery.img, system.img, userdata.img
這些都是刷機時可能需要的。

--unpack-bootimg [檔案]
[檔案]為空時,預設使用boot.img
解開後,會有兩個檔案,kernel和ramdisk.gz
同時,注意輸出,比如base, cmdline, name等等

--repack-bootimg [base] [cmdline]
[base]為空時,使用0x200000
[cmdline]為空時,使用mem=211 console=null androidboot.hardware=qcom
生成bootimg時,會使用kernel和ramdisk.gz(如果存在ramdisk.cpio.gz,優先使用),生成boot.img
更新:
--repack-bootimg [base] [cmdline] [page_size] [padding_header] [padding_kernel] [padding_ramdisk]
具體的引數請在注意unpack時的原始引數。

--unpack-ramdisk [檔案] [目錄]
[檔案]為空時,使用ramdisk.gz
[目錄]為空時,使用initrd, (請保證這個目錄不存在)
輸出:cpiolist.txt, initrd目錄下的檔案

--repack-ramdisk [cpiolist]
[cpiolist]為空時,讀取cpiolist.txt
根據cpiolist.txt生成ramdisk.cpio.gz
cpiolist.txt格式
1). 檔案
file 目標系統路徑 當前系統路徑 目標系統許可權
2). 目錄
dir 目錄系統路徑 目錄系統許可權
3). 軟連結
slink 目錄系統路徑 連結路徑 目標系統許可權

--unpack-yafffs [檔案] [目錄]
[檔案]為空時,使用userdata.img (呃,這個比system.img小)
[目錄]為空時,使用檔案除.img外的其它內容,比如userdata.img時使用userdata

ps:這些引數就算看不懂也沒關係,可以不用加引數,直接用預設的就行,如解包updata.app的話就輸入bootimg --unpack-updata就好。



boot.img基址 base的計算方法(轉)
       如果您看這個帖子,沒有耐心的話,我只能對你說,出現任何問題都是你自己的錯,有點耐心繼續看吧,雖然在文章最後有點邪惡,大家原諒一下!我在工具包中給了一個引數,對於我的GT540肯定沒有什麼問題,但是對於其他手機我不敢保證,所以可能還需您自己計算,或者使用版區前輩得到的數值!如果您做完之後刷回到手機之後會卡在開機介面,螢幕一閃一閃啊黑屏啊之類的症狀層出不窮,普遍有兩種可能。
       一、boot.img是加過密的。各位手機出產的公司,在做ROM的時候,以他們獨自的加密演算法,對整個檔案進行CRC驗算,然後將驗算值新增到boot.img的最末尾。刷機的時候,手機的硬體BIOS就像一名盡職的士兵,對此進行驗算,對不上口令的,那麼對不起,請君離開,不離開我報警了~~呃,報不了警,那反正我不讓你進門~~
       二、boot.img還有一個重要的引數,基址 base,用於告訴手機從哪個地址開始,是準備給記憶體盤的入口,哪個地址是給kernel的入口。如果你對不上號,對不起,不能非法入室的。           
如果是第一種,那隻能望風而逃,罷手了。
     各種查閱,終於發現在ROM的boardconfig.h中存在地址偏移的define。雖然本人手機的ROM中不存在這檔案,但各android系統這個偏移是通用的,一般沒吃錯藥不會去改。
偏移DEFINE如下:
  • #define PHYSICAL_DRAM_BASE   0x00200000<!--IWMS_AD_BEGIN-->   //基址,各不相同,我們的目的是為了獲得這個基址,但由於沒有ROM原始碼,這貌似是不可能的。<!--IWMS_AD_END-->#define KERNEL_ADDR          (PHYSICAL_DRAM_BASE + 0x00008000)#define RAMDISK_ADDR         (PHYSICAL_DRAM_BASE + 0x01000000)#define TAGS_ADDR            (PHYSICAL_DRAM_BASE + 0x00000100)#define NEWTAGS_ADDR         (PHYSICAL_DRAM_BASE + 0x00004000)

複製程式碼
還記得WIKI中有這句話吧?For Nexus One : Add --base 0x20000000 to mkbootimg command-line.  翻譯一下,如果是nexus one手機,那麼需要在mkbootimg命令中加入 --base 0x20000000。。現在是不是很熟了?原來基址寫在這裡,mkbootimg會自動為你加入偏移量,並寫入boot.img。。
好吧,我們現在需要知道,這些值是在哪個位置的。
為什麼需要呢?在第上面,我們已經知道了偏移量了,那麼如果我們再從官方ROM的boot.img中獲取 kernel_addr,再用kernel_addr -偏移量0x00008000,不就可以得出基址了嗎?
     沒轍,需要知道bootimg工具把它們寫到哪了,只能檢視mkbootimg的原始碼(幸好bootimg作為一個典型的LINUX工具,是開源的。若換成WIN,哥就真悲情了)。
     各種查詢,找到bootimg.c檔案,看吧。
     header + padding + kernel + padding + ramdisk + padding + ...(padding是補全,還記得上面所說的,一個盒子裝10張卡片,11張卡片需要幾個盒子的事情吧?第二個盒子由於只放了一張卡片,所以需要9張空白卡片來填充位置,即padding)
4 * 2, magic,固定為"ANDROID!"
4 * 1, kernel長度,小端unsigned型別
4 * 1, kernel地址,應為base + 0x00008000
4 * 1, ramdisk長度,小端unsigned
4 * 1, ramdisk地址,應為base + 0x01000000
4 * 1, second stage長度,小端unsigned,為0
4 * 1, second stage地址,應為base + 0x00f00000
4 * 1, tags地址,應為base + 0x00000100
4 * 1, page大小,小端unsigned, 為2048或者4096
4 * 2, 未使用,固定為0x00
4 * 4, 板子名字,一般為空
4 * 128, 核心命令引數,一大串
4 * 8, id,不知道啥玩意,0x00