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)
總結
以上是生活随笔為你收集整理的android boot.img 结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: boot.img的分析
- 下一篇: Android构建boot.img(一)