天天看點

Android boot.img 結構分析

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

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的前面的資料塊保持為ramdisk.img

找到1F8B0800000000到檔案尾部的資料塊保持為kernel

 out/host/linux-x86/bin/mkbootimg  --kernel

out/target/product/msm7630_surf/kernel --ramdisk

out/target/product/msm7630_surf/ramdisk.img --cmdline

        根據上面的指令我們可以首先看看mkbootimg 這個工具的源檔案:system/core/mkbootimg.c。看完之

後我們就能很清晰地看到boot.img的内部構造,它是由boot header /kernel  /ramdisk /second

stage構成的,其中前3項是必須的,最後一項是可選的。

header + padding + kernel + padding + ramdisk + padding + ...

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 * 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 來看會比較好了解.

Android boot.img 結構分析

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

Android boot.img 結構分析
Android boot.img 結構分析

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

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

Android boot.img 結構分析

然後進入到 kernel 的入口函數: entry(0, machtype, tags)

繼續閱讀