[IMX6Q]u-boot启动kernel流程

来源:互联网 发布:linux localdns查看 编辑:程序博客网 时间:2024/06/06 09:35

u-boot版本:v2009.08


u-boot利用了env里的cmd来实现调用boot linux的接口, 效果等同于在u-boot中敲"booti xxx..."

start_armboot -> board_late_init:

int board_late_init(void){int ret = 0;#ifdef MX6Q_SABRESD_ANDROID_Hswitch (get_boot_device()) {case SD_BOOT:if (!getenv("fastboot_dev"))setenv("fastboot_dev", "mmc2");/*本例的boot device是SD,并且device number是2*/if (!getenv("bootcmd"))setenv("bootcmd", "booti mmc2");break;......}#endif......return 0;}
start_armboot ->main_loop:

void main_loop (void){....../*获取前面set的bootcmd,值是"booti mmc2"*/s = getenv ("bootcmd");debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");/*如果u-boot开机阶段没有收到按键事件,那么就去启动kernel*/if (bootdelay >= 0 && s && !abortboot (bootdelay)) {......# ifndef CONFIG_SYS_HUSH_PARSER/*调用booti mmc2去boot linux*/run_command (s, 0);# else......}
booti命令对应的定义如下:

U_BOOT_CMD(booti,3,1,do_booti,"booti   - boot android bootimg from memory\n","[<addr> | mmc0 | mmc1 | mmc2 | mmcX] [<partition>] \n    - boot application image stored in memory or mmc\n""\t'addr' should be the address of boot image which is zImage+ramdisk.img\n""\t'mmcX' is the mmc device you store your boot.img, which will read the boot.img from 1M offset('/boot' partition)\n""\t 'partition' (optional) is the partition id of your device, if no partition give, will going to 'boot' partition\n");
do_booti:

int do_booti(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]){......if (mmcc != -1) {#ifdef CONFIG_MMC....../*获取device信息*/mmc = find_mmc_device(mmcc);if (!mmc) {printf("booti: cannot find '%d' mmc device\n", mmcc);goto fail;}......#ifdef CONFIG_ANDROID_BOOT_PARTITION_MMC#ifdef CONFIG_ANDROID_RECOVERY_PARTITION_MMC/*开机可能是进入正常boot模式,也可以是进入recovery模式,取决于传进来的参数,本例是kernel*/if (!strcmp(ptn, "boot"))partno = CONFIG_ANDROID_BOOT_PARTITION_MMC;if (!strcmp(ptn, "recovery"))partno = CONFIG_ANDROID_RECOVERY_PARTITION_MMC;/*获取kernel对应的partition info*/if (get_partition_info(dev_desc, partno, &info)) {printf("booti: device don't have such partition:%s\n", ptn);goto fail;}#endif#endif#ifdef CONFIG_FASTBOOT......#else/*获取kernel的hdr,此信息是在编译boot.img的时候就存放在它起始的某个固定位置。*/if (mmc->block_dev.block_read(mmcc, info.start,      1, (void *)hdr) < 0) {printf("booti: mmc failed to read bootimg header\n");goto fail;}......sector = info.start + (hdr->page_size / 512);#endif/*读取kernel到RAM中的kernel_addr*/if (mmc->block_dev.block_read(mmcc, sector,      (hdr->kernel_size / 512) + 1,      (void *)hdr->kernel_addr) < 0) {printf("booti: mmc failed to read kernel\n");goto fail;}/* flush cache after read */flush_cache((ulong)hdr->kernel_addr, hdr->kernel_size); /* FIXME */sector += ALIGN_SECTOR(hdr->kernel_size, hdr->page_size) / 512;/*读取ramdisk到kernel的ramdisk_addr*/if (mmc->block_dev.block_read(mmcc, sector,      (hdr->ramdisk_size / 512) + 1,      (void *)hdr->ramdisk_addr) < 0) {printf("booti: mmc failed to read kernel\n");goto fail;}/* flush cache after read */flush_cache((ulong)hdr->ramdisk_addr, hdr->ramdisk_size); /* FIXME */#elsereturn -1;#endif} else {......}....../*根据hdr信息来boot linux*/do_booti_linux(hdr);......}

void do_booti_linux (boot_img_hdr *hdr){ulong initrd_start, initrd_end;#ifdef CONFIG_SERIAL_TAGchar appended_cmd_line[512];#endifvoid (*theKernel)(int zero, int arch, uint params);bd_t *bd = gd->bd;#ifdef CONFIG_CMDLINE_TAGchar *commandline = getenv("bootargs");/* If no bootargs env, just use hdr command line *//*本例bootargs没有定义*/if (!commandline) {/*获取cmdline,此值在device/fsl/imx6/BoardConfigCommon.mk中定义。*/commandline = (char *)hdr->cmdline;......    }#endif/*kernel address就是boot kernel的函数指针地址了*/theKernel = (void (*)(int, int, uint))(hdr->kernel_addr);/*获取ramdisk start 和 end地址*/initrd_start = hdr->ramdisk_addr;initrd_end = initrd_start + hdr->ramdisk_size;/*将memory,serial,revision,commandline等都放在各自的struct tag中,kernel启动之后会解析它们。*/#if defined (CONFIG_SETUP_MEMORY_TAGS)setup_start_tag(bd);#ifdef CONFIG_SERIAL_TAGsetup_serial_tag (¶ms);#endif#ifdef CONFIG_REVISION_TAGsetup_revision_tag (¶ms);#endif#ifdef CONFIG_SETUP_MEMORY_TAGSsetup_memory_tags (bd);#endif#ifdef CONFIG_CMDLINE_TAGsetup_commandline_tag (bd, commandline);#endif#ifdef CONFIG_INITRD_TAGif (hdr->ramdisk_size)setup_initrd_tag (bd, initrd_start, initrd_end);#endif......setup_end_tag (bd);#endif....../*启动kernel, never return back!*/theKernel (0, bd->bi_arch_number, bd->bi_boot_params);}
注意theKernel()的参数,第二个是machine type,kernel会去匹配,如果没有找到对应的type id,那么就无法正常启动kernel.

int board_init(void){....../* board id for linux */gd->bd->bi_arch_number = MACH_TYPE_MX6Q_SABRESD;......}
第三个参数就是前面的那些tags.

到此,kernel就启动起来了。

2 0
原创粉丝点击