Android系统镜像中boot.img如何生成,在此篇文章解开它的神秘面纱。
源码位置:android/system/core/mkbootimg/
boot.img是由文件头信息,内核数据以及文件系统数据组成,它们之间非页面对齐部分用0填充
mkbootimg工具的使用:
int usage(void)
{
fprintf(stderr,"usage: mkbootimg\n"
" --kernel <filename>\n"
" --ramdisk <filename>\n"
" [ --second <2ndbootloader-filename> ]\n"
" [ --cmdline <kernel-commandline> ]\n"
" [ --board <boardname> ]\n"
" [ --base <address> ]\n"
" [ --pagesize <pagesize> ]\n"
" -o|--output <filename>\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中