首先來看看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 來看會比較好了解.
由此可知 boot_img_hdr 中各成員值為:
TAGS_ADDR 如上 target//rules.mk 所定義的 : 0x40200100, 是以 boot_linux(), 就是傳入TAGS_ADDR,
然後将資料寫入 tag, tag 的結構如下所示.
然後進入到 kernel 的入口函數: entry(0, machtype, tags)