zoukankan      html  css  js  c++  java
  • 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)

  • 相关阅读:
    sql server 交集,差集的用法 (集合运算)
    sql server join ,inner join ,left join ,right join 的使用
    SQL Server 中截取字符串常用的函数
    JS&Jquery中的循环/遍历
    Jquery一些实用函数
    jQuery扩展函数设置所有对象只读
    JQuery处理DOM元素-属性操作
    判断iframe页面是否加载完成
    给表增加主键,先判断表是否存在主键
    Jquery对select下拉框的操作
  • 原文地址:https://www.cnblogs.com/liang123/p/6325477.html
Copyright © 2011-2022 走看看