boot.img的生成过程,解析mkbootimg

Android系统镜像中boot.img如何生成,在此篇文章解开它的神秘面纱。

源码位置:android/system/core/mkbootimg/

boot.img是由文件头信息,内核数据以及文件系统数据组成,它们之间非页面对齐部分用0填充

mkbootimg工具的使用:
int usage(void)
{
    fprintf(stderr,"usage: mkbootimg\n"
            "       --kernel \n"
            "       --ramdisk \n"
            "       [ --second <2ndbootloader-filename> ]\n"
            "       [ --cmdline ]\n"
            "       [ --board ]\n"
            "       [ --base

]\n"
            "       [ --pagesize ]\n"
            "       -o|--output \n"
            );
    return 1;
}

在瑞芯微平台上 Android boot.img生成步骤如下:

mkbootimg --kernel $OUT/kernel --ramdisk $OUT/ramdisk.img --second kernel/resource.img --output $OUT/boot.img

boot.img对应的结构体原型:

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加载到内存的位置和包含的镜像的偏移大小:

    unsigned base           = 0x10000000;   //内核加载到内存中的基地址,与内核加载到内存的位置一致
    unsigned kernel_offset  = 0x00008000;   //内核的偏移大小
    unsigned ramdisk_offset = 0x01000000;
    unsigned second_offset  = 0x00f00000;   //扩展模块的偏移大小,在瑞芯微平台主要是resource.img(资源文件)
    unsigned tags_offset    = 0x00000100;
    size_t cmdlen;

获取参数: 

while(argc > 0){
        char *arg = argv[0];
        char *val = argv[1];
        if(argc < 2) {
            return usage();
        }
        argc -= 2;
        argv += 2;
        if(!strcmp(arg, "--output") || !strcmp(arg, "-o")) {
            bootimg = val;
        } else if(!strcmp(arg, "--kernel")) {
            kernel_fn = val;
        } else if(!strcmp(arg, "--ramdisk")) {
            ramdisk_fn = val;
        } else if(!strcmp(arg, "--second")) {
            second_fn = val;

boot.img中镜像加载到内存的位置,填充结构体: 

    hdr.page_size = pagesize;  //内存块的大小

    hdr.kernel_addr =  base + kernel_offset;  //内核加载的位置
    hdr.ramdisk_addr = base + ramdisk_offset; //radisk文件系统加载的位置
    hdr.second_addr =  base + second_offset; //扩展项加载的位置
    hdr.tags_addr =    base + tags_offset;

将文件整合到boot.img下:
    kernel_data = load_file(kernel_fn, &hdr.kernel_size);
    if(kernel_data == 0) {
        fprintf(stderr,"error: could not load kernel '%s'\n", kernel_fn);
        return 1;
    }

    if(!strcmp(ramdisk_fn,"NONE")) {
        ramdisk_data = 0;
        hdr.ramdisk_size = 0;
    } else {
        ramdisk_data = load_file(ramdisk_fn, &hdr.ramdisk_size);
        if(ramdisk_data == 0) {
            fprintf(stderr,"error: could not load ramdisk '%s'\n", ramdisk_fn);
            return 1;
        }
    }

    if(second_fn) {
        second_data = load_file(second_fn, &hdr.second_size);
        if(second_data == 0) {
            fprintf(stderr,"error: could not load secondstage '%s'\n", second_fn);
            return 1;
        }
    }

load_file函数将相应的文件偏移整合到boot.img中 

 

你可能感兴趣的:(Android系统开发)