android 的boot.img

android 的boot.img 包括 boot header,kernel, ramdisk

首先來看看Makefile是如何產生我們的boot.img的:

boot鏡像不是普通意義上的文件系統,而是一種特殊的Android定製格式,由文件頭信息boot header,壓縮的內核,文件系統數據ramdisk以及second stage loader(可選)組成,它們之間非頁面對齊部分用0填充
,可以從mkbootimg.h文件中看到。

文件頭信息的具體結構可以在system/core/mkbootimg/bootimg.h中看到:
struct boot_img_hdr  
{  
    unsigned char magic[BOOT_MAGIC_SIZE];  
    unsigned  kernel_size;  
    unsigned  kernel_addr;  
    unsigned  ramdisk_size;  
    unsigned  ramdisk_addr;  
    unsigned  second_size;  
    unsigned  second_addr;  
    unsigned  tags_addr;  
    unsigned  page_size;  
    unsigned  unused[2];  
    unsigned  char  name[BOOT_NAME_SIZE]  
    unsigned  char cmdline[BOOT_ARGS_SIZE]  
    unsigned  id[8]; //存放時間戳,校驗和,SHA加密等內容  
}

boot,img文件跳過4k的文件頭之後,包括兩個 gz包,一個是boot.img-kernel.gz:Linux內核,一個是boot.img-ramdisk.cpio.gz

大概的組成結構如下

 

*
** +-----------------+ 
** | boot header     | 1 page
** +-----------------+
** | kernel              | n pages  
** +-----------------+
** | ramdisk           | m pages  
** +-----------------+
** | second stage    | o pages
** +-----------------+

boot header爲包括命令行參數等等,地址爲000-----0xFFF

ramdisk爲 1F8B0800000000開頭

kernel爲 0000A0E1 重複8遍開頭

 


關於boot header這個數據結構我們需要重點注意,在這裏我們關注其中幾個比較重要的值,這些值定義在boot/boardconfig.h裏面,不同的芯片對應vendor下不同的boardconfig,在這裏我們的值分別是(分別是kernel/ramdis/tags載入ram的物理地址):

#define PHYSICAL_DRAM_BASE   0x00200000 
#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)

上面這些值分別和我們開篇時候提到的那幾個名詞相對應,比如kernel_addr就是ZTEXTADDR,RAMDISK_ADDR就是INITRD_PHYS,而TAGS_ADDR就是PARAMS_PHYS。bootloader會從boot.img的分區中將kernel和ramdisk分別讀入RAM上面定義的地址中,然後就會跳到ZTEXTADDR開始執行。

ramdisk映像是一個最基礎的小型文件系統,它包括了初始化系統所需要的全部核心文件,例如:初始化init進程以及init.rc(可以用於設置很多系統的參數)等文件。以下是一個典型的ramdisk中包含的文件列表:
./init.trout.rc
./default.prop
./proc
./dev
./init.rc
./init
./sys
./init.goldfish.rc
./sbin
./sbin/adbd
./system
./data

如果要分離可以用winhex將boot。img打開

找到0000A0E1 到1F8B0800000000的前面的數據塊保持爲kernel

找到1F8B0800000000到文件尾部的數據塊保持爲ramdisk.img 

 out/host/linux-x86/bin/mkbootimg  --kernel out/target/product/msm7630_surf/kernel --ramdisk out/target/product/msm7630_surf/ramdisk.img --cmdline "console=ttyMSM1,115200n8 androidboot.hardware=qcom" --base 0x00200000 --pagesize 4096 --output out/target/product/msm7630_surf/boot.img

 

        根據上面的命令我們可以首先看看mkbootimg 這個工具的源文件:system/core/mkbootimg.c。看完之後我們就能很清晰地看到boot.img的內部構造,它是由boot header /kernel  /ramdisk /second stage構成的,其中前3項是必須的,最後一項是可選的。mkbootimg分析參數後,依次寫入header, kernel ,ramdisk .


 

header + padding + kernel + padding + ramdisk + padding + ...
4 * 2, magic,固定爲"ANDROID!"
4 * 1, kernel長度,小端unsigned
4 * 1, kernel地址,應爲base + 0x00008000 (base爲0x200000)
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, 內核命令參數,爲mem=211M console=ttyMSM2,115200n8 androidboot.hardware=qcom console=ttyUSBCONSOLE0 androidboot.console=ttyUSBCONSOLE0
4 * 8, id, 爲sha之類,實際寫0x00就可
padding, 以上header爲608字節,把這部分補齊到page_size * 2大小 
kernel_size, kernel內容
padding,把kernel_size補齊到page_size * 2
ramdisk_size, ramdisk內容
padding, 把ramdisk補齊到page_size * 2
second_size, second內容,一般爲0
padding, 補齊second_sise爲page_size,一般爲0

 

配合 boot.img 來看會比較好理解.

由此可知 boot_img_hdr 中各成員值爲:

 

 

 

TAGS_ADDR 如上 target/<your-platform>/rules.mk 所定義的 : 0x40200100, 所以 boot_linux(), 就是傳入TAGS_ADDR,

 

然後將資料寫入 tag, tag 的結構如下所示.

 

然後進入到 kernel 的入口函數: entry(0, machtype, tags)
--------------------- 
作者:zhenwenxian 
來源:CSDN 
原文:https://blog.csdn.net/zhenwenxian/article/details/6219431/ 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章