boot.img介绍

bootloader阶段会从boot/recovery分区中读取kernel/ramdisk到ram上,然后引导kernel,
加载虚拟文件系统ramdisk,启动init,然后读取rom中的文件系统的内容。

组成

分析其header可以知道boot.img的组织结构如下:

struct boot_img_hdr_v0 {
    uint8_t magic[BOOT_MAGIC_SIZE];                                                                                                                                                     

    uint32_t kernel_size; /* size in bytes */
    uint32_t kernel_addr; /* physical load addr */

    uint32_t ramdisk_size; /* size in bytes */
    uint32_t ramdisk_addr; /* physical load addr */

    uint32_t second_size; /* size in bytes */
    uint32_t second_addr; /* physical load addr */

    uint32_t tags_addr; /* physical addr for kernel tags */
    uint32_t page_size; /* flash page size we assume */
    /*
     * version for the boot image header.
     */
    uint32_t header_version;

    /* operating system version and security patch level; for
     * version "A.B.C" and patch level "Y-M-D":
     * ver = A << 14 | B << 7 | C         (7 bits for each of A, B, C)
     * lvl = ((Y - 2000) & 127) << 4 | M  (7 bits for Y, 4 bits for M)
     * os_version = ver << 11 | lvl */
    uint32_t os_version;

    uint8_t name[BOOT_NAME_SIZE]; /* asciiz product name */

    uint8_t cmdline[BOOT_ARGS_SIZE];

    uint32_t id[8]; /* timestamp / checksum / sha1 / etc */

    /* Supplemental command line data; kept here to maintain
     * binary compatibility with older versions of mkbootimg */
    uint8_t extra_cmdline[BOOT_EXTRA_ARGS_SIZE];
} __attribute__((packed));

看下各个部分大小计算方式:

 the structure of boot image is as
 * follows:
 *
 * +-----------------+
 * | boot header     | 1 page
 * +-----------------+
 * | kernel          | n pages
 * +-----------------+
 * | ramdisk         | m pages
 * +-----------------+
 * | second stage    | o pages
 * +-----------------+
 *
 * n = (kernel_size + page_size - 1) / page_size
 * m = (ramdisk_size + page_size - 1) / page_size
 * o = (second_size + page_size - 1) / page_size
 *
 * 0. all entities are page_size aligned in flash
 * 1. kernel and ramdisk are required (size != 0)
 * 2. second is optional (second_size == 0 -> no second)
 * 3. load each element (kernel, ramdisk, second) at
 *    the specified physical address (kernel_addr, etc)
 * 4. prepare tags at tag_addr.  kernel_args[] is
 *    appended to the kernel commandline in the tags.
 * 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
 * 6. if second_size != 0: jump to second_addr
 *    else: jump to kernel_addr
 */

当然了还有一个叫boot_img_hdr_v1,是在v0后追加了一个recovery dtbo 的section,这个东东是给没有A/B slot的设备上recovery时需要用的。

struct boot_img_hdr_v1 : public boot_img_hdr_v0 {
    uint32_t recovery_dtbo_size;   /* size in bytes for recovery DTBO image */
    uint64_t recovery_dtbo_offset; /* offset to recovery dtbo in boot image */
    uint32_t header_size;
} __attribute__((packed));

bootloader会从boot header得到kernel/ramdisk/second/device的大小和要加载到ram上的地址,读取aboot/recovery分区的内容到ram。当我们使用fastboot刷分区时候会执行,以高通为例。
(注:下面为例方便贴至一处,不以实际为准),

static unsigned page_size = 2048;
static unsigned base_addr      = 0x10000000;
static unsigned kernel_offset  = 0x00008000;
static unsigned ramdisk_offset = 0x01000000;
static unsigned second_offset  = 0x00f00000;
static unsigned tags_offset    = 0x00000100;

boot_img_hdr_v1* mkbootimg(void* kernel, int64_t kernel_size, off_t kernel_offset, void* ramdisk,
                           int64_t ramdisk_size, off_t ramdisk_offset, void* second,
                           int64_t second_size, off_t second_offset, size_t page_size, size_t base,
                           off_t tags_offset, uint32_t header_version, int64_t* bootimg_size) {
    size_t page_mask = page_size - 1;

    int64_t header_actual = (sizeof(boot_img_hdr_v1) + page_mask) & (~page_mask);
    int64_t kernel_actual = (kernel_size + page_mask) & (~page_mask);
    int64_t ramdisk_actual = (ramdisk_size + page_mask) & (~page_mask);
    int64_t second_actual = (second_size + page_mask) & (~page_mask);

    *bootimg_size = header_actual + kernel_actual + ramdisk_actual + second_actual;

    boot_img_hdr_v1* hdr = reinterpret_cast<boot_img_hdr_v1*>(calloc(*bootimg_size, 1));
    if (hdr == nullptr) {
        return hdr;
    }   

    memcpy(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE);

    hdr->kernel_size =  kernel_size;
    hdr->ramdisk_size = ramdisk_size;
    hdr->second_size =  second_size;

    hdr->kernel_addr =  base + kernel_offset;
    hdr->ramdisk_addr = base + ramdisk_offset;
    hdr->second_addr =  base + second_offset;
    hdr->tags_addr =    base + tags_offset;

    hdr->page_size =    page_size;

    if (header_version) {
        hdr->header_version = header_version;
        hdr->header_size = sizeof(boot_img_hdr_v1);
    }   

    memcpy(hdr->magic + page_size, kernel, kernel_size);
    memcpy(hdr->magic + page_size + kernel_actual, ramdisk, ramdisk_size);
    memcpy(hdr->magic + page_size + kernel_actual + ramdisk_actual, second, second_size);
    return hdr;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值